]> git.proxmox.com Git - qemu.git/blame - target-arm/translate.c
target-arm: get rid of gen_set_psr_T0 and replace it by gen_set_psr/gen_set_psr_im
[qemu.git] / target-arm / translate.c
CommitLineData
2c0262af
FB
1/*
2 * ARM translation
5fafdf24 3 *
2c0262af 4 * Copyright (c) 2003 Fabrice Bellard
9ee6e8bb 5 * Copyright (c) 2005-2007 CodeSourcery
18c9b560 6 * Copyright (c) 2007 OpenedHand, Ltd.
2c0262af
FB
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
8167ee88 19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
2c0262af
FB
20 */
21#include <stdarg.h>
22#include <stdlib.h>
23#include <stdio.h>
24#include <string.h>
25#include <inttypes.h>
26
27#include "cpu.h"
28#include "exec-all.h"
29#include "disas.h"
57fec1fe 30#include "tcg-op.h"
79383c9c 31#include "qemu-log.h"
1497c961 32
a7812ae4 33#include "helpers.h"
1497c961 34#define GEN_HELPER 1
b26eefb6 35#include "helpers.h"
2c0262af 36
9ee6e8bb
PB
37#define ENABLE_ARCH_5J 0
38#define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
39#define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
40#define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
41#define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
b5ff1b31 42
86753403 43#define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
b5ff1b31 44
2c0262af
FB
45/* internal defines */
46typedef struct DisasContext {
0fa85d43 47 target_ulong pc;
2c0262af 48 int is_jmp;
e50e6a20
FB
49 /* Nonzero if this instruction has been conditionally skipped. */
50 int condjmp;
51 /* The label that will be jumped to when the instruction is skipped. */
52 int condlabel;
9ee6e8bb
PB
53 /* Thumb-2 condtional execution bits. */
54 int condexec_mask;
55 int condexec_cond;
2c0262af 56 struct TranslationBlock *tb;
8aaca4c0 57 int singlestep_enabled;
5899f386 58 int thumb;
b5ff1b31
FB
59#if !defined(CONFIG_USER_ONLY)
60 int user;
61#endif
2c0262af
FB
62} DisasContext;
63
b5ff1b31
FB
64#if defined(CONFIG_USER_ONLY)
65#define IS_USER(s) 1
66#else
67#define IS_USER(s) (s->user)
68#endif
69
9ee6e8bb
PB
70/* These instructions trap after executing, so defer them until after the
71 conditional executions state has been updated. */
72#define DISAS_WFI 4
73#define DISAS_SWI 5
2c0262af 74
a7812ae4 75static TCGv_ptr cpu_env;
ad69471c 76/* We reuse the same 64-bit temporaries for efficiency. */
a7812ae4 77static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
155c3eac 78static TCGv_i32 cpu_R[16];
ad69471c 79
b26eefb6 80/* FIXME: These should be removed. */
8f8e3aa4 81static TCGv cpu_T[2];
a7812ae4
PB
82static TCGv cpu_F0s, cpu_F1s;
83static TCGv_i64 cpu_F0d, cpu_F1d;
b26eefb6 84
2e70f6ef
PB
85#define ICOUNT_TEMP cpu_T[0]
86#include "gen-icount.h"
87
155c3eac
FN
88static const char *regnames[] =
89 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
90 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
91
b26eefb6
PB
92/* initialize TCG globals. */
93void arm_translate_init(void)
94{
155c3eac
FN
95 int i;
96
a7812ae4
PB
97 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
98
99 cpu_T[0] = tcg_global_reg_new_i32(TCG_AREG1, "T0");
100 cpu_T[1] = tcg_global_reg_new_i32(TCG_AREG2, "T1");
b26eefb6 101
155c3eac
FN
102 for (i = 0; i < 16; i++) {
103 cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
104 offsetof(CPUState, regs[i]),
105 regnames[i]);
106 }
107
a7812ae4
PB
108#define GEN_HELPER 2
109#include "helpers.h"
b26eefb6
PB
110}
111
b26eefb6 112static int num_temps;
b26eefb6
PB
113
114/* Allocate a temporary variable. */
a7812ae4 115static TCGv_i32 new_tmp(void)
b26eefb6 116{
12edd4f2
FN
117 num_temps++;
118 return tcg_temp_new_i32();
b26eefb6
PB
119}
120
121/* Release a temporary variable. */
122static void dead_tmp(TCGv tmp)
123{
12edd4f2 124 tcg_temp_free(tmp);
b26eefb6 125 num_temps--;
b26eefb6
PB
126}
127
d9ba4830
PB
128static inline TCGv load_cpu_offset(int offset)
129{
130 TCGv tmp = new_tmp();
131 tcg_gen_ld_i32(tmp, cpu_env, offset);
132 return tmp;
133}
134
135#define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
136
137static inline void store_cpu_offset(TCGv var, int offset)
138{
139 tcg_gen_st_i32(var, cpu_env, offset);
140 dead_tmp(var);
141}
142
143#define store_cpu_field(var, name) \
144 store_cpu_offset(var, offsetof(CPUState, name))
145
b26eefb6
PB
146/* Set a variable to the value of a CPU register. */
147static void load_reg_var(DisasContext *s, TCGv var, int reg)
148{
149 if (reg == 15) {
150 uint32_t addr;
151 /* normaly, since we updated PC, we need only to add one insn */
152 if (s->thumb)
153 addr = (long)s->pc + 2;
154 else
155 addr = (long)s->pc + 4;
156 tcg_gen_movi_i32(var, addr);
157 } else {
155c3eac 158 tcg_gen_mov_i32(var, cpu_R[reg]);
b26eefb6
PB
159 }
160}
161
162/* Create a new temporary and set it to the value of a CPU register. */
163static inline TCGv load_reg(DisasContext *s, int reg)
164{
165 TCGv tmp = new_tmp();
166 load_reg_var(s, tmp, reg);
167 return tmp;
168}
169
170/* Set a CPU register. The source must be a temporary and will be
171 marked as dead. */
172static void store_reg(DisasContext *s, int reg, TCGv var)
173{
174 if (reg == 15) {
175 tcg_gen_andi_i32(var, var, ~1);
176 s->is_jmp = DISAS_JUMP;
177 }
155c3eac 178 tcg_gen_mov_i32(cpu_R[reg], var);
b26eefb6
PB
179 dead_tmp(var);
180}
181
182
183/* Basic operations. */
184#define gen_op_movl_T0_T1() tcg_gen_mov_i32(cpu_T[0], cpu_T[1])
b26eefb6
PB
185#define gen_op_movl_T0_im(im) tcg_gen_movi_i32(cpu_T[0], im)
186#define gen_op_movl_T1_im(im) tcg_gen_movi_i32(cpu_T[1], im)
b26eefb6
PB
187
188#define gen_op_addl_T1_im(im) tcg_gen_addi_i32(cpu_T[1], cpu_T[1], im)
189#define gen_op_addl_T0_T1() tcg_gen_add_i32(cpu_T[0], cpu_T[0], cpu_T[1])
190#define gen_op_subl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[0], cpu_T[1])
191#define gen_op_rsbl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[1], cpu_T[0])
192
8984bd2e
PB
193#define gen_op_addl_T0_T1_cc() gen_helper_add_cc(cpu_T[0], cpu_T[0], cpu_T[1])
194#define gen_op_adcl_T0_T1_cc() gen_helper_adc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
195#define gen_op_subl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[0], cpu_T[1])
196#define gen_op_sbcl_T0_T1_cc() gen_helper_sbc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
197#define gen_op_rsbl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[1], cpu_T[0])
8984bd2e 198
b26eefb6
PB
199#define gen_op_andl_T0_T1() tcg_gen_and_i32(cpu_T[0], cpu_T[0], cpu_T[1])
200#define gen_op_xorl_T0_T1() tcg_gen_xor_i32(cpu_T[0], cpu_T[0], cpu_T[1])
201#define gen_op_orl_T0_T1() tcg_gen_or_i32(cpu_T[0], cpu_T[0], cpu_T[1])
202#define gen_op_notl_T0() tcg_gen_not_i32(cpu_T[0], cpu_T[0])
203#define gen_op_notl_T1() tcg_gen_not_i32(cpu_T[1], cpu_T[1])
204#define gen_op_logic_T0_cc() gen_logic_CC(cpu_T[0]);
205#define gen_op_logic_T1_cc() gen_logic_CC(cpu_T[1]);
206
b26eefb6
PB
207#define gen_op_shll_T1_im(im) tcg_gen_shli_i32(cpu_T[1], cpu_T[1], im)
208#define gen_op_shrl_T1_im(im) tcg_gen_shri_i32(cpu_T[1], cpu_T[1], im)
b26eefb6
PB
209
210/* Value extensions. */
86831435
PB
211#define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
212#define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
b26eefb6
PB
213#define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
214#define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
215
1497c961
PB
216#define gen_sxtb16(var) gen_helper_sxtb16(var, var)
217#define gen_uxtb16(var) gen_helper_uxtb16(var, var)
8f01245e
PB
218
219#define gen_op_mul_T0_T1() tcg_gen_mul_i32(cpu_T[0], cpu_T[0], cpu_T[1])
b26eefb6 220
d9ba4830
PB
221#define gen_set_cpsr(var, mask) gen_helper_cpsr_write(var, tcg_const_i32(mask))
222/* Set NZCV flags from the high 4 bits of var. */
223#define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
224
225static void gen_exception(int excp)
226{
227 TCGv tmp = new_tmp();
228 tcg_gen_movi_i32(tmp, excp);
229 gen_helper_exception(tmp);
230 dead_tmp(tmp);
231}
232
3670669c
PB
233static void gen_smul_dual(TCGv a, TCGv b)
234{
235 TCGv tmp1 = new_tmp();
236 TCGv tmp2 = new_tmp();
22478e79
AZ
237 tcg_gen_ext16s_i32(tmp1, a);
238 tcg_gen_ext16s_i32(tmp2, b);
3670669c
PB
239 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
240 dead_tmp(tmp2);
241 tcg_gen_sari_i32(a, a, 16);
242 tcg_gen_sari_i32(b, b, 16);
243 tcg_gen_mul_i32(b, b, a);
244 tcg_gen_mov_i32(a, tmp1);
245 dead_tmp(tmp1);
246}
247
248/* Byteswap each halfword. */
249static void gen_rev16(TCGv var)
250{
251 TCGv tmp = new_tmp();
252 tcg_gen_shri_i32(tmp, var, 8);
253 tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
254 tcg_gen_shli_i32(var, var, 8);
255 tcg_gen_andi_i32(var, var, 0xff00ff00);
256 tcg_gen_or_i32(var, var, tmp);
257 dead_tmp(tmp);
258}
259
260/* Byteswap low halfword and sign extend. */
261static void gen_revsh(TCGv var)
262{
263 TCGv tmp = new_tmp();
264 tcg_gen_shri_i32(tmp, var, 8);
265 tcg_gen_andi_i32(tmp, tmp, 0x00ff);
266 tcg_gen_shli_i32(var, var, 8);
267 tcg_gen_ext8s_i32(var, var);
268 tcg_gen_or_i32(var, var, tmp);
269 dead_tmp(tmp);
270}
271
272/* Unsigned bitfield extract. */
273static void gen_ubfx(TCGv var, int shift, uint32_t mask)
274{
275 if (shift)
276 tcg_gen_shri_i32(var, var, shift);
277 tcg_gen_andi_i32(var, var, mask);
278}
279
280/* Signed bitfield extract. */
281static void gen_sbfx(TCGv var, int shift, int width)
282{
283 uint32_t signbit;
284
285 if (shift)
286 tcg_gen_sari_i32(var, var, shift);
287 if (shift + width < 32) {
288 signbit = 1u << (width - 1);
289 tcg_gen_andi_i32(var, var, (1u << width) - 1);
290 tcg_gen_xori_i32(var, var, signbit);
291 tcg_gen_subi_i32(var, var, signbit);
292 }
293}
294
295/* Bitfield insertion. Insert val into base. Clobbers base and val. */
296static void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask)
297{
3670669c 298 tcg_gen_andi_i32(val, val, mask);
8f8e3aa4
PB
299 tcg_gen_shli_i32(val, val, shift);
300 tcg_gen_andi_i32(base, base, ~(mask << shift));
3670669c
PB
301 tcg_gen_or_i32(dest, base, val);
302}
303
d9ba4830
PB
304/* Round the top 32 bits of a 64-bit value. */
305static void gen_roundqd(TCGv a, TCGv b)
3670669c 306{
d9ba4830
PB
307 tcg_gen_shri_i32(a, a, 31);
308 tcg_gen_add_i32(a, a, b);
3670669c
PB
309}
310
8f01245e
PB
311/* FIXME: Most targets have native widening multiplication.
312 It would be good to use that instead of a full wide multiply. */
5e3f878a 313/* 32x32->64 multiply. Marks inputs as dead. */
a7812ae4 314static TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b)
5e3f878a 315{
a7812ae4
PB
316 TCGv_i64 tmp1 = tcg_temp_new_i64();
317 TCGv_i64 tmp2 = tcg_temp_new_i64();
5e3f878a
PB
318
319 tcg_gen_extu_i32_i64(tmp1, a);
320 dead_tmp(a);
321 tcg_gen_extu_i32_i64(tmp2, b);
322 dead_tmp(b);
323 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
324 return tmp1;
325}
326
a7812ae4 327static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b)
5e3f878a 328{
a7812ae4
PB
329 TCGv_i64 tmp1 = tcg_temp_new_i64();
330 TCGv_i64 tmp2 = tcg_temp_new_i64();
5e3f878a
PB
331
332 tcg_gen_ext_i32_i64(tmp1, a);
333 dead_tmp(a);
334 tcg_gen_ext_i32_i64(tmp2, b);
335 dead_tmp(b);
336 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
337 return tmp1;
338}
339
8f01245e
PB
340/* Unsigned 32x32->64 multiply. */
341static void gen_op_mull_T0_T1(void)
342{
a7812ae4
PB
343 TCGv_i64 tmp1 = tcg_temp_new_i64();
344 TCGv_i64 tmp2 = tcg_temp_new_i64();
8f01245e
PB
345
346 tcg_gen_extu_i32_i64(tmp1, cpu_T[0]);
347 tcg_gen_extu_i32_i64(tmp2, cpu_T[1]);
348 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
349 tcg_gen_trunc_i64_i32(cpu_T[0], tmp1);
350 tcg_gen_shri_i64(tmp1, tmp1, 32);
351 tcg_gen_trunc_i64_i32(cpu_T[1], tmp1);
352}
353
354/* Signed 32x32->64 multiply. */
d9ba4830 355static void gen_imull(TCGv a, TCGv b)
8f01245e 356{
a7812ae4
PB
357 TCGv_i64 tmp1 = tcg_temp_new_i64();
358 TCGv_i64 tmp2 = tcg_temp_new_i64();
8f01245e 359
d9ba4830
PB
360 tcg_gen_ext_i32_i64(tmp1, a);
361 tcg_gen_ext_i32_i64(tmp2, b);
8f01245e 362 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
d9ba4830 363 tcg_gen_trunc_i64_i32(a, tmp1);
8f01245e 364 tcg_gen_shri_i64(tmp1, tmp1, 32);
d9ba4830
PB
365 tcg_gen_trunc_i64_i32(b, tmp1);
366}
d9ba4830 367
8f01245e
PB
368/* Swap low and high halfwords. */
369static void gen_swap_half(TCGv var)
370{
371 TCGv tmp = new_tmp();
372 tcg_gen_shri_i32(tmp, var, 16);
373 tcg_gen_shli_i32(var, var, 16);
374 tcg_gen_or_i32(var, var, tmp);
3670669c 375 dead_tmp(tmp);
8f01245e
PB
376}
377
b26eefb6
PB
378/* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
379 tmp = (t0 ^ t1) & 0x8000;
380 t0 &= ~0x8000;
381 t1 &= ~0x8000;
382 t0 = (t0 + t1) ^ tmp;
383 */
384
385static void gen_add16(TCGv t0, TCGv t1)
386{
387 TCGv tmp = new_tmp();
388 tcg_gen_xor_i32(tmp, t0, t1);
389 tcg_gen_andi_i32(tmp, tmp, 0x8000);
390 tcg_gen_andi_i32(t0, t0, ~0x8000);
391 tcg_gen_andi_i32(t1, t1, ~0x8000);
392 tcg_gen_add_i32(t0, t0, t1);
393 tcg_gen_xor_i32(t0, t0, tmp);
394 dead_tmp(tmp);
395 dead_tmp(t1);
396}
397
9a119ff6
PB
398#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
399
b26eefb6
PB
400/* Set CF to the top bit of var. */
401static void gen_set_CF_bit31(TCGv var)
402{
403 TCGv tmp = new_tmp();
404 tcg_gen_shri_i32(tmp, var, 31);
4cc633c3 405 gen_set_CF(tmp);
b26eefb6
PB
406 dead_tmp(tmp);
407}
408
409/* Set N and Z flags from var. */
410static inline void gen_logic_CC(TCGv var)
411{
6fbe23d5
PB
412 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NF));
413 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, ZF));
b26eefb6
PB
414}
415
416/* T0 += T1 + CF. */
417static void gen_adc_T0_T1(void)
418{
d9ba4830 419 TCGv tmp;
b26eefb6 420 gen_op_addl_T0_T1();
d9ba4830 421 tmp = load_cpu_field(CF);
b26eefb6
PB
422 tcg_gen_add_i32(cpu_T[0], cpu_T[0], tmp);
423 dead_tmp(tmp);
424}
425
e9bb4aa9
JR
426/* dest = T0 + T1 + CF. */
427static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1)
428{
429 TCGv tmp;
430 tcg_gen_add_i32(dest, t0, t1);
431 tmp = load_cpu_field(CF);
432 tcg_gen_add_i32(dest, dest, tmp);
433 dead_tmp(tmp);
434}
435
3670669c
PB
436/* dest = T0 - T1 + CF - 1. */
437static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
438{
d9ba4830 439 TCGv tmp;
3670669c 440 tcg_gen_sub_i32(dest, t0, t1);
d9ba4830 441 tmp = load_cpu_field(CF);
3670669c
PB
442 tcg_gen_add_i32(dest, dest, tmp);
443 tcg_gen_subi_i32(dest, dest, 1);
444 dead_tmp(tmp);
445}
446
447#define gen_sbc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[0], cpu_T[1])
448#define gen_rsc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[1], cpu_T[0])
449
b26eefb6
PB
450/* T0 &= ~T1. Clobbers T1. */
451/* FIXME: Implement bic natively. */
8f8e3aa4
PB
452static inline void tcg_gen_bic_i32(TCGv dest, TCGv t0, TCGv t1)
453{
454 TCGv tmp = new_tmp();
455 tcg_gen_not_i32(tmp, t1);
456 tcg_gen_and_i32(dest, t0, tmp);
457 dead_tmp(tmp);
458}
b26eefb6
PB
459static inline void gen_op_bicl_T0_T1(void)
460{
461 gen_op_notl_T1();
462 gen_op_andl_T0_T1();
463}
464
ad69471c
PB
465/* FIXME: Implement this natively. */
466#define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
467
b26eefb6
PB
468/* FIXME: Implement this natively. */
469static void tcg_gen_rori_i32(TCGv t0, TCGv t1, int i)
470{
471 TCGv tmp;
472
473 if (i == 0)
474 return;
475
476 tmp = new_tmp();
477 tcg_gen_shri_i32(tmp, t1, i);
478 tcg_gen_shli_i32(t1, t1, 32 - i);
479 tcg_gen_or_i32(t0, t1, tmp);
480 dead_tmp(tmp);
481}
482
9a119ff6 483static void shifter_out_im(TCGv var, int shift)
b26eefb6 484{
9a119ff6
PB
485 TCGv tmp = new_tmp();
486 if (shift == 0) {
487 tcg_gen_andi_i32(tmp, var, 1);
b26eefb6 488 } else {
9a119ff6 489 tcg_gen_shri_i32(tmp, var, shift);
4cc633c3 490 if (shift != 31)
9a119ff6
PB
491 tcg_gen_andi_i32(tmp, tmp, 1);
492 }
493 gen_set_CF(tmp);
494 dead_tmp(tmp);
495}
b26eefb6 496
9a119ff6
PB
497/* Shift by immediate. Includes special handling for shift == 0. */
498static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
499{
500 switch (shiftop) {
501 case 0: /* LSL */
502 if (shift != 0) {
503 if (flags)
504 shifter_out_im(var, 32 - shift);
505 tcg_gen_shli_i32(var, var, shift);
506 }
507 break;
508 case 1: /* LSR */
509 if (shift == 0) {
510 if (flags) {
511 tcg_gen_shri_i32(var, var, 31);
512 gen_set_CF(var);
513 }
514 tcg_gen_movi_i32(var, 0);
515 } else {
516 if (flags)
517 shifter_out_im(var, shift - 1);
518 tcg_gen_shri_i32(var, var, shift);
519 }
520 break;
521 case 2: /* ASR */
522 if (shift == 0)
523 shift = 32;
524 if (flags)
525 shifter_out_im(var, shift - 1);
526 if (shift == 32)
527 shift = 31;
528 tcg_gen_sari_i32(var, var, shift);
529 break;
530 case 3: /* ROR/RRX */
531 if (shift != 0) {
532 if (flags)
533 shifter_out_im(var, shift - 1);
534 tcg_gen_rori_i32(var, var, shift); break;
535 } else {
d9ba4830 536 TCGv tmp = load_cpu_field(CF);
9a119ff6
PB
537 if (flags)
538 shifter_out_im(var, 0);
539 tcg_gen_shri_i32(var, var, 1);
b26eefb6
PB
540 tcg_gen_shli_i32(tmp, tmp, 31);
541 tcg_gen_or_i32(var, var, tmp);
542 dead_tmp(tmp);
b26eefb6
PB
543 }
544 }
545};
546
8984bd2e
PB
547static inline void gen_arm_shift_reg(TCGv var, int shiftop,
548 TCGv shift, int flags)
549{
550 if (flags) {
551 switch (shiftop) {
552 case 0: gen_helper_shl_cc(var, var, shift); break;
553 case 1: gen_helper_shr_cc(var, var, shift); break;
554 case 2: gen_helper_sar_cc(var, var, shift); break;
555 case 3: gen_helper_ror_cc(var, var, shift); break;
556 }
557 } else {
558 switch (shiftop) {
559 case 0: gen_helper_shl(var, var, shift); break;
560 case 1: gen_helper_shr(var, var, shift); break;
561 case 2: gen_helper_sar(var, var, shift); break;
562 case 3: gen_helper_ror(var, var, shift); break;
563 }
564 }
565 dead_tmp(shift);
566}
567
6ddbc6e4
PB
568#define PAS_OP(pfx) \
569 switch (op2) { \
570 case 0: gen_pas_helper(glue(pfx,add16)); break; \
571 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
572 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
573 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
574 case 4: gen_pas_helper(glue(pfx,add8)); break; \
575 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
576 }
d9ba4830 577static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
6ddbc6e4 578{
a7812ae4 579 TCGv_ptr tmp;
6ddbc6e4
PB
580
581 switch (op1) {
582#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
583 case 1:
a7812ae4 584 tmp = tcg_temp_new_ptr();
6ddbc6e4
PB
585 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
586 PAS_OP(s)
587 break;
588 case 5:
a7812ae4 589 tmp = tcg_temp_new_ptr();
6ddbc6e4
PB
590 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
591 PAS_OP(u)
592 break;
593#undef gen_pas_helper
594#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
595 case 2:
596 PAS_OP(q);
597 break;
598 case 3:
599 PAS_OP(sh);
600 break;
601 case 6:
602 PAS_OP(uq);
603 break;
604 case 7:
605 PAS_OP(uh);
606 break;
607#undef gen_pas_helper
608 }
609}
9ee6e8bb
PB
610#undef PAS_OP
611
6ddbc6e4
PB
612/* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
613#define PAS_OP(pfx) \
614 switch (op2) { \
615 case 0: gen_pas_helper(glue(pfx,add8)); break; \
616 case 1: gen_pas_helper(glue(pfx,add16)); break; \
617 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
618 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
619 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
620 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
621 }
d9ba4830 622static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
6ddbc6e4 623{
a7812ae4 624 TCGv_ptr tmp;
6ddbc6e4
PB
625
626 switch (op1) {
627#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
628 case 0:
a7812ae4 629 tmp = tcg_temp_new_ptr();
6ddbc6e4
PB
630 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
631 PAS_OP(s)
632 break;
633 case 4:
a7812ae4 634 tmp = tcg_temp_new_ptr();
6ddbc6e4
PB
635 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
636 PAS_OP(u)
637 break;
638#undef gen_pas_helper
639#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
640 case 1:
641 PAS_OP(q);
642 break;
643 case 2:
644 PAS_OP(sh);
645 break;
646 case 5:
647 PAS_OP(uq);
648 break;
649 case 6:
650 PAS_OP(uh);
651 break;
652#undef gen_pas_helper
653 }
654}
9ee6e8bb
PB
655#undef PAS_OP
656
d9ba4830
PB
657static void gen_test_cc(int cc, int label)
658{
659 TCGv tmp;
660 TCGv tmp2;
d9ba4830
PB
661 int inv;
662
d9ba4830
PB
663 switch (cc) {
664 case 0: /* eq: Z */
6fbe23d5 665 tmp = load_cpu_field(ZF);
cb63669a 666 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
d9ba4830
PB
667 break;
668 case 1: /* ne: !Z */
6fbe23d5 669 tmp = load_cpu_field(ZF);
cb63669a 670 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
d9ba4830
PB
671 break;
672 case 2: /* cs: C */
673 tmp = load_cpu_field(CF);
cb63669a 674 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
d9ba4830
PB
675 break;
676 case 3: /* cc: !C */
677 tmp = load_cpu_field(CF);
cb63669a 678 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
d9ba4830
PB
679 break;
680 case 4: /* mi: N */
6fbe23d5 681 tmp = load_cpu_field(NF);
cb63669a 682 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
d9ba4830
PB
683 break;
684 case 5: /* pl: !N */
6fbe23d5 685 tmp = load_cpu_field(NF);
cb63669a 686 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
d9ba4830
PB
687 break;
688 case 6: /* vs: V */
689 tmp = load_cpu_field(VF);
cb63669a 690 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
d9ba4830
PB
691 break;
692 case 7: /* vc: !V */
693 tmp = load_cpu_field(VF);
cb63669a 694 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
d9ba4830
PB
695 break;
696 case 8: /* hi: C && !Z */
697 inv = gen_new_label();
698 tmp = load_cpu_field(CF);
cb63669a 699 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
d9ba4830 700 dead_tmp(tmp);
6fbe23d5 701 tmp = load_cpu_field(ZF);
cb63669a 702 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
d9ba4830
PB
703 gen_set_label(inv);
704 break;
705 case 9: /* ls: !C || Z */
706 tmp = load_cpu_field(CF);
cb63669a 707 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
d9ba4830 708 dead_tmp(tmp);
6fbe23d5 709 tmp = load_cpu_field(ZF);
cb63669a 710 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
d9ba4830
PB
711 break;
712 case 10: /* ge: N == V -> N ^ V == 0 */
713 tmp = load_cpu_field(VF);
6fbe23d5 714 tmp2 = load_cpu_field(NF);
d9ba4830
PB
715 tcg_gen_xor_i32(tmp, tmp, tmp2);
716 dead_tmp(tmp2);
cb63669a 717 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
d9ba4830
PB
718 break;
719 case 11: /* lt: N != V -> N ^ V != 0 */
720 tmp = load_cpu_field(VF);
6fbe23d5 721 tmp2 = load_cpu_field(NF);
d9ba4830
PB
722 tcg_gen_xor_i32(tmp, tmp, tmp2);
723 dead_tmp(tmp2);
cb63669a 724 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
d9ba4830
PB
725 break;
726 case 12: /* gt: !Z && N == V */
727 inv = gen_new_label();
6fbe23d5 728 tmp = load_cpu_field(ZF);
cb63669a 729 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
d9ba4830
PB
730 dead_tmp(tmp);
731 tmp = load_cpu_field(VF);
6fbe23d5 732 tmp2 = load_cpu_field(NF);
d9ba4830
PB
733 tcg_gen_xor_i32(tmp, tmp, tmp2);
734 dead_tmp(tmp2);
cb63669a 735 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
d9ba4830
PB
736 gen_set_label(inv);
737 break;
738 case 13: /* le: Z || N != V */
6fbe23d5 739 tmp = load_cpu_field(ZF);
cb63669a 740 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
d9ba4830
PB
741 dead_tmp(tmp);
742 tmp = load_cpu_field(VF);
6fbe23d5 743 tmp2 = load_cpu_field(NF);
d9ba4830
PB
744 tcg_gen_xor_i32(tmp, tmp, tmp2);
745 dead_tmp(tmp2);
cb63669a 746 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
d9ba4830
PB
747 break;
748 default:
749 fprintf(stderr, "Bad condition code 0x%x\n", cc);
750 abort();
751 }
752 dead_tmp(tmp);
753}
2c0262af 754
b1d8e52e 755static const uint8_t table_logic_cc[16] = {
2c0262af
FB
756 1, /* and */
757 1, /* xor */
758 0, /* sub */
759 0, /* rsb */
760 0, /* add */
761 0, /* adc */
762 0, /* sbc */
763 0, /* rsc */
764 1, /* andl */
765 1, /* xorl */
766 0, /* cmp */
767 0, /* cmn */
768 1, /* orr */
769 1, /* mov */
770 1, /* bic */
771 1, /* mvn */
772};
3b46e624 773
d9ba4830
PB
774/* Set PC and Thumb state from an immediate address. */
775static inline void gen_bx_im(DisasContext *s, uint32_t addr)
99c475ab 776{
b26eefb6 777 TCGv tmp;
99c475ab 778
b26eefb6 779 s->is_jmp = DISAS_UPDATE;
d9ba4830 780 if (s->thumb != (addr & 1)) {
155c3eac 781 tmp = new_tmp();
d9ba4830
PB
782 tcg_gen_movi_i32(tmp, addr & 1);
783 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
155c3eac 784 dead_tmp(tmp);
d9ba4830 785 }
155c3eac 786 tcg_gen_movi_i32(cpu_R[15], addr & ~1);
d9ba4830
PB
787}
788
789/* Set PC and Thumb state from var. var is marked as dead. */
790static inline void gen_bx(DisasContext *s, TCGv var)
791{
d9ba4830 792 s->is_jmp = DISAS_UPDATE;
155c3eac
FN
793 tcg_gen_andi_i32(cpu_R[15], var, ~1);
794 tcg_gen_andi_i32(var, var, 1);
795 store_cpu_field(var, thumb);
d9ba4830
PB
796}
797
21aeb343
JR
798/* Variant of store_reg which uses branch&exchange logic when storing
799 to r15 in ARM architecture v7 and above. The source must be a temporary
800 and will be marked as dead. */
801static inline void store_reg_bx(CPUState *env, DisasContext *s,
802 int reg, TCGv var)
803{
804 if (reg == 15 && ENABLE_ARCH_7) {
805 gen_bx(s, var);
806 } else {
807 store_reg(s, reg, var);
808 }
809}
810
b0109805
PB
811static inline TCGv gen_ld8s(TCGv addr, int index)
812{
813 TCGv tmp = new_tmp();
814 tcg_gen_qemu_ld8s(tmp, addr, index);
815 return tmp;
816}
817static inline TCGv gen_ld8u(TCGv addr, int index)
818{
819 TCGv tmp = new_tmp();
820 tcg_gen_qemu_ld8u(tmp, addr, index);
821 return tmp;
822}
823static inline TCGv gen_ld16s(TCGv addr, int index)
824{
825 TCGv tmp = new_tmp();
826 tcg_gen_qemu_ld16s(tmp, addr, index);
827 return tmp;
828}
829static inline TCGv gen_ld16u(TCGv addr, int index)
830{
831 TCGv tmp = new_tmp();
832 tcg_gen_qemu_ld16u(tmp, addr, index);
833 return tmp;
834}
835static inline TCGv gen_ld32(TCGv addr, int index)
836{
837 TCGv tmp = new_tmp();
838 tcg_gen_qemu_ld32u(tmp, addr, index);
839 return tmp;
840}
841static inline void gen_st8(TCGv val, TCGv addr, int index)
842{
843 tcg_gen_qemu_st8(val, addr, index);
844 dead_tmp(val);
845}
846static inline void gen_st16(TCGv val, TCGv addr, int index)
847{
848 tcg_gen_qemu_st16(val, addr, index);
849 dead_tmp(val);
850}
851static inline void gen_st32(TCGv val, TCGv addr, int index)
852{
853 tcg_gen_qemu_st32(val, addr, index);
854 dead_tmp(val);
855}
b5ff1b31 856
2c0262af
FB
857static inline void gen_movl_T0_reg(DisasContext *s, int reg)
858{
b26eefb6 859 load_reg_var(s, cpu_T[0], reg);
2c0262af
FB
860}
861
862static inline void gen_movl_T1_reg(DisasContext *s, int reg)
863{
b26eefb6 864 load_reg_var(s, cpu_T[1], reg);
2c0262af
FB
865}
866
5e3f878a
PB
867static inline void gen_set_pc_im(uint32_t val)
868{
155c3eac 869 tcg_gen_movi_i32(cpu_R[15], val);
5e3f878a
PB
870}
871
2c0262af
FB
872static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
873{
b26eefb6
PB
874 TCGv tmp;
875 if (reg == 15) {
876 tmp = new_tmp();
877 tcg_gen_andi_i32(tmp, cpu_T[t], ~1);
878 } else {
879 tmp = cpu_T[t];
880 }
155c3eac 881 tcg_gen_mov_i32(cpu_R[reg], tmp);
2c0262af 882 if (reg == 15) {
b26eefb6 883 dead_tmp(tmp);
2c0262af
FB
884 s->is_jmp = DISAS_JUMP;
885 }
886}
887
888static inline void gen_movl_reg_T0(DisasContext *s, int reg)
889{
890 gen_movl_reg_TN(s, reg, 0);
891}
892
893static inline void gen_movl_reg_T1(DisasContext *s, int reg)
894{
895 gen_movl_reg_TN(s, reg, 1);
896}
897
b5ff1b31
FB
898/* Force a TB lookup after an instruction that changes the CPU state. */
899static inline void gen_lookup_tb(DisasContext *s)
900{
901 gen_op_movl_T0_im(s->pc);
902 gen_movl_reg_T0(s, 15);
903 s->is_jmp = DISAS_UPDATE;
904}
905
b0109805
PB
906static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
907 TCGv var)
2c0262af 908{
1e8d4eec 909 int val, rm, shift, shiftop;
b26eefb6 910 TCGv offset;
2c0262af
FB
911
912 if (!(insn & (1 << 25))) {
913 /* immediate */
914 val = insn & 0xfff;
915 if (!(insn & (1 << 23)))
916 val = -val;
537730b9 917 if (val != 0)
b0109805 918 tcg_gen_addi_i32(var, var, val);
2c0262af
FB
919 } else {
920 /* shift/register */
921 rm = (insn) & 0xf;
922 shift = (insn >> 7) & 0x1f;
1e8d4eec 923 shiftop = (insn >> 5) & 3;
b26eefb6 924 offset = load_reg(s, rm);
9a119ff6 925 gen_arm_shift_im(offset, shiftop, shift, 0);
2c0262af 926 if (!(insn & (1 << 23)))
b0109805 927 tcg_gen_sub_i32(var, var, offset);
2c0262af 928 else
b0109805 929 tcg_gen_add_i32(var, var, offset);
b26eefb6 930 dead_tmp(offset);
2c0262af
FB
931 }
932}
933
191f9a93 934static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
b0109805 935 int extra, TCGv var)
2c0262af
FB
936{
937 int val, rm;
b26eefb6 938 TCGv offset;
3b46e624 939
2c0262af
FB
940 if (insn & (1 << 22)) {
941 /* immediate */
942 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
943 if (!(insn & (1 << 23)))
944 val = -val;
18acad92 945 val += extra;
537730b9 946 if (val != 0)
b0109805 947 tcg_gen_addi_i32(var, var, val);
2c0262af
FB
948 } else {
949 /* register */
191f9a93 950 if (extra)
b0109805 951 tcg_gen_addi_i32(var, var, extra);
2c0262af 952 rm = (insn) & 0xf;
b26eefb6 953 offset = load_reg(s, rm);
2c0262af 954 if (!(insn & (1 << 23)))
b0109805 955 tcg_gen_sub_i32(var, var, offset);
2c0262af 956 else
b0109805 957 tcg_gen_add_i32(var, var, offset);
b26eefb6 958 dead_tmp(offset);
2c0262af
FB
959 }
960}
961
4373f3ce
PB
962#define VFP_OP2(name) \
963static inline void gen_vfp_##name(int dp) \
964{ \
965 if (dp) \
966 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
967 else \
968 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
b7bcbe95
FB
969}
970
4373f3ce
PB
971VFP_OP2(add)
972VFP_OP2(sub)
973VFP_OP2(mul)
974VFP_OP2(div)
975
976#undef VFP_OP2
977
978static inline void gen_vfp_abs(int dp)
979{
980 if (dp)
981 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
982 else
983 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
984}
985
986static inline void gen_vfp_neg(int dp)
987{
988 if (dp)
989 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
990 else
991 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
992}
993
994static inline void gen_vfp_sqrt(int dp)
995{
996 if (dp)
997 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
998 else
999 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1000}
1001
1002static inline void gen_vfp_cmp(int dp)
1003{
1004 if (dp)
1005 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1006 else
1007 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1008}
1009
1010static inline void gen_vfp_cmpe(int dp)
1011{
1012 if (dp)
1013 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1014 else
1015 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1016}
1017
1018static inline void gen_vfp_F1_ld0(int dp)
1019{
1020 if (dp)
5b340b51 1021 tcg_gen_movi_i64(cpu_F1d, 0);
4373f3ce 1022 else
5b340b51 1023 tcg_gen_movi_i32(cpu_F1s, 0);
4373f3ce
PB
1024}
1025
1026static inline void gen_vfp_uito(int dp)
1027{
1028 if (dp)
1029 gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env);
1030 else
1031 gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env);
1032}
1033
1034static inline void gen_vfp_sito(int dp)
1035{
1036 if (dp)
66230e0d 1037 gen_helper_vfp_sitod(cpu_F0d, cpu_F0s, cpu_env);
4373f3ce 1038 else
66230e0d 1039 gen_helper_vfp_sitos(cpu_F0s, cpu_F0s, cpu_env);
4373f3ce
PB
1040}
1041
1042static inline void gen_vfp_toui(int dp)
1043{
1044 if (dp)
1045 gen_helper_vfp_touid(cpu_F0s, cpu_F0d, cpu_env);
1046 else
1047 gen_helper_vfp_touis(cpu_F0s, cpu_F0s, cpu_env);
1048}
1049
1050static inline void gen_vfp_touiz(int dp)
1051{
1052 if (dp)
1053 gen_helper_vfp_touizd(cpu_F0s, cpu_F0d, cpu_env);
1054 else
1055 gen_helper_vfp_touizs(cpu_F0s, cpu_F0s, cpu_env);
1056}
1057
1058static inline void gen_vfp_tosi(int dp)
1059{
1060 if (dp)
1061 gen_helper_vfp_tosid(cpu_F0s, cpu_F0d, cpu_env);
1062 else
1063 gen_helper_vfp_tosis(cpu_F0s, cpu_F0s, cpu_env);
1064}
1065
1066static inline void gen_vfp_tosiz(int dp)
9ee6e8bb
PB
1067{
1068 if (dp)
4373f3ce 1069 gen_helper_vfp_tosizd(cpu_F0s, cpu_F0d, cpu_env);
9ee6e8bb 1070 else
4373f3ce
PB
1071 gen_helper_vfp_tosizs(cpu_F0s, cpu_F0s, cpu_env);
1072}
1073
1074#define VFP_GEN_FIX(name) \
1075static inline void gen_vfp_##name(int dp, int shift) \
1076{ \
1077 if (dp) \
1078 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\
1079 else \
1080 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\
9ee6e8bb 1081}
4373f3ce
PB
1082VFP_GEN_FIX(tosh)
1083VFP_GEN_FIX(tosl)
1084VFP_GEN_FIX(touh)
1085VFP_GEN_FIX(toul)
1086VFP_GEN_FIX(shto)
1087VFP_GEN_FIX(slto)
1088VFP_GEN_FIX(uhto)
1089VFP_GEN_FIX(ulto)
1090#undef VFP_GEN_FIX
9ee6e8bb 1091
b5ff1b31
FB
1092static inline void gen_vfp_ld(DisasContext *s, int dp)
1093{
1094 if (dp)
4373f3ce 1095 tcg_gen_qemu_ld64(cpu_F0d, cpu_T[1], IS_USER(s));
b5ff1b31 1096 else
4373f3ce 1097 tcg_gen_qemu_ld32u(cpu_F0s, cpu_T[1], IS_USER(s));
b5ff1b31
FB
1098}
1099
1100static inline void gen_vfp_st(DisasContext *s, int dp)
1101{
1102 if (dp)
4373f3ce 1103 tcg_gen_qemu_st64(cpu_F0d, cpu_T[1], IS_USER(s));
b5ff1b31 1104 else
4373f3ce 1105 tcg_gen_qemu_st32(cpu_F0s, cpu_T[1], IS_USER(s));
b5ff1b31
FB
1106}
1107
8e96005d
FB
1108static inline long
1109vfp_reg_offset (int dp, int reg)
1110{
1111 if (dp)
1112 return offsetof(CPUARMState, vfp.regs[reg]);
1113 else if (reg & 1) {
1114 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1115 + offsetof(CPU_DoubleU, l.upper);
1116 } else {
1117 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1118 + offsetof(CPU_DoubleU, l.lower);
1119 }
1120}
9ee6e8bb
PB
1121
1122/* Return the offset of a 32-bit piece of a NEON register.
1123 zero is the least significant end of the register. */
1124static inline long
1125neon_reg_offset (int reg, int n)
1126{
1127 int sreg;
1128 sreg = reg * 2 + n;
1129 return vfp_reg_offset(0, sreg);
1130}
1131
ad69471c
PB
1132/* FIXME: Remove these. */
1133#define neon_T0 cpu_T[0]
1134#define neon_T1 cpu_T[1]
1135#define NEON_GET_REG(T, reg, n) \
1136 tcg_gen_ld_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1137#define NEON_SET_REG(T, reg, n) \
1138 tcg_gen_st_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
9ee6e8bb 1139
8f8e3aa4
PB
1140static TCGv neon_load_reg(int reg, int pass)
1141{
1142 TCGv tmp = new_tmp();
1143 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1144 return tmp;
1145}
1146
1147static void neon_store_reg(int reg, int pass, TCGv var)
1148{
1149 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1150 dead_tmp(var);
1151}
1152
a7812ae4 1153static inline void neon_load_reg64(TCGv_i64 var, int reg)
ad69471c
PB
1154{
1155 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1156}
1157
a7812ae4 1158static inline void neon_store_reg64(TCGv_i64 var, int reg)
ad69471c
PB
1159{
1160 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1161}
1162
4373f3ce
PB
1163#define tcg_gen_ld_f32 tcg_gen_ld_i32
1164#define tcg_gen_ld_f64 tcg_gen_ld_i64
1165#define tcg_gen_st_f32 tcg_gen_st_i32
1166#define tcg_gen_st_f64 tcg_gen_st_i64
1167
b7bcbe95
FB
1168static inline void gen_mov_F0_vreg(int dp, int reg)
1169{
1170 if (dp)
4373f3ce 1171 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95 1172 else
4373f3ce 1173 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95
FB
1174}
1175
1176static inline void gen_mov_F1_vreg(int dp, int reg)
1177{
1178 if (dp)
4373f3ce 1179 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95 1180 else
4373f3ce 1181 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95
FB
1182}
1183
1184static inline void gen_mov_vreg_F0(int dp, int reg)
1185{
1186 if (dp)
4373f3ce 1187 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95 1188 else
4373f3ce 1189 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95
FB
1190}
1191
18c9b560
AZ
1192#define ARM_CP_RW_BIT (1 << 20)
1193
a7812ae4 1194static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
e677137d
PB
1195{
1196 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1197}
1198
a7812ae4 1199static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
e677137d
PB
1200{
1201 tcg_gen_st_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1202}
1203
1204static inline void gen_op_iwmmxt_movl_wCx_T0(int reg)
1205{
1206 tcg_gen_st_i32(cpu_T[0], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1207}
1208
1209static inline void gen_op_iwmmxt_movl_T0_wCx(int reg)
1210{
1211 tcg_gen_ld_i32(cpu_T[0], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1212}
1213
1214static inline void gen_op_iwmmxt_movl_T1_wCx(int reg)
1215{
1216 tcg_gen_ld_i32(cpu_T[1], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1217}
1218
1219static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1220{
1221 iwmmxt_store_reg(cpu_M0, rn);
1222}
1223
1224static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1225{
1226 iwmmxt_load_reg(cpu_M0, rn);
1227}
1228
1229static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1230{
1231 iwmmxt_load_reg(cpu_V1, rn);
1232 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1233}
1234
1235static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1236{
1237 iwmmxt_load_reg(cpu_V1, rn);
1238 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1239}
1240
1241static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1242{
1243 iwmmxt_load_reg(cpu_V1, rn);
1244 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1245}
1246
1247#define IWMMXT_OP(name) \
1248static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1249{ \
1250 iwmmxt_load_reg(cpu_V1, rn); \
1251 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1252}
1253
1254#define IWMMXT_OP_ENV(name) \
1255static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1256{ \
1257 iwmmxt_load_reg(cpu_V1, rn); \
1258 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1259}
1260
1261#define IWMMXT_OP_ENV_SIZE(name) \
1262IWMMXT_OP_ENV(name##b) \
1263IWMMXT_OP_ENV(name##w) \
1264IWMMXT_OP_ENV(name##l)
1265
1266#define IWMMXT_OP_ENV1(name) \
1267static inline void gen_op_iwmmxt_##name##_M0(void) \
1268{ \
1269 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1270}
1271
1272IWMMXT_OP(maddsq)
1273IWMMXT_OP(madduq)
1274IWMMXT_OP(sadb)
1275IWMMXT_OP(sadw)
1276IWMMXT_OP(mulslw)
1277IWMMXT_OP(mulshw)
1278IWMMXT_OP(mululw)
1279IWMMXT_OP(muluhw)
1280IWMMXT_OP(macsw)
1281IWMMXT_OP(macuw)
1282
1283IWMMXT_OP_ENV_SIZE(unpackl)
1284IWMMXT_OP_ENV_SIZE(unpackh)
1285
1286IWMMXT_OP_ENV1(unpacklub)
1287IWMMXT_OP_ENV1(unpackluw)
1288IWMMXT_OP_ENV1(unpacklul)
1289IWMMXT_OP_ENV1(unpackhub)
1290IWMMXT_OP_ENV1(unpackhuw)
1291IWMMXT_OP_ENV1(unpackhul)
1292IWMMXT_OP_ENV1(unpacklsb)
1293IWMMXT_OP_ENV1(unpacklsw)
1294IWMMXT_OP_ENV1(unpacklsl)
1295IWMMXT_OP_ENV1(unpackhsb)
1296IWMMXT_OP_ENV1(unpackhsw)
1297IWMMXT_OP_ENV1(unpackhsl)
1298
1299IWMMXT_OP_ENV_SIZE(cmpeq)
1300IWMMXT_OP_ENV_SIZE(cmpgtu)
1301IWMMXT_OP_ENV_SIZE(cmpgts)
1302
1303IWMMXT_OP_ENV_SIZE(mins)
1304IWMMXT_OP_ENV_SIZE(minu)
1305IWMMXT_OP_ENV_SIZE(maxs)
1306IWMMXT_OP_ENV_SIZE(maxu)
1307
1308IWMMXT_OP_ENV_SIZE(subn)
1309IWMMXT_OP_ENV_SIZE(addn)
1310IWMMXT_OP_ENV_SIZE(subu)
1311IWMMXT_OP_ENV_SIZE(addu)
1312IWMMXT_OP_ENV_SIZE(subs)
1313IWMMXT_OP_ENV_SIZE(adds)
1314
1315IWMMXT_OP_ENV(avgb0)
1316IWMMXT_OP_ENV(avgb1)
1317IWMMXT_OP_ENV(avgw0)
1318IWMMXT_OP_ENV(avgw1)
1319
1320IWMMXT_OP(msadb)
1321
1322IWMMXT_OP_ENV(packuw)
1323IWMMXT_OP_ENV(packul)
1324IWMMXT_OP_ENV(packuq)
1325IWMMXT_OP_ENV(packsw)
1326IWMMXT_OP_ENV(packsl)
1327IWMMXT_OP_ENV(packsq)
1328
1329static inline void gen_op_iwmmxt_muladdsl_M0_T0_T1(void)
1330{
1331 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1332}
1333
1334static inline void gen_op_iwmmxt_muladdsw_M0_T0_T1(void)
1335{
1336 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1337}
1338
1339static inline void gen_op_iwmmxt_muladdswl_M0_T0_T1(void)
1340{
1341 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1342}
1343
1344static inline void gen_op_iwmmxt_align_M0_T0_wRn(int rn)
1345{
1346 iwmmxt_load_reg(cpu_V1, rn);
1347 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, cpu_T[0]);
1348}
1349
1350static inline void gen_op_iwmmxt_insr_M0_T0_T1(int shift)
1351{
1352 TCGv tmp = tcg_const_i32(shift);
1353 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1], tmp);
1354}
1355
1356static inline void gen_op_iwmmxt_extrsb_T0_M0(int shift)
1357{
1358 tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1359 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1360 tcg_gen_ext8s_i32(cpu_T[0], cpu_T[0]);
1361}
1362
1363static inline void gen_op_iwmmxt_extrsw_T0_M0(int shift)
1364{
1365 tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1366 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1367 tcg_gen_ext16s_i32(cpu_T[0], cpu_T[0]);
1368}
1369
1370static inline void gen_op_iwmmxt_extru_T0_M0(int shift, uint32_t mask)
1371{
1372 tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1373 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1374 if (mask != ~0u)
1375 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], mask);
1376}
1377
1378static void gen_op_iwmmxt_set_mup(void)
1379{
1380 TCGv tmp;
1381 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1382 tcg_gen_ori_i32(tmp, tmp, 2);
1383 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1384}
1385
1386static void gen_op_iwmmxt_set_cup(void)
1387{
1388 TCGv tmp;
1389 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1390 tcg_gen_ori_i32(tmp, tmp, 1);
1391 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1392}
1393
1394static void gen_op_iwmmxt_setpsr_nz(void)
1395{
1396 TCGv tmp = new_tmp();
1397 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1398 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1399}
1400
1401static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1402{
1403 iwmmxt_load_reg(cpu_V1, rn);
86831435 1404 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
e677137d
PB
1405 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1406}
1407
1408
1409static void gen_iwmmxt_movl_T0_T1_wRn(int rn)
1410{
1411 iwmmxt_load_reg(cpu_V0, rn);
1412 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_V0);
1413 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1414 tcg_gen_trunc_i64_i32(cpu_T[1], cpu_V0);
1415}
1416
1417static void gen_iwmmxt_movl_wRn_T0_T1(int rn)
1418{
36aa55dc 1419 tcg_gen_concat_i32_i64(cpu_V0, cpu_T[0], cpu_T[1]);
e677137d
PB
1420 iwmmxt_store_reg(cpu_V0, rn);
1421}
1422
18c9b560
AZ
1423static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn)
1424{
1425 int rd;
1426 uint32_t offset;
1427
1428 rd = (insn >> 16) & 0xf;
1429 gen_movl_T1_reg(s, rd);
1430
1431 offset = (insn & 0xff) << ((insn >> 7) & 2);
1432 if (insn & (1 << 24)) {
1433 /* Pre indexed */
1434 if (insn & (1 << 23))
1435 gen_op_addl_T1_im(offset);
1436 else
1437 gen_op_addl_T1_im(-offset);
1438
1439 if (insn & (1 << 21))
1440 gen_movl_reg_T1(s, rd);
1441 } else if (insn & (1 << 21)) {
1442 /* Post indexed */
1443 if (insn & (1 << 23))
1444 gen_op_movl_T0_im(offset);
1445 else
1446 gen_op_movl_T0_im(- offset);
1447 gen_op_addl_T0_T1();
1448 gen_movl_reg_T0(s, rd);
1449 } else if (!(insn & (1 << 23)))
1450 return 1;
1451 return 0;
1452}
1453
1454static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask)
1455{
1456 int rd = (insn >> 0) & 0xf;
1457
1458 if (insn & (1 << 8))
1459 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3)
1460 return 1;
1461 else
1462 gen_op_iwmmxt_movl_T0_wCx(rd);
1463 else
e677137d 1464 gen_iwmmxt_movl_T0_T1_wRn(rd);
18c9b560
AZ
1465
1466 gen_op_movl_T1_im(mask);
1467 gen_op_andl_T0_T1();
1468 return 0;
1469}
1470
1471/* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1472 (ie. an undefined instruction). */
1473static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
1474{
1475 int rd, wrd;
1476 int rdhi, rdlo, rd0, rd1, i;
b0109805 1477 TCGv tmp;
18c9b560
AZ
1478
1479 if ((insn & 0x0e000e00) == 0x0c000000) {
1480 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1481 wrd = insn & 0xf;
1482 rdlo = (insn >> 12) & 0xf;
1483 rdhi = (insn >> 16) & 0xf;
1484 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
e677137d 1485 gen_iwmmxt_movl_T0_T1_wRn(wrd);
18c9b560
AZ
1486 gen_movl_reg_T0(s, rdlo);
1487 gen_movl_reg_T1(s, rdhi);
1488 } else { /* TMCRR */
1489 gen_movl_T0_reg(s, rdlo);
1490 gen_movl_T1_reg(s, rdhi);
e677137d 1491 gen_iwmmxt_movl_wRn_T0_T1(wrd);
18c9b560
AZ
1492 gen_op_iwmmxt_set_mup();
1493 }
1494 return 0;
1495 }
1496
1497 wrd = (insn >> 12) & 0xf;
1498 if (gen_iwmmxt_address(s, insn))
1499 return 1;
1500 if (insn & ARM_CP_RW_BIT) {
1501 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
b0109805
PB
1502 tmp = gen_ld32(cpu_T[1], IS_USER(s));
1503 tcg_gen_mov_i32(cpu_T[0], tmp);
1504 dead_tmp(tmp);
18c9b560
AZ
1505 gen_op_iwmmxt_movl_wCx_T0(wrd);
1506 } else {
e677137d
PB
1507 i = 1;
1508 if (insn & (1 << 8)) {
1509 if (insn & (1 << 22)) { /* WLDRD */
1510 tcg_gen_qemu_ld64(cpu_M0, cpu_T[1], IS_USER(s));
1511 i = 0;
1512 } else { /* WLDRW wRd */
1513 tmp = gen_ld32(cpu_T[1], IS_USER(s));
1514 }
1515 } else {
1516 if (insn & (1 << 22)) { /* WLDRH */
1517 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
1518 } else { /* WLDRB */
1519 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
1520 }
1521 }
1522 if (i) {
1523 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1524 dead_tmp(tmp);
1525 }
18c9b560
AZ
1526 gen_op_iwmmxt_movq_wRn_M0(wrd);
1527 }
1528 } else {
1529 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1530 gen_op_iwmmxt_movl_T0_wCx(wrd);
b0109805
PB
1531 tmp = new_tmp();
1532 tcg_gen_mov_i32(tmp, cpu_T[0]);
1533 gen_st32(tmp, cpu_T[1], IS_USER(s));
18c9b560
AZ
1534 } else {
1535 gen_op_iwmmxt_movq_M0_wRn(wrd);
e677137d
PB
1536 tmp = new_tmp();
1537 if (insn & (1 << 8)) {
1538 if (insn & (1 << 22)) { /* WSTRD */
1539 dead_tmp(tmp);
1540 tcg_gen_qemu_st64(cpu_M0, cpu_T[1], IS_USER(s));
1541 } else { /* WSTRW wRd */
1542 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1543 gen_st32(tmp, cpu_T[1], IS_USER(s));
1544 }
1545 } else {
1546 if (insn & (1 << 22)) { /* WSTRH */
1547 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1548 gen_st16(tmp, cpu_T[1], IS_USER(s));
1549 } else { /* WSTRB */
1550 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1551 gen_st8(tmp, cpu_T[1], IS_USER(s));
1552 }
1553 }
18c9b560
AZ
1554 }
1555 }
1556 return 0;
1557 }
1558
1559 if ((insn & 0x0f000000) != 0x0e000000)
1560 return 1;
1561
1562 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1563 case 0x000: /* WOR */
1564 wrd = (insn >> 12) & 0xf;
1565 rd0 = (insn >> 0) & 0xf;
1566 rd1 = (insn >> 16) & 0xf;
1567 gen_op_iwmmxt_movq_M0_wRn(rd0);
1568 gen_op_iwmmxt_orq_M0_wRn(rd1);
1569 gen_op_iwmmxt_setpsr_nz();
1570 gen_op_iwmmxt_movq_wRn_M0(wrd);
1571 gen_op_iwmmxt_set_mup();
1572 gen_op_iwmmxt_set_cup();
1573 break;
1574 case 0x011: /* TMCR */
1575 if (insn & 0xf)
1576 return 1;
1577 rd = (insn >> 12) & 0xf;
1578 wrd = (insn >> 16) & 0xf;
1579 switch (wrd) {
1580 case ARM_IWMMXT_wCID:
1581 case ARM_IWMMXT_wCASF:
1582 break;
1583 case ARM_IWMMXT_wCon:
1584 gen_op_iwmmxt_set_cup();
1585 /* Fall through. */
1586 case ARM_IWMMXT_wCSSF:
1587 gen_op_iwmmxt_movl_T0_wCx(wrd);
1588 gen_movl_T1_reg(s, rd);
1589 gen_op_bicl_T0_T1();
1590 gen_op_iwmmxt_movl_wCx_T0(wrd);
1591 break;
1592 case ARM_IWMMXT_wCGR0:
1593 case ARM_IWMMXT_wCGR1:
1594 case ARM_IWMMXT_wCGR2:
1595 case ARM_IWMMXT_wCGR3:
1596 gen_op_iwmmxt_set_cup();
1597 gen_movl_reg_T0(s, rd);
1598 gen_op_iwmmxt_movl_wCx_T0(wrd);
1599 break;
1600 default:
1601 return 1;
1602 }
1603 break;
1604 case 0x100: /* WXOR */
1605 wrd = (insn >> 12) & 0xf;
1606 rd0 = (insn >> 0) & 0xf;
1607 rd1 = (insn >> 16) & 0xf;
1608 gen_op_iwmmxt_movq_M0_wRn(rd0);
1609 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1610 gen_op_iwmmxt_setpsr_nz();
1611 gen_op_iwmmxt_movq_wRn_M0(wrd);
1612 gen_op_iwmmxt_set_mup();
1613 gen_op_iwmmxt_set_cup();
1614 break;
1615 case 0x111: /* TMRC */
1616 if (insn & 0xf)
1617 return 1;
1618 rd = (insn >> 12) & 0xf;
1619 wrd = (insn >> 16) & 0xf;
1620 gen_op_iwmmxt_movl_T0_wCx(wrd);
1621 gen_movl_reg_T0(s, rd);
1622 break;
1623 case 0x300: /* WANDN */
1624 wrd = (insn >> 12) & 0xf;
1625 rd0 = (insn >> 0) & 0xf;
1626 rd1 = (insn >> 16) & 0xf;
1627 gen_op_iwmmxt_movq_M0_wRn(rd0);
e677137d 1628 tcg_gen_neg_i64(cpu_M0, cpu_M0);
18c9b560
AZ
1629 gen_op_iwmmxt_andq_M0_wRn(rd1);
1630 gen_op_iwmmxt_setpsr_nz();
1631 gen_op_iwmmxt_movq_wRn_M0(wrd);
1632 gen_op_iwmmxt_set_mup();
1633 gen_op_iwmmxt_set_cup();
1634 break;
1635 case 0x200: /* WAND */
1636 wrd = (insn >> 12) & 0xf;
1637 rd0 = (insn >> 0) & 0xf;
1638 rd1 = (insn >> 16) & 0xf;
1639 gen_op_iwmmxt_movq_M0_wRn(rd0);
1640 gen_op_iwmmxt_andq_M0_wRn(rd1);
1641 gen_op_iwmmxt_setpsr_nz();
1642 gen_op_iwmmxt_movq_wRn_M0(wrd);
1643 gen_op_iwmmxt_set_mup();
1644 gen_op_iwmmxt_set_cup();
1645 break;
1646 case 0x810: case 0xa10: /* WMADD */
1647 wrd = (insn >> 12) & 0xf;
1648 rd0 = (insn >> 0) & 0xf;
1649 rd1 = (insn >> 16) & 0xf;
1650 gen_op_iwmmxt_movq_M0_wRn(rd0);
1651 if (insn & (1 << 21))
1652 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1653 else
1654 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1655 gen_op_iwmmxt_movq_wRn_M0(wrd);
1656 gen_op_iwmmxt_set_mup();
1657 break;
1658 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1659 wrd = (insn >> 12) & 0xf;
1660 rd0 = (insn >> 16) & 0xf;
1661 rd1 = (insn >> 0) & 0xf;
1662 gen_op_iwmmxt_movq_M0_wRn(rd0);
1663 switch ((insn >> 22) & 3) {
1664 case 0:
1665 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1666 break;
1667 case 1:
1668 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1669 break;
1670 case 2:
1671 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1672 break;
1673 case 3:
1674 return 1;
1675 }
1676 gen_op_iwmmxt_movq_wRn_M0(wrd);
1677 gen_op_iwmmxt_set_mup();
1678 gen_op_iwmmxt_set_cup();
1679 break;
1680 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1681 wrd = (insn >> 12) & 0xf;
1682 rd0 = (insn >> 16) & 0xf;
1683 rd1 = (insn >> 0) & 0xf;
1684 gen_op_iwmmxt_movq_M0_wRn(rd0);
1685 switch ((insn >> 22) & 3) {
1686 case 0:
1687 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1688 break;
1689 case 1:
1690 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1691 break;
1692 case 2:
1693 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1694 break;
1695 case 3:
1696 return 1;
1697 }
1698 gen_op_iwmmxt_movq_wRn_M0(wrd);
1699 gen_op_iwmmxt_set_mup();
1700 gen_op_iwmmxt_set_cup();
1701 break;
1702 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1703 wrd = (insn >> 12) & 0xf;
1704 rd0 = (insn >> 16) & 0xf;
1705 rd1 = (insn >> 0) & 0xf;
1706 gen_op_iwmmxt_movq_M0_wRn(rd0);
1707 if (insn & (1 << 22))
1708 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1709 else
1710 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1711 if (!(insn & (1 << 20)))
1712 gen_op_iwmmxt_addl_M0_wRn(wrd);
1713 gen_op_iwmmxt_movq_wRn_M0(wrd);
1714 gen_op_iwmmxt_set_mup();
1715 break;
1716 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1717 wrd = (insn >> 12) & 0xf;
1718 rd0 = (insn >> 16) & 0xf;
1719 rd1 = (insn >> 0) & 0xf;
1720 gen_op_iwmmxt_movq_M0_wRn(rd0);
e677137d
PB
1721 if (insn & (1 << 21)) {
1722 if (insn & (1 << 20))
1723 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1724 else
1725 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1726 } else {
1727 if (insn & (1 << 20))
1728 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1729 else
1730 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1731 }
18c9b560
AZ
1732 gen_op_iwmmxt_movq_wRn_M0(wrd);
1733 gen_op_iwmmxt_set_mup();
1734 break;
1735 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1736 wrd = (insn >> 12) & 0xf;
1737 rd0 = (insn >> 16) & 0xf;
1738 rd1 = (insn >> 0) & 0xf;
1739 gen_op_iwmmxt_movq_M0_wRn(rd0);
1740 if (insn & (1 << 21))
1741 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1742 else
1743 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1744 if (!(insn & (1 << 20))) {
e677137d
PB
1745 iwmmxt_load_reg(cpu_V1, wrd);
1746 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
18c9b560
AZ
1747 }
1748 gen_op_iwmmxt_movq_wRn_M0(wrd);
1749 gen_op_iwmmxt_set_mup();
1750 break;
1751 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1752 wrd = (insn >> 12) & 0xf;
1753 rd0 = (insn >> 16) & 0xf;
1754 rd1 = (insn >> 0) & 0xf;
1755 gen_op_iwmmxt_movq_M0_wRn(rd0);
1756 switch ((insn >> 22) & 3) {
1757 case 0:
1758 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1759 break;
1760 case 1:
1761 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1762 break;
1763 case 2:
1764 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1765 break;
1766 case 3:
1767 return 1;
1768 }
1769 gen_op_iwmmxt_movq_wRn_M0(wrd);
1770 gen_op_iwmmxt_set_mup();
1771 gen_op_iwmmxt_set_cup();
1772 break;
1773 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1774 wrd = (insn >> 12) & 0xf;
1775 rd0 = (insn >> 16) & 0xf;
1776 rd1 = (insn >> 0) & 0xf;
1777 gen_op_iwmmxt_movq_M0_wRn(rd0);
e677137d
PB
1778 if (insn & (1 << 22)) {
1779 if (insn & (1 << 20))
1780 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1781 else
1782 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1783 } else {
1784 if (insn & (1 << 20))
1785 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1786 else
1787 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1788 }
18c9b560
AZ
1789 gen_op_iwmmxt_movq_wRn_M0(wrd);
1790 gen_op_iwmmxt_set_mup();
1791 gen_op_iwmmxt_set_cup();
1792 break;
1793 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1794 wrd = (insn >> 12) & 0xf;
1795 rd0 = (insn >> 16) & 0xf;
1796 rd1 = (insn >> 0) & 0xf;
1797 gen_op_iwmmxt_movq_M0_wRn(rd0);
1798 gen_op_iwmmxt_movl_T0_wCx(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1799 gen_op_movl_T1_im(7);
1800 gen_op_andl_T0_T1();
1801 gen_op_iwmmxt_align_M0_T0_wRn(rd1);
1802 gen_op_iwmmxt_movq_wRn_M0(wrd);
1803 gen_op_iwmmxt_set_mup();
1804 break;
1805 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1806 rd = (insn >> 12) & 0xf;
1807 wrd = (insn >> 16) & 0xf;
1808 gen_movl_T0_reg(s, rd);
1809 gen_op_iwmmxt_movq_M0_wRn(wrd);
1810 switch ((insn >> 6) & 3) {
1811 case 0:
1812 gen_op_movl_T1_im(0xff);
1813 gen_op_iwmmxt_insr_M0_T0_T1((insn & 7) << 3);
1814 break;
1815 case 1:
1816 gen_op_movl_T1_im(0xffff);
1817 gen_op_iwmmxt_insr_M0_T0_T1((insn & 3) << 4);
1818 break;
1819 case 2:
1820 gen_op_movl_T1_im(0xffffffff);
1821 gen_op_iwmmxt_insr_M0_T0_T1((insn & 1) << 5);
1822 break;
1823 case 3:
1824 return 1;
1825 }
1826 gen_op_iwmmxt_movq_wRn_M0(wrd);
1827 gen_op_iwmmxt_set_mup();
1828 break;
1829 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1830 rd = (insn >> 12) & 0xf;
1831 wrd = (insn >> 16) & 0xf;
1832 if (rd == 15)
1833 return 1;
1834 gen_op_iwmmxt_movq_M0_wRn(wrd);
1835 switch ((insn >> 22) & 3) {
1836 case 0:
1837 if (insn & 8)
1838 gen_op_iwmmxt_extrsb_T0_M0((insn & 7) << 3);
1839 else {
e677137d 1840 gen_op_iwmmxt_extru_T0_M0((insn & 7) << 3, 0xff);
18c9b560
AZ
1841 }
1842 break;
1843 case 1:
1844 if (insn & 8)
1845 gen_op_iwmmxt_extrsw_T0_M0((insn & 3) << 4);
1846 else {
e677137d 1847 gen_op_iwmmxt_extru_T0_M0((insn & 3) << 4, 0xffff);
18c9b560
AZ
1848 }
1849 break;
1850 case 2:
e677137d 1851 gen_op_iwmmxt_extru_T0_M0((insn & 1) << 5, ~0u);
18c9b560
AZ
1852 break;
1853 case 3:
1854 return 1;
1855 }
b26eefb6 1856 gen_movl_reg_T0(s, rd);
18c9b560
AZ
1857 break;
1858 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1859 if ((insn & 0x000ff008) != 0x0003f000)
1860 return 1;
1861 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1862 switch ((insn >> 22) & 3) {
1863 case 0:
1864 gen_op_shrl_T1_im(((insn & 7) << 2) + 0);
1865 break;
1866 case 1:
1867 gen_op_shrl_T1_im(((insn & 3) << 3) + 4);
1868 break;
1869 case 2:
1870 gen_op_shrl_T1_im(((insn & 1) << 4) + 12);
1871 break;
1872 case 3:
1873 return 1;
1874 }
1875 gen_op_shll_T1_im(28);
d9ba4830 1876 gen_set_nzcv(cpu_T[1]);
18c9b560
AZ
1877 break;
1878 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1879 rd = (insn >> 12) & 0xf;
1880 wrd = (insn >> 16) & 0xf;
1881 gen_movl_T0_reg(s, rd);
1882 switch ((insn >> 6) & 3) {
1883 case 0:
e677137d 1884 gen_helper_iwmmxt_bcstb(cpu_M0, cpu_T[0]);
18c9b560
AZ
1885 break;
1886 case 1:
e677137d 1887 gen_helper_iwmmxt_bcstw(cpu_M0, cpu_T[0]);
18c9b560
AZ
1888 break;
1889 case 2:
e677137d 1890 gen_helper_iwmmxt_bcstl(cpu_M0, cpu_T[0]);
18c9b560
AZ
1891 break;
1892 case 3:
1893 return 1;
1894 }
1895 gen_op_iwmmxt_movq_wRn_M0(wrd);
1896 gen_op_iwmmxt_set_mup();
1897 break;
1898 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1899 if ((insn & 0x000ff00f) != 0x0003f000)
1900 return 1;
1901 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1902 switch ((insn >> 22) & 3) {
1903 case 0:
1904 for (i = 0; i < 7; i ++) {
1905 gen_op_shll_T1_im(4);
1906 gen_op_andl_T0_T1();
1907 }
1908 break;
1909 case 1:
1910 for (i = 0; i < 3; i ++) {
1911 gen_op_shll_T1_im(8);
1912 gen_op_andl_T0_T1();
1913 }
1914 break;
1915 case 2:
1916 gen_op_shll_T1_im(16);
1917 gen_op_andl_T0_T1();
1918 break;
1919 case 3:
1920 return 1;
1921 }
d9ba4830 1922 gen_set_nzcv(cpu_T[0]);
18c9b560
AZ
1923 break;
1924 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1925 wrd = (insn >> 12) & 0xf;
1926 rd0 = (insn >> 16) & 0xf;
1927 gen_op_iwmmxt_movq_M0_wRn(rd0);
1928 switch ((insn >> 22) & 3) {
1929 case 0:
e677137d 1930 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
18c9b560
AZ
1931 break;
1932 case 1:
e677137d 1933 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
18c9b560
AZ
1934 break;
1935 case 2:
e677137d 1936 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
18c9b560
AZ
1937 break;
1938 case 3:
1939 return 1;
1940 }
1941 gen_op_iwmmxt_movq_wRn_M0(wrd);
1942 gen_op_iwmmxt_set_mup();
1943 break;
1944 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1945 if ((insn & 0x000ff00f) != 0x0003f000)
1946 return 1;
1947 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1948 switch ((insn >> 22) & 3) {
1949 case 0:
1950 for (i = 0; i < 7; i ++) {
1951 gen_op_shll_T1_im(4);
1952 gen_op_orl_T0_T1();
1953 }
1954 break;
1955 case 1:
1956 for (i = 0; i < 3; i ++) {
1957 gen_op_shll_T1_im(8);
1958 gen_op_orl_T0_T1();
1959 }
1960 break;
1961 case 2:
1962 gen_op_shll_T1_im(16);
1963 gen_op_orl_T0_T1();
1964 break;
1965 case 3:
1966 return 1;
1967 }
d9ba4830 1968 gen_set_nzcv(cpu_T[0]);
18c9b560
AZ
1969 break;
1970 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1971 rd = (insn >> 12) & 0xf;
1972 rd0 = (insn >> 16) & 0xf;
1973 if ((insn & 0xf) != 0)
1974 return 1;
1975 gen_op_iwmmxt_movq_M0_wRn(rd0);
1976 switch ((insn >> 22) & 3) {
1977 case 0:
e677137d 1978 gen_helper_iwmmxt_msbb(cpu_T[0], cpu_M0);
18c9b560
AZ
1979 break;
1980 case 1:
e677137d 1981 gen_helper_iwmmxt_msbw(cpu_T[0], cpu_M0);
18c9b560
AZ
1982 break;
1983 case 2:
e677137d 1984 gen_helper_iwmmxt_msbl(cpu_T[0], cpu_M0);
18c9b560
AZ
1985 break;
1986 case 3:
1987 return 1;
1988 }
1989 gen_movl_reg_T0(s, rd);
1990 break;
1991 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1992 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1993 wrd = (insn >> 12) & 0xf;
1994 rd0 = (insn >> 16) & 0xf;
1995 rd1 = (insn >> 0) & 0xf;
1996 gen_op_iwmmxt_movq_M0_wRn(rd0);
1997 switch ((insn >> 22) & 3) {
1998 case 0:
1999 if (insn & (1 << 21))
2000 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
2001 else
2002 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
2003 break;
2004 case 1:
2005 if (insn & (1 << 21))
2006 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
2007 else
2008 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2009 break;
2010 case 2:
2011 if (insn & (1 << 21))
2012 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2013 else
2014 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2015 break;
2016 case 3:
2017 return 1;
2018 }
2019 gen_op_iwmmxt_movq_wRn_M0(wrd);
2020 gen_op_iwmmxt_set_mup();
2021 gen_op_iwmmxt_set_cup();
2022 break;
2023 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2024 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2025 wrd = (insn >> 12) & 0xf;
2026 rd0 = (insn >> 16) & 0xf;
2027 gen_op_iwmmxt_movq_M0_wRn(rd0);
2028 switch ((insn >> 22) & 3) {
2029 case 0:
2030 if (insn & (1 << 21))
2031 gen_op_iwmmxt_unpacklsb_M0();
2032 else
2033 gen_op_iwmmxt_unpacklub_M0();
2034 break;
2035 case 1:
2036 if (insn & (1 << 21))
2037 gen_op_iwmmxt_unpacklsw_M0();
2038 else
2039 gen_op_iwmmxt_unpackluw_M0();
2040 break;
2041 case 2:
2042 if (insn & (1 << 21))
2043 gen_op_iwmmxt_unpacklsl_M0();
2044 else
2045 gen_op_iwmmxt_unpacklul_M0();
2046 break;
2047 case 3:
2048 return 1;
2049 }
2050 gen_op_iwmmxt_movq_wRn_M0(wrd);
2051 gen_op_iwmmxt_set_mup();
2052 gen_op_iwmmxt_set_cup();
2053 break;
2054 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2055 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2056 wrd = (insn >> 12) & 0xf;
2057 rd0 = (insn >> 16) & 0xf;
2058 gen_op_iwmmxt_movq_M0_wRn(rd0);
2059 switch ((insn >> 22) & 3) {
2060 case 0:
2061 if (insn & (1 << 21))
2062 gen_op_iwmmxt_unpackhsb_M0();
2063 else
2064 gen_op_iwmmxt_unpackhub_M0();
2065 break;
2066 case 1:
2067 if (insn & (1 << 21))
2068 gen_op_iwmmxt_unpackhsw_M0();
2069 else
2070 gen_op_iwmmxt_unpackhuw_M0();
2071 break;
2072 case 2:
2073 if (insn & (1 << 21))
2074 gen_op_iwmmxt_unpackhsl_M0();
2075 else
2076 gen_op_iwmmxt_unpackhul_M0();
2077 break;
2078 case 3:
2079 return 1;
2080 }
2081 gen_op_iwmmxt_movq_wRn_M0(wrd);
2082 gen_op_iwmmxt_set_mup();
2083 gen_op_iwmmxt_set_cup();
2084 break;
2085 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2086 case 0x214: case 0x614: case 0xa14: case 0xe14:
2087 wrd = (insn >> 12) & 0xf;
2088 rd0 = (insn >> 16) & 0xf;
2089 gen_op_iwmmxt_movq_M0_wRn(rd0);
2090 if (gen_iwmmxt_shift(insn, 0xff))
2091 return 1;
2092 switch ((insn >> 22) & 3) {
2093 case 0:
2094 return 1;
2095 case 1:
e677137d 2096 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
18c9b560
AZ
2097 break;
2098 case 2:
e677137d 2099 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
18c9b560
AZ
2100 break;
2101 case 3:
e677137d 2102 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
18c9b560
AZ
2103 break;
2104 }
2105 gen_op_iwmmxt_movq_wRn_M0(wrd);
2106 gen_op_iwmmxt_set_mup();
2107 gen_op_iwmmxt_set_cup();
2108 break;
2109 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2110 case 0x014: case 0x414: case 0x814: case 0xc14:
2111 wrd = (insn >> 12) & 0xf;
2112 rd0 = (insn >> 16) & 0xf;
2113 gen_op_iwmmxt_movq_M0_wRn(rd0);
2114 if (gen_iwmmxt_shift(insn, 0xff))
2115 return 1;
2116 switch ((insn >> 22) & 3) {
2117 case 0:
2118 return 1;
2119 case 1:
e677137d 2120 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
18c9b560
AZ
2121 break;
2122 case 2:
e677137d 2123 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
18c9b560
AZ
2124 break;
2125 case 3:
e677137d 2126 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
18c9b560
AZ
2127 break;
2128 }
2129 gen_op_iwmmxt_movq_wRn_M0(wrd);
2130 gen_op_iwmmxt_set_mup();
2131 gen_op_iwmmxt_set_cup();
2132 break;
2133 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2134 case 0x114: case 0x514: case 0x914: case 0xd14:
2135 wrd = (insn >> 12) & 0xf;
2136 rd0 = (insn >> 16) & 0xf;
2137 gen_op_iwmmxt_movq_M0_wRn(rd0);
2138 if (gen_iwmmxt_shift(insn, 0xff))
2139 return 1;
2140 switch ((insn >> 22) & 3) {
2141 case 0:
2142 return 1;
2143 case 1:
e677137d 2144 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
18c9b560
AZ
2145 break;
2146 case 2:
e677137d 2147 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
18c9b560
AZ
2148 break;
2149 case 3:
e677137d 2150 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
18c9b560
AZ
2151 break;
2152 }
2153 gen_op_iwmmxt_movq_wRn_M0(wrd);
2154 gen_op_iwmmxt_set_mup();
2155 gen_op_iwmmxt_set_cup();
2156 break;
2157 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2158 case 0x314: case 0x714: case 0xb14: case 0xf14:
2159 wrd = (insn >> 12) & 0xf;
2160 rd0 = (insn >> 16) & 0xf;
2161 gen_op_iwmmxt_movq_M0_wRn(rd0);
2162 switch ((insn >> 22) & 3) {
2163 case 0:
2164 return 1;
2165 case 1:
2166 if (gen_iwmmxt_shift(insn, 0xf))
2167 return 1;
e677137d 2168 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
18c9b560
AZ
2169 break;
2170 case 2:
2171 if (gen_iwmmxt_shift(insn, 0x1f))
2172 return 1;
e677137d 2173 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
18c9b560
AZ
2174 break;
2175 case 3:
2176 if (gen_iwmmxt_shift(insn, 0x3f))
2177 return 1;
e677137d 2178 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
18c9b560
AZ
2179 break;
2180 }
2181 gen_op_iwmmxt_movq_wRn_M0(wrd);
2182 gen_op_iwmmxt_set_mup();
2183 gen_op_iwmmxt_set_cup();
2184 break;
2185 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2186 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2187 wrd = (insn >> 12) & 0xf;
2188 rd0 = (insn >> 16) & 0xf;
2189 rd1 = (insn >> 0) & 0xf;
2190 gen_op_iwmmxt_movq_M0_wRn(rd0);
2191 switch ((insn >> 22) & 3) {
2192 case 0:
2193 if (insn & (1 << 21))
2194 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2195 else
2196 gen_op_iwmmxt_minub_M0_wRn(rd1);
2197 break;
2198 case 1:
2199 if (insn & (1 << 21))
2200 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2201 else
2202 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2203 break;
2204 case 2:
2205 if (insn & (1 << 21))
2206 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2207 else
2208 gen_op_iwmmxt_minul_M0_wRn(rd1);
2209 break;
2210 case 3:
2211 return 1;
2212 }
2213 gen_op_iwmmxt_movq_wRn_M0(wrd);
2214 gen_op_iwmmxt_set_mup();
2215 break;
2216 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2217 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2218 wrd = (insn >> 12) & 0xf;
2219 rd0 = (insn >> 16) & 0xf;
2220 rd1 = (insn >> 0) & 0xf;
2221 gen_op_iwmmxt_movq_M0_wRn(rd0);
2222 switch ((insn >> 22) & 3) {
2223 case 0:
2224 if (insn & (1 << 21))
2225 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2226 else
2227 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2228 break;
2229 case 1:
2230 if (insn & (1 << 21))
2231 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2232 else
2233 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2234 break;
2235 case 2:
2236 if (insn & (1 << 21))
2237 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2238 else
2239 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2240 break;
2241 case 3:
2242 return 1;
2243 }
2244 gen_op_iwmmxt_movq_wRn_M0(wrd);
2245 gen_op_iwmmxt_set_mup();
2246 break;
2247 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2248 case 0x402: case 0x502: case 0x602: case 0x702:
2249 wrd = (insn >> 12) & 0xf;
2250 rd0 = (insn >> 16) & 0xf;
2251 rd1 = (insn >> 0) & 0xf;
2252 gen_op_iwmmxt_movq_M0_wRn(rd0);
2253 gen_op_movl_T0_im((insn >> 20) & 3);
2254 gen_op_iwmmxt_align_M0_T0_wRn(rd1);
2255 gen_op_iwmmxt_movq_wRn_M0(wrd);
2256 gen_op_iwmmxt_set_mup();
2257 break;
2258 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2259 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2260 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2261 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2262 wrd = (insn >> 12) & 0xf;
2263 rd0 = (insn >> 16) & 0xf;
2264 rd1 = (insn >> 0) & 0xf;
2265 gen_op_iwmmxt_movq_M0_wRn(rd0);
2266 switch ((insn >> 20) & 0xf) {
2267 case 0x0:
2268 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2269 break;
2270 case 0x1:
2271 gen_op_iwmmxt_subub_M0_wRn(rd1);
2272 break;
2273 case 0x3:
2274 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2275 break;
2276 case 0x4:
2277 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2278 break;
2279 case 0x5:
2280 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2281 break;
2282 case 0x7:
2283 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2284 break;
2285 case 0x8:
2286 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2287 break;
2288 case 0x9:
2289 gen_op_iwmmxt_subul_M0_wRn(rd1);
2290 break;
2291 case 0xb:
2292 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2293 break;
2294 default:
2295 return 1;
2296 }
2297 gen_op_iwmmxt_movq_wRn_M0(wrd);
2298 gen_op_iwmmxt_set_mup();
2299 gen_op_iwmmxt_set_cup();
2300 break;
2301 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2302 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2303 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2304 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2305 wrd = (insn >> 12) & 0xf;
2306 rd0 = (insn >> 16) & 0xf;
2307 gen_op_iwmmxt_movq_M0_wRn(rd0);
2308 gen_op_movl_T0_im(((insn >> 16) & 0xf0) | (insn & 0x0f));
e677137d 2309 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
18c9b560
AZ
2310 gen_op_iwmmxt_movq_wRn_M0(wrd);
2311 gen_op_iwmmxt_set_mup();
2312 gen_op_iwmmxt_set_cup();
2313 break;
2314 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2315 case 0x418: case 0x518: case 0x618: case 0x718:
2316 case 0x818: case 0x918: case 0xa18: case 0xb18:
2317 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2318 wrd = (insn >> 12) & 0xf;
2319 rd0 = (insn >> 16) & 0xf;
2320 rd1 = (insn >> 0) & 0xf;
2321 gen_op_iwmmxt_movq_M0_wRn(rd0);
2322 switch ((insn >> 20) & 0xf) {
2323 case 0x0:
2324 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2325 break;
2326 case 0x1:
2327 gen_op_iwmmxt_addub_M0_wRn(rd1);
2328 break;
2329 case 0x3:
2330 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2331 break;
2332 case 0x4:
2333 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2334 break;
2335 case 0x5:
2336 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2337 break;
2338 case 0x7:
2339 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2340 break;
2341 case 0x8:
2342 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2343 break;
2344 case 0x9:
2345 gen_op_iwmmxt_addul_M0_wRn(rd1);
2346 break;
2347 case 0xb:
2348 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2349 break;
2350 default:
2351 return 1;
2352 }
2353 gen_op_iwmmxt_movq_wRn_M0(wrd);
2354 gen_op_iwmmxt_set_mup();
2355 gen_op_iwmmxt_set_cup();
2356 break;
2357 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2358 case 0x408: case 0x508: case 0x608: case 0x708:
2359 case 0x808: case 0x908: case 0xa08: case 0xb08:
2360 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2361 wrd = (insn >> 12) & 0xf;
2362 rd0 = (insn >> 16) & 0xf;
2363 rd1 = (insn >> 0) & 0xf;
2364 gen_op_iwmmxt_movq_M0_wRn(rd0);
2365 if (!(insn & (1 << 20)))
2366 return 1;
2367 switch ((insn >> 22) & 3) {
2368 case 0:
2369 return 1;
2370 case 1:
2371 if (insn & (1 << 21))
2372 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2373 else
2374 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2375 break;
2376 case 2:
2377 if (insn & (1 << 21))
2378 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2379 else
2380 gen_op_iwmmxt_packul_M0_wRn(rd1);
2381 break;
2382 case 3:
2383 if (insn & (1 << 21))
2384 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2385 else
2386 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2387 break;
2388 }
2389 gen_op_iwmmxt_movq_wRn_M0(wrd);
2390 gen_op_iwmmxt_set_mup();
2391 gen_op_iwmmxt_set_cup();
2392 break;
2393 case 0x201: case 0x203: case 0x205: case 0x207:
2394 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2395 case 0x211: case 0x213: case 0x215: case 0x217:
2396 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2397 wrd = (insn >> 5) & 0xf;
2398 rd0 = (insn >> 12) & 0xf;
2399 rd1 = (insn >> 0) & 0xf;
2400 if (rd0 == 0xf || rd1 == 0xf)
2401 return 1;
2402 gen_op_iwmmxt_movq_M0_wRn(wrd);
2403 switch ((insn >> 16) & 0xf) {
2404 case 0x0: /* TMIA */
b26eefb6
PB
2405 gen_movl_T0_reg(s, rd0);
2406 gen_movl_T1_reg(s, rd1);
18c9b560
AZ
2407 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2408 break;
2409 case 0x8: /* TMIAPH */
b26eefb6
PB
2410 gen_movl_T0_reg(s, rd0);
2411 gen_movl_T1_reg(s, rd1);
18c9b560
AZ
2412 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2413 break;
2414 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
b26eefb6 2415 gen_movl_T1_reg(s, rd0);
18c9b560
AZ
2416 if (insn & (1 << 16))
2417 gen_op_shrl_T1_im(16);
2418 gen_op_movl_T0_T1();
b26eefb6 2419 gen_movl_T1_reg(s, rd1);
18c9b560
AZ
2420 if (insn & (1 << 17))
2421 gen_op_shrl_T1_im(16);
2422 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2423 break;
2424 default:
2425 return 1;
2426 }
2427 gen_op_iwmmxt_movq_wRn_M0(wrd);
2428 gen_op_iwmmxt_set_mup();
2429 break;
2430 default:
2431 return 1;
2432 }
2433
2434 return 0;
2435}
2436
2437/* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2438 (ie. an undefined instruction). */
2439static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2440{
2441 int acc, rd0, rd1, rdhi, rdlo;
2442
2443 if ((insn & 0x0ff00f10) == 0x0e200010) {
2444 /* Multiply with Internal Accumulate Format */
2445 rd0 = (insn >> 12) & 0xf;
2446 rd1 = insn & 0xf;
2447 acc = (insn >> 5) & 7;
2448
2449 if (acc != 0)
2450 return 1;
2451
2452 switch ((insn >> 16) & 0xf) {
2453 case 0x0: /* MIA */
b26eefb6
PB
2454 gen_movl_T0_reg(s, rd0);
2455 gen_movl_T1_reg(s, rd1);
18c9b560
AZ
2456 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2457 break;
2458 case 0x8: /* MIAPH */
b26eefb6
PB
2459 gen_movl_T0_reg(s, rd0);
2460 gen_movl_T1_reg(s, rd1);
18c9b560
AZ
2461 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2462 break;
2463 case 0xc: /* MIABB */
2464 case 0xd: /* MIABT */
2465 case 0xe: /* MIATB */
2466 case 0xf: /* MIATT */
b26eefb6 2467 gen_movl_T1_reg(s, rd0);
18c9b560
AZ
2468 if (insn & (1 << 16))
2469 gen_op_shrl_T1_im(16);
2470 gen_op_movl_T0_T1();
b26eefb6 2471 gen_movl_T1_reg(s, rd1);
18c9b560
AZ
2472 if (insn & (1 << 17))
2473 gen_op_shrl_T1_im(16);
2474 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2475 break;
2476 default:
2477 return 1;
2478 }
2479
2480 gen_op_iwmmxt_movq_wRn_M0(acc);
2481 return 0;
2482 }
2483
2484 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2485 /* Internal Accumulator Access Format */
2486 rdhi = (insn >> 16) & 0xf;
2487 rdlo = (insn >> 12) & 0xf;
2488 acc = insn & 7;
2489
2490 if (acc != 0)
2491 return 1;
2492
2493 if (insn & ARM_CP_RW_BIT) { /* MRA */
e677137d 2494 gen_iwmmxt_movl_T0_T1_wRn(acc);
b26eefb6 2495 gen_movl_reg_T0(s, rdlo);
18c9b560
AZ
2496 gen_op_movl_T0_im((1 << (40 - 32)) - 1);
2497 gen_op_andl_T0_T1();
b26eefb6 2498 gen_movl_reg_T0(s, rdhi);
18c9b560 2499 } else { /* MAR */
b26eefb6
PB
2500 gen_movl_T0_reg(s, rdlo);
2501 gen_movl_T1_reg(s, rdhi);
e677137d 2502 gen_iwmmxt_movl_wRn_T0_T1(acc);
18c9b560
AZ
2503 }
2504 return 0;
2505 }
2506
2507 return 1;
2508}
2509
c1713132
AZ
2510/* Disassemble system coprocessor instruction. Return nonzero if
2511 instruction is not defined. */
2512static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2513{
8984bd2e 2514 TCGv tmp;
c1713132
AZ
2515 uint32_t rd = (insn >> 12) & 0xf;
2516 uint32_t cp = (insn >> 8) & 0xf;
2517 if (IS_USER(s)) {
2518 return 1;
2519 }
2520
18c9b560 2521 if (insn & ARM_CP_RW_BIT) {
c1713132
AZ
2522 if (!env->cp[cp].cp_read)
2523 return 1;
8984bd2e
PB
2524 gen_set_pc_im(s->pc);
2525 tmp = new_tmp();
2526 gen_helper_get_cp(tmp, cpu_env, tcg_const_i32(insn));
2527 store_reg(s, rd, tmp);
c1713132
AZ
2528 } else {
2529 if (!env->cp[cp].cp_write)
2530 return 1;
8984bd2e
PB
2531 gen_set_pc_im(s->pc);
2532 tmp = load_reg(s, rd);
2533 gen_helper_set_cp(cpu_env, tcg_const_i32(insn), tmp);
a60de947 2534 dead_tmp(tmp);
c1713132
AZ
2535 }
2536 return 0;
2537}
2538
9ee6e8bb
PB
2539static int cp15_user_ok(uint32_t insn)
2540{
2541 int cpn = (insn >> 16) & 0xf;
2542 int cpm = insn & 0xf;
2543 int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2544
2545 if (cpn == 13 && cpm == 0) {
2546 /* TLS register. */
2547 if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
2548 return 1;
2549 }
2550 if (cpn == 7) {
2551 /* ISB, DSB, DMB. */
2552 if ((cpm == 5 && op == 4)
2553 || (cpm == 10 && (op == 4 || op == 5)))
2554 return 1;
2555 }
2556 return 0;
2557}
2558
b5ff1b31
FB
2559/* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2560 instruction is not defined. */
a90b7318 2561static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
b5ff1b31
FB
2562{
2563 uint32_t rd;
8984bd2e 2564 TCGv tmp;
b5ff1b31 2565
9ee6e8bb
PB
2566 /* M profile cores use memory mapped registers instead of cp15. */
2567 if (arm_feature(env, ARM_FEATURE_M))
2568 return 1;
2569
2570 if ((insn & (1 << 25)) == 0) {
2571 if (insn & (1 << 20)) {
2572 /* mrrc */
2573 return 1;
2574 }
2575 /* mcrr. Used for block cache operations, so implement as no-op. */
2576 return 0;
2577 }
2578 if ((insn & (1 << 4)) == 0) {
2579 /* cdp */
2580 return 1;
2581 }
2582 if (IS_USER(s) && !cp15_user_ok(insn)) {
b5ff1b31
FB
2583 return 1;
2584 }
9332f9da
FB
2585 if ((insn & 0x0fff0fff) == 0x0e070f90
2586 || (insn & 0x0fff0fff) == 0x0e070f58) {
2587 /* Wait for interrupt. */
8984bd2e 2588 gen_set_pc_im(s->pc);
9ee6e8bb 2589 s->is_jmp = DISAS_WFI;
9332f9da
FB
2590 return 0;
2591 }
b5ff1b31 2592 rd = (insn >> 12) & 0xf;
18c9b560 2593 if (insn & ARM_CP_RW_BIT) {
8984bd2e
PB
2594 tmp = new_tmp();
2595 gen_helper_get_cp15(tmp, cpu_env, tcg_const_i32(insn));
b5ff1b31
FB
2596 /* If the destination register is r15 then sets condition codes. */
2597 if (rd != 15)
8984bd2e
PB
2598 store_reg(s, rd, tmp);
2599 else
2600 dead_tmp(tmp);
b5ff1b31 2601 } else {
8984bd2e
PB
2602 tmp = load_reg(s, rd);
2603 gen_helper_set_cp15(cpu_env, tcg_const_i32(insn), tmp);
2604 dead_tmp(tmp);
a90b7318
AZ
2605 /* Normally we would always end the TB here, but Linux
2606 * arch/arm/mach-pxa/sleep.S expects two instructions following
2607 * an MMU enable to execute from cache. Imitate this behaviour. */
2608 if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
2609 (insn & 0x0fff0fff) != 0x0e010f10)
2610 gen_lookup_tb(s);
b5ff1b31 2611 }
b5ff1b31
FB
2612 return 0;
2613}
2614
9ee6e8bb
PB
2615#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2616#define VFP_SREG(insn, bigbit, smallbit) \
2617 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2618#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2619 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2620 reg = (((insn) >> (bigbit)) & 0x0f) \
2621 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2622 } else { \
2623 if (insn & (1 << (smallbit))) \
2624 return 1; \
2625 reg = ((insn) >> (bigbit)) & 0x0f; \
2626 }} while (0)
2627
2628#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2629#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2630#define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2631#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2632#define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2633#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2634
4373f3ce
PB
2635/* Move between integer and VFP cores. */
2636static TCGv gen_vfp_mrs(void)
2637{
2638 TCGv tmp = new_tmp();
2639 tcg_gen_mov_i32(tmp, cpu_F0s);
2640 return tmp;
2641}
2642
2643static void gen_vfp_msr(TCGv tmp)
2644{
2645 tcg_gen_mov_i32(cpu_F0s, tmp);
2646 dead_tmp(tmp);
2647}
2648
9ee6e8bb
PB
2649static inline int
2650vfp_enabled(CPUState * env)
2651{
2652 return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
2653}
2654
ad69471c
PB
2655static void gen_neon_dup_u8(TCGv var, int shift)
2656{
2657 TCGv tmp = new_tmp();
2658 if (shift)
2659 tcg_gen_shri_i32(var, var, shift);
86831435 2660 tcg_gen_ext8u_i32(var, var);
ad69471c
PB
2661 tcg_gen_shli_i32(tmp, var, 8);
2662 tcg_gen_or_i32(var, var, tmp);
2663 tcg_gen_shli_i32(tmp, var, 16);
2664 tcg_gen_or_i32(var, var, tmp);
2665 dead_tmp(tmp);
2666}
2667
2668static void gen_neon_dup_low16(TCGv var)
2669{
2670 TCGv tmp = new_tmp();
86831435 2671 tcg_gen_ext16u_i32(var, var);
ad69471c
PB
2672 tcg_gen_shli_i32(tmp, var, 16);
2673 tcg_gen_or_i32(var, var, tmp);
2674 dead_tmp(tmp);
2675}
2676
2677static void gen_neon_dup_high16(TCGv var)
2678{
2679 TCGv tmp = new_tmp();
2680 tcg_gen_andi_i32(var, var, 0xffff0000);
2681 tcg_gen_shri_i32(tmp, var, 16);
2682 tcg_gen_or_i32(var, var, tmp);
2683 dead_tmp(tmp);
2684}
2685
b7bcbe95
FB
2686/* Disassemble a VFP instruction. Returns nonzero if an error occured
2687 (ie. an undefined instruction). */
2688static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2689{
2690 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2691 int dp, veclen;
4373f3ce 2692 TCGv tmp;
ad69471c 2693 TCGv tmp2;
b7bcbe95 2694
40f137e1
PB
2695 if (!arm_feature(env, ARM_FEATURE_VFP))
2696 return 1;
2697
9ee6e8bb
PB
2698 if (!vfp_enabled(env)) {
2699 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
40f137e1
PB
2700 if ((insn & 0x0fe00fff) != 0x0ee00a10)
2701 return 1;
2702 rn = (insn >> 16) & 0xf;
9ee6e8bb
PB
2703 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2704 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
40f137e1
PB
2705 return 1;
2706 }
b7bcbe95
FB
2707 dp = ((insn & 0xf00) == 0xb00);
2708 switch ((insn >> 24) & 0xf) {
2709 case 0xe:
2710 if (insn & (1 << 4)) {
2711 /* single register transfer */
b7bcbe95
FB
2712 rd = (insn >> 12) & 0xf;
2713 if (dp) {
9ee6e8bb
PB
2714 int size;
2715 int pass;
2716
2717 VFP_DREG_N(rn, insn);
2718 if (insn & 0xf)
b7bcbe95 2719 return 1;
9ee6e8bb
PB
2720 if (insn & 0x00c00060
2721 && !arm_feature(env, ARM_FEATURE_NEON))
2722 return 1;
2723
2724 pass = (insn >> 21) & 1;
2725 if (insn & (1 << 22)) {
2726 size = 0;
2727 offset = ((insn >> 5) & 3) * 8;
2728 } else if (insn & (1 << 5)) {
2729 size = 1;
2730 offset = (insn & (1 << 6)) ? 16 : 0;
2731 } else {
2732 size = 2;
2733 offset = 0;
2734 }
18c9b560 2735 if (insn & ARM_CP_RW_BIT) {
b7bcbe95 2736 /* vfp->arm */
ad69471c 2737 tmp = neon_load_reg(rn, pass);
9ee6e8bb
PB
2738 switch (size) {
2739 case 0:
9ee6e8bb 2740 if (offset)
ad69471c 2741 tcg_gen_shri_i32(tmp, tmp, offset);
9ee6e8bb 2742 if (insn & (1 << 23))
ad69471c 2743 gen_uxtb(tmp);
9ee6e8bb 2744 else
ad69471c 2745 gen_sxtb(tmp);
9ee6e8bb
PB
2746 break;
2747 case 1:
9ee6e8bb
PB
2748 if (insn & (1 << 23)) {
2749 if (offset) {
ad69471c 2750 tcg_gen_shri_i32(tmp, tmp, 16);
9ee6e8bb 2751 } else {
ad69471c 2752 gen_uxth(tmp);
9ee6e8bb
PB
2753 }
2754 } else {
2755 if (offset) {
ad69471c 2756 tcg_gen_sari_i32(tmp, tmp, 16);
9ee6e8bb 2757 } else {
ad69471c 2758 gen_sxth(tmp);
9ee6e8bb
PB
2759 }
2760 }
2761 break;
2762 case 2:
9ee6e8bb
PB
2763 break;
2764 }
ad69471c 2765 store_reg(s, rd, tmp);
b7bcbe95
FB
2766 } else {
2767 /* arm->vfp */
ad69471c 2768 tmp = load_reg(s, rd);
9ee6e8bb
PB
2769 if (insn & (1 << 23)) {
2770 /* VDUP */
2771 if (size == 0) {
ad69471c 2772 gen_neon_dup_u8(tmp, 0);
9ee6e8bb 2773 } else if (size == 1) {
ad69471c 2774 gen_neon_dup_low16(tmp);
9ee6e8bb 2775 }
cbbccffc
PB
2776 for (n = 0; n <= pass * 2; n++) {
2777 tmp2 = new_tmp();
2778 tcg_gen_mov_i32(tmp2, tmp);
2779 neon_store_reg(rn, n, tmp2);
2780 }
2781 neon_store_reg(rn, n, tmp);
9ee6e8bb
PB
2782 } else {
2783 /* VMOV */
2784 switch (size) {
2785 case 0:
ad69471c
PB
2786 tmp2 = neon_load_reg(rn, pass);
2787 gen_bfi(tmp, tmp2, tmp, offset, 0xff);
2788 dead_tmp(tmp2);
9ee6e8bb
PB
2789 break;
2790 case 1:
ad69471c
PB
2791 tmp2 = neon_load_reg(rn, pass);
2792 gen_bfi(tmp, tmp2, tmp, offset, 0xffff);
2793 dead_tmp(tmp2);
9ee6e8bb
PB
2794 break;
2795 case 2:
9ee6e8bb
PB
2796 break;
2797 }
ad69471c 2798 neon_store_reg(rn, pass, tmp);
9ee6e8bb 2799 }
b7bcbe95 2800 }
9ee6e8bb
PB
2801 } else { /* !dp */
2802 if ((insn & 0x6f) != 0x00)
2803 return 1;
2804 rn = VFP_SREG_N(insn);
18c9b560 2805 if (insn & ARM_CP_RW_BIT) {
b7bcbe95
FB
2806 /* vfp->arm */
2807 if (insn & (1 << 21)) {
2808 /* system register */
40f137e1 2809 rn >>= 1;
9ee6e8bb 2810
b7bcbe95 2811 switch (rn) {
40f137e1 2812 case ARM_VFP_FPSID:
4373f3ce 2813 /* VFP2 allows access to FSID from userspace.
9ee6e8bb
PB
2814 VFP3 restricts all id registers to privileged
2815 accesses. */
2816 if (IS_USER(s)
2817 && arm_feature(env, ARM_FEATURE_VFP3))
2818 return 1;
4373f3ce 2819 tmp = load_cpu_field(vfp.xregs[rn]);
9ee6e8bb 2820 break;
40f137e1 2821 case ARM_VFP_FPEXC:
9ee6e8bb
PB
2822 if (IS_USER(s))
2823 return 1;
4373f3ce 2824 tmp = load_cpu_field(vfp.xregs[rn]);
9ee6e8bb 2825 break;
40f137e1
PB
2826 case ARM_VFP_FPINST:
2827 case ARM_VFP_FPINST2:
9ee6e8bb
PB
2828 /* Not present in VFP3. */
2829 if (IS_USER(s)
2830 || arm_feature(env, ARM_FEATURE_VFP3))
2831 return 1;
4373f3ce 2832 tmp = load_cpu_field(vfp.xregs[rn]);
b7bcbe95 2833 break;
40f137e1 2834 case ARM_VFP_FPSCR:
601d70b9 2835 if (rd == 15) {
4373f3ce
PB
2836 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2837 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2838 } else {
2839 tmp = new_tmp();
2840 gen_helper_vfp_get_fpscr(tmp, cpu_env);
2841 }
b7bcbe95 2842 break;
9ee6e8bb
PB
2843 case ARM_VFP_MVFR0:
2844 case ARM_VFP_MVFR1:
2845 if (IS_USER(s)
2846 || !arm_feature(env, ARM_FEATURE_VFP3))
2847 return 1;
4373f3ce 2848 tmp = load_cpu_field(vfp.xregs[rn]);
9ee6e8bb 2849 break;
b7bcbe95
FB
2850 default:
2851 return 1;
2852 }
2853 } else {
2854 gen_mov_F0_vreg(0, rn);
4373f3ce 2855 tmp = gen_vfp_mrs();
b7bcbe95
FB
2856 }
2857 if (rd == 15) {
b5ff1b31 2858 /* Set the 4 flag bits in the CPSR. */
4373f3ce
PB
2859 gen_set_nzcv(tmp);
2860 dead_tmp(tmp);
2861 } else {
2862 store_reg(s, rd, tmp);
2863 }
b7bcbe95
FB
2864 } else {
2865 /* arm->vfp */
4373f3ce 2866 tmp = load_reg(s, rd);
b7bcbe95 2867 if (insn & (1 << 21)) {
40f137e1 2868 rn >>= 1;
b7bcbe95
FB
2869 /* system register */
2870 switch (rn) {
40f137e1 2871 case ARM_VFP_FPSID:
9ee6e8bb
PB
2872 case ARM_VFP_MVFR0:
2873 case ARM_VFP_MVFR1:
b7bcbe95
FB
2874 /* Writes are ignored. */
2875 break;
40f137e1 2876 case ARM_VFP_FPSCR:
4373f3ce
PB
2877 gen_helper_vfp_set_fpscr(cpu_env, tmp);
2878 dead_tmp(tmp);
b5ff1b31 2879 gen_lookup_tb(s);
b7bcbe95 2880 break;
40f137e1 2881 case ARM_VFP_FPEXC:
9ee6e8bb
PB
2882 if (IS_USER(s))
2883 return 1;
4373f3ce 2884 store_cpu_field(tmp, vfp.xregs[rn]);
40f137e1
PB
2885 gen_lookup_tb(s);
2886 break;
2887 case ARM_VFP_FPINST:
2888 case ARM_VFP_FPINST2:
4373f3ce 2889 store_cpu_field(tmp, vfp.xregs[rn]);
40f137e1 2890 break;
b7bcbe95
FB
2891 default:
2892 return 1;
2893 }
2894 } else {
4373f3ce 2895 gen_vfp_msr(tmp);
b7bcbe95
FB
2896 gen_mov_vreg_F0(0, rn);
2897 }
2898 }
2899 }
2900 } else {
2901 /* data processing */
2902 /* The opcode is in bits 23, 21, 20 and 6. */
2903 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2904 if (dp) {
2905 if (op == 15) {
2906 /* rn is opcode */
2907 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2908 } else {
2909 /* rn is register number */
9ee6e8bb 2910 VFP_DREG_N(rn, insn);
b7bcbe95
FB
2911 }
2912
2913 if (op == 15 && (rn == 15 || rn > 17)) {
2914 /* Integer or single precision destination. */
9ee6e8bb 2915 rd = VFP_SREG_D(insn);
b7bcbe95 2916 } else {
9ee6e8bb 2917 VFP_DREG_D(rd, insn);
b7bcbe95
FB
2918 }
2919
2920 if (op == 15 && (rn == 16 || rn == 17)) {
2921 /* Integer source. */
2922 rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
2923 } else {
9ee6e8bb 2924 VFP_DREG_M(rm, insn);
b7bcbe95
FB
2925 }
2926 } else {
9ee6e8bb 2927 rn = VFP_SREG_N(insn);
b7bcbe95
FB
2928 if (op == 15 && rn == 15) {
2929 /* Double precision destination. */
9ee6e8bb
PB
2930 VFP_DREG_D(rd, insn);
2931 } else {
2932 rd = VFP_SREG_D(insn);
2933 }
2934 rm = VFP_SREG_M(insn);
b7bcbe95
FB
2935 }
2936
2937 veclen = env->vfp.vec_len;
2938 if (op == 15 && rn > 3)
2939 veclen = 0;
2940
2941 /* Shut up compiler warnings. */
2942 delta_m = 0;
2943 delta_d = 0;
2944 bank_mask = 0;
3b46e624 2945
b7bcbe95
FB
2946 if (veclen > 0) {
2947 if (dp)
2948 bank_mask = 0xc;
2949 else
2950 bank_mask = 0x18;
2951
2952 /* Figure out what type of vector operation this is. */
2953 if ((rd & bank_mask) == 0) {
2954 /* scalar */
2955 veclen = 0;
2956 } else {
2957 if (dp)
2958 delta_d = (env->vfp.vec_stride >> 1) + 1;
2959 else
2960 delta_d = env->vfp.vec_stride + 1;
2961
2962 if ((rm & bank_mask) == 0) {
2963 /* mixed scalar/vector */
2964 delta_m = 0;
2965 } else {
2966 /* vector */
2967 delta_m = delta_d;
2968 }
2969 }
2970 }
2971
2972 /* Load the initial operands. */
2973 if (op == 15) {
2974 switch (rn) {
2975 case 16:
2976 case 17:
2977 /* Integer source */
2978 gen_mov_F0_vreg(0, rm);
2979 break;
2980 case 8:
2981 case 9:
2982 /* Compare */
2983 gen_mov_F0_vreg(dp, rd);
2984 gen_mov_F1_vreg(dp, rm);
2985 break;
2986 case 10:
2987 case 11:
2988 /* Compare with zero */
2989 gen_mov_F0_vreg(dp, rd);
2990 gen_vfp_F1_ld0(dp);
2991 break;
9ee6e8bb
PB
2992 case 20:
2993 case 21:
2994 case 22:
2995 case 23:
644ad806
PB
2996 case 28:
2997 case 29:
2998 case 30:
2999 case 31:
9ee6e8bb
PB
3000 /* Source and destination the same. */
3001 gen_mov_F0_vreg(dp, rd);
3002 break;
b7bcbe95
FB
3003 default:
3004 /* One source operand. */
3005 gen_mov_F0_vreg(dp, rm);
9ee6e8bb 3006 break;
b7bcbe95
FB
3007 }
3008 } else {
3009 /* Two source operands. */
3010 gen_mov_F0_vreg(dp, rn);
3011 gen_mov_F1_vreg(dp, rm);
3012 }
3013
3014 for (;;) {
3015 /* Perform the calculation. */
3016 switch (op) {
3017 case 0: /* mac: fd + (fn * fm) */
3018 gen_vfp_mul(dp);
3019 gen_mov_F1_vreg(dp, rd);
3020 gen_vfp_add(dp);
3021 break;
3022 case 1: /* nmac: fd - (fn * fm) */
3023 gen_vfp_mul(dp);
3024 gen_vfp_neg(dp);
3025 gen_mov_F1_vreg(dp, rd);
3026 gen_vfp_add(dp);
3027 break;
3028 case 2: /* msc: -fd + (fn * fm) */
3029 gen_vfp_mul(dp);
3030 gen_mov_F1_vreg(dp, rd);
3031 gen_vfp_sub(dp);
3032 break;
3033 case 3: /* nmsc: -fd - (fn * fm) */
3034 gen_vfp_mul(dp);
b7bcbe95 3035 gen_vfp_neg(dp);
c9fb531a
PB
3036 gen_mov_F1_vreg(dp, rd);
3037 gen_vfp_sub(dp);
b7bcbe95
FB
3038 break;
3039 case 4: /* mul: fn * fm */
3040 gen_vfp_mul(dp);
3041 break;
3042 case 5: /* nmul: -(fn * fm) */
3043 gen_vfp_mul(dp);
3044 gen_vfp_neg(dp);
3045 break;
3046 case 6: /* add: fn + fm */
3047 gen_vfp_add(dp);
3048 break;
3049 case 7: /* sub: fn - fm */
3050 gen_vfp_sub(dp);
3051 break;
3052 case 8: /* div: fn / fm */
3053 gen_vfp_div(dp);
3054 break;
9ee6e8bb
PB
3055 case 14: /* fconst */
3056 if (!arm_feature(env, ARM_FEATURE_VFP3))
3057 return 1;
3058
3059 n = (insn << 12) & 0x80000000;
3060 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3061 if (dp) {
3062 if (i & 0x40)
3063 i |= 0x3f80;
3064 else
3065 i |= 0x4000;
3066 n |= i << 16;
4373f3ce 3067 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
9ee6e8bb
PB
3068 } else {
3069 if (i & 0x40)
3070 i |= 0x780;
3071 else
3072 i |= 0x800;
3073 n |= i << 19;
5b340b51 3074 tcg_gen_movi_i32(cpu_F0s, n);
9ee6e8bb 3075 }
9ee6e8bb 3076 break;
b7bcbe95
FB
3077 case 15: /* extension space */
3078 switch (rn) {
3079 case 0: /* cpy */
3080 /* no-op */
3081 break;
3082 case 1: /* abs */
3083 gen_vfp_abs(dp);
3084 break;
3085 case 2: /* neg */
3086 gen_vfp_neg(dp);
3087 break;
3088 case 3: /* sqrt */
3089 gen_vfp_sqrt(dp);
3090 break;
3091 case 8: /* cmp */
3092 gen_vfp_cmp(dp);
3093 break;
3094 case 9: /* cmpe */
3095 gen_vfp_cmpe(dp);
3096 break;
3097 case 10: /* cmpz */
3098 gen_vfp_cmp(dp);
3099 break;
3100 case 11: /* cmpez */
3101 gen_vfp_F1_ld0(dp);
3102 gen_vfp_cmpe(dp);
3103 break;
3104 case 15: /* single<->double conversion */
3105 if (dp)
4373f3ce 3106 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
b7bcbe95 3107 else
4373f3ce 3108 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
b7bcbe95
FB
3109 break;
3110 case 16: /* fuito */
3111 gen_vfp_uito(dp);
3112 break;
3113 case 17: /* fsito */
3114 gen_vfp_sito(dp);
3115 break;
9ee6e8bb
PB
3116 case 20: /* fshto */
3117 if (!arm_feature(env, ARM_FEATURE_VFP3))
3118 return 1;
644ad806 3119 gen_vfp_shto(dp, 16 - rm);
9ee6e8bb
PB
3120 break;
3121 case 21: /* fslto */
3122 if (!arm_feature(env, ARM_FEATURE_VFP3))
3123 return 1;
644ad806 3124 gen_vfp_slto(dp, 32 - rm);
9ee6e8bb
PB
3125 break;
3126 case 22: /* fuhto */
3127 if (!arm_feature(env, ARM_FEATURE_VFP3))
3128 return 1;
644ad806 3129 gen_vfp_uhto(dp, 16 - rm);
9ee6e8bb
PB
3130 break;
3131 case 23: /* fulto */
3132 if (!arm_feature(env, ARM_FEATURE_VFP3))
3133 return 1;
644ad806 3134 gen_vfp_ulto(dp, 32 - rm);
9ee6e8bb 3135 break;
b7bcbe95
FB
3136 case 24: /* ftoui */
3137 gen_vfp_toui(dp);
3138 break;
3139 case 25: /* ftouiz */
3140 gen_vfp_touiz(dp);
3141 break;
3142 case 26: /* ftosi */
3143 gen_vfp_tosi(dp);
3144 break;
3145 case 27: /* ftosiz */
3146 gen_vfp_tosiz(dp);
3147 break;
9ee6e8bb
PB
3148 case 28: /* ftosh */
3149 if (!arm_feature(env, ARM_FEATURE_VFP3))
3150 return 1;
644ad806 3151 gen_vfp_tosh(dp, 16 - rm);
9ee6e8bb
PB
3152 break;
3153 case 29: /* ftosl */
3154 if (!arm_feature(env, ARM_FEATURE_VFP3))
3155 return 1;
644ad806 3156 gen_vfp_tosl(dp, 32 - rm);
9ee6e8bb
PB
3157 break;
3158 case 30: /* ftouh */
3159 if (!arm_feature(env, ARM_FEATURE_VFP3))
3160 return 1;
644ad806 3161 gen_vfp_touh(dp, 16 - rm);
9ee6e8bb
PB
3162 break;
3163 case 31: /* ftoul */
3164 if (!arm_feature(env, ARM_FEATURE_VFP3))
3165 return 1;
644ad806 3166 gen_vfp_toul(dp, 32 - rm);
9ee6e8bb 3167 break;
b7bcbe95
FB
3168 default: /* undefined */
3169 printf ("rn:%d\n", rn);
3170 return 1;
3171 }
3172 break;
3173 default: /* undefined */
3174 printf ("op:%d\n", op);
3175 return 1;
3176 }
3177
3178 /* Write back the result. */
3179 if (op == 15 && (rn >= 8 && rn <= 11))
3180 ; /* Comparison, do nothing. */
3181 else if (op == 15 && rn > 17)
3182 /* Integer result. */
3183 gen_mov_vreg_F0(0, rd);
3184 else if (op == 15 && rn == 15)
3185 /* conversion */
3186 gen_mov_vreg_F0(!dp, rd);
3187 else
3188 gen_mov_vreg_F0(dp, rd);
3189
3190 /* break out of the loop if we have finished */
3191 if (veclen == 0)
3192 break;
3193
3194 if (op == 15 && delta_m == 0) {
3195 /* single source one-many */
3196 while (veclen--) {
3197 rd = ((rd + delta_d) & (bank_mask - 1))
3198 | (rd & bank_mask);
3199 gen_mov_vreg_F0(dp, rd);
3200 }
3201 break;
3202 }
3203 /* Setup the next operands. */
3204 veclen--;
3205 rd = ((rd + delta_d) & (bank_mask - 1))
3206 | (rd & bank_mask);
3207
3208 if (op == 15) {
3209 /* One source operand. */
3210 rm = ((rm + delta_m) & (bank_mask - 1))
3211 | (rm & bank_mask);
3212 gen_mov_F0_vreg(dp, rm);
3213 } else {
3214 /* Two source operands. */
3215 rn = ((rn + delta_d) & (bank_mask - 1))
3216 | (rn & bank_mask);
3217 gen_mov_F0_vreg(dp, rn);
3218 if (delta_m) {
3219 rm = ((rm + delta_m) & (bank_mask - 1))
3220 | (rm & bank_mask);
3221 gen_mov_F1_vreg(dp, rm);
3222 }
3223 }
3224 }
3225 }
3226 break;
3227 case 0xc:
3228 case 0xd:
9ee6e8bb 3229 if (dp && (insn & 0x03e00000) == 0x00400000) {
b7bcbe95
FB
3230 /* two-register transfer */
3231 rn = (insn >> 16) & 0xf;
3232 rd = (insn >> 12) & 0xf;
3233 if (dp) {
9ee6e8bb
PB
3234 VFP_DREG_M(rm, insn);
3235 } else {
3236 rm = VFP_SREG_M(insn);
3237 }
b7bcbe95 3238
18c9b560 3239 if (insn & ARM_CP_RW_BIT) {
b7bcbe95
FB
3240 /* vfp->arm */
3241 if (dp) {
4373f3ce
PB
3242 gen_mov_F0_vreg(0, rm * 2);
3243 tmp = gen_vfp_mrs();
3244 store_reg(s, rd, tmp);
3245 gen_mov_F0_vreg(0, rm * 2 + 1);
3246 tmp = gen_vfp_mrs();
3247 store_reg(s, rn, tmp);
b7bcbe95
FB
3248 } else {
3249 gen_mov_F0_vreg(0, rm);
4373f3ce
PB
3250 tmp = gen_vfp_mrs();
3251 store_reg(s, rn, tmp);
b7bcbe95 3252 gen_mov_F0_vreg(0, rm + 1);
4373f3ce
PB
3253 tmp = gen_vfp_mrs();
3254 store_reg(s, rd, tmp);
b7bcbe95
FB
3255 }
3256 } else {
3257 /* arm->vfp */
3258 if (dp) {
4373f3ce
PB
3259 tmp = load_reg(s, rd);
3260 gen_vfp_msr(tmp);
3261 gen_mov_vreg_F0(0, rm * 2);
3262 tmp = load_reg(s, rn);
3263 gen_vfp_msr(tmp);
3264 gen_mov_vreg_F0(0, rm * 2 + 1);
b7bcbe95 3265 } else {
4373f3ce
PB
3266 tmp = load_reg(s, rn);
3267 gen_vfp_msr(tmp);
b7bcbe95 3268 gen_mov_vreg_F0(0, rm);
4373f3ce
PB
3269 tmp = load_reg(s, rd);
3270 gen_vfp_msr(tmp);
b7bcbe95
FB
3271 gen_mov_vreg_F0(0, rm + 1);
3272 }
3273 }
3274 } else {
3275 /* Load/store */
3276 rn = (insn >> 16) & 0xf;
3277 if (dp)
9ee6e8bb 3278 VFP_DREG_D(rd, insn);
b7bcbe95 3279 else
9ee6e8bb
PB
3280 rd = VFP_SREG_D(insn);
3281 if (s->thumb && rn == 15) {
3282 gen_op_movl_T1_im(s->pc & ~2);
3283 } else {
3284 gen_movl_T1_reg(s, rn);
3285 }
b7bcbe95
FB
3286 if ((insn & 0x01200000) == 0x01000000) {
3287 /* Single load/store */
3288 offset = (insn & 0xff) << 2;
3289 if ((insn & (1 << 23)) == 0)
3290 offset = -offset;
3291 gen_op_addl_T1_im(offset);
3292 if (insn & (1 << 20)) {
b5ff1b31 3293 gen_vfp_ld(s, dp);
b7bcbe95
FB
3294 gen_mov_vreg_F0(dp, rd);
3295 } else {
3296 gen_mov_F0_vreg(dp, rd);
b5ff1b31 3297 gen_vfp_st(s, dp);
b7bcbe95
FB
3298 }
3299 } else {
3300 /* load/store multiple */
3301 if (dp)
3302 n = (insn >> 1) & 0x7f;
3303 else
3304 n = insn & 0xff;
3305
3306 if (insn & (1 << 24)) /* pre-decrement */
3307 gen_op_addl_T1_im(-((insn & 0xff) << 2));
3308
3309 if (dp)
3310 offset = 8;
3311 else
3312 offset = 4;
3313 for (i = 0; i < n; i++) {
18c9b560 3314 if (insn & ARM_CP_RW_BIT) {
b7bcbe95 3315 /* load */
b5ff1b31 3316 gen_vfp_ld(s, dp);
b7bcbe95
FB
3317 gen_mov_vreg_F0(dp, rd + i);
3318 } else {
3319 /* store */
3320 gen_mov_F0_vreg(dp, rd + i);
b5ff1b31 3321 gen_vfp_st(s, dp);
b7bcbe95
FB
3322 }
3323 gen_op_addl_T1_im(offset);
3324 }
3325 if (insn & (1 << 21)) {
3326 /* writeback */
3327 if (insn & (1 << 24))
3328 offset = -offset * n;
3329 else if (dp && (insn & 1))
3330 offset = 4;
3331 else
3332 offset = 0;
3333
3334 if (offset != 0)
3335 gen_op_addl_T1_im(offset);
3336 gen_movl_reg_T1(s, rn);
3337 }
3338 }
3339 }
3340 break;
3341 default:
3342 /* Should never happen. */
3343 return 1;
3344 }
3345 return 0;
3346}
3347
6e256c93 3348static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
c53be334 3349{
6e256c93
FB
3350 TranslationBlock *tb;
3351
3352 tb = s->tb;
3353 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
57fec1fe 3354 tcg_gen_goto_tb(n);
8984bd2e 3355 gen_set_pc_im(dest);
57fec1fe 3356 tcg_gen_exit_tb((long)tb + n);
6e256c93 3357 } else {
8984bd2e 3358 gen_set_pc_im(dest);
57fec1fe 3359 tcg_gen_exit_tb(0);
6e256c93 3360 }
c53be334
FB
3361}
3362
8aaca4c0
FB
3363static inline void gen_jmp (DisasContext *s, uint32_t dest)
3364{
551bd27f 3365 if (unlikely(s->singlestep_enabled)) {
8aaca4c0 3366 /* An indirect jump so that we still trigger the debug exception. */
5899f386 3367 if (s->thumb)
d9ba4830
PB
3368 dest |= 1;
3369 gen_bx_im(s, dest);
8aaca4c0 3370 } else {
6e256c93 3371 gen_goto_tb(s, 0, dest);
8aaca4c0
FB
3372 s->is_jmp = DISAS_TB_JUMP;
3373 }
3374}
3375
d9ba4830 3376static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
b5ff1b31 3377{
ee097184 3378 if (x)
d9ba4830 3379 tcg_gen_sari_i32(t0, t0, 16);
b5ff1b31 3380 else
d9ba4830 3381 gen_sxth(t0);
ee097184 3382 if (y)
d9ba4830 3383 tcg_gen_sari_i32(t1, t1, 16);
b5ff1b31 3384 else
d9ba4830
PB
3385 gen_sxth(t1);
3386 tcg_gen_mul_i32(t0, t0, t1);
b5ff1b31
FB
3387}
3388
3389/* Return the mask of PSR bits set by a MSR instruction. */
9ee6e8bb 3390static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
b5ff1b31
FB
3391 uint32_t mask;
3392
3393 mask = 0;
3394 if (flags & (1 << 0))
3395 mask |= 0xff;
3396 if (flags & (1 << 1))
3397 mask |= 0xff00;
3398 if (flags & (1 << 2))
3399 mask |= 0xff0000;
3400 if (flags & (1 << 3))
3401 mask |= 0xff000000;
9ee6e8bb 3402
2ae23e75 3403 /* Mask out undefined bits. */
9ee6e8bb
PB
3404 mask &= ~CPSR_RESERVED;
3405 if (!arm_feature(env, ARM_FEATURE_V6))
e160c51c 3406 mask &= ~(CPSR_E | CPSR_GE);
9ee6e8bb 3407 if (!arm_feature(env, ARM_FEATURE_THUMB2))
e160c51c 3408 mask &= ~CPSR_IT;
9ee6e8bb 3409 /* Mask out execution state bits. */
2ae23e75 3410 if (!spsr)
e160c51c 3411 mask &= ~CPSR_EXEC;
b5ff1b31
FB
3412 /* Mask out privileged bits. */
3413 if (IS_USER(s))
9ee6e8bb 3414 mask &= CPSR_USER;
b5ff1b31
FB
3415 return mask;
3416}
3417
2fbac54b
FN
3418/* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3419static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0)
b5ff1b31 3420{
d9ba4830 3421 TCGv tmp;
b5ff1b31
FB
3422 if (spsr) {
3423 /* ??? This is also undefined in system mode. */
3424 if (IS_USER(s))
3425 return 1;
d9ba4830
PB
3426
3427 tmp = load_cpu_field(spsr);
3428 tcg_gen_andi_i32(tmp, tmp, ~mask);
2fbac54b
FN
3429 tcg_gen_andi_i32(t0, t0, mask);
3430 tcg_gen_or_i32(tmp, tmp, t0);
d9ba4830 3431 store_cpu_field(tmp, spsr);
b5ff1b31 3432 } else {
2fbac54b 3433 gen_set_cpsr(t0, mask);
b5ff1b31 3434 }
2fbac54b 3435 dead_tmp(t0);
b5ff1b31
FB
3436 gen_lookup_tb(s);
3437 return 0;
3438}
3439
2fbac54b
FN
3440/* Returns nonzero if access to the PSR is not permitted. */
3441static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3442{
3443 TCGv tmp;
3444 tmp = new_tmp();
3445 tcg_gen_movi_i32(tmp, val);
3446 return gen_set_psr(s, mask, spsr, tmp);
3447}
3448
e9bb4aa9
JR
3449/* Generate an old-style exception return. Marks pc as dead. */
3450static void gen_exception_return(DisasContext *s, TCGv pc)
b5ff1b31 3451{
d9ba4830 3452 TCGv tmp;
e9bb4aa9 3453 store_reg(s, 15, pc);
d9ba4830
PB
3454 tmp = load_cpu_field(spsr);
3455 gen_set_cpsr(tmp, 0xffffffff);
3456 dead_tmp(tmp);
b5ff1b31
FB
3457 s->is_jmp = DISAS_UPDATE;
3458}
3459
b0109805
PB
3460/* Generate a v6 exception return. Marks both values as dead. */
3461static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
2c0262af 3462{
b0109805
PB
3463 gen_set_cpsr(cpsr, 0xffffffff);
3464 dead_tmp(cpsr);
3465 store_reg(s, 15, pc);
9ee6e8bb
PB
3466 s->is_jmp = DISAS_UPDATE;
3467}
3b46e624 3468
9ee6e8bb
PB
3469static inline void
3470gen_set_condexec (DisasContext *s)
3471{
3472 if (s->condexec_mask) {
8f01245e
PB
3473 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3474 TCGv tmp = new_tmp();
3475 tcg_gen_movi_i32(tmp, val);
d9ba4830 3476 store_cpu_field(tmp, condexec_bits);
9ee6e8bb
PB
3477 }
3478}
3b46e624 3479
9ee6e8bb
PB
3480static void gen_nop_hint(DisasContext *s, int val)
3481{
3482 switch (val) {
3483 case 3: /* wfi */
8984bd2e 3484 gen_set_pc_im(s->pc);
9ee6e8bb
PB
3485 s->is_jmp = DISAS_WFI;
3486 break;
3487 case 2: /* wfe */
3488 case 4: /* sev */
3489 /* TODO: Implement SEV and WFE. May help SMP performance. */
3490 default: /* nop */
3491 break;
3492 }
3493}
99c475ab 3494
ad69471c
PB
3495/* These macros help make the code more readable when migrating from the
3496 old dyngen helpers. They should probably be removed when
3497 T0/T1 are removed. */
3498#define CPU_T001 cpu_T[0], cpu_T[0], cpu_T[1]
3499#define CPU_T0E01 cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]
9ee6e8bb 3500
ad69471c 3501#define CPU_V001 cpu_V0, cpu_V0, cpu_V1
9ee6e8bb
PB
3502
3503static inline int gen_neon_add(int size)
3504{
3505 switch (size) {
ad69471c
PB
3506 case 0: gen_helper_neon_add_u8(CPU_T001); break;
3507 case 1: gen_helper_neon_add_u16(CPU_T001); break;
9ee6e8bb
PB
3508 case 2: gen_op_addl_T0_T1(); break;
3509 default: return 1;
3510 }
3511 return 0;
3512}
3513
ad69471c
PB
3514static inline void gen_neon_rsb(int size)
3515{
3516 switch (size) {
3517 case 0: gen_helper_neon_sub_u8(cpu_T[0], cpu_T[1], cpu_T[0]); break;
3518 case 1: gen_helper_neon_sub_u16(cpu_T[0], cpu_T[1], cpu_T[0]); break;
3519 case 2: gen_op_rsbl_T0_T1(); break;
3520 default: return;
3521 }
3522}
3523
3524/* 32-bit pairwise ops end up the same as the elementwise versions. */
3525#define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3526#define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3527#define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3528#define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3529
3530/* FIXME: This is wrong. They set the wrong overflow bit. */
3531#define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3532#define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3533#define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3534#define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3535
3536#define GEN_NEON_INTEGER_OP_ENV(name) do { \
3537 switch ((size << 1) | u) { \
3538 case 0: \
3539 gen_helper_neon_##name##_s8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3540 break; \
3541 case 1: \
3542 gen_helper_neon_##name##_u8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3543 break; \
3544 case 2: \
3545 gen_helper_neon_##name##_s16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3546 break; \
3547 case 3: \
3548 gen_helper_neon_##name##_u16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3549 break; \
3550 case 4: \
3551 gen_helper_neon_##name##_s32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3552 break; \
3553 case 5: \
3554 gen_helper_neon_##name##_u32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3555 break; \
3556 default: return 1; \
3557 }} while (0)
9ee6e8bb
PB
3558
3559#define GEN_NEON_INTEGER_OP(name) do { \
3560 switch ((size << 1) | u) { \
ad69471c
PB
3561 case 0: \
3562 gen_helper_neon_##name##_s8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3563 break; \
3564 case 1: \
3565 gen_helper_neon_##name##_u8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3566 break; \
3567 case 2: \
3568 gen_helper_neon_##name##_s16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3569 break; \
3570 case 3: \
3571 gen_helper_neon_##name##_u16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3572 break; \
3573 case 4: \
3574 gen_helper_neon_##name##_s32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3575 break; \
3576 case 5: \
3577 gen_helper_neon_##name##_u32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3578 break; \
9ee6e8bb
PB
3579 default: return 1; \
3580 }} while (0)
3581
3582static inline void
3583gen_neon_movl_scratch_T0(int scratch)
3584{
3585 uint32_t offset;
3586
3587 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
ad69471c 3588 tcg_gen_st_i32(cpu_T[0], cpu_env, offset);
9ee6e8bb
PB
3589}
3590
3591static inline void
3592gen_neon_movl_scratch_T1(int scratch)
3593{
3594 uint32_t offset;
3595
3596 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
ad69471c 3597 tcg_gen_st_i32(cpu_T[1], cpu_env, offset);
9ee6e8bb
PB
3598}
3599
3600static inline void
3601gen_neon_movl_T0_scratch(int scratch)
3602{
3603 uint32_t offset;
3604
3605 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
ad69471c 3606 tcg_gen_ld_i32(cpu_T[0], cpu_env, offset);
9ee6e8bb
PB
3607}
3608
3609static inline void
3610gen_neon_movl_T1_scratch(int scratch)
3611{
3612 uint32_t offset;
3613
3614 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
ad69471c 3615 tcg_gen_ld_i32(cpu_T[1], cpu_env, offset);
9ee6e8bb
PB
3616}
3617
3618static inline void gen_neon_get_scalar(int size, int reg)
3619{
3620 if (size == 1) {
3621 NEON_GET_REG(T0, reg >> 1, reg & 1);
3622 } else {
3623 NEON_GET_REG(T0, reg >> 2, (reg >> 1) & 1);
3624 if (reg & 1)
ad69471c 3625 gen_neon_dup_low16(cpu_T[0]);
9ee6e8bb 3626 else
ad69471c 3627 gen_neon_dup_high16(cpu_T[0]);
9ee6e8bb
PB
3628 }
3629}
3630
3631static void gen_neon_unzip(int reg, int q, int tmp, int size)
3632{
3633 int n;
3634
3635 for (n = 0; n < q + 1; n += 2) {
3636 NEON_GET_REG(T0, reg, n);
3637 NEON_GET_REG(T0, reg, n + n);
3638 switch (size) {
ad69471c
PB
3639 case 0: gen_helper_neon_unzip_u8(); break;
3640 case 1: gen_helper_neon_zip_u16(); break; /* zip and unzip are the same. */
9ee6e8bb
PB
3641 case 2: /* no-op */; break;
3642 default: abort();
3643 }
3644 gen_neon_movl_scratch_T0(tmp + n);
3645 gen_neon_movl_scratch_T1(tmp + n + 1);
3646 }
3647}
3648
3649static struct {
3650 int nregs;
3651 int interleave;
3652 int spacing;
3653} neon_ls_element_type[11] = {
3654 {4, 4, 1},
3655 {4, 4, 2},
3656 {4, 1, 1},
3657 {4, 2, 1},
3658 {3, 3, 1},
3659 {3, 3, 2},
3660 {3, 1, 1},
3661 {1, 1, 1},
3662 {2, 2, 1},
3663 {2, 2, 2},
3664 {2, 1, 1}
3665};
3666
3667/* Translate a NEON load/store element instruction. Return nonzero if the
3668 instruction is invalid. */
3669static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3670{
3671 int rd, rn, rm;
3672 int op;
3673 int nregs;
3674 int interleave;
3675 int stride;
3676 int size;
3677 int reg;
3678 int pass;
3679 int load;
3680 int shift;
9ee6e8bb 3681 int n;
b0109805 3682 TCGv tmp;
8f8e3aa4 3683 TCGv tmp2;
9ee6e8bb
PB
3684
3685 if (!vfp_enabled(env))
3686 return 1;
3687 VFP_DREG_D(rd, insn);
3688 rn = (insn >> 16) & 0xf;
3689 rm = insn & 0xf;
3690 load = (insn & (1 << 21)) != 0;
3691 if ((insn & (1 << 23)) == 0) {
3692 /* Load store all elements. */
3693 op = (insn >> 8) & 0xf;
3694 size = (insn >> 6) & 3;
3695 if (op > 10 || size == 3)
3696 return 1;
3697 nregs = neon_ls_element_type[op].nregs;
3698 interleave = neon_ls_element_type[op].interleave;
3699 gen_movl_T1_reg(s, rn);
3700 stride = (1 << size) * interleave;
3701 for (reg = 0; reg < nregs; reg++) {
3702 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3703 gen_movl_T1_reg(s, rn);
3704 gen_op_addl_T1_im((1 << size) * reg);
3705 } else if (interleave == 2 && nregs == 4 && reg == 2) {
3706 gen_movl_T1_reg(s, rn);
3707 gen_op_addl_T1_im(1 << size);
3708 }
3709 for (pass = 0; pass < 2; pass++) {
3710 if (size == 2) {
3711 if (load) {
b0109805 3712 tmp = gen_ld32(cpu_T[1], IS_USER(s));
ad69471c 3713 neon_store_reg(rd, pass, tmp);
9ee6e8bb 3714 } else {
ad69471c 3715 tmp = neon_load_reg(rd, pass);
b0109805 3716 gen_st32(tmp, cpu_T[1], IS_USER(s));
9ee6e8bb
PB
3717 }
3718 gen_op_addl_T1_im(stride);
3719 } else if (size == 1) {
3720 if (load) {
b0109805 3721 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
9ee6e8bb 3722 gen_op_addl_T1_im(stride);
8f8e3aa4 3723 tmp2 = gen_ld16u(cpu_T[1], IS_USER(s));
9ee6e8bb 3724 gen_op_addl_T1_im(stride);
8f8e3aa4
PB
3725 gen_bfi(tmp, tmp, tmp2, 16, 0xffff);
3726 dead_tmp(tmp2);
3727 neon_store_reg(rd, pass, tmp);
9ee6e8bb 3728 } else {
8f8e3aa4
PB
3729 tmp = neon_load_reg(rd, pass);
3730 tmp2 = new_tmp();
3731 tcg_gen_shri_i32(tmp2, tmp, 16);
b0109805 3732 gen_st16(tmp, cpu_T[1], IS_USER(s));
9ee6e8bb 3733 gen_op_addl_T1_im(stride);
8f8e3aa4 3734 gen_st16(tmp2, cpu_T[1], IS_USER(s));
9ee6e8bb
PB
3735 gen_op_addl_T1_im(stride);
3736 }
3737 } else /* size == 0 */ {
3738 if (load) {
a50f5b91 3739 TCGV_UNUSED(tmp2);
9ee6e8bb 3740 for (n = 0; n < 4; n++) {
b0109805 3741 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
9ee6e8bb
PB
3742 gen_op_addl_T1_im(stride);
3743 if (n == 0) {
8f8e3aa4 3744 tmp2 = tmp;
9ee6e8bb 3745 } else {
8f8e3aa4
PB
3746 gen_bfi(tmp2, tmp2, tmp, n * 8, 0xff);
3747 dead_tmp(tmp);
9ee6e8bb 3748 }
9ee6e8bb 3749 }
8f8e3aa4 3750 neon_store_reg(rd, pass, tmp2);
9ee6e8bb 3751 } else {
8f8e3aa4 3752 tmp2 = neon_load_reg(rd, pass);
9ee6e8bb 3753 for (n = 0; n < 4; n++) {
8f8e3aa4 3754 tmp = new_tmp();
9ee6e8bb 3755 if (n == 0) {
8f8e3aa4 3756 tcg_gen_mov_i32(tmp, tmp2);
9ee6e8bb 3757 } else {
8f8e3aa4 3758 tcg_gen_shri_i32(tmp, tmp2, n * 8);
9ee6e8bb 3759 }
b0109805 3760 gen_st8(tmp, cpu_T[1], IS_USER(s));
9ee6e8bb 3761 gen_op_addl_T1_im(stride);
9ee6e8bb 3762 }
8f8e3aa4 3763 dead_tmp(tmp2);
9ee6e8bb
PB
3764 }
3765 }
3766 }
3767 rd += neon_ls_element_type[op].spacing;
3768 }
3769 stride = nregs * 8;
3770 } else {
3771 size = (insn >> 10) & 3;
3772 if (size == 3) {
3773 /* Load single element to all lanes. */
3774 if (!load)
3775 return 1;
3776 size = (insn >> 6) & 3;
3777 nregs = ((insn >> 8) & 3) + 1;
3778 stride = (insn & (1 << 5)) ? 2 : 1;
ff8263a9 3779 gen_movl_T1_reg(s, rn);
9ee6e8bb
PB
3780 for (reg = 0; reg < nregs; reg++) {
3781 switch (size) {
3782 case 0:
b0109805 3783 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
ad69471c 3784 gen_neon_dup_u8(tmp, 0);
9ee6e8bb
PB
3785 break;
3786 case 1:
b0109805 3787 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
ad69471c 3788 gen_neon_dup_low16(tmp);
9ee6e8bb
PB
3789 break;
3790 case 2:
b0109805 3791 tmp = gen_ld32(cpu_T[0], IS_USER(s));
9ee6e8bb
PB
3792 break;
3793 case 3:
3794 return 1;
a50f5b91
PB
3795 default: /* Avoid compiler warnings. */
3796 abort();
99c475ab 3797 }
9ee6e8bb 3798 gen_op_addl_T1_im(1 << size);
ad69471c
PB
3799 tmp2 = new_tmp();
3800 tcg_gen_mov_i32(tmp2, tmp);
3801 neon_store_reg(rd, 0, tmp2);
3018f259 3802 neon_store_reg(rd, 1, tmp);
9ee6e8bb
PB
3803 rd += stride;
3804 }
3805 stride = (1 << size) * nregs;
3806 } else {
3807 /* Single element. */
3808 pass = (insn >> 7) & 1;
3809 switch (size) {
3810 case 0:
3811 shift = ((insn >> 5) & 3) * 8;
9ee6e8bb
PB
3812 stride = 1;
3813 break;
3814 case 1:
3815 shift = ((insn >> 6) & 1) * 16;
9ee6e8bb
PB
3816 stride = (insn & (1 << 5)) ? 2 : 1;
3817 break;
3818 case 2:
3819 shift = 0;
9ee6e8bb
PB
3820 stride = (insn & (1 << 6)) ? 2 : 1;
3821 break;
3822 default:
3823 abort();
3824 }
3825 nregs = ((insn >> 8) & 3) + 1;
3826 gen_movl_T1_reg(s, rn);
3827 for (reg = 0; reg < nregs; reg++) {
3828 if (load) {
9ee6e8bb
PB
3829 switch (size) {
3830 case 0:
b0109805 3831 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
9ee6e8bb
PB
3832 break;
3833 case 1:
b0109805 3834 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
9ee6e8bb
PB
3835 break;
3836 case 2:
b0109805 3837 tmp = gen_ld32(cpu_T[1], IS_USER(s));
9ee6e8bb 3838 break;
a50f5b91
PB
3839 default: /* Avoid compiler warnings. */
3840 abort();
9ee6e8bb
PB
3841 }
3842 if (size != 2) {
8f8e3aa4
PB
3843 tmp2 = neon_load_reg(rd, pass);
3844 gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
3845 dead_tmp(tmp2);
9ee6e8bb 3846 }
8f8e3aa4 3847 neon_store_reg(rd, pass, tmp);
9ee6e8bb 3848 } else { /* Store */
8f8e3aa4
PB
3849 tmp = neon_load_reg(rd, pass);
3850 if (shift)
3851 tcg_gen_shri_i32(tmp, tmp, shift);
9ee6e8bb
PB
3852 switch (size) {
3853 case 0:
b0109805 3854 gen_st8(tmp, cpu_T[1], IS_USER(s));
9ee6e8bb
PB
3855 break;
3856 case 1:
b0109805 3857 gen_st16(tmp, cpu_T[1], IS_USER(s));
9ee6e8bb
PB
3858 break;
3859 case 2:
b0109805 3860 gen_st32(tmp, cpu_T[1], IS_USER(s));
9ee6e8bb 3861 break;
99c475ab 3862 }
99c475ab 3863 }
9ee6e8bb
PB
3864 rd += stride;
3865 gen_op_addl_T1_im(1 << size);
99c475ab 3866 }
9ee6e8bb 3867 stride = nregs * (1 << size);
99c475ab 3868 }
9ee6e8bb
PB
3869 }
3870 if (rm != 15) {
b26eefb6
PB
3871 TCGv base;
3872
3873 base = load_reg(s, rn);
9ee6e8bb 3874 if (rm == 13) {
b26eefb6 3875 tcg_gen_addi_i32(base, base, stride);
9ee6e8bb 3876 } else {
b26eefb6
PB
3877 TCGv index;
3878 index = load_reg(s, rm);
3879 tcg_gen_add_i32(base, base, index);
3880 dead_tmp(index);
9ee6e8bb 3881 }
b26eefb6 3882 store_reg(s, rn, base);
9ee6e8bb
PB
3883 }
3884 return 0;
3885}
3b46e624 3886
8f8e3aa4
PB
3887/* Bitwise select. dest = c ? t : f. Clobbers T and F. */
3888static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
3889{
3890 tcg_gen_and_i32(t, t, c);
3891 tcg_gen_bic_i32(f, f, c);
3892 tcg_gen_or_i32(dest, t, f);
3893}
3894
a7812ae4 3895static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src)
ad69471c
PB
3896{
3897 switch (size) {
3898 case 0: gen_helper_neon_narrow_u8(dest, src); break;
3899 case 1: gen_helper_neon_narrow_u16(dest, src); break;
3900 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
3901 default: abort();
3902 }
3903}
3904
a7812ae4 3905static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
ad69471c
PB
3906{
3907 switch (size) {
3908 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
3909 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
3910 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
3911 default: abort();
3912 }
3913}
3914
a7812ae4 3915static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
ad69471c
PB
3916{
3917 switch (size) {
3918 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
3919 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
3920 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
3921 default: abort();
3922 }
3923}
3924
3925static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
3926 int q, int u)
3927{
3928 if (q) {
3929 if (u) {
3930 switch (size) {
3931 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3932 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
3933 default: abort();
3934 }
3935 } else {
3936 switch (size) {
3937 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
3938 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
3939 default: abort();
3940 }
3941 }
3942 } else {
3943 if (u) {
3944 switch (size) {
3945 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3946 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
3947 default: abort();
3948 }
3949 } else {
3950 switch (size) {
3951 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
3952 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
3953 default: abort();
3954 }
3955 }
3956 }
3957}
3958
a7812ae4 3959static inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u)
ad69471c
PB
3960{
3961 if (u) {
3962 switch (size) {
3963 case 0: gen_helper_neon_widen_u8(dest, src); break;
3964 case 1: gen_helper_neon_widen_u16(dest, src); break;
3965 case 2: tcg_gen_extu_i32_i64(dest, src); break;
3966 default: abort();
3967 }
3968 } else {
3969 switch (size) {
3970 case 0: gen_helper_neon_widen_s8(dest, src); break;
3971 case 1: gen_helper_neon_widen_s16(dest, src); break;
3972 case 2: tcg_gen_ext_i32_i64(dest, src); break;
3973 default: abort();
3974 }
3975 }
3976 dead_tmp(src);
3977}
3978
3979static inline void gen_neon_addl(int size)
3980{
3981 switch (size) {
3982 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
3983 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
3984 case 2: tcg_gen_add_i64(CPU_V001); break;
3985 default: abort();
3986 }
3987}
3988
3989static inline void gen_neon_subl(int size)
3990{
3991 switch (size) {
3992 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
3993 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
3994 case 2: tcg_gen_sub_i64(CPU_V001); break;
3995 default: abort();
3996 }
3997}
3998
a7812ae4 3999static inline void gen_neon_negl(TCGv_i64 var, int size)
ad69471c
PB
4000{
4001 switch (size) {
4002 case 0: gen_helper_neon_negl_u16(var, var); break;
4003 case 1: gen_helper_neon_negl_u32(var, var); break;
4004 case 2: gen_helper_neon_negl_u64(var, var); break;
4005 default: abort();
4006 }
4007}
4008
a7812ae4 4009static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
ad69471c
PB
4010{
4011 switch (size) {
4012 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4013 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4014 default: abort();
4015 }
4016}
4017
a7812ae4 4018static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
ad69471c 4019{
a7812ae4 4020 TCGv_i64 tmp;
ad69471c
PB
4021
4022 switch ((size << 1) | u) {
4023 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4024 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4025 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4026 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4027 case 4:
4028 tmp = gen_muls_i64_i32(a, b);
4029 tcg_gen_mov_i64(dest, tmp);
4030 break;
4031 case 5:
4032 tmp = gen_mulu_i64_i32(a, b);
4033 tcg_gen_mov_i64(dest, tmp);
4034 break;
4035 default: abort();
4036 }
4037 if (size < 2) {
4038 dead_tmp(b);
4039 dead_tmp(a);
4040 }
4041}
4042
9ee6e8bb
PB
4043/* Translate a NEON data processing instruction. Return nonzero if the
4044 instruction is invalid.
ad69471c
PB
4045 We process data in a mixture of 32-bit and 64-bit chunks.
4046 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
2c0262af 4047
9ee6e8bb
PB
4048static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
4049{
4050 int op;
4051 int q;
4052 int rd, rn, rm;
4053 int size;
4054 int shift;
4055 int pass;
4056 int count;
4057 int pairwise;
4058 int u;
4059 int n;
4060 uint32_t imm;
8f8e3aa4
PB
4061 TCGv tmp;
4062 TCGv tmp2;
4063 TCGv tmp3;
a7812ae4 4064 TCGv_i64 tmp64;
9ee6e8bb
PB
4065
4066 if (!vfp_enabled(env))
4067 return 1;
4068 q = (insn & (1 << 6)) != 0;
4069 u = (insn >> 24) & 1;
4070 VFP_DREG_D(rd, insn);
4071 VFP_DREG_N(rn, insn);
4072 VFP_DREG_M(rm, insn);
4073 size = (insn >> 20) & 3;
4074 if ((insn & (1 << 23)) == 0) {
4075 /* Three register same length. */
4076 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
ad69471c
PB
4077 if (size == 3 && (op == 1 || op == 5 || op == 8 || op == 9
4078 || op == 10 || op == 11 || op == 16)) {
4079 /* 64-bit element instructions. */
9ee6e8bb 4080 for (pass = 0; pass < (q ? 2 : 1); pass++) {
ad69471c
PB
4081 neon_load_reg64(cpu_V0, rn + pass);
4082 neon_load_reg64(cpu_V1, rm + pass);
9ee6e8bb
PB
4083 switch (op) {
4084 case 1: /* VQADD */
4085 if (u) {
ad69471c 4086 gen_helper_neon_add_saturate_u64(CPU_V001);
2c0262af 4087 } else {
ad69471c 4088 gen_helper_neon_add_saturate_s64(CPU_V001);
2c0262af 4089 }
9ee6e8bb
PB
4090 break;
4091 case 5: /* VQSUB */
4092 if (u) {
ad69471c
PB
4093 gen_helper_neon_sub_saturate_u64(CPU_V001);
4094 } else {
4095 gen_helper_neon_sub_saturate_s64(CPU_V001);
4096 }
4097 break;
4098 case 8: /* VSHL */
4099 if (u) {
4100 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4101 } else {
4102 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4103 }
4104 break;
4105 case 9: /* VQSHL */
4106 if (u) {
4107 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4108 cpu_V0, cpu_V0);
4109 } else {
4110 gen_helper_neon_qshl_s64(cpu_V1, cpu_env,
4111 cpu_V1, cpu_V0);
4112 }
4113 break;
4114 case 10: /* VRSHL */
4115 if (u) {
4116 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
1e8d4eec 4117 } else {
ad69471c
PB
4118 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4119 }
4120 break;
4121 case 11: /* VQRSHL */
4122 if (u) {
4123 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4124 cpu_V1, cpu_V0);
4125 } else {
4126 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4127 cpu_V1, cpu_V0);
1e8d4eec 4128 }
9ee6e8bb
PB
4129 break;
4130 case 16:
4131 if (u) {
ad69471c 4132 tcg_gen_sub_i64(CPU_V001);
9ee6e8bb 4133 } else {
ad69471c 4134 tcg_gen_add_i64(CPU_V001);
9ee6e8bb
PB
4135 }
4136 break;
4137 default:
4138 abort();
2c0262af 4139 }
ad69471c 4140 neon_store_reg64(cpu_V0, rd + pass);
2c0262af 4141 }
9ee6e8bb 4142 return 0;
2c0262af 4143 }
9ee6e8bb
PB
4144 switch (op) {
4145 case 8: /* VSHL */
4146 case 9: /* VQSHL */
4147 case 10: /* VRSHL */
ad69471c 4148 case 11: /* VQRSHL */
9ee6e8bb 4149 {
ad69471c
PB
4150 int rtmp;
4151 /* Shift instruction operands are reversed. */
4152 rtmp = rn;
9ee6e8bb 4153 rn = rm;
ad69471c 4154 rm = rtmp;
9ee6e8bb
PB
4155 pairwise = 0;
4156 }
2c0262af 4157 break;
9ee6e8bb
PB
4158 case 20: /* VPMAX */
4159 case 21: /* VPMIN */
4160 case 23: /* VPADD */
4161 pairwise = 1;
2c0262af 4162 break;
9ee6e8bb
PB
4163 case 26: /* VPADD (float) */
4164 pairwise = (u && size < 2);
2c0262af 4165 break;
9ee6e8bb
PB
4166 case 30: /* VPMIN/VPMAX (float) */
4167 pairwise = u;
2c0262af 4168 break;
9ee6e8bb
PB
4169 default:
4170 pairwise = 0;
2c0262af 4171 break;
9ee6e8bb
PB
4172 }
4173 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4174
4175 if (pairwise) {
4176 /* Pairwise. */
4177 if (q)
4178 n = (pass & 1) * 2;
2c0262af 4179 else
9ee6e8bb
PB
4180 n = 0;
4181 if (pass < q + 1) {
4182 NEON_GET_REG(T0, rn, n);
4183 NEON_GET_REG(T1, rn, n + 1);
4184 } else {
4185 NEON_GET_REG(T0, rm, n);
4186 NEON_GET_REG(T1, rm, n + 1);
4187 }
4188 } else {
4189 /* Elementwise. */
4190 NEON_GET_REG(T0, rn, pass);
4191 NEON_GET_REG(T1, rm, pass);
4192 }
4193 switch (op) {
4194 case 0: /* VHADD */
4195 GEN_NEON_INTEGER_OP(hadd);
4196 break;
4197 case 1: /* VQADD */
ad69471c 4198 GEN_NEON_INTEGER_OP_ENV(qadd);
2c0262af 4199 break;
9ee6e8bb
PB
4200 case 2: /* VRHADD */
4201 GEN_NEON_INTEGER_OP(rhadd);
2c0262af 4202 break;
9ee6e8bb
PB
4203 case 3: /* Logic ops. */
4204 switch ((u << 2) | size) {
4205 case 0: /* VAND */
2c0262af 4206 gen_op_andl_T0_T1();
9ee6e8bb
PB
4207 break;
4208 case 1: /* BIC */
4209 gen_op_bicl_T0_T1();
4210 break;
4211 case 2: /* VORR */
4212 gen_op_orl_T0_T1();
4213 break;
4214 case 3: /* VORN */
4215 gen_op_notl_T1();
4216 gen_op_orl_T0_T1();
4217 break;
4218 case 4: /* VEOR */
4219 gen_op_xorl_T0_T1();
4220 break;
4221 case 5: /* VBSL */
8f8e3aa4
PB
4222 tmp = neon_load_reg(rd, pass);
4223 gen_neon_bsl(cpu_T[0], cpu_T[0], cpu_T[1], tmp);
4224 dead_tmp(tmp);
9ee6e8bb
PB
4225 break;
4226 case 6: /* VBIT */
8f8e3aa4
PB
4227 tmp = neon_load_reg(rd, pass);
4228 gen_neon_bsl(cpu_T[0], cpu_T[0], tmp, cpu_T[1]);
4229 dead_tmp(tmp);
9ee6e8bb
PB
4230 break;
4231 case 7: /* VBIF */
8f8e3aa4
PB
4232 tmp = neon_load_reg(rd, pass);
4233 gen_neon_bsl(cpu_T[0], tmp, cpu_T[0], cpu_T[1]);
4234 dead_tmp(tmp);
9ee6e8bb 4235 break;
2c0262af
FB
4236 }
4237 break;
9ee6e8bb
PB
4238 case 4: /* VHSUB */
4239 GEN_NEON_INTEGER_OP(hsub);
4240 break;
4241 case 5: /* VQSUB */
ad69471c 4242 GEN_NEON_INTEGER_OP_ENV(qsub);
2c0262af 4243 break;
9ee6e8bb
PB
4244 case 6: /* VCGT */
4245 GEN_NEON_INTEGER_OP(cgt);
4246 break;
4247 case 7: /* VCGE */
4248 GEN_NEON_INTEGER_OP(cge);
4249 break;
4250 case 8: /* VSHL */
ad69471c 4251 GEN_NEON_INTEGER_OP(shl);
2c0262af 4252 break;
9ee6e8bb 4253 case 9: /* VQSHL */
ad69471c 4254 GEN_NEON_INTEGER_OP_ENV(qshl);
2c0262af 4255 break;
9ee6e8bb 4256 case 10: /* VRSHL */
ad69471c 4257 GEN_NEON_INTEGER_OP(rshl);
2c0262af 4258 break;
9ee6e8bb 4259 case 11: /* VQRSHL */
ad69471c 4260 GEN_NEON_INTEGER_OP_ENV(qrshl);
9ee6e8bb
PB
4261 break;
4262 case 12: /* VMAX */
4263 GEN_NEON_INTEGER_OP(max);
4264 break;
4265 case 13: /* VMIN */
4266 GEN_NEON_INTEGER_OP(min);
4267 break;
4268 case 14: /* VABD */
4269 GEN_NEON_INTEGER_OP(abd);
4270 break;
4271 case 15: /* VABA */
4272 GEN_NEON_INTEGER_OP(abd);
4273 NEON_GET_REG(T1, rd, pass);
4274 gen_neon_add(size);
4275 break;
4276 case 16:
4277 if (!u) { /* VADD */
4278 if (gen_neon_add(size))
4279 return 1;
4280 } else { /* VSUB */
4281 switch (size) {
ad69471c
PB
4282 case 0: gen_helper_neon_sub_u8(CPU_T001); break;
4283 case 1: gen_helper_neon_sub_u16(CPU_T001); break;
9ee6e8bb
PB
4284 case 2: gen_op_subl_T0_T1(); break;
4285 default: return 1;
4286 }
4287 }
4288 break;
4289 case 17:
4290 if (!u) { /* VTST */
4291 switch (size) {
ad69471c
PB
4292 case 0: gen_helper_neon_tst_u8(CPU_T001); break;
4293 case 1: gen_helper_neon_tst_u16(CPU_T001); break;
4294 case 2: gen_helper_neon_tst_u32(CPU_T001); break;
9ee6e8bb
PB
4295 default: return 1;
4296 }
4297 } else { /* VCEQ */
4298 switch (size) {
ad69471c
PB
4299 case 0: gen_helper_neon_ceq_u8(CPU_T001); break;
4300 case 1: gen_helper_neon_ceq_u16(CPU_T001); break;
4301 case 2: gen_helper_neon_ceq_u32(CPU_T001); break;
9ee6e8bb
PB
4302 default: return 1;
4303 }
4304 }
4305 break;
4306 case 18: /* Multiply. */
4307 switch (size) {
ad69471c
PB
4308 case 0: gen_helper_neon_mul_u8(CPU_T001); break;
4309 case 1: gen_helper_neon_mul_u16(CPU_T001); break;
9ee6e8bb
PB
4310 case 2: gen_op_mul_T0_T1(); break;
4311 default: return 1;
4312 }
4313 NEON_GET_REG(T1, rd, pass);
4314 if (u) { /* VMLS */
ad69471c 4315 gen_neon_rsb(size);
9ee6e8bb
PB
4316 } else { /* VMLA */
4317 gen_neon_add(size);
4318 }
4319 break;
4320 case 19: /* VMUL */
4321 if (u) { /* polynomial */
ad69471c 4322 gen_helper_neon_mul_p8(CPU_T001);
9ee6e8bb
PB
4323 } else { /* Integer */
4324 switch (size) {
ad69471c
PB
4325 case 0: gen_helper_neon_mul_u8(CPU_T001); break;
4326 case 1: gen_helper_neon_mul_u16(CPU_T001); break;
9ee6e8bb
PB
4327 case 2: gen_op_mul_T0_T1(); break;
4328 default: return 1;
4329 }
4330 }
4331 break;
4332 case 20: /* VPMAX */
4333 GEN_NEON_INTEGER_OP(pmax);
4334 break;
4335 case 21: /* VPMIN */
4336 GEN_NEON_INTEGER_OP(pmin);
4337 break;
4338 case 22: /* Hultiply high. */
4339 if (!u) { /* VQDMULH */
4340 switch (size) {
ad69471c
PB
4341 case 1: gen_helper_neon_qdmulh_s16(CPU_T0E01); break;
4342 case 2: gen_helper_neon_qdmulh_s32(CPU_T0E01); break;
9ee6e8bb
PB
4343 default: return 1;
4344 }
4345 } else { /* VQRDHMUL */
4346 switch (size) {
ad69471c
PB
4347 case 1: gen_helper_neon_qrdmulh_s16(CPU_T0E01); break;
4348 case 2: gen_helper_neon_qrdmulh_s32(CPU_T0E01); break;
9ee6e8bb
PB
4349 default: return 1;
4350 }
4351 }
4352 break;
4353 case 23: /* VPADD */
4354 if (u)
4355 return 1;
4356 switch (size) {
ad69471c
PB
4357 case 0: gen_helper_neon_padd_u8(CPU_T001); break;
4358 case 1: gen_helper_neon_padd_u16(CPU_T001); break;
9ee6e8bb
PB
4359 case 2: gen_op_addl_T0_T1(); break;
4360 default: return 1;
4361 }
4362 break;
4363 case 26: /* Floating point arithnetic. */
4364 switch ((u << 2) | size) {
4365 case 0: /* VADD */
ad69471c 4366 gen_helper_neon_add_f32(CPU_T001);
9ee6e8bb
PB
4367 break;
4368 case 2: /* VSUB */
ad69471c 4369 gen_helper_neon_sub_f32(CPU_T001);
9ee6e8bb
PB
4370 break;
4371 case 4: /* VPADD */
ad69471c 4372 gen_helper_neon_add_f32(CPU_T001);
9ee6e8bb
PB
4373 break;
4374 case 6: /* VABD */
ad69471c 4375 gen_helper_neon_abd_f32(CPU_T001);
9ee6e8bb
PB
4376 break;
4377 default:
4378 return 1;
4379 }
4380 break;
4381 case 27: /* Float multiply. */
ad69471c 4382 gen_helper_neon_mul_f32(CPU_T001);
9ee6e8bb
PB
4383 if (!u) {
4384 NEON_GET_REG(T1, rd, pass);
4385 if (size == 0) {
ad69471c 4386 gen_helper_neon_add_f32(CPU_T001);
9ee6e8bb 4387 } else {
ad69471c 4388 gen_helper_neon_sub_f32(cpu_T[0], cpu_T[1], cpu_T[0]);
9ee6e8bb
PB
4389 }
4390 }
4391 break;
4392 case 28: /* Float compare. */
4393 if (!u) {
ad69471c 4394 gen_helper_neon_ceq_f32(CPU_T001);
b5ff1b31 4395 } else {
9ee6e8bb 4396 if (size == 0)
ad69471c 4397 gen_helper_neon_cge_f32(CPU_T001);
9ee6e8bb 4398 else
ad69471c 4399 gen_helper_neon_cgt_f32(CPU_T001);
b5ff1b31 4400 }
2c0262af 4401 break;
9ee6e8bb
PB
4402 case 29: /* Float compare absolute. */
4403 if (!u)
4404 return 1;
4405 if (size == 0)
ad69471c 4406 gen_helper_neon_acge_f32(CPU_T001);
9ee6e8bb 4407 else
ad69471c 4408 gen_helper_neon_acgt_f32(CPU_T001);
2c0262af 4409 break;
9ee6e8bb
PB
4410 case 30: /* Float min/max. */
4411 if (size == 0)
ad69471c 4412 gen_helper_neon_max_f32(CPU_T001);
9ee6e8bb 4413 else
ad69471c 4414 gen_helper_neon_min_f32(CPU_T001);
9ee6e8bb
PB
4415 break;
4416 case 31:
4417 if (size == 0)
4373f3ce 4418 gen_helper_recps_f32(cpu_T[0], cpu_T[0], cpu_T[1], cpu_env);
9ee6e8bb 4419 else
4373f3ce 4420 gen_helper_rsqrts_f32(cpu_T[0], cpu_T[0], cpu_T[1], cpu_env);
2c0262af 4421 break;
9ee6e8bb
PB
4422 default:
4423 abort();
2c0262af 4424 }
9ee6e8bb
PB
4425 /* Save the result. For elementwise operations we can put it
4426 straight into the destination register. For pairwise operations
4427 we have to be careful to avoid clobbering the source operands. */
4428 if (pairwise && rd == rm) {
4429 gen_neon_movl_scratch_T0(pass);
4430 } else {
4431 NEON_SET_REG(T0, rd, pass);
4432 }
4433
4434 } /* for pass */
4435 if (pairwise && rd == rm) {
4436 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4437 gen_neon_movl_T0_scratch(pass);
4438 NEON_SET_REG(T0, rd, pass);
4439 }
4440 }
ad69471c 4441 /* End of 3 register same size operations. */
9ee6e8bb
PB
4442 } else if (insn & (1 << 4)) {
4443 if ((insn & 0x00380080) != 0) {
4444 /* Two registers and shift. */
4445 op = (insn >> 8) & 0xf;
4446 if (insn & (1 << 7)) {
4447 /* 64-bit shift. */
4448 size = 3;
4449 } else {
4450 size = 2;
4451 while ((insn & (1 << (size + 19))) == 0)
4452 size--;
4453 }
4454 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
4455 /* To avoid excessive dumplication of ops we implement shift
4456 by immediate using the variable shift operations. */
4457 if (op < 8) {
4458 /* Shift by immediate:
4459 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4460 /* Right shifts are encoded as N - shift, where N is the
4461 element size in bits. */
4462 if (op <= 4)
4463 shift = shift - (1 << (size + 3));
9ee6e8bb
PB
4464 if (size == 3) {
4465 count = q + 1;
4466 } else {
4467 count = q ? 4: 2;
4468 }
4469 switch (size) {
4470 case 0:
4471 imm = (uint8_t) shift;
4472 imm |= imm << 8;
4473 imm |= imm << 16;
4474 break;
4475 case 1:
4476 imm = (uint16_t) shift;
4477 imm |= imm << 16;
4478 break;
4479 case 2:
4480 case 3:
4481 imm = shift;
4482 break;
4483 default:
4484 abort();
4485 }
4486
4487 for (pass = 0; pass < count; pass++) {
ad69471c
PB
4488 if (size == 3) {
4489 neon_load_reg64(cpu_V0, rm + pass);
4490 tcg_gen_movi_i64(cpu_V1, imm);
4491 switch (op) {
4492 case 0: /* VSHR */
4493 case 1: /* VSRA */
4494 if (u)
4495 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
9ee6e8bb 4496 else
ad69471c 4497 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
9ee6e8bb 4498 break;
ad69471c
PB
4499 case 2: /* VRSHR */
4500 case 3: /* VRSRA */
4501 if (u)
4502 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
9ee6e8bb 4503 else
ad69471c 4504 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
9ee6e8bb 4505 break;
ad69471c
PB
4506 case 4: /* VSRI */
4507 if (!u)
4508 return 1;
4509 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4510 break;
4511 case 5: /* VSHL, VSLI */
4512 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4513 break;
4514 case 6: /* VQSHL */
4515 if (u)
4516 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
9ee6e8bb 4517 else
ad69471c
PB
4518 gen_helper_neon_qshl_s64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4519 break;
4520 case 7: /* VQSHLU */
4521 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
9ee6e8bb 4522 break;
9ee6e8bb 4523 }
ad69471c
PB
4524 if (op == 1 || op == 3) {
4525 /* Accumulate. */
4526 neon_load_reg64(cpu_V0, rd + pass);
4527 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
4528 } else if (op == 4 || (op == 5 && u)) {
4529 /* Insert */
4530 cpu_abort(env, "VS[LR]I.64 not implemented");
4531 }
4532 neon_store_reg64(cpu_V0, rd + pass);
4533 } else { /* size < 3 */
4534 /* Operands in T0 and T1. */
4535 gen_op_movl_T1_im(imm);
4536 NEON_GET_REG(T0, rm, pass);
4537 switch (op) {
4538 case 0: /* VSHR */
4539 case 1: /* VSRA */
4540 GEN_NEON_INTEGER_OP(shl);
4541 break;
4542 case 2: /* VRSHR */
4543 case 3: /* VRSRA */
4544 GEN_NEON_INTEGER_OP(rshl);
4545 break;
4546 case 4: /* VSRI */
4547 if (!u)
4548 return 1;
4549 GEN_NEON_INTEGER_OP(shl);
4550 break;
4551 case 5: /* VSHL, VSLI */
4552 switch (size) {
4553 case 0: gen_helper_neon_shl_u8(CPU_T001); break;
4554 case 1: gen_helper_neon_shl_u16(CPU_T001); break;
4555 case 2: gen_helper_neon_shl_u32(CPU_T001); break;
4556 default: return 1;
4557 }
4558 break;
4559 case 6: /* VQSHL */
4560 GEN_NEON_INTEGER_OP_ENV(qshl);
4561 break;
4562 case 7: /* VQSHLU */
4563 switch (size) {
4564 case 0: gen_helper_neon_qshl_u8(CPU_T0E01); break;
4565 case 1: gen_helper_neon_qshl_u16(CPU_T0E01); break;
4566 case 2: gen_helper_neon_qshl_u32(CPU_T0E01); break;
4567 default: return 1;
4568 }
4569 break;
4570 }
4571
4572 if (op == 1 || op == 3) {
4573 /* Accumulate. */
4574 NEON_GET_REG(T1, rd, pass);
4575 gen_neon_add(size);
4576 } else if (op == 4 || (op == 5 && u)) {
4577 /* Insert */
4578 switch (size) {
4579 case 0:
4580 if (op == 4)
4581 imm = 0xff >> -shift;
4582 else
4583 imm = (uint8_t)(0xff << shift);
4584 imm |= imm << 8;
4585 imm |= imm << 16;
4586 break;
4587 case 1:
4588 if (op == 4)
4589 imm = 0xffff >> -shift;
4590 else
4591 imm = (uint16_t)(0xffff << shift);
4592 imm |= imm << 16;
4593 break;
4594 case 2:
4595 if (op == 4)
4596 imm = 0xffffffffu >> -shift;
4597 else
4598 imm = 0xffffffffu << shift;
4599 break;
4600 default:
4601 abort();
4602 }
4603 tmp = neon_load_reg(rd, pass);
4604 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], imm);
4605 tcg_gen_andi_i32(tmp, tmp, ~imm);
4606 tcg_gen_or_i32(cpu_T[0], cpu_T[0], tmp);
4607 }
9ee6e8bb
PB
4608 NEON_SET_REG(T0, rd, pass);
4609 }
4610 } /* for pass */
4611 } else if (op < 10) {
ad69471c 4612 /* Shift by immediate and narrow:
9ee6e8bb
PB
4613 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4614 shift = shift - (1 << (size + 3));
4615 size++;
9ee6e8bb
PB
4616 switch (size) {
4617 case 1:
ad69471c 4618 imm = (uint16_t)shift;
9ee6e8bb 4619 imm |= imm << 16;
ad69471c 4620 tmp2 = tcg_const_i32(imm);
a7812ae4 4621 TCGV_UNUSED_I64(tmp64);
9ee6e8bb
PB
4622 break;
4623 case 2:
ad69471c
PB
4624 imm = (uint32_t)shift;
4625 tmp2 = tcg_const_i32(imm);
a7812ae4 4626 TCGV_UNUSED_I64(tmp64);
4cc633c3 4627 break;
9ee6e8bb 4628 case 3:
a7812ae4
PB
4629 tmp64 = tcg_const_i64(shift);
4630 TCGV_UNUSED(tmp2);
9ee6e8bb
PB
4631 break;
4632 default:
4633 abort();
4634 }
4635
ad69471c
PB
4636 for (pass = 0; pass < 2; pass++) {
4637 if (size == 3) {
4638 neon_load_reg64(cpu_V0, rm + pass);
4639 if (q) {
4640 if (u)
a7812ae4 4641 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, tmp64);
ad69471c 4642 else
a7812ae4 4643 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, tmp64);
ad69471c
PB
4644 } else {
4645 if (u)
a7812ae4 4646 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, tmp64);
ad69471c 4647 else
a7812ae4 4648 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, tmp64);
ad69471c 4649 }
2c0262af 4650 } else {
ad69471c
PB
4651 tmp = neon_load_reg(rm + pass, 0);
4652 gen_neon_shift_narrow(size, tmp, tmp2, q, u);
36aa55dc
PB
4653 tmp3 = neon_load_reg(rm + pass, 1);
4654 gen_neon_shift_narrow(size, tmp3, tmp2, q, u);
4655 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
ad69471c 4656 dead_tmp(tmp);
36aa55dc 4657 dead_tmp(tmp3);
9ee6e8bb 4658 }
ad69471c
PB
4659 tmp = new_tmp();
4660 if (op == 8 && !u) {
4661 gen_neon_narrow(size - 1, tmp, cpu_V0);
9ee6e8bb 4662 } else {
ad69471c
PB
4663 if (op == 8)
4664 gen_neon_narrow_sats(size - 1, tmp, cpu_V0);
9ee6e8bb 4665 else
ad69471c
PB
4666 gen_neon_narrow_satu(size - 1, tmp, cpu_V0);
4667 }
4668 if (pass == 0) {
4669 tmp2 = tmp;
4670 } else {
4671 neon_store_reg(rd, 0, tmp2);
4672 neon_store_reg(rd, 1, tmp);
9ee6e8bb
PB
4673 }
4674 } /* for pass */
4675 } else if (op == 10) {
4676 /* VSHLL */
ad69471c 4677 if (q || size == 3)
9ee6e8bb 4678 return 1;
ad69471c
PB
4679 tmp = neon_load_reg(rm, 0);
4680 tmp2 = neon_load_reg(rm, 1);
9ee6e8bb 4681 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
4682 if (pass == 1)
4683 tmp = tmp2;
4684
4685 gen_neon_widen(cpu_V0, tmp, size, u);
9ee6e8bb 4686
9ee6e8bb
PB
4687 if (shift != 0) {
4688 /* The shift is less than the width of the source
ad69471c
PB
4689 type, so we can just shift the whole register. */
4690 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
4691 if (size < 2 || !u) {
4692 uint64_t imm64;
4693 if (size == 0) {
4694 imm = (0xffu >> (8 - shift));
4695 imm |= imm << 16;
4696 } else {
4697 imm = 0xffff >> (16 - shift);
9ee6e8bb 4698 }
ad69471c
PB
4699 imm64 = imm | (((uint64_t)imm) << 32);
4700 tcg_gen_andi_i64(cpu_V0, cpu_V0, imm64);
9ee6e8bb
PB
4701 }
4702 }
ad69471c 4703 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
4704 }
4705 } else if (op == 15 || op == 16) {
4706 /* VCVT fixed-point. */
4707 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4373f3ce 4708 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
9ee6e8bb
PB
4709 if (op & 1) {
4710 if (u)
4373f3ce 4711 gen_vfp_ulto(0, shift);
9ee6e8bb 4712 else
4373f3ce 4713 gen_vfp_slto(0, shift);
9ee6e8bb
PB
4714 } else {
4715 if (u)
4373f3ce 4716 gen_vfp_toul(0, shift);
9ee6e8bb 4717 else
4373f3ce 4718 gen_vfp_tosl(0, shift);
2c0262af 4719 }
4373f3ce 4720 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
2c0262af
FB
4721 }
4722 } else {
9ee6e8bb
PB
4723 return 1;
4724 }
4725 } else { /* (insn & 0x00380080) == 0 */
4726 int invert;
4727
4728 op = (insn >> 8) & 0xf;
4729 /* One register and immediate. */
4730 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
4731 invert = (insn & (1 << 5)) != 0;
4732 switch (op) {
4733 case 0: case 1:
4734 /* no-op */
4735 break;
4736 case 2: case 3:
4737 imm <<= 8;
4738 break;
4739 case 4: case 5:
4740 imm <<= 16;
4741 break;
4742 case 6: case 7:
4743 imm <<= 24;
4744 break;
4745 case 8: case 9:
4746 imm |= imm << 16;
4747 break;
4748 case 10: case 11:
4749 imm = (imm << 8) | (imm << 24);
4750 break;
4751 case 12:
4752 imm = (imm < 8) | 0xff;
4753 break;
4754 case 13:
4755 imm = (imm << 16) | 0xffff;
4756 break;
4757 case 14:
4758 imm |= (imm << 8) | (imm << 16) | (imm << 24);
4759 if (invert)
4760 imm = ~imm;
4761 break;
4762 case 15:
4763 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
4764 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
4765 break;
4766 }
4767 if (invert)
4768 imm = ~imm;
4769
4770 if (op != 14 || !invert)
4771 gen_op_movl_T1_im(imm);
4772
4773 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4774 if (op & 1 && op < 12) {
ad69471c 4775 tmp = neon_load_reg(rd, pass);
9ee6e8bb
PB
4776 if (invert) {
4777 /* The immediate value has already been inverted, so
4778 BIC becomes AND. */
ad69471c 4779 tcg_gen_andi_i32(tmp, tmp, imm);
9ee6e8bb 4780 } else {
ad69471c 4781 tcg_gen_ori_i32(tmp, tmp, imm);
9ee6e8bb 4782 }
9ee6e8bb 4783 } else {
ad69471c
PB
4784 /* VMOV, VMVN. */
4785 tmp = new_tmp();
9ee6e8bb 4786 if (op == 14 && invert) {
ad69471c
PB
4787 uint32_t val;
4788 val = 0;
9ee6e8bb
PB
4789 for (n = 0; n < 4; n++) {
4790 if (imm & (1 << (n + (pass & 1) * 4)))
ad69471c 4791 val |= 0xff << (n * 8);
9ee6e8bb 4792 }
ad69471c
PB
4793 tcg_gen_movi_i32(tmp, val);
4794 } else {
4795 tcg_gen_movi_i32(tmp, imm);
9ee6e8bb 4796 }
9ee6e8bb 4797 }
ad69471c 4798 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
4799 }
4800 }
e4b3861d 4801 } else { /* (insn & 0x00800010 == 0x00800000) */
9ee6e8bb
PB
4802 if (size != 3) {
4803 op = (insn >> 8) & 0xf;
4804 if ((insn & (1 << 6)) == 0) {
4805 /* Three registers of different lengths. */
4806 int src1_wide;
4807 int src2_wide;
4808 int prewiden;
4809 /* prewiden, src1_wide, src2_wide */
4810 static const int neon_3reg_wide[16][3] = {
4811 {1, 0, 0}, /* VADDL */
4812 {1, 1, 0}, /* VADDW */
4813 {1, 0, 0}, /* VSUBL */
4814 {1, 1, 0}, /* VSUBW */
4815 {0, 1, 1}, /* VADDHN */
4816 {0, 0, 0}, /* VABAL */
4817 {0, 1, 1}, /* VSUBHN */
4818 {0, 0, 0}, /* VABDL */
4819 {0, 0, 0}, /* VMLAL */
4820 {0, 0, 0}, /* VQDMLAL */
4821 {0, 0, 0}, /* VMLSL */
4822 {0, 0, 0}, /* VQDMLSL */
4823 {0, 0, 0}, /* Integer VMULL */
4824 {0, 0, 0}, /* VQDMULL */
4825 {0, 0, 0} /* Polynomial VMULL */
4826 };
4827
4828 prewiden = neon_3reg_wide[op][0];
4829 src1_wide = neon_3reg_wide[op][1];
4830 src2_wide = neon_3reg_wide[op][2];
4831
ad69471c
PB
4832 if (size == 0 && (op == 9 || op == 11 || op == 13))
4833 return 1;
4834
9ee6e8bb
PB
4835 /* Avoid overlapping operands. Wide source operands are
4836 always aligned so will never overlap with wide
4837 destinations in problematic ways. */
8f8e3aa4
PB
4838 if (rd == rm && !src2_wide) {
4839 NEON_GET_REG(T0, rm, 1);
4840 gen_neon_movl_scratch_T0(2);
4841 } else if (rd == rn && !src1_wide) {
4842 NEON_GET_REG(T0, rn, 1);
4843 gen_neon_movl_scratch_T0(2);
9ee6e8bb 4844 }
a50f5b91 4845 TCGV_UNUSED(tmp3);
9ee6e8bb 4846 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
4847 if (src1_wide) {
4848 neon_load_reg64(cpu_V0, rn + pass);
a50f5b91 4849 TCGV_UNUSED(tmp);
9ee6e8bb 4850 } else {
ad69471c
PB
4851 if (pass == 1 && rd == rn) {
4852 gen_neon_movl_T0_scratch(2);
4853 tmp = new_tmp();
4854 tcg_gen_mov_i32(tmp, cpu_T[0]);
9ee6e8bb 4855 } else {
ad69471c
PB
4856 tmp = neon_load_reg(rn, pass);
4857 }
4858 if (prewiden) {
4859 gen_neon_widen(cpu_V0, tmp, size, u);
9ee6e8bb
PB
4860 }
4861 }
ad69471c
PB
4862 if (src2_wide) {
4863 neon_load_reg64(cpu_V1, rm + pass);
a50f5b91 4864 TCGV_UNUSED(tmp2);
9ee6e8bb 4865 } else {
ad69471c 4866 if (pass == 1 && rd == rm) {
8f8e3aa4 4867 gen_neon_movl_T0_scratch(2);
ad69471c
PB
4868 tmp2 = new_tmp();
4869 tcg_gen_mov_i32(tmp2, cpu_T[0]);
9ee6e8bb 4870 } else {
ad69471c
PB
4871 tmp2 = neon_load_reg(rm, pass);
4872 }
4873 if (prewiden) {
4874 gen_neon_widen(cpu_V1, tmp2, size, u);
9ee6e8bb 4875 }
9ee6e8bb
PB
4876 }
4877 switch (op) {
4878 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
ad69471c 4879 gen_neon_addl(size);
9ee6e8bb
PB
4880 break;
4881 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
ad69471c 4882 gen_neon_subl(size);
9ee6e8bb
PB
4883 break;
4884 case 5: case 7: /* VABAL, VABDL */
4885 switch ((size << 1) | u) {
ad69471c
PB
4886 case 0:
4887 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
4888 break;
4889 case 1:
4890 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
4891 break;
4892 case 2:
4893 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
4894 break;
4895 case 3:
4896 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
4897 break;
4898 case 4:
4899 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
4900 break;
4901 case 5:
4902 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
4903 break;
9ee6e8bb
PB
4904 default: abort();
4905 }
ad69471c
PB
4906 dead_tmp(tmp2);
4907 dead_tmp(tmp);
9ee6e8bb
PB
4908 break;
4909 case 8: case 9: case 10: case 11: case 12: case 13:
4910 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
ad69471c 4911 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
9ee6e8bb
PB
4912 break;
4913 case 14: /* Polynomial VMULL */
4914 cpu_abort(env, "Polynomial VMULL not implemented");
4915
4916 default: /* 15 is RESERVED. */
4917 return 1;
4918 }
4919 if (op == 5 || op == 13 || (op >= 8 && op <= 11)) {
4920 /* Accumulate. */
4921 if (op == 10 || op == 11) {
ad69471c 4922 gen_neon_negl(cpu_V0, size);
9ee6e8bb
PB
4923 }
4924
9ee6e8bb 4925 if (op != 13) {
ad69471c 4926 neon_load_reg64(cpu_V1, rd + pass);
9ee6e8bb
PB
4927 }
4928
4929 switch (op) {
4930 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
ad69471c 4931 gen_neon_addl(size);
9ee6e8bb
PB
4932 break;
4933 case 9: case 11: /* VQDMLAL, VQDMLSL */
ad69471c
PB
4934 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4935 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
4936 break;
9ee6e8bb
PB
4937 /* Fall through. */
4938 case 13: /* VQDMULL */
ad69471c 4939 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
9ee6e8bb
PB
4940 break;
4941 default:
4942 abort();
4943 }
ad69471c 4944 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
4945 } else if (op == 4 || op == 6) {
4946 /* Narrowing operation. */
ad69471c 4947 tmp = new_tmp();
9ee6e8bb
PB
4948 if (u) {
4949 switch (size) {
ad69471c
PB
4950 case 0:
4951 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
4952 break;
4953 case 1:
4954 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
4955 break;
4956 case 2:
4957 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
4958 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
4959 break;
9ee6e8bb
PB
4960 default: abort();
4961 }
4962 } else {
4963 switch (size) {
ad69471c
PB
4964 case 0:
4965 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
4966 break;
4967 case 1:
4968 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
4969 break;
4970 case 2:
4971 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
4972 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
4973 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
4974 break;
9ee6e8bb
PB
4975 default: abort();
4976 }
4977 }
ad69471c
PB
4978 if (pass == 0) {
4979 tmp3 = tmp;
4980 } else {
4981 neon_store_reg(rd, 0, tmp3);
4982 neon_store_reg(rd, 1, tmp);
4983 }
9ee6e8bb
PB
4984 } else {
4985 /* Write back the result. */
ad69471c 4986 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
4987 }
4988 }
4989 } else {
4990 /* Two registers and a scalar. */
4991 switch (op) {
4992 case 0: /* Integer VMLA scalar */
4993 case 1: /* Float VMLA scalar */
4994 case 4: /* Integer VMLS scalar */
4995 case 5: /* Floating point VMLS scalar */
4996 case 8: /* Integer VMUL scalar */
4997 case 9: /* Floating point VMUL scalar */
4998 case 12: /* VQDMULH scalar */
4999 case 13: /* VQRDMULH scalar */
5000 gen_neon_get_scalar(size, rm);
8f8e3aa4 5001 gen_neon_movl_scratch_T0(0);
9ee6e8bb
PB
5002 for (pass = 0; pass < (u ? 4 : 2); pass++) {
5003 if (pass != 0)
8f8e3aa4 5004 gen_neon_movl_T0_scratch(0);
9ee6e8bb
PB
5005 NEON_GET_REG(T1, rn, pass);
5006 if (op == 12) {
5007 if (size == 1) {
ad69471c 5008 gen_helper_neon_qdmulh_s16(CPU_T0E01);
9ee6e8bb 5009 } else {
ad69471c 5010 gen_helper_neon_qdmulh_s32(CPU_T0E01);
9ee6e8bb
PB
5011 }
5012 } else if (op == 13) {
5013 if (size == 1) {
ad69471c 5014 gen_helper_neon_qrdmulh_s16(CPU_T0E01);
9ee6e8bb 5015 } else {
ad69471c 5016 gen_helper_neon_qrdmulh_s32(CPU_T0E01);
9ee6e8bb
PB
5017 }
5018 } else if (op & 1) {
ad69471c 5019 gen_helper_neon_mul_f32(CPU_T001);
9ee6e8bb
PB
5020 } else {
5021 switch (size) {
ad69471c
PB
5022 case 0: gen_helper_neon_mul_u8(CPU_T001); break;
5023 case 1: gen_helper_neon_mul_u16(CPU_T001); break;
9ee6e8bb
PB
5024 case 2: gen_op_mul_T0_T1(); break;
5025 default: return 1;
5026 }
5027 }
5028 if (op < 8) {
5029 /* Accumulate. */
5030 NEON_GET_REG(T1, rd, pass);
5031 switch (op) {
5032 case 0:
5033 gen_neon_add(size);
5034 break;
5035 case 1:
ad69471c 5036 gen_helper_neon_add_f32(CPU_T001);
9ee6e8bb
PB
5037 break;
5038 case 4:
ad69471c 5039 gen_neon_rsb(size);
9ee6e8bb
PB
5040 break;
5041 case 5:
ad69471c 5042 gen_helper_neon_sub_f32(cpu_T[0], cpu_T[1], cpu_T[0]);
9ee6e8bb
PB
5043 break;
5044 default:
5045 abort();
5046 }
5047 }
5048 NEON_SET_REG(T0, rd, pass);
5049 }
5050 break;
5051 case 2: /* VMLAL sclar */
5052 case 3: /* VQDMLAL scalar */
5053 case 6: /* VMLSL scalar */
5054 case 7: /* VQDMLSL scalar */
5055 case 10: /* VMULL scalar */
5056 case 11: /* VQDMULL scalar */
ad69471c
PB
5057 if (size == 0 && (op == 3 || op == 7 || op == 11))
5058 return 1;
5059
9ee6e8bb 5060 gen_neon_get_scalar(size, rm);
ad69471c
PB
5061 NEON_GET_REG(T1, rn, 1);
5062
9ee6e8bb 5063 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
5064 if (pass == 0) {
5065 tmp = neon_load_reg(rn, 0);
9ee6e8bb 5066 } else {
ad69471c
PB
5067 tmp = new_tmp();
5068 tcg_gen_mov_i32(tmp, cpu_T[1]);
9ee6e8bb 5069 }
ad69471c
PB
5070 tmp2 = new_tmp();
5071 tcg_gen_mov_i32(tmp2, cpu_T[0]);
5072 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
9ee6e8bb 5073 if (op == 6 || op == 7) {
ad69471c
PB
5074 gen_neon_negl(cpu_V0, size);
5075 }
5076 if (op != 11) {
5077 neon_load_reg64(cpu_V1, rd + pass);
9ee6e8bb 5078 }
9ee6e8bb
PB
5079 switch (op) {
5080 case 2: case 6:
ad69471c 5081 gen_neon_addl(size);
9ee6e8bb
PB
5082 break;
5083 case 3: case 7:
ad69471c
PB
5084 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5085 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
9ee6e8bb
PB
5086 break;
5087 case 10:
5088 /* no-op */
5089 break;
5090 case 11:
ad69471c 5091 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
9ee6e8bb
PB
5092 break;
5093 default:
5094 abort();
5095 }
ad69471c 5096 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
5097 }
5098 break;
5099 default: /* 14 and 15 are RESERVED */
5100 return 1;
5101 }
5102 }
5103 } else { /* size == 3 */
5104 if (!u) {
5105 /* Extract. */
9ee6e8bb 5106 imm = (insn >> 8) & 0xf;
ad69471c
PB
5107 count = q + 1;
5108
5109 if (imm > 7 && !q)
5110 return 1;
5111
5112 if (imm == 0) {
5113 neon_load_reg64(cpu_V0, rn);
5114 if (q) {
5115 neon_load_reg64(cpu_V1, rn + 1);
9ee6e8bb 5116 }
ad69471c
PB
5117 } else if (imm == 8) {
5118 neon_load_reg64(cpu_V0, rn + 1);
5119 if (q) {
5120 neon_load_reg64(cpu_V1, rm);
9ee6e8bb 5121 }
ad69471c 5122 } else if (q) {
a7812ae4 5123 tmp64 = tcg_temp_new_i64();
ad69471c
PB
5124 if (imm < 8) {
5125 neon_load_reg64(cpu_V0, rn);
a7812ae4 5126 neon_load_reg64(tmp64, rn + 1);
ad69471c
PB
5127 } else {
5128 neon_load_reg64(cpu_V0, rn + 1);
a7812ae4 5129 neon_load_reg64(tmp64, rm);
ad69471c
PB
5130 }
5131 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
a7812ae4 5132 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
ad69471c
PB
5133 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5134 if (imm < 8) {
5135 neon_load_reg64(cpu_V1, rm);
9ee6e8bb 5136 } else {
ad69471c
PB
5137 neon_load_reg64(cpu_V1, rm + 1);
5138 imm -= 8;
9ee6e8bb 5139 }
ad69471c 5140 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
a7812ae4
PB
5141 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
5142 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
ad69471c 5143 } else {
a7812ae4 5144 /* BUGFIX */
ad69471c 5145 neon_load_reg64(cpu_V0, rn);
a7812ae4 5146 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
ad69471c 5147 neon_load_reg64(cpu_V1, rm);
a7812ae4 5148 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
ad69471c
PB
5149 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5150 }
5151 neon_store_reg64(cpu_V0, rd);
5152 if (q) {
5153 neon_store_reg64(cpu_V1, rd + 1);
9ee6e8bb
PB
5154 }
5155 } else if ((insn & (1 << 11)) == 0) {
5156 /* Two register misc. */
5157 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
5158 size = (insn >> 18) & 3;
5159 switch (op) {
5160 case 0: /* VREV64 */
5161 if (size == 3)
5162 return 1;
5163 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5164 NEON_GET_REG(T0, rm, pass * 2);
5165 NEON_GET_REG(T1, rm, pass * 2 + 1);
5166 switch (size) {
66896cb8 5167 case 0: tcg_gen_bswap32_i32(cpu_T[0], cpu_T[0]); break;
8f01245e 5168 case 1: gen_swap_half(cpu_T[0]); break;
9ee6e8bb
PB
5169 case 2: /* no-op */ break;
5170 default: abort();
5171 }
5172 NEON_SET_REG(T0, rd, pass * 2 + 1);
5173 if (size == 2) {
5174 NEON_SET_REG(T1, rd, pass * 2);
5175 } else {
5176 gen_op_movl_T0_T1();
5177 switch (size) {
66896cb8 5178 case 0: tcg_gen_bswap32_i32(cpu_T[0], cpu_T[0]); break;
8f01245e 5179 case 1: gen_swap_half(cpu_T[0]); break;
9ee6e8bb
PB
5180 default: abort();
5181 }
5182 NEON_SET_REG(T0, rd, pass * 2);
5183 }
5184 }
5185 break;
5186 case 4: case 5: /* VPADDL */
5187 case 12: case 13: /* VPADAL */
9ee6e8bb
PB
5188 if (size == 3)
5189 return 1;
ad69471c
PB
5190 for (pass = 0; pass < q + 1; pass++) {
5191 tmp = neon_load_reg(rm, pass * 2);
5192 gen_neon_widen(cpu_V0, tmp, size, op & 1);
5193 tmp = neon_load_reg(rm, pass * 2 + 1);
5194 gen_neon_widen(cpu_V1, tmp, size, op & 1);
5195 switch (size) {
5196 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
5197 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
5198 case 2: tcg_gen_add_i64(CPU_V001); break;
5199 default: abort();
5200 }
9ee6e8bb
PB
5201 if (op >= 12) {
5202 /* Accumulate. */
ad69471c
PB
5203 neon_load_reg64(cpu_V1, rd + pass);
5204 gen_neon_addl(size);
9ee6e8bb 5205 }
ad69471c 5206 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
5207 }
5208 break;
5209 case 33: /* VTRN */
5210 if (size == 2) {
5211 for (n = 0; n < (q ? 4 : 2); n += 2) {
5212 NEON_GET_REG(T0, rm, n);
5213 NEON_GET_REG(T1, rd, n + 1);
5214 NEON_SET_REG(T1, rm, n);
5215 NEON_SET_REG(T0, rd, n + 1);
5216 }
5217 } else {
5218 goto elementwise;
5219 }
5220 break;
5221 case 34: /* VUZP */
5222 /* Reg Before After
5223 Rd A3 A2 A1 A0 B2 B0 A2 A0
5224 Rm B3 B2 B1 B0 B3 B1 A3 A1
5225 */
5226 if (size == 3)
5227 return 1;
5228 gen_neon_unzip(rd, q, 0, size);
5229 gen_neon_unzip(rm, q, 4, size);
5230 if (q) {
5231 static int unzip_order_q[8] =
5232 {0, 2, 4, 6, 1, 3, 5, 7};
5233 for (n = 0; n < 8; n++) {
5234 int reg = (n < 4) ? rd : rm;
5235 gen_neon_movl_T0_scratch(unzip_order_q[n]);
5236 NEON_SET_REG(T0, reg, n % 4);
5237 }
5238 } else {
5239 static int unzip_order[4] =
5240 {0, 4, 1, 5};
5241 for (n = 0; n < 4; n++) {
5242 int reg = (n < 2) ? rd : rm;
5243 gen_neon_movl_T0_scratch(unzip_order[n]);
5244 NEON_SET_REG(T0, reg, n % 2);
5245 }
5246 }
5247 break;
5248 case 35: /* VZIP */
5249 /* Reg Before After
5250 Rd A3 A2 A1 A0 B1 A1 B0 A0
5251 Rm B3 B2 B1 B0 B3 A3 B2 A2
5252 */
5253 if (size == 3)
5254 return 1;
5255 count = (q ? 4 : 2);
5256 for (n = 0; n < count; n++) {
5257 NEON_GET_REG(T0, rd, n);
5258 NEON_GET_REG(T1, rd, n);
5259 switch (size) {
ad69471c
PB
5260 case 0: gen_helper_neon_zip_u8(); break;
5261 case 1: gen_helper_neon_zip_u16(); break;
9ee6e8bb
PB
5262 case 2: /* no-op */; break;
5263 default: abort();
5264 }
5265 gen_neon_movl_scratch_T0(n * 2);
5266 gen_neon_movl_scratch_T1(n * 2 + 1);
5267 }
5268 for (n = 0; n < count * 2; n++) {
5269 int reg = (n < count) ? rd : rm;
5270 gen_neon_movl_T0_scratch(n);
5271 NEON_SET_REG(T0, reg, n % count);
5272 }
5273 break;
5274 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
ad69471c
PB
5275 if (size == 3)
5276 return 1;
a50f5b91 5277 TCGV_UNUSED(tmp2);
9ee6e8bb 5278 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
5279 neon_load_reg64(cpu_V0, rm + pass);
5280 tmp = new_tmp();
9ee6e8bb 5281 if (op == 36 && q == 0) {
ad69471c 5282 gen_neon_narrow(size, tmp, cpu_V0);
9ee6e8bb 5283 } else if (q) {
ad69471c 5284 gen_neon_narrow_satu(size, tmp, cpu_V0);
9ee6e8bb 5285 } else {
ad69471c
PB
5286 gen_neon_narrow_sats(size, tmp, cpu_V0);
5287 }
5288 if (pass == 0) {
5289 tmp2 = tmp;
5290 } else {
5291 neon_store_reg(rd, 0, tmp2);
5292 neon_store_reg(rd, 1, tmp);
9ee6e8bb 5293 }
9ee6e8bb
PB
5294 }
5295 break;
5296 case 38: /* VSHLL */
ad69471c 5297 if (q || size == 3)
9ee6e8bb 5298 return 1;
ad69471c
PB
5299 tmp = neon_load_reg(rm, 0);
5300 tmp2 = neon_load_reg(rm, 1);
9ee6e8bb 5301 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
5302 if (pass == 1)
5303 tmp = tmp2;
5304 gen_neon_widen(cpu_V0, tmp, size, 1);
5305 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
5306 }
5307 break;
5308 default:
5309 elementwise:
5310 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5311 if (op == 30 || op == 31 || op >= 58) {
4373f3ce
PB
5312 tcg_gen_ld_f32(cpu_F0s, cpu_env,
5313 neon_reg_offset(rm, pass));
9ee6e8bb
PB
5314 } else {
5315 NEON_GET_REG(T0, rm, pass);
5316 }
5317 switch (op) {
5318 case 1: /* VREV32 */
5319 switch (size) {
66896cb8 5320 case 0: tcg_gen_bswap32_i32(cpu_T[0], cpu_T[0]); break;
8f01245e 5321 case 1: gen_swap_half(cpu_T[0]); break;
9ee6e8bb
PB
5322 default: return 1;
5323 }
5324 break;
5325 case 2: /* VREV16 */
5326 if (size != 0)
5327 return 1;
3670669c 5328 gen_rev16(cpu_T[0]);
9ee6e8bb 5329 break;
9ee6e8bb
PB
5330 case 8: /* CLS */
5331 switch (size) {
ad69471c
PB
5332 case 0: gen_helper_neon_cls_s8(cpu_T[0], cpu_T[0]); break;
5333 case 1: gen_helper_neon_cls_s16(cpu_T[0], cpu_T[0]); break;
5334 case 2: gen_helper_neon_cls_s32(cpu_T[0], cpu_T[0]); break;
9ee6e8bb
PB
5335 default: return 1;
5336 }
5337 break;
5338 case 9: /* CLZ */
5339 switch (size) {
ad69471c
PB
5340 case 0: gen_helper_neon_clz_u8(cpu_T[0], cpu_T[0]); break;
5341 case 1: gen_helper_neon_clz_u16(cpu_T[0], cpu_T[0]); break;
1497c961 5342 case 2: gen_helper_clz(cpu_T[0], cpu_T[0]); break;
9ee6e8bb
PB
5343 default: return 1;
5344 }
5345 break;
5346 case 10: /* CNT */
5347 if (size != 0)
5348 return 1;
ad69471c 5349 gen_helper_neon_cnt_u8(cpu_T[0], cpu_T[0]);
9ee6e8bb
PB
5350 break;
5351 case 11: /* VNOT */
5352 if (size != 0)
5353 return 1;
5354 gen_op_notl_T0();
5355 break;
5356 case 14: /* VQABS */
5357 switch (size) {
ad69471c
PB
5358 case 0: gen_helper_neon_qabs_s8(cpu_T[0], cpu_env, cpu_T[0]); break;
5359 case 1: gen_helper_neon_qabs_s16(cpu_T[0], cpu_env, cpu_T[0]); break;
5360 case 2: gen_helper_neon_qabs_s32(cpu_T[0], cpu_env, cpu_T[0]); break;
9ee6e8bb
PB
5361 default: return 1;
5362 }
5363 break;
5364 case 15: /* VQNEG */
5365 switch (size) {
ad69471c
PB
5366 case 0: gen_helper_neon_qneg_s8(cpu_T[0], cpu_env, cpu_T[0]); break;
5367 case 1: gen_helper_neon_qneg_s16(cpu_T[0], cpu_env, cpu_T[0]); break;
5368 case 2: gen_helper_neon_qneg_s32(cpu_T[0], cpu_env, cpu_T[0]); break;
9ee6e8bb
PB
5369 default: return 1;
5370 }
5371 break;
5372 case 16: case 19: /* VCGT #0, VCLE #0 */
5373 gen_op_movl_T1_im(0);
5374 switch(size) {
ad69471c
PB
5375 case 0: gen_helper_neon_cgt_s8(CPU_T001); break;
5376 case 1: gen_helper_neon_cgt_s16(CPU_T001); break;
5377 case 2: gen_helper_neon_cgt_s32(CPU_T001); break;
9ee6e8bb
PB
5378 default: return 1;
5379 }
5380 if (op == 19)
5381 gen_op_notl_T0();
5382 break;
5383 case 17: case 20: /* VCGE #0, VCLT #0 */
5384 gen_op_movl_T1_im(0);
5385 switch(size) {
ad69471c
PB
5386 case 0: gen_helper_neon_cge_s8(CPU_T001); break;
5387 case 1: gen_helper_neon_cge_s16(CPU_T001); break;
5388 case 2: gen_helper_neon_cge_s32(CPU_T001); break;
9ee6e8bb
PB
5389 default: return 1;
5390 }
5391 if (op == 20)
5392 gen_op_notl_T0();
5393 break;
5394 case 18: /* VCEQ #0 */
5395 gen_op_movl_T1_im(0);
5396 switch(size) {
ad69471c
PB
5397 case 0: gen_helper_neon_ceq_u8(CPU_T001); break;
5398 case 1: gen_helper_neon_ceq_u16(CPU_T001); break;
5399 case 2: gen_helper_neon_ceq_u32(CPU_T001); break;
9ee6e8bb
PB
5400 default: return 1;
5401 }
5402 break;
5403 case 22: /* VABS */
5404 switch(size) {
ad69471c
PB
5405 case 0: gen_helper_neon_abs_s8(cpu_T[0], cpu_T[0]); break;
5406 case 1: gen_helper_neon_abs_s16(cpu_T[0], cpu_T[0]); break;
5407 case 2: tcg_gen_abs_i32(cpu_T[0], cpu_T[0]); break;
9ee6e8bb
PB
5408 default: return 1;
5409 }
5410 break;
5411 case 23: /* VNEG */
5412 gen_op_movl_T1_im(0);
ad69471c
PB
5413 if (size == 3)
5414 return 1;
5415 gen_neon_rsb(size);
9ee6e8bb
PB
5416 break;
5417 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5418 gen_op_movl_T1_im(0);
ad69471c 5419 gen_helper_neon_cgt_f32(CPU_T001);
9ee6e8bb
PB
5420 if (op == 27)
5421 gen_op_notl_T0();
5422 break;
5423 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5424 gen_op_movl_T1_im(0);
ad69471c 5425 gen_helper_neon_cge_f32(CPU_T001);
9ee6e8bb
PB
5426 if (op == 28)
5427 gen_op_notl_T0();
5428 break;
5429 case 26: /* Float VCEQ #0 */
5430 gen_op_movl_T1_im(0);
ad69471c 5431 gen_helper_neon_ceq_f32(CPU_T001);
9ee6e8bb
PB
5432 break;
5433 case 30: /* Float VABS */
4373f3ce 5434 gen_vfp_abs(0);
9ee6e8bb
PB
5435 break;
5436 case 31: /* Float VNEG */
4373f3ce 5437 gen_vfp_neg(0);
9ee6e8bb
PB
5438 break;
5439 case 32: /* VSWP */
5440 NEON_GET_REG(T1, rd, pass);
5441 NEON_SET_REG(T1, rm, pass);
5442 break;
5443 case 33: /* VTRN */
5444 NEON_GET_REG(T1, rd, pass);
5445 switch (size) {
ad69471c
PB
5446 case 0: gen_helper_neon_trn_u8(); break;
5447 case 1: gen_helper_neon_trn_u16(); break;
9ee6e8bb
PB
5448 case 2: abort();
5449 default: return 1;
5450 }
5451 NEON_SET_REG(T1, rm, pass);
5452 break;
5453 case 56: /* Integer VRECPE */
4373f3ce 5454 gen_helper_recpe_u32(cpu_T[0], cpu_T[0], cpu_env);
9ee6e8bb
PB
5455 break;
5456 case 57: /* Integer VRSQRTE */
4373f3ce 5457 gen_helper_rsqrte_u32(cpu_T[0], cpu_T[0], cpu_env);
9ee6e8bb
PB
5458 break;
5459 case 58: /* Float VRECPE */
4373f3ce 5460 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
9ee6e8bb
PB
5461 break;
5462 case 59: /* Float VRSQRTE */
4373f3ce 5463 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
9ee6e8bb
PB
5464 break;
5465 case 60: /* VCVT.F32.S32 */
4373f3ce 5466 gen_vfp_tosiz(0);
9ee6e8bb
PB
5467 break;
5468 case 61: /* VCVT.F32.U32 */
4373f3ce 5469 gen_vfp_touiz(0);
9ee6e8bb
PB
5470 break;
5471 case 62: /* VCVT.S32.F32 */
4373f3ce 5472 gen_vfp_sito(0);
9ee6e8bb
PB
5473 break;
5474 case 63: /* VCVT.U32.F32 */
4373f3ce 5475 gen_vfp_uito(0);
9ee6e8bb
PB
5476 break;
5477 default:
5478 /* Reserved: 21, 29, 39-56 */
5479 return 1;
5480 }
5481 if (op == 30 || op == 31 || op >= 58) {
4373f3ce
PB
5482 tcg_gen_st_f32(cpu_F0s, cpu_env,
5483 neon_reg_offset(rd, pass));
9ee6e8bb
PB
5484 } else {
5485 NEON_SET_REG(T0, rd, pass);
5486 }
5487 }
5488 break;
5489 }
5490 } else if ((insn & (1 << 10)) == 0) {
5491 /* VTBL, VTBX. */
3018f259 5492 n = ((insn >> 5) & 0x18) + 8;
9ee6e8bb 5493 if (insn & (1 << 6)) {
8f8e3aa4 5494 tmp = neon_load_reg(rd, 0);
9ee6e8bb 5495 } else {
8f8e3aa4
PB
5496 tmp = new_tmp();
5497 tcg_gen_movi_i32(tmp, 0);
9ee6e8bb 5498 }
8f8e3aa4
PB
5499 tmp2 = neon_load_reg(rm, 0);
5500 gen_helper_neon_tbl(tmp2, tmp2, tmp, tcg_const_i32(rn),
5501 tcg_const_i32(n));
3018f259 5502 dead_tmp(tmp);
9ee6e8bb 5503 if (insn & (1 << 6)) {
8f8e3aa4 5504 tmp = neon_load_reg(rd, 1);
9ee6e8bb 5505 } else {
8f8e3aa4
PB
5506 tmp = new_tmp();
5507 tcg_gen_movi_i32(tmp, 0);
9ee6e8bb 5508 }
8f8e3aa4
PB
5509 tmp3 = neon_load_reg(rm, 1);
5510 gen_helper_neon_tbl(tmp3, tmp3, tmp, tcg_const_i32(rn),
5511 tcg_const_i32(n));
5512 neon_store_reg(rd, 0, tmp2);
3018f259
PB
5513 neon_store_reg(rd, 1, tmp3);
5514 dead_tmp(tmp);
9ee6e8bb
PB
5515 } else if ((insn & 0x380) == 0) {
5516 /* VDUP */
5517 if (insn & (1 << 19)) {
5518 NEON_SET_REG(T0, rm, 1);
5519 } else {
5520 NEON_SET_REG(T0, rm, 0);
5521 }
5522 if (insn & (1 << 16)) {
ad69471c 5523 gen_neon_dup_u8(cpu_T[0], ((insn >> 17) & 3) * 8);
9ee6e8bb
PB
5524 } else if (insn & (1 << 17)) {
5525 if ((insn >> 18) & 1)
ad69471c 5526 gen_neon_dup_high16(cpu_T[0]);
9ee6e8bb 5527 else
ad69471c 5528 gen_neon_dup_low16(cpu_T[0]);
9ee6e8bb
PB
5529 }
5530 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5531 NEON_SET_REG(T0, rd, pass);
5532 }
5533 } else {
5534 return 1;
5535 }
5536 }
5537 }
5538 return 0;
5539}
5540
fe1479c3
PB
5541static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
5542{
5543 int crn = (insn >> 16) & 0xf;
5544 int crm = insn & 0xf;
5545 int op1 = (insn >> 21) & 7;
5546 int op2 = (insn >> 5) & 7;
5547 int rt = (insn >> 12) & 0xf;
5548 TCGv tmp;
5549
5550 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5551 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5552 /* TEECR */
5553 if (IS_USER(s))
5554 return 1;
5555 tmp = load_cpu_field(teecr);
5556 store_reg(s, rt, tmp);
5557 return 0;
5558 }
5559 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5560 /* TEEHBR */
5561 if (IS_USER(s) && (env->teecr & 1))
5562 return 1;
5563 tmp = load_cpu_field(teehbr);
5564 store_reg(s, rt, tmp);
5565 return 0;
5566 }
5567 }
5568 fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5569 op1, crn, crm, op2);
5570 return 1;
5571}
5572
5573static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
5574{
5575 int crn = (insn >> 16) & 0xf;
5576 int crm = insn & 0xf;
5577 int op1 = (insn >> 21) & 7;
5578 int op2 = (insn >> 5) & 7;
5579 int rt = (insn >> 12) & 0xf;
5580 TCGv tmp;
5581
5582 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5583 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5584 /* TEECR */
5585 if (IS_USER(s))
5586 return 1;
5587 tmp = load_reg(s, rt);
5588 gen_helper_set_teecr(cpu_env, tmp);
5589 dead_tmp(tmp);
5590 return 0;
5591 }
5592 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5593 /* TEEHBR */
5594 if (IS_USER(s) && (env->teecr & 1))
5595 return 1;
5596 tmp = load_reg(s, rt);
5597 store_cpu_field(tmp, teehbr);
5598 return 0;
5599 }
5600 }
5601 fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5602 op1, crn, crm, op2);
5603 return 1;
5604}
5605
9ee6e8bb
PB
5606static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
5607{
5608 int cpnum;
5609
5610 cpnum = (insn >> 8) & 0xf;
5611 if (arm_feature(env, ARM_FEATURE_XSCALE)
5612 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
5613 return 1;
5614
5615 switch (cpnum) {
5616 case 0:
5617 case 1:
5618 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5619 return disas_iwmmxt_insn(env, s, insn);
5620 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
5621 return disas_dsp_insn(env, s, insn);
5622 }
5623 return 1;
5624 case 10:
5625 case 11:
5626 return disas_vfp_insn (env, s, insn);
fe1479c3
PB
5627 case 14:
5628 /* Coprocessors 7-15 are architecturally reserved by ARM.
5629 Unfortunately Intel decided to ignore this. */
5630 if (arm_feature(env, ARM_FEATURE_XSCALE))
5631 goto board;
5632 if (insn & (1 << 20))
5633 return disas_cp14_read(env, s, insn);
5634 else
5635 return disas_cp14_write(env, s, insn);
9ee6e8bb
PB
5636 case 15:
5637 return disas_cp15_insn (env, s, insn);
5638 default:
fe1479c3 5639 board:
9ee6e8bb
PB
5640 /* Unknown coprocessor. See if the board has hooked it. */
5641 return disas_cp_insn (env, s, insn);
5642 }
5643}
5644
5e3f878a
PB
5645
5646/* Store a 64-bit value to a register pair. Clobbers val. */
a7812ae4 5647static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
5e3f878a
PB
5648{
5649 TCGv tmp;
5650 tmp = new_tmp();
5651 tcg_gen_trunc_i64_i32(tmp, val);
5652 store_reg(s, rlow, tmp);
5653 tmp = new_tmp();
5654 tcg_gen_shri_i64(val, val, 32);
5655 tcg_gen_trunc_i64_i32(tmp, val);
5656 store_reg(s, rhigh, tmp);
5657}
5658
5659/* load a 32-bit value from a register and perform a 64-bit accumulate. */
a7812ae4 5660static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
5e3f878a 5661{
a7812ae4 5662 TCGv_i64 tmp;
5e3f878a
PB
5663 TCGv tmp2;
5664
36aa55dc 5665 /* Load value and extend to 64 bits. */
a7812ae4 5666 tmp = tcg_temp_new_i64();
5e3f878a
PB
5667 tmp2 = load_reg(s, rlow);
5668 tcg_gen_extu_i32_i64(tmp, tmp2);
5669 dead_tmp(tmp2);
5670 tcg_gen_add_i64(val, val, tmp);
5671}
5672
5673/* load and add a 64-bit value from a register pair. */
a7812ae4 5674static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
5e3f878a 5675{
a7812ae4 5676 TCGv_i64 tmp;
36aa55dc
PB
5677 TCGv tmpl;
5678 TCGv tmph;
5e3f878a
PB
5679
5680 /* Load 64-bit value rd:rn. */
36aa55dc
PB
5681 tmpl = load_reg(s, rlow);
5682 tmph = load_reg(s, rhigh);
a7812ae4 5683 tmp = tcg_temp_new_i64();
36aa55dc
PB
5684 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
5685 dead_tmp(tmpl);
5686 dead_tmp(tmph);
5e3f878a
PB
5687 tcg_gen_add_i64(val, val, tmp);
5688}
5689
5690/* Set N and Z flags from a 64-bit value. */
a7812ae4 5691static void gen_logicq_cc(TCGv_i64 val)
5e3f878a
PB
5692{
5693 TCGv tmp = new_tmp();
5694 gen_helper_logicq_cc(tmp, val);
6fbe23d5
PB
5695 gen_logic_CC(tmp);
5696 dead_tmp(tmp);
5e3f878a
PB
5697}
5698
9ee6e8bb
PB
5699static void disas_arm_insn(CPUState * env, DisasContext *s)
5700{
5701 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
b26eefb6 5702 TCGv tmp;
3670669c 5703 TCGv tmp2;
6ddbc6e4 5704 TCGv tmp3;
b0109805 5705 TCGv addr;
a7812ae4 5706 TCGv_i64 tmp64;
9ee6e8bb
PB
5707
5708 insn = ldl_code(s->pc);
5709 s->pc += 4;
5710
5711 /* M variants do not implement ARM mode. */
5712 if (IS_M(env))
5713 goto illegal_op;
5714 cond = insn >> 28;
5715 if (cond == 0xf){
5716 /* Unconditional instructions. */
5717 if (((insn >> 25) & 7) == 1) {
5718 /* NEON Data processing. */
5719 if (!arm_feature(env, ARM_FEATURE_NEON))
5720 goto illegal_op;
5721
5722 if (disas_neon_data_insn(env, s, insn))
5723 goto illegal_op;
5724 return;
5725 }
5726 if ((insn & 0x0f100000) == 0x04000000) {
5727 /* NEON load/store. */
5728 if (!arm_feature(env, ARM_FEATURE_NEON))
5729 goto illegal_op;
5730
5731 if (disas_neon_ls_insn(env, s, insn))
5732 goto illegal_op;
5733 return;
5734 }
5735 if ((insn & 0x0d70f000) == 0x0550f000)
5736 return; /* PLD */
5737 else if ((insn & 0x0ffffdff) == 0x01010000) {
5738 ARCH(6);
5739 /* setend */
5740 if (insn & (1 << 9)) {
5741 /* BE8 mode not implemented. */
5742 goto illegal_op;
5743 }
5744 return;
5745 } else if ((insn & 0x0fffff00) == 0x057ff000) {
5746 switch ((insn >> 4) & 0xf) {
5747 case 1: /* clrex */
5748 ARCH(6K);
8f8e3aa4 5749 gen_helper_clrex(cpu_env);
9ee6e8bb
PB
5750 return;
5751 case 4: /* dsb */
5752 case 5: /* dmb */
5753 case 6: /* isb */
5754 ARCH(7);
5755 /* We don't emulate caches so these are a no-op. */
5756 return;
5757 default:
5758 goto illegal_op;
5759 }
5760 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
5761 /* srs */
c67b6b71 5762 int32_t offset;
9ee6e8bb
PB
5763 if (IS_USER(s))
5764 goto illegal_op;
5765 ARCH(6);
5766 op1 = (insn & 0x1f);
5767 if (op1 == (env->uncached_cpsr & CPSR_M)) {
b0109805 5768 addr = load_reg(s, 13);
9ee6e8bb 5769 } else {
b0109805
PB
5770 addr = new_tmp();
5771 gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op1));
9ee6e8bb
PB
5772 }
5773 i = (insn >> 23) & 3;
5774 switch (i) {
5775 case 0: offset = -4; break; /* DA */
c67b6b71
FN
5776 case 1: offset = 0; break; /* IA */
5777 case 2: offset = -8; break; /* DB */
9ee6e8bb
PB
5778 case 3: offset = 4; break; /* IB */
5779 default: abort();
5780 }
5781 if (offset)
b0109805
PB
5782 tcg_gen_addi_i32(addr, addr, offset);
5783 tmp = load_reg(s, 14);
5784 gen_st32(tmp, addr, 0);
c67b6b71 5785 tmp = load_cpu_field(spsr);
b0109805
PB
5786 tcg_gen_addi_i32(addr, addr, 4);
5787 gen_st32(tmp, addr, 0);
9ee6e8bb
PB
5788 if (insn & (1 << 21)) {
5789 /* Base writeback. */
5790 switch (i) {
5791 case 0: offset = -8; break;
c67b6b71
FN
5792 case 1: offset = 4; break;
5793 case 2: offset = -4; break;
9ee6e8bb
PB
5794 case 3: offset = 0; break;
5795 default: abort();
5796 }
5797 if (offset)
c67b6b71 5798 tcg_gen_addi_i32(addr, addr, offset);
9ee6e8bb 5799 if (op1 == (env->uncached_cpsr & CPSR_M)) {
c67b6b71 5800 store_reg(s, 13, addr);
9ee6e8bb 5801 } else {
c67b6b71
FN
5802 gen_helper_set_r13_banked(cpu_env, tcg_const_i32(op1), addr);
5803 dead_tmp(addr);
9ee6e8bb 5804 }
b0109805
PB
5805 } else {
5806 dead_tmp(addr);
9ee6e8bb
PB
5807 }
5808 } else if ((insn & 0x0e5fffe0) == 0x081d0a00) {
5809 /* rfe */
c67b6b71 5810 int32_t offset;
9ee6e8bb
PB
5811 if (IS_USER(s))
5812 goto illegal_op;
5813 ARCH(6);
5814 rn = (insn >> 16) & 0xf;
b0109805 5815 addr = load_reg(s, rn);
9ee6e8bb
PB
5816 i = (insn >> 23) & 3;
5817 switch (i) {
b0109805 5818 case 0: offset = -4; break; /* DA */
c67b6b71
FN
5819 case 1: offset = 0; break; /* IA */
5820 case 2: offset = -8; break; /* DB */
b0109805 5821 case 3: offset = 4; break; /* IB */
9ee6e8bb
PB
5822 default: abort();
5823 }
5824 if (offset)
b0109805
PB
5825 tcg_gen_addi_i32(addr, addr, offset);
5826 /* Load PC into tmp and CPSR into tmp2. */
5827 tmp = gen_ld32(addr, 0);
5828 tcg_gen_addi_i32(addr, addr, 4);
5829 tmp2 = gen_ld32(addr, 0);
9ee6e8bb
PB
5830 if (insn & (1 << 21)) {
5831 /* Base writeback. */
5832 switch (i) {
b0109805 5833 case 0: offset = -8; break;
c67b6b71
FN
5834 case 1: offset = 4; break;
5835 case 2: offset = -4; break;
b0109805 5836 case 3: offset = 0; break;
9ee6e8bb
PB
5837 default: abort();
5838 }
5839 if (offset)
b0109805
PB
5840 tcg_gen_addi_i32(addr, addr, offset);
5841 store_reg(s, rn, addr);
5842 } else {
5843 dead_tmp(addr);
9ee6e8bb 5844 }
b0109805 5845 gen_rfe(s, tmp, tmp2);
c67b6b71 5846 return;
9ee6e8bb
PB
5847 } else if ((insn & 0x0e000000) == 0x0a000000) {
5848 /* branch link and change to thumb (blx <offset>) */
5849 int32_t offset;
5850
5851 val = (uint32_t)s->pc;
d9ba4830
PB
5852 tmp = new_tmp();
5853 tcg_gen_movi_i32(tmp, val);
5854 store_reg(s, 14, tmp);
9ee6e8bb
PB
5855 /* Sign-extend the 24-bit offset */
5856 offset = (((int32_t)insn) << 8) >> 8;
5857 /* offset * 4 + bit24 * 2 + (thumb bit) */
5858 val += (offset << 2) | ((insn >> 23) & 2) | 1;
5859 /* pipeline offset */
5860 val += 4;
d9ba4830 5861 gen_bx_im(s, val);
9ee6e8bb
PB
5862 return;
5863 } else if ((insn & 0x0e000f00) == 0x0c000100) {
5864 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5865 /* iWMMXt register transfer. */
5866 if (env->cp15.c15_cpar & (1 << 1))
5867 if (!disas_iwmmxt_insn(env, s, insn))
5868 return;
5869 }
5870 } else if ((insn & 0x0fe00000) == 0x0c400000) {
5871 /* Coprocessor double register transfer. */
5872 } else if ((insn & 0x0f000010) == 0x0e000010) {
5873 /* Additional coprocessor register transfer. */
7997d92f 5874 } else if ((insn & 0x0ff10020) == 0x01000000) {
9ee6e8bb
PB
5875 uint32_t mask;
5876 uint32_t val;
5877 /* cps (privileged) */
5878 if (IS_USER(s))
5879 return;
5880 mask = val = 0;
5881 if (insn & (1 << 19)) {
5882 if (insn & (1 << 8))
5883 mask |= CPSR_A;
5884 if (insn & (1 << 7))
5885 mask |= CPSR_I;
5886 if (insn & (1 << 6))
5887 mask |= CPSR_F;
5888 if (insn & (1 << 18))
5889 val |= mask;
5890 }
7997d92f 5891 if (insn & (1 << 17)) {
9ee6e8bb
PB
5892 mask |= CPSR_M;
5893 val |= (insn & 0x1f);
5894 }
5895 if (mask) {
2fbac54b 5896 gen_set_psr_im(s, mask, 0, val);
9ee6e8bb
PB
5897 }
5898 return;
5899 }
5900 goto illegal_op;
5901 }
5902 if (cond != 0xe) {
5903 /* if not always execute, we generate a conditional jump to
5904 next instruction */
5905 s->condlabel = gen_new_label();
d9ba4830 5906 gen_test_cc(cond ^ 1, s->condlabel);
9ee6e8bb
PB
5907 s->condjmp = 1;
5908 }
5909 if ((insn & 0x0f900000) == 0x03000000) {
5910 if ((insn & (1 << 21)) == 0) {
5911 ARCH(6T2);
5912 rd = (insn >> 12) & 0xf;
5913 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
5914 if ((insn & (1 << 22)) == 0) {
5915 /* MOVW */
5e3f878a
PB
5916 tmp = new_tmp();
5917 tcg_gen_movi_i32(tmp, val);
9ee6e8bb
PB
5918 } else {
5919 /* MOVT */
5e3f878a 5920 tmp = load_reg(s, rd);
86831435 5921 tcg_gen_ext16u_i32(tmp, tmp);
5e3f878a 5922 tcg_gen_ori_i32(tmp, tmp, val << 16);
9ee6e8bb 5923 }
5e3f878a 5924 store_reg(s, rd, tmp);
9ee6e8bb
PB
5925 } else {
5926 if (((insn >> 12) & 0xf) != 0xf)
5927 goto illegal_op;
5928 if (((insn >> 16) & 0xf) == 0) {
5929 gen_nop_hint(s, insn & 0xff);
5930 } else {
5931 /* CPSR = immediate */
5932 val = insn & 0xff;
5933 shift = ((insn >> 8) & 0xf) * 2;
5934 if (shift)
5935 val = (val >> shift) | (val << (32 - shift));
9ee6e8bb 5936 i = ((insn & (1 << 22)) != 0);
2fbac54b 5937 if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
9ee6e8bb
PB
5938 goto illegal_op;
5939 }
5940 }
5941 } else if ((insn & 0x0f900000) == 0x01000000
5942 && (insn & 0x00000090) != 0x00000090) {
5943 /* miscellaneous instructions */
5944 op1 = (insn >> 21) & 3;
5945 sh = (insn >> 4) & 0xf;
5946 rm = insn & 0xf;
5947 switch (sh) {
5948 case 0x0: /* move program status register */
5949 if (op1 & 1) {
5950 /* PSR = reg */
2fbac54b 5951 tmp = load_reg(s, rm);
9ee6e8bb 5952 i = ((op1 & 2) != 0);
2fbac54b 5953 if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
9ee6e8bb
PB
5954 goto illegal_op;
5955 } else {
5956 /* reg = PSR */
5957 rd = (insn >> 12) & 0xf;
5958 if (op1 & 2) {
5959 if (IS_USER(s))
5960 goto illegal_op;
d9ba4830 5961 tmp = load_cpu_field(spsr);
9ee6e8bb 5962 } else {
d9ba4830
PB
5963 tmp = new_tmp();
5964 gen_helper_cpsr_read(tmp);
9ee6e8bb 5965 }
d9ba4830 5966 store_reg(s, rd, tmp);
9ee6e8bb
PB
5967 }
5968 break;
5969 case 0x1:
5970 if (op1 == 1) {
5971 /* branch/exchange thumb (bx). */
d9ba4830
PB
5972 tmp = load_reg(s, rm);
5973 gen_bx(s, tmp);
9ee6e8bb
PB
5974 } else if (op1 == 3) {
5975 /* clz */
5976 rd = (insn >> 12) & 0xf;
1497c961
PB
5977 tmp = load_reg(s, rm);
5978 gen_helper_clz(tmp, tmp);
5979 store_reg(s, rd, tmp);
9ee6e8bb
PB
5980 } else {
5981 goto illegal_op;
5982 }
5983 break;
5984 case 0x2:
5985 if (op1 == 1) {
5986 ARCH(5J); /* bxj */
5987 /* Trivial implementation equivalent to bx. */
d9ba4830
PB
5988 tmp = load_reg(s, rm);
5989 gen_bx(s, tmp);
9ee6e8bb
PB
5990 } else {
5991 goto illegal_op;
5992 }
5993 break;
5994 case 0x3:
5995 if (op1 != 1)
5996 goto illegal_op;
5997
5998 /* branch link/exchange thumb (blx) */
d9ba4830
PB
5999 tmp = load_reg(s, rm);
6000 tmp2 = new_tmp();
6001 tcg_gen_movi_i32(tmp2, s->pc);
6002 store_reg(s, 14, tmp2);
6003 gen_bx(s, tmp);
9ee6e8bb
PB
6004 break;
6005 case 0x5: /* saturating add/subtract */
6006 rd = (insn >> 12) & 0xf;
6007 rn = (insn >> 16) & 0xf;
b40d0353 6008 tmp = load_reg(s, rm);
5e3f878a 6009 tmp2 = load_reg(s, rn);
9ee6e8bb 6010 if (op1 & 2)
5e3f878a 6011 gen_helper_double_saturate(tmp2, tmp2);
9ee6e8bb 6012 if (op1 & 1)
5e3f878a 6013 gen_helper_sub_saturate(tmp, tmp, tmp2);
9ee6e8bb 6014 else
5e3f878a
PB
6015 gen_helper_add_saturate(tmp, tmp, tmp2);
6016 dead_tmp(tmp2);
6017 store_reg(s, rd, tmp);
9ee6e8bb
PB
6018 break;
6019 case 7: /* bkpt */
6020 gen_set_condexec(s);
5e3f878a 6021 gen_set_pc_im(s->pc - 4);
d9ba4830 6022 gen_exception(EXCP_BKPT);
9ee6e8bb
PB
6023 s->is_jmp = DISAS_JUMP;
6024 break;
6025 case 0x8: /* signed multiply */
6026 case 0xa:
6027 case 0xc:
6028 case 0xe:
6029 rs = (insn >> 8) & 0xf;
6030 rn = (insn >> 12) & 0xf;
6031 rd = (insn >> 16) & 0xf;
6032 if (op1 == 1) {
6033 /* (32 * 16) >> 16 */
5e3f878a
PB
6034 tmp = load_reg(s, rm);
6035 tmp2 = load_reg(s, rs);
9ee6e8bb 6036 if (sh & 4)
5e3f878a 6037 tcg_gen_sari_i32(tmp2, tmp2, 16);
9ee6e8bb 6038 else
5e3f878a 6039 gen_sxth(tmp2);
a7812ae4
PB
6040 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6041 tcg_gen_shri_i64(tmp64, tmp64, 16);
5e3f878a 6042 tmp = new_tmp();
a7812ae4 6043 tcg_gen_trunc_i64_i32(tmp, tmp64);
9ee6e8bb 6044 if ((sh & 2) == 0) {
5e3f878a
PB
6045 tmp2 = load_reg(s, rn);
6046 gen_helper_add_setq(tmp, tmp, tmp2);
6047 dead_tmp(tmp2);
9ee6e8bb 6048 }
5e3f878a 6049 store_reg(s, rd, tmp);
9ee6e8bb
PB
6050 } else {
6051 /* 16 * 16 */
5e3f878a
PB
6052 tmp = load_reg(s, rm);
6053 tmp2 = load_reg(s, rs);
6054 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
6055 dead_tmp(tmp2);
9ee6e8bb 6056 if (op1 == 2) {
a7812ae4
PB
6057 tmp64 = tcg_temp_new_i64();
6058 tcg_gen_ext_i32_i64(tmp64, tmp);
22478e79 6059 dead_tmp(tmp);
a7812ae4
PB
6060 gen_addq(s, tmp64, rn, rd);
6061 gen_storeq_reg(s, rn, rd, tmp64);
9ee6e8bb
PB
6062 } else {
6063 if (op1 == 0) {
5e3f878a
PB
6064 tmp2 = load_reg(s, rn);
6065 gen_helper_add_setq(tmp, tmp, tmp2);
6066 dead_tmp(tmp2);
9ee6e8bb 6067 }
5e3f878a 6068 store_reg(s, rd, tmp);
9ee6e8bb
PB
6069 }
6070 }
6071 break;
6072 default:
6073 goto illegal_op;
6074 }
6075 } else if (((insn & 0x0e000000) == 0 &&
6076 (insn & 0x00000090) != 0x90) ||
6077 ((insn & 0x0e000000) == (1 << 25))) {
6078 int set_cc, logic_cc, shiftop;
6079
6080 op1 = (insn >> 21) & 0xf;
6081 set_cc = (insn >> 20) & 1;
6082 logic_cc = table_logic_cc[op1] & set_cc;
6083
6084 /* data processing instruction */
6085 if (insn & (1 << 25)) {
6086 /* immediate operand */
6087 val = insn & 0xff;
6088 shift = ((insn >> 8) & 0xf) * 2;
e9bb4aa9 6089 if (shift) {
9ee6e8bb 6090 val = (val >> shift) | (val << (32 - shift));
e9bb4aa9
JR
6091 }
6092 tmp2 = new_tmp();
6093 tcg_gen_movi_i32(tmp2, val);
6094 if (logic_cc && shift) {
6095 gen_set_CF_bit31(tmp2);
6096 }
9ee6e8bb
PB
6097 } else {
6098 /* register */
6099 rm = (insn) & 0xf;
e9bb4aa9 6100 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
6101 shiftop = (insn >> 5) & 3;
6102 if (!(insn & (1 << 4))) {
6103 shift = (insn >> 7) & 0x1f;
e9bb4aa9 6104 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
9ee6e8bb
PB
6105 } else {
6106 rs = (insn >> 8) & 0xf;
8984bd2e 6107 tmp = load_reg(s, rs);
e9bb4aa9 6108 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
9ee6e8bb
PB
6109 }
6110 }
6111 if (op1 != 0x0f && op1 != 0x0d) {
6112 rn = (insn >> 16) & 0xf;
e9bb4aa9
JR
6113 tmp = load_reg(s, rn);
6114 } else {
6115 TCGV_UNUSED(tmp);
9ee6e8bb
PB
6116 }
6117 rd = (insn >> 12) & 0xf;
6118 switch(op1) {
6119 case 0x00:
e9bb4aa9
JR
6120 tcg_gen_and_i32(tmp, tmp, tmp2);
6121 if (logic_cc) {
6122 gen_logic_CC(tmp);
6123 }
21aeb343 6124 store_reg_bx(env, s, rd, tmp);
9ee6e8bb
PB
6125 break;
6126 case 0x01:
e9bb4aa9
JR
6127 tcg_gen_xor_i32(tmp, tmp, tmp2);
6128 if (logic_cc) {
6129 gen_logic_CC(tmp);
6130 }
21aeb343 6131 store_reg_bx(env, s, rd, tmp);
9ee6e8bb
PB
6132 break;
6133 case 0x02:
6134 if (set_cc && rd == 15) {
6135 /* SUBS r15, ... is used for exception return. */
e9bb4aa9 6136 if (IS_USER(s)) {
9ee6e8bb 6137 goto illegal_op;
e9bb4aa9
JR
6138 }
6139 gen_helper_sub_cc(tmp, tmp, tmp2);
6140 gen_exception_return(s, tmp);
9ee6e8bb 6141 } else {
e9bb4aa9
JR
6142 if (set_cc) {
6143 gen_helper_sub_cc(tmp, tmp, tmp2);
6144 } else {
6145 tcg_gen_sub_i32(tmp, tmp, tmp2);
6146 }
21aeb343 6147 store_reg_bx(env, s, rd, tmp);
9ee6e8bb
PB
6148 }
6149 break;
6150 case 0x03:
e9bb4aa9
JR
6151 if (set_cc) {
6152 gen_helper_sub_cc(tmp, tmp2, tmp);
6153 } else {
6154 tcg_gen_sub_i32(tmp, tmp2, tmp);
6155 }
21aeb343 6156 store_reg_bx(env, s, rd, tmp);
9ee6e8bb
PB
6157 break;
6158 case 0x04:
e9bb4aa9
JR
6159 if (set_cc) {
6160 gen_helper_add_cc(tmp, tmp, tmp2);
6161 } else {
6162 tcg_gen_add_i32(tmp, tmp, tmp2);
6163 }
21aeb343 6164 store_reg_bx(env, s, rd, tmp);
9ee6e8bb
PB
6165 break;
6166 case 0x05:
e9bb4aa9
JR
6167 if (set_cc) {
6168 gen_helper_adc_cc(tmp, tmp, tmp2);
6169 } else {
6170 gen_add_carry(tmp, tmp, tmp2);
6171 }
21aeb343 6172 store_reg_bx(env, s, rd, tmp);
9ee6e8bb
PB
6173 break;
6174 case 0x06:
e9bb4aa9
JR
6175 if (set_cc) {
6176 gen_helper_sbc_cc(tmp, tmp, tmp2);
6177 } else {
6178 gen_sub_carry(tmp, tmp, tmp2);
6179 }
21aeb343 6180 store_reg_bx(env, s, rd, tmp);
9ee6e8bb
PB
6181 break;
6182 case 0x07:
e9bb4aa9
JR
6183 if (set_cc) {
6184 gen_helper_sbc_cc(tmp, tmp2, tmp);
6185 } else {
6186 gen_sub_carry(tmp, tmp2, tmp);
6187 }
21aeb343 6188 store_reg_bx(env, s, rd, tmp);
9ee6e8bb
PB
6189 break;
6190 case 0x08:
6191 if (set_cc) {
e9bb4aa9
JR
6192 tcg_gen_and_i32(tmp, tmp, tmp2);
6193 gen_logic_CC(tmp);
9ee6e8bb 6194 }
e9bb4aa9 6195 dead_tmp(tmp);
9ee6e8bb
PB
6196 break;
6197 case 0x09:
6198 if (set_cc) {
e9bb4aa9
JR
6199 tcg_gen_xor_i32(tmp, tmp, tmp2);
6200 gen_logic_CC(tmp);
9ee6e8bb 6201 }
e9bb4aa9 6202 dead_tmp(tmp);
9ee6e8bb
PB
6203 break;
6204 case 0x0a:
6205 if (set_cc) {
e9bb4aa9 6206 gen_helper_sub_cc(tmp, tmp, tmp2);
9ee6e8bb 6207 }
e9bb4aa9 6208 dead_tmp(tmp);
9ee6e8bb
PB
6209 break;
6210 case 0x0b:
6211 if (set_cc) {
e9bb4aa9 6212 gen_helper_add_cc(tmp, tmp, tmp2);
9ee6e8bb 6213 }
e9bb4aa9 6214 dead_tmp(tmp);
9ee6e8bb
PB
6215 break;
6216 case 0x0c:
e9bb4aa9
JR
6217 tcg_gen_or_i32(tmp, tmp, tmp2);
6218 if (logic_cc) {
6219 gen_logic_CC(tmp);
6220 }
21aeb343 6221 store_reg_bx(env, s, rd, tmp);
9ee6e8bb
PB
6222 break;
6223 case 0x0d:
6224 if (logic_cc && rd == 15) {
6225 /* MOVS r15, ... is used for exception return. */
e9bb4aa9 6226 if (IS_USER(s)) {
9ee6e8bb 6227 goto illegal_op;
e9bb4aa9
JR
6228 }
6229 gen_exception_return(s, tmp2);
9ee6e8bb 6230 } else {
e9bb4aa9
JR
6231 if (logic_cc) {
6232 gen_logic_CC(tmp2);
6233 }
21aeb343 6234 store_reg_bx(env, s, rd, tmp2);
9ee6e8bb
PB
6235 }
6236 break;
6237 case 0x0e:
e9bb4aa9
JR
6238 tcg_gen_bic_i32(tmp, tmp, tmp2);
6239 if (logic_cc) {
6240 gen_logic_CC(tmp);
6241 }
21aeb343 6242 store_reg_bx(env, s, rd, tmp);
9ee6e8bb
PB
6243 break;
6244 default:
6245 case 0x0f:
e9bb4aa9
JR
6246 tcg_gen_not_i32(tmp2, tmp2);
6247 if (logic_cc) {
6248 gen_logic_CC(tmp2);
6249 }
21aeb343 6250 store_reg_bx(env, s, rd, tmp2);
9ee6e8bb
PB
6251 break;
6252 }
e9bb4aa9
JR
6253 if (op1 != 0x0f && op1 != 0x0d) {
6254 dead_tmp(tmp2);
6255 }
9ee6e8bb
PB
6256 } else {
6257 /* other instructions */
6258 op1 = (insn >> 24) & 0xf;
6259 switch(op1) {
6260 case 0x0:
6261 case 0x1:
6262 /* multiplies, extra load/stores */
6263 sh = (insn >> 5) & 3;
6264 if (sh == 0) {
6265 if (op1 == 0x0) {
6266 rd = (insn >> 16) & 0xf;
6267 rn = (insn >> 12) & 0xf;
6268 rs = (insn >> 8) & 0xf;
6269 rm = (insn) & 0xf;
6270 op1 = (insn >> 20) & 0xf;
6271 switch (op1) {
6272 case 0: case 1: case 2: case 3: case 6:
6273 /* 32 bit mul */
5e3f878a
PB
6274 tmp = load_reg(s, rs);
6275 tmp2 = load_reg(s, rm);
6276 tcg_gen_mul_i32(tmp, tmp, tmp2);
6277 dead_tmp(tmp2);
9ee6e8bb
PB
6278 if (insn & (1 << 22)) {
6279 /* Subtract (mls) */
6280 ARCH(6T2);
5e3f878a
PB
6281 tmp2 = load_reg(s, rn);
6282 tcg_gen_sub_i32(tmp, tmp2, tmp);
6283 dead_tmp(tmp2);
9ee6e8bb
PB
6284 } else if (insn & (1 << 21)) {
6285 /* Add */
5e3f878a
PB
6286 tmp2 = load_reg(s, rn);
6287 tcg_gen_add_i32(tmp, tmp, tmp2);
6288 dead_tmp(tmp2);
9ee6e8bb
PB
6289 }
6290 if (insn & (1 << 20))
5e3f878a
PB
6291 gen_logic_CC(tmp);
6292 store_reg(s, rd, tmp);
9ee6e8bb
PB
6293 break;
6294 default:
6295 /* 64 bit mul */
5e3f878a
PB
6296 tmp = load_reg(s, rs);
6297 tmp2 = load_reg(s, rm);
9ee6e8bb 6298 if (insn & (1 << 22))
a7812ae4 6299 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9ee6e8bb 6300 else
a7812ae4 6301 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
9ee6e8bb 6302 if (insn & (1 << 21)) /* mult accumulate */
a7812ae4 6303 gen_addq(s, tmp64, rn, rd);
9ee6e8bb
PB
6304 if (!(insn & (1 << 23))) { /* double accumulate */
6305 ARCH(6);
a7812ae4
PB
6306 gen_addq_lo(s, tmp64, rn);
6307 gen_addq_lo(s, tmp64, rd);
9ee6e8bb
PB
6308 }
6309 if (insn & (1 << 20))
a7812ae4
PB
6310 gen_logicq_cc(tmp64);
6311 gen_storeq_reg(s, rn, rd, tmp64);
9ee6e8bb
PB
6312 break;
6313 }
6314 } else {
6315 rn = (insn >> 16) & 0xf;
6316 rd = (insn >> 12) & 0xf;
6317 if (insn & (1 << 23)) {
6318 /* load/store exclusive */
86753403
PB
6319 op1 = (insn >> 21) & 0x3;
6320 if (op1)
a47f43d2 6321 ARCH(6K);
86753403
PB
6322 else
6323 ARCH(6);
9ee6e8bb 6324 gen_movl_T1_reg(s, rn);
72f1c62f 6325 addr = cpu_T[1];
9ee6e8bb 6326 if (insn & (1 << 20)) {
8f8e3aa4 6327 gen_helper_mark_exclusive(cpu_env, cpu_T[1]);
86753403
PB
6328 switch (op1) {
6329 case 0: /* ldrex */
6330 tmp = gen_ld32(addr, IS_USER(s));
6331 break;
6332 case 1: /* ldrexd */
6333 tmp = gen_ld32(addr, IS_USER(s));
6334 store_reg(s, rd, tmp);
6335 tcg_gen_addi_i32(addr, addr, 4);
6336 tmp = gen_ld32(addr, IS_USER(s));
6337 rd++;
6338 break;
6339 case 2: /* ldrexb */
6340 tmp = gen_ld8u(addr, IS_USER(s));
6341 break;
6342 case 3: /* ldrexh */
6343 tmp = gen_ld16u(addr, IS_USER(s));
6344 break;
6345 default:
6346 abort();
6347 }
8f8e3aa4 6348 store_reg(s, rd, tmp);
9ee6e8bb 6349 } else {
8f8e3aa4 6350 int label = gen_new_label();
9ee6e8bb 6351 rm = insn & 0xf;
8f8e3aa4 6352 gen_helper_test_exclusive(cpu_T[0], cpu_env, addr);
cb63669a
PB
6353 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_T[0],
6354 0, label);
8f8e3aa4 6355 tmp = load_reg(s,rm);
86753403
PB
6356 switch (op1) {
6357 case 0: /* strex */
6358 gen_st32(tmp, addr, IS_USER(s));
6359 break;
6360 case 1: /* strexd */
6361 gen_st32(tmp, addr, IS_USER(s));
6362 tcg_gen_addi_i32(addr, addr, 4);
6363 tmp = load_reg(s, rm + 1);
6364 gen_st32(tmp, addr, IS_USER(s));
6365 break;
6366 case 2: /* strexb */
6367 gen_st8(tmp, addr, IS_USER(s));
6368 break;
6369 case 3: /* strexh */
6370 gen_st16(tmp, addr, IS_USER(s));
6371 break;
6372 default:
6373 abort();
6374 }
2637a3be 6375 gen_set_label(label);
8f8e3aa4 6376 gen_movl_reg_T0(s, rd);
9ee6e8bb 6377 }
9ee6e8bb
PB
6378 } else {
6379 /* SWP instruction */
6380 rm = (insn) & 0xf;
6381
8984bd2e
PB
6382 /* ??? This is not really atomic. However we know
6383 we never have multiple CPUs running in parallel,
6384 so it is good enough. */
6385 addr = load_reg(s, rn);
6386 tmp = load_reg(s, rm);
9ee6e8bb 6387 if (insn & (1 << 22)) {
8984bd2e
PB
6388 tmp2 = gen_ld8u(addr, IS_USER(s));
6389 gen_st8(tmp, addr, IS_USER(s));
9ee6e8bb 6390 } else {
8984bd2e
PB
6391 tmp2 = gen_ld32(addr, IS_USER(s));
6392 gen_st32(tmp, addr, IS_USER(s));
9ee6e8bb 6393 }
8984bd2e
PB
6394 dead_tmp(addr);
6395 store_reg(s, rd, tmp2);
9ee6e8bb
PB
6396 }
6397 }
6398 } else {
6399 int address_offset;
6400 int load;
6401 /* Misc load/store */
6402 rn = (insn >> 16) & 0xf;
6403 rd = (insn >> 12) & 0xf;
b0109805 6404 addr = load_reg(s, rn);
9ee6e8bb 6405 if (insn & (1 << 24))
b0109805 6406 gen_add_datah_offset(s, insn, 0, addr);
9ee6e8bb
PB
6407 address_offset = 0;
6408 if (insn & (1 << 20)) {
6409 /* load */
6410 switch(sh) {
6411 case 1:
b0109805 6412 tmp = gen_ld16u(addr, IS_USER(s));
9ee6e8bb
PB
6413 break;
6414 case 2:
b0109805 6415 tmp = gen_ld8s(addr, IS_USER(s));
9ee6e8bb
PB
6416 break;
6417 default:
6418 case 3:
b0109805 6419 tmp = gen_ld16s(addr, IS_USER(s));
9ee6e8bb
PB
6420 break;
6421 }
6422 load = 1;
6423 } else if (sh & 2) {
6424 /* doubleword */
6425 if (sh & 1) {
6426 /* store */
b0109805
PB
6427 tmp = load_reg(s, rd);
6428 gen_st32(tmp, addr, IS_USER(s));
6429 tcg_gen_addi_i32(addr, addr, 4);
6430 tmp = load_reg(s, rd + 1);
6431 gen_st32(tmp, addr, IS_USER(s));
9ee6e8bb
PB
6432 load = 0;
6433 } else {
6434 /* load */
b0109805
PB
6435 tmp = gen_ld32(addr, IS_USER(s));
6436 store_reg(s, rd, tmp);
6437 tcg_gen_addi_i32(addr, addr, 4);
6438 tmp = gen_ld32(addr, IS_USER(s));
9ee6e8bb
PB
6439 rd++;
6440 load = 1;
6441 }
6442 address_offset = -4;
6443 } else {
6444 /* store */
b0109805
PB
6445 tmp = load_reg(s, rd);
6446 gen_st16(tmp, addr, IS_USER(s));
9ee6e8bb
PB
6447 load = 0;
6448 }
6449 /* Perform base writeback before the loaded value to
6450 ensure correct behavior with overlapping index registers.
6451 ldrd with base writeback is is undefined if the
6452 destination and index registers overlap. */
6453 if (!(insn & (1 << 24))) {
b0109805
PB
6454 gen_add_datah_offset(s, insn, address_offset, addr);
6455 store_reg(s, rn, addr);
9ee6e8bb
PB
6456 } else if (insn & (1 << 21)) {
6457 if (address_offset)
b0109805
PB
6458 tcg_gen_addi_i32(addr, addr, address_offset);
6459 store_reg(s, rn, addr);
6460 } else {
6461 dead_tmp(addr);
9ee6e8bb
PB
6462 }
6463 if (load) {
6464 /* Complete the load. */
b0109805 6465 store_reg(s, rd, tmp);
9ee6e8bb
PB
6466 }
6467 }
6468 break;
6469 case 0x4:
6470 case 0x5:
6471 goto do_ldst;
6472 case 0x6:
6473 case 0x7:
6474 if (insn & (1 << 4)) {
6475 ARCH(6);
6476 /* Armv6 Media instructions. */
6477 rm = insn & 0xf;
6478 rn = (insn >> 16) & 0xf;
2c0262af 6479 rd = (insn >> 12) & 0xf;
9ee6e8bb
PB
6480 rs = (insn >> 8) & 0xf;
6481 switch ((insn >> 23) & 3) {
6482 case 0: /* Parallel add/subtract. */
6483 op1 = (insn >> 20) & 7;
6ddbc6e4
PB
6484 tmp = load_reg(s, rn);
6485 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
6486 sh = (insn >> 5) & 7;
6487 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
6488 goto illegal_op;
6ddbc6e4
PB
6489 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
6490 dead_tmp(tmp2);
6491 store_reg(s, rd, tmp);
9ee6e8bb
PB
6492 break;
6493 case 1:
6494 if ((insn & 0x00700020) == 0) {
6c95676b 6495 /* Halfword pack. */
3670669c
PB
6496 tmp = load_reg(s, rn);
6497 tmp2 = load_reg(s, rm);
9ee6e8bb 6498 shift = (insn >> 7) & 0x1f;
3670669c
PB
6499 if (insn & (1 << 6)) {
6500 /* pkhtb */
22478e79
AZ
6501 if (shift == 0)
6502 shift = 31;
6503 tcg_gen_sari_i32(tmp2, tmp2, shift);
3670669c 6504 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
86831435 6505 tcg_gen_ext16u_i32(tmp2, tmp2);
3670669c
PB
6506 } else {
6507 /* pkhbt */
22478e79
AZ
6508 if (shift)
6509 tcg_gen_shli_i32(tmp2, tmp2, shift);
86831435 6510 tcg_gen_ext16u_i32(tmp, tmp);
3670669c
PB
6511 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
6512 }
6513 tcg_gen_or_i32(tmp, tmp, tmp2);
22478e79 6514 dead_tmp(tmp2);
3670669c 6515 store_reg(s, rd, tmp);
9ee6e8bb
PB
6516 } else if ((insn & 0x00200020) == 0x00200000) {
6517 /* [us]sat */
6ddbc6e4 6518 tmp = load_reg(s, rm);
9ee6e8bb
PB
6519 shift = (insn >> 7) & 0x1f;
6520 if (insn & (1 << 6)) {
6521 if (shift == 0)
6522 shift = 31;
6ddbc6e4 6523 tcg_gen_sari_i32(tmp, tmp, shift);
9ee6e8bb 6524 } else {
6ddbc6e4 6525 tcg_gen_shli_i32(tmp, tmp, shift);
9ee6e8bb
PB
6526 }
6527 sh = (insn >> 16) & 0x1f;
6528 if (sh != 0) {
6529 if (insn & (1 << 22))
6ddbc6e4 6530 gen_helper_usat(tmp, tmp, tcg_const_i32(sh));
9ee6e8bb 6531 else
6ddbc6e4 6532 gen_helper_ssat(tmp, tmp, tcg_const_i32(sh));
9ee6e8bb 6533 }
6ddbc6e4 6534 store_reg(s, rd, tmp);
9ee6e8bb
PB
6535 } else if ((insn & 0x00300fe0) == 0x00200f20) {
6536 /* [us]sat16 */
6ddbc6e4 6537 tmp = load_reg(s, rm);
9ee6e8bb
PB
6538 sh = (insn >> 16) & 0x1f;
6539 if (sh != 0) {
6540 if (insn & (1 << 22))
6ddbc6e4 6541 gen_helper_usat16(tmp, tmp, tcg_const_i32(sh));
9ee6e8bb 6542 else
6ddbc6e4 6543 gen_helper_ssat16(tmp, tmp, tcg_const_i32(sh));
9ee6e8bb 6544 }
6ddbc6e4 6545 store_reg(s, rd, tmp);
9ee6e8bb
PB
6546 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
6547 /* Select bytes. */
6ddbc6e4
PB
6548 tmp = load_reg(s, rn);
6549 tmp2 = load_reg(s, rm);
6550 tmp3 = new_tmp();
6551 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
6552 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
6553 dead_tmp(tmp3);
6554 dead_tmp(tmp2);
6555 store_reg(s, rd, tmp);
9ee6e8bb 6556 } else if ((insn & 0x000003e0) == 0x00000060) {
5e3f878a 6557 tmp = load_reg(s, rm);
9ee6e8bb
PB
6558 shift = (insn >> 10) & 3;
6559 /* ??? In many cases it's not neccessary to do a
6560 rotate, a shift is sufficient. */
6561 if (shift != 0)
5e3f878a 6562 tcg_gen_rori_i32(tmp, tmp, shift * 8);
9ee6e8bb
PB
6563 op1 = (insn >> 20) & 7;
6564 switch (op1) {
5e3f878a
PB
6565 case 0: gen_sxtb16(tmp); break;
6566 case 2: gen_sxtb(tmp); break;
6567 case 3: gen_sxth(tmp); break;
6568 case 4: gen_uxtb16(tmp); break;
6569 case 6: gen_uxtb(tmp); break;
6570 case 7: gen_uxth(tmp); break;
9ee6e8bb
PB
6571 default: goto illegal_op;
6572 }
6573 if (rn != 15) {
5e3f878a 6574 tmp2 = load_reg(s, rn);
9ee6e8bb 6575 if ((op1 & 3) == 0) {
5e3f878a 6576 gen_add16(tmp, tmp2);
9ee6e8bb 6577 } else {
5e3f878a
PB
6578 tcg_gen_add_i32(tmp, tmp, tmp2);
6579 dead_tmp(tmp2);
9ee6e8bb
PB
6580 }
6581 }
6c95676b 6582 store_reg(s, rd, tmp);
9ee6e8bb
PB
6583 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
6584 /* rev */
b0109805 6585 tmp = load_reg(s, rm);
9ee6e8bb
PB
6586 if (insn & (1 << 22)) {
6587 if (insn & (1 << 7)) {
b0109805 6588 gen_revsh(tmp);
9ee6e8bb
PB
6589 } else {
6590 ARCH(6T2);
b0109805 6591 gen_helper_rbit(tmp, tmp);
9ee6e8bb
PB
6592 }
6593 } else {
6594 if (insn & (1 << 7))
b0109805 6595 gen_rev16(tmp);
9ee6e8bb 6596 else
66896cb8 6597 tcg_gen_bswap32_i32(tmp, tmp);
9ee6e8bb 6598 }
b0109805 6599 store_reg(s, rd, tmp);
9ee6e8bb
PB
6600 } else {
6601 goto illegal_op;
6602 }
6603 break;
6604 case 2: /* Multiplies (Type 3). */
5e3f878a
PB
6605 tmp = load_reg(s, rm);
6606 tmp2 = load_reg(s, rs);
9ee6e8bb
PB
6607 if (insn & (1 << 20)) {
6608 /* Signed multiply most significant [accumulate]. */
a7812ae4 6609 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9ee6e8bb 6610 if (insn & (1 << 5))
a7812ae4
PB
6611 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
6612 tcg_gen_shri_i64(tmp64, tmp64, 32);
5e3f878a 6613 tmp = new_tmp();
a7812ae4 6614 tcg_gen_trunc_i64_i32(tmp, tmp64);
955a7dd5
AZ
6615 if (rd != 15) {
6616 tmp2 = load_reg(s, rd);
9ee6e8bb 6617 if (insn & (1 << 6)) {
5e3f878a 6618 tcg_gen_sub_i32(tmp, tmp, tmp2);
9ee6e8bb 6619 } else {
5e3f878a 6620 tcg_gen_add_i32(tmp, tmp, tmp2);
9ee6e8bb 6621 }
5e3f878a 6622 dead_tmp(tmp2);
9ee6e8bb 6623 }
955a7dd5 6624 store_reg(s, rn, tmp);
9ee6e8bb
PB
6625 } else {
6626 if (insn & (1 << 5))
5e3f878a
PB
6627 gen_swap_half(tmp2);
6628 gen_smul_dual(tmp, tmp2);
6629 /* This addition cannot overflow. */
6630 if (insn & (1 << 6)) {
6631 tcg_gen_sub_i32(tmp, tmp, tmp2);
6632 } else {
6633 tcg_gen_add_i32(tmp, tmp, tmp2);
6634 }
6635 dead_tmp(tmp2);
9ee6e8bb 6636 if (insn & (1 << 22)) {
5e3f878a 6637 /* smlald, smlsld */
a7812ae4
PB
6638 tmp64 = tcg_temp_new_i64();
6639 tcg_gen_ext_i32_i64(tmp64, tmp);
5e3f878a 6640 dead_tmp(tmp);
a7812ae4
PB
6641 gen_addq(s, tmp64, rd, rn);
6642 gen_storeq_reg(s, rd, rn, tmp64);
9ee6e8bb 6643 } else {
5e3f878a 6644 /* smuad, smusd, smlad, smlsd */
22478e79 6645 if (rd != 15)
9ee6e8bb 6646 {
22478e79 6647 tmp2 = load_reg(s, rd);
5e3f878a
PB
6648 gen_helper_add_setq(tmp, tmp, tmp2);
6649 dead_tmp(tmp2);
9ee6e8bb 6650 }
22478e79 6651 store_reg(s, rn, tmp);
9ee6e8bb
PB
6652 }
6653 }
6654 break;
6655 case 3:
6656 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
6657 switch (op1) {
6658 case 0: /* Unsigned sum of absolute differences. */
6ddbc6e4
PB
6659 ARCH(6);
6660 tmp = load_reg(s, rm);
6661 tmp2 = load_reg(s, rs);
6662 gen_helper_usad8(tmp, tmp, tmp2);
6663 dead_tmp(tmp2);
ded9d295
AZ
6664 if (rd != 15) {
6665 tmp2 = load_reg(s, rd);
6ddbc6e4
PB
6666 tcg_gen_add_i32(tmp, tmp, tmp2);
6667 dead_tmp(tmp2);
9ee6e8bb 6668 }
ded9d295 6669 store_reg(s, rn, tmp);
9ee6e8bb
PB
6670 break;
6671 case 0x20: case 0x24: case 0x28: case 0x2c:
6672 /* Bitfield insert/clear. */
6673 ARCH(6T2);
6674 shift = (insn >> 7) & 0x1f;
6675 i = (insn >> 16) & 0x1f;
6676 i = i + 1 - shift;
6677 if (rm == 15) {
5e3f878a
PB
6678 tmp = new_tmp();
6679 tcg_gen_movi_i32(tmp, 0);
9ee6e8bb 6680 } else {
5e3f878a 6681 tmp = load_reg(s, rm);
9ee6e8bb
PB
6682 }
6683 if (i != 32) {
5e3f878a 6684 tmp2 = load_reg(s, rd);
8f8e3aa4 6685 gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
5e3f878a 6686 dead_tmp(tmp2);
9ee6e8bb 6687 }
5e3f878a 6688 store_reg(s, rd, tmp);
9ee6e8bb
PB
6689 break;
6690 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6691 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
4cc633c3 6692 ARCH(6T2);
5e3f878a 6693 tmp = load_reg(s, rm);
9ee6e8bb
PB
6694 shift = (insn >> 7) & 0x1f;
6695 i = ((insn >> 16) & 0x1f) + 1;
6696 if (shift + i > 32)
6697 goto illegal_op;
6698 if (i < 32) {
6699 if (op1 & 0x20) {
5e3f878a 6700 gen_ubfx(tmp, shift, (1u << i) - 1);
9ee6e8bb 6701 } else {
5e3f878a 6702 gen_sbfx(tmp, shift, i);
9ee6e8bb
PB
6703 }
6704 }
5e3f878a 6705 store_reg(s, rd, tmp);
9ee6e8bb
PB
6706 break;
6707 default:
6708 goto illegal_op;
6709 }
6710 break;
6711 }
6712 break;
6713 }
6714 do_ldst:
6715 /* Check for undefined extension instructions
6716 * per the ARM Bible IE:
6717 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6718 */
6719 sh = (0xf << 20) | (0xf << 4);
6720 if (op1 == 0x7 && ((insn & sh) == sh))
6721 {
6722 goto illegal_op;
6723 }
6724 /* load/store byte/word */
6725 rn = (insn >> 16) & 0xf;
6726 rd = (insn >> 12) & 0xf;
b0109805 6727 tmp2 = load_reg(s, rn);
9ee6e8bb
PB
6728 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
6729 if (insn & (1 << 24))
b0109805 6730 gen_add_data_offset(s, insn, tmp2);
9ee6e8bb
PB
6731 if (insn & (1 << 20)) {
6732 /* load */
9ee6e8bb 6733 if (insn & (1 << 22)) {
b0109805 6734 tmp = gen_ld8u(tmp2, i);
9ee6e8bb 6735 } else {
b0109805 6736 tmp = gen_ld32(tmp2, i);
9ee6e8bb 6737 }
9ee6e8bb
PB
6738 } else {
6739 /* store */
b0109805 6740 tmp = load_reg(s, rd);
9ee6e8bb 6741 if (insn & (1 << 22))
b0109805 6742 gen_st8(tmp, tmp2, i);
9ee6e8bb 6743 else
b0109805 6744 gen_st32(tmp, tmp2, i);
9ee6e8bb
PB
6745 }
6746 if (!(insn & (1 << 24))) {
b0109805
PB
6747 gen_add_data_offset(s, insn, tmp2);
6748 store_reg(s, rn, tmp2);
6749 } else if (insn & (1 << 21)) {
6750 store_reg(s, rn, tmp2);
6751 } else {
6752 dead_tmp(tmp2);
9ee6e8bb
PB
6753 }
6754 if (insn & (1 << 20)) {
6755 /* Complete the load. */
6756 if (rd == 15)
b0109805 6757 gen_bx(s, tmp);
9ee6e8bb 6758 else
b0109805 6759 store_reg(s, rd, tmp);
9ee6e8bb
PB
6760 }
6761 break;
6762 case 0x08:
6763 case 0x09:
6764 {
6765 int j, n, user, loaded_base;
b0109805 6766 TCGv loaded_var;
9ee6e8bb
PB
6767 /* load/store multiple words */
6768 /* XXX: store correct base if write back */
6769 user = 0;
6770 if (insn & (1 << 22)) {
6771 if (IS_USER(s))
6772 goto illegal_op; /* only usable in supervisor mode */
6773
6774 if ((insn & (1 << 15)) == 0)
6775 user = 1;
6776 }
6777 rn = (insn >> 16) & 0xf;
b0109805 6778 addr = load_reg(s, rn);
9ee6e8bb
PB
6779
6780 /* compute total size */
6781 loaded_base = 0;
a50f5b91 6782 TCGV_UNUSED(loaded_var);
9ee6e8bb
PB
6783 n = 0;
6784 for(i=0;i<16;i++) {
6785 if (insn & (1 << i))
6786 n++;
6787 }
6788 /* XXX: test invalid n == 0 case ? */
6789 if (insn & (1 << 23)) {
6790 if (insn & (1 << 24)) {
6791 /* pre increment */
b0109805 6792 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb
PB
6793 } else {
6794 /* post increment */
6795 }
6796 } else {
6797 if (insn & (1 << 24)) {
6798 /* pre decrement */
b0109805 6799 tcg_gen_addi_i32(addr, addr, -(n * 4));
9ee6e8bb
PB
6800 } else {
6801 /* post decrement */
6802 if (n != 1)
b0109805 6803 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
9ee6e8bb
PB
6804 }
6805 }
6806 j = 0;
6807 for(i=0;i<16;i++) {
6808 if (insn & (1 << i)) {
6809 if (insn & (1 << 20)) {
6810 /* load */
b0109805 6811 tmp = gen_ld32(addr, IS_USER(s));
9ee6e8bb 6812 if (i == 15) {
b0109805 6813 gen_bx(s, tmp);
9ee6e8bb 6814 } else if (user) {
b0109805
PB
6815 gen_helper_set_user_reg(tcg_const_i32(i), tmp);
6816 dead_tmp(tmp);
9ee6e8bb 6817 } else if (i == rn) {
b0109805 6818 loaded_var = tmp;
9ee6e8bb
PB
6819 loaded_base = 1;
6820 } else {
b0109805 6821 store_reg(s, i, tmp);
9ee6e8bb
PB
6822 }
6823 } else {
6824 /* store */
6825 if (i == 15) {
6826 /* special case: r15 = PC + 8 */
6827 val = (long)s->pc + 4;
b0109805
PB
6828 tmp = new_tmp();
6829 tcg_gen_movi_i32(tmp, val);
9ee6e8bb 6830 } else if (user) {
b0109805
PB
6831 tmp = new_tmp();
6832 gen_helper_get_user_reg(tmp, tcg_const_i32(i));
9ee6e8bb 6833 } else {
b0109805 6834 tmp = load_reg(s, i);
9ee6e8bb 6835 }
b0109805 6836 gen_st32(tmp, addr, IS_USER(s));
9ee6e8bb
PB
6837 }
6838 j++;
6839 /* no need to add after the last transfer */
6840 if (j != n)
b0109805 6841 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb
PB
6842 }
6843 }
6844 if (insn & (1 << 21)) {
6845 /* write back */
6846 if (insn & (1 << 23)) {
6847 if (insn & (1 << 24)) {
6848 /* pre increment */
6849 } else {
6850 /* post increment */
b0109805 6851 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb
PB
6852 }
6853 } else {
6854 if (insn & (1 << 24)) {
6855 /* pre decrement */
6856 if (n != 1)
b0109805 6857 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
9ee6e8bb
PB
6858 } else {
6859 /* post decrement */
b0109805 6860 tcg_gen_addi_i32(addr, addr, -(n * 4));
9ee6e8bb
PB
6861 }
6862 }
b0109805
PB
6863 store_reg(s, rn, addr);
6864 } else {
6865 dead_tmp(addr);
9ee6e8bb
PB
6866 }
6867 if (loaded_base) {
b0109805 6868 store_reg(s, rn, loaded_var);
9ee6e8bb
PB
6869 }
6870 if ((insn & (1 << 22)) && !user) {
6871 /* Restore CPSR from SPSR. */
d9ba4830
PB
6872 tmp = load_cpu_field(spsr);
6873 gen_set_cpsr(tmp, 0xffffffff);
6874 dead_tmp(tmp);
9ee6e8bb
PB
6875 s->is_jmp = DISAS_UPDATE;
6876 }
6877 }
6878 break;
6879 case 0xa:
6880 case 0xb:
6881 {
6882 int32_t offset;
6883
6884 /* branch (and link) */
6885 val = (int32_t)s->pc;
6886 if (insn & (1 << 24)) {
5e3f878a
PB
6887 tmp = new_tmp();
6888 tcg_gen_movi_i32(tmp, val);
6889 store_reg(s, 14, tmp);
9ee6e8bb
PB
6890 }
6891 offset = (((int32_t)insn << 8) >> 8);
6892 val += (offset << 2) + 4;
6893 gen_jmp(s, val);
6894 }
6895 break;
6896 case 0xc:
6897 case 0xd:
6898 case 0xe:
6899 /* Coprocessor. */
6900 if (disas_coproc_insn(env, s, insn))
6901 goto illegal_op;
6902 break;
6903 case 0xf:
6904 /* swi */
5e3f878a 6905 gen_set_pc_im(s->pc);
9ee6e8bb
PB
6906 s->is_jmp = DISAS_SWI;
6907 break;
6908 default:
6909 illegal_op:
6910 gen_set_condexec(s);
5e3f878a 6911 gen_set_pc_im(s->pc - 4);
d9ba4830 6912 gen_exception(EXCP_UDEF);
9ee6e8bb
PB
6913 s->is_jmp = DISAS_JUMP;
6914 break;
6915 }
6916 }
6917}
6918
6919/* Return true if this is a Thumb-2 logical op. */
6920static int
6921thumb2_logic_op(int op)
6922{
6923 return (op < 8);
6924}
6925
6926/* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
6927 then set condition code flags based on the result of the operation.
6928 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
6929 to the high bit of T1.
6930 Returns zero if the opcode is valid. */
6931
6932static int
6933gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out)
6934{
6935 int logic_cc;
6936
6937 logic_cc = 0;
6938 switch (op) {
6939 case 0: /* and */
6940 gen_op_andl_T0_T1();
6941 logic_cc = conds;
6942 break;
6943 case 1: /* bic */
6944 gen_op_bicl_T0_T1();
6945 logic_cc = conds;
6946 break;
6947 case 2: /* orr */
6948 gen_op_orl_T0_T1();
6949 logic_cc = conds;
6950 break;
6951 case 3: /* orn */
6952 gen_op_notl_T1();
6953 gen_op_orl_T0_T1();
6954 logic_cc = conds;
6955 break;
6956 case 4: /* eor */
6957 gen_op_xorl_T0_T1();
6958 logic_cc = conds;
6959 break;
6960 case 8: /* add */
6961 if (conds)
6962 gen_op_addl_T0_T1_cc();
6963 else
6964 gen_op_addl_T0_T1();
6965 break;
6966 case 10: /* adc */
6967 if (conds)
6968 gen_op_adcl_T0_T1_cc();
6969 else
b26eefb6 6970 gen_adc_T0_T1();
9ee6e8bb
PB
6971 break;
6972 case 11: /* sbc */
6973 if (conds)
6974 gen_op_sbcl_T0_T1_cc();
6975 else
3670669c 6976 gen_sbc_T0_T1();
9ee6e8bb
PB
6977 break;
6978 case 13: /* sub */
6979 if (conds)
6980 gen_op_subl_T0_T1_cc();
6981 else
6982 gen_op_subl_T0_T1();
6983 break;
6984 case 14: /* rsb */
6985 if (conds)
6986 gen_op_rsbl_T0_T1_cc();
6987 else
6988 gen_op_rsbl_T0_T1();
6989 break;
6990 default: /* 5, 6, 7, 9, 12, 15. */
6991 return 1;
6992 }
6993 if (logic_cc) {
6994 gen_op_logic_T0_cc();
6995 if (shifter_out)
b26eefb6 6996 gen_set_CF_bit31(cpu_T[1]);
9ee6e8bb
PB
6997 }
6998 return 0;
6999}
7000
7001/* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7002 is not legal. */
7003static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
7004{
b0109805 7005 uint32_t insn, imm, shift, offset;
9ee6e8bb 7006 uint32_t rd, rn, rm, rs;
b26eefb6 7007 TCGv tmp;
6ddbc6e4
PB
7008 TCGv tmp2;
7009 TCGv tmp3;
b0109805 7010 TCGv addr;
a7812ae4 7011 TCGv_i64 tmp64;
9ee6e8bb
PB
7012 int op;
7013 int shiftop;
7014 int conds;
7015 int logic_cc;
7016
7017 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
7018 || arm_feature (env, ARM_FEATURE_M))) {
601d70b9 7019 /* Thumb-1 cores may need to treat bl and blx as a pair of
9ee6e8bb
PB
7020 16-bit instructions to get correct prefetch abort behavior. */
7021 insn = insn_hw1;
7022 if ((insn & (1 << 12)) == 0) {
7023 /* Second half of blx. */
7024 offset = ((insn & 0x7ff) << 1);
d9ba4830
PB
7025 tmp = load_reg(s, 14);
7026 tcg_gen_addi_i32(tmp, tmp, offset);
7027 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
9ee6e8bb 7028
d9ba4830 7029 tmp2 = new_tmp();
b0109805 7030 tcg_gen_movi_i32(tmp2, s->pc | 1);
d9ba4830
PB
7031 store_reg(s, 14, tmp2);
7032 gen_bx(s, tmp);
9ee6e8bb
PB
7033 return 0;
7034 }
7035 if (insn & (1 << 11)) {
7036 /* Second half of bl. */
7037 offset = ((insn & 0x7ff) << 1) | 1;
d9ba4830 7038 tmp = load_reg(s, 14);
6a0d8a1d 7039 tcg_gen_addi_i32(tmp, tmp, offset);
9ee6e8bb 7040
d9ba4830 7041 tmp2 = new_tmp();
b0109805 7042 tcg_gen_movi_i32(tmp2, s->pc | 1);
d9ba4830
PB
7043 store_reg(s, 14, tmp2);
7044 gen_bx(s, tmp);
9ee6e8bb
PB
7045 return 0;
7046 }
7047 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
7048 /* Instruction spans a page boundary. Implement it as two
7049 16-bit instructions in case the second half causes an
7050 prefetch abort. */
7051 offset = ((int32_t)insn << 21) >> 9;
b0109805 7052 gen_op_movl_T0_im(s->pc + 2 + offset);
9ee6e8bb
PB
7053 gen_movl_reg_T0(s, 14);
7054 return 0;
7055 }
7056 /* Fall through to 32-bit decode. */
7057 }
7058
7059 insn = lduw_code(s->pc);
7060 s->pc += 2;
7061 insn |= (uint32_t)insn_hw1 << 16;
7062
7063 if ((insn & 0xf800e800) != 0xf000e800) {
7064 ARCH(6T2);
7065 }
7066
7067 rn = (insn >> 16) & 0xf;
7068 rs = (insn >> 12) & 0xf;
7069 rd = (insn >> 8) & 0xf;
7070 rm = insn & 0xf;
7071 switch ((insn >> 25) & 0xf) {
7072 case 0: case 1: case 2: case 3:
7073 /* 16-bit instructions. Should never happen. */
7074 abort();
7075 case 4:
7076 if (insn & (1 << 22)) {
7077 /* Other load/store, table branch. */
7078 if (insn & 0x01200000) {
7079 /* Load/store doubleword. */
7080 if (rn == 15) {
b0109805
PB
7081 addr = new_tmp();
7082 tcg_gen_movi_i32(addr, s->pc & ~3);
9ee6e8bb 7083 } else {
b0109805 7084 addr = load_reg(s, rn);
9ee6e8bb
PB
7085 }
7086 offset = (insn & 0xff) * 4;
7087 if ((insn & (1 << 23)) == 0)
7088 offset = -offset;
7089 if (insn & (1 << 24)) {
b0109805 7090 tcg_gen_addi_i32(addr, addr, offset);
9ee6e8bb
PB
7091 offset = 0;
7092 }
7093 if (insn & (1 << 20)) {
7094 /* ldrd */
b0109805
PB
7095 tmp = gen_ld32(addr, IS_USER(s));
7096 store_reg(s, rs, tmp);
7097 tcg_gen_addi_i32(addr, addr, 4);
7098 tmp = gen_ld32(addr, IS_USER(s));
7099 store_reg(s, rd, tmp);
9ee6e8bb
PB
7100 } else {
7101 /* strd */
b0109805
PB
7102 tmp = load_reg(s, rs);
7103 gen_st32(tmp, addr, IS_USER(s));
7104 tcg_gen_addi_i32(addr, addr, 4);
7105 tmp = load_reg(s, rd);
7106 gen_st32(tmp, addr, IS_USER(s));
9ee6e8bb
PB
7107 }
7108 if (insn & (1 << 21)) {
7109 /* Base writeback. */
7110 if (rn == 15)
7111 goto illegal_op;
b0109805
PB
7112 tcg_gen_addi_i32(addr, addr, offset - 4);
7113 store_reg(s, rn, addr);
7114 } else {
7115 dead_tmp(addr);
9ee6e8bb
PB
7116 }
7117 } else if ((insn & (1 << 23)) == 0) {
7118 /* Load/store exclusive word. */
2c0262af 7119 gen_movl_T1_reg(s, rn);
72f1c62f 7120 addr = cpu_T[1];
2c0262af 7121 if (insn & (1 << 20)) {
8f8e3aa4
PB
7122 gen_helper_mark_exclusive(cpu_env, cpu_T[1]);
7123 tmp = gen_ld32(addr, IS_USER(s));
7124 store_reg(s, rd, tmp);
9ee6e8bb 7125 } else {
8f8e3aa4
PB
7126 int label = gen_new_label();
7127 gen_helper_test_exclusive(cpu_T[0], cpu_env, addr);
cb63669a
PB
7128 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_T[0],
7129 0, label);
8f8e3aa4
PB
7130 tmp = load_reg(s, rs);
7131 gen_st32(tmp, cpu_T[1], IS_USER(s));
7132 gen_set_label(label);
7133 gen_movl_reg_T0(s, rd);
9ee6e8bb 7134 }
9ee6e8bb
PB
7135 } else if ((insn & (1 << 6)) == 0) {
7136 /* Table Branch. */
7137 if (rn == 15) {
b0109805
PB
7138 addr = new_tmp();
7139 tcg_gen_movi_i32(addr, s->pc);
9ee6e8bb 7140 } else {
b0109805 7141 addr = load_reg(s, rn);
9ee6e8bb 7142 }
b26eefb6 7143 tmp = load_reg(s, rm);
b0109805 7144 tcg_gen_add_i32(addr, addr, tmp);
9ee6e8bb
PB
7145 if (insn & (1 << 4)) {
7146 /* tbh */
b0109805 7147 tcg_gen_add_i32(addr, addr, tmp);
b26eefb6 7148 dead_tmp(tmp);
b0109805 7149 tmp = gen_ld16u(addr, IS_USER(s));
9ee6e8bb 7150 } else { /* tbb */
b26eefb6 7151 dead_tmp(tmp);
b0109805 7152 tmp = gen_ld8u(addr, IS_USER(s));
9ee6e8bb 7153 }
b0109805
PB
7154 dead_tmp(addr);
7155 tcg_gen_shli_i32(tmp, tmp, 1);
7156 tcg_gen_addi_i32(tmp, tmp, s->pc);
7157 store_reg(s, 15, tmp);
9ee6e8bb
PB
7158 } else {
7159 /* Load/store exclusive byte/halfword/doubleword. */
8f8e3aa4
PB
7160 /* ??? These are not really atomic. However we know
7161 we never have multiple CPUs running in parallel,
7162 so it is good enough. */
9ee6e8bb 7163 op = (insn >> 4) & 0x3;
8f8e3aa4
PB
7164 /* Must use a global reg for the address because we have
7165 a conditional branch in the store instruction. */
9ee6e8bb 7166 gen_movl_T1_reg(s, rn);
8f8e3aa4 7167 addr = cpu_T[1];
9ee6e8bb 7168 if (insn & (1 << 20)) {
8f8e3aa4 7169 gen_helper_mark_exclusive(cpu_env, addr);
9ee6e8bb
PB
7170 switch (op) {
7171 case 0:
8f8e3aa4 7172 tmp = gen_ld8u(addr, IS_USER(s));
9ee6e8bb 7173 break;
2c0262af 7174 case 1:
8f8e3aa4 7175 tmp = gen_ld16u(addr, IS_USER(s));
2c0262af 7176 break;
9ee6e8bb 7177 case 3:
8f8e3aa4
PB
7178 tmp = gen_ld32(addr, IS_USER(s));
7179 tcg_gen_addi_i32(addr, addr, 4);
7180 tmp2 = gen_ld32(addr, IS_USER(s));
7181 store_reg(s, rd, tmp2);
2c0262af
FB
7182 break;
7183 default:
9ee6e8bb
PB
7184 goto illegal_op;
7185 }
8f8e3aa4 7186 store_reg(s, rs, tmp);
9ee6e8bb 7187 } else {
8f8e3aa4
PB
7188 int label = gen_new_label();
7189 /* Must use a global that is not killed by the branch. */
7190 gen_helper_test_exclusive(cpu_T[0], cpu_env, addr);
cb63669a 7191 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_T[0], 0, label);
8f8e3aa4 7192 tmp = load_reg(s, rs);
9ee6e8bb
PB
7193 switch (op) {
7194 case 0:
8f8e3aa4 7195 gen_st8(tmp, addr, IS_USER(s));
9ee6e8bb
PB
7196 break;
7197 case 1:
8f8e3aa4 7198 gen_st16(tmp, addr, IS_USER(s));
9ee6e8bb 7199 break;
2c0262af 7200 case 3:
8f8e3aa4
PB
7201 gen_st32(tmp, addr, IS_USER(s));
7202 tcg_gen_addi_i32(addr, addr, 4);
7203 tmp = load_reg(s, rd);
7204 gen_st32(tmp, addr, IS_USER(s));
2c0262af 7205 break;
9ee6e8bb
PB
7206 default:
7207 goto illegal_op;
2c0262af 7208 }
8f8e3aa4 7209 gen_set_label(label);
9ee6e8bb
PB
7210 gen_movl_reg_T0(s, rm);
7211 }
7212 }
7213 } else {
7214 /* Load/store multiple, RFE, SRS. */
7215 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
7216 /* Not available in user mode. */
b0109805 7217 if (IS_USER(s))
9ee6e8bb
PB
7218 goto illegal_op;
7219 if (insn & (1 << 20)) {
7220 /* rfe */
b0109805
PB
7221 addr = load_reg(s, rn);
7222 if ((insn & (1 << 24)) == 0)
7223 tcg_gen_addi_i32(addr, addr, -8);
7224 /* Load PC into tmp and CPSR into tmp2. */
7225 tmp = gen_ld32(addr, 0);
7226 tcg_gen_addi_i32(addr, addr, 4);
7227 tmp2 = gen_ld32(addr, 0);
9ee6e8bb
PB
7228 if (insn & (1 << 21)) {
7229 /* Base writeback. */
b0109805
PB
7230 if (insn & (1 << 24)) {
7231 tcg_gen_addi_i32(addr, addr, 4);
7232 } else {
7233 tcg_gen_addi_i32(addr, addr, -4);
7234 }
7235 store_reg(s, rn, addr);
7236 } else {
7237 dead_tmp(addr);
9ee6e8bb 7238 }
b0109805 7239 gen_rfe(s, tmp, tmp2);
9ee6e8bb
PB
7240 } else {
7241 /* srs */
7242 op = (insn & 0x1f);
7243 if (op == (env->uncached_cpsr & CPSR_M)) {
b0109805 7244 addr = load_reg(s, 13);
9ee6e8bb 7245 } else {
b0109805
PB
7246 addr = new_tmp();
7247 gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op));
9ee6e8bb
PB
7248 }
7249 if ((insn & (1 << 24)) == 0) {
b0109805 7250 tcg_gen_addi_i32(addr, addr, -8);
9ee6e8bb 7251 }
b0109805
PB
7252 tmp = load_reg(s, 14);
7253 gen_st32(tmp, addr, 0);
7254 tcg_gen_addi_i32(addr, addr, 4);
7255 tmp = new_tmp();
7256 gen_helper_cpsr_read(tmp);
7257 gen_st32(tmp, addr, 0);
9ee6e8bb
PB
7258 if (insn & (1 << 21)) {
7259 if ((insn & (1 << 24)) == 0) {
b0109805 7260 tcg_gen_addi_i32(addr, addr, -4);
9ee6e8bb 7261 } else {
b0109805 7262 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb
PB
7263 }
7264 if (op == (env->uncached_cpsr & CPSR_M)) {
b0109805 7265 store_reg(s, 13, addr);
9ee6e8bb 7266 } else {
b0109805
PB
7267 gen_helper_set_r13_banked(cpu_env,
7268 tcg_const_i32(op), addr);
9ee6e8bb 7269 }
b0109805
PB
7270 } else {
7271 dead_tmp(addr);
9ee6e8bb
PB
7272 }
7273 }
7274 } else {
7275 int i;
7276 /* Load/store multiple. */
b0109805 7277 addr = load_reg(s, rn);
9ee6e8bb
PB
7278 offset = 0;
7279 for (i = 0; i < 16; i++) {
7280 if (insn & (1 << i))
7281 offset += 4;
7282 }
7283 if (insn & (1 << 24)) {
b0109805 7284 tcg_gen_addi_i32(addr, addr, -offset);
9ee6e8bb
PB
7285 }
7286
7287 for (i = 0; i < 16; i++) {
7288 if ((insn & (1 << i)) == 0)
7289 continue;
7290 if (insn & (1 << 20)) {
7291 /* Load. */
b0109805 7292 tmp = gen_ld32(addr, IS_USER(s));
9ee6e8bb 7293 if (i == 15) {
b0109805 7294 gen_bx(s, tmp);
9ee6e8bb 7295 } else {
b0109805 7296 store_reg(s, i, tmp);
9ee6e8bb
PB
7297 }
7298 } else {
7299 /* Store. */
b0109805
PB
7300 tmp = load_reg(s, i);
7301 gen_st32(tmp, addr, IS_USER(s));
9ee6e8bb 7302 }
b0109805 7303 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb
PB
7304 }
7305 if (insn & (1 << 21)) {
7306 /* Base register writeback. */
7307 if (insn & (1 << 24)) {
b0109805 7308 tcg_gen_addi_i32(addr, addr, -offset);
9ee6e8bb
PB
7309 }
7310 /* Fault if writeback register is in register list. */
7311 if (insn & (1 << rn))
7312 goto illegal_op;
b0109805
PB
7313 store_reg(s, rn, addr);
7314 } else {
7315 dead_tmp(addr);
9ee6e8bb
PB
7316 }
7317 }
7318 }
7319 break;
7320 case 5: /* Data processing register constant shift. */
7321 if (rn == 15)
7322 gen_op_movl_T0_im(0);
7323 else
7324 gen_movl_T0_reg(s, rn);
7325 gen_movl_T1_reg(s, rm);
7326 op = (insn >> 21) & 0xf;
7327 shiftop = (insn >> 4) & 3;
7328 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7329 conds = (insn & (1 << 20)) != 0;
7330 logic_cc = (conds && thumb2_logic_op(op));
9a119ff6 7331 gen_arm_shift_im(cpu_T[1], shiftop, shift, logic_cc);
9ee6e8bb
PB
7332 if (gen_thumb2_data_op(s, op, conds, 0))
7333 goto illegal_op;
7334 if (rd != 15)
7335 gen_movl_reg_T0(s, rd);
7336 break;
7337 case 13: /* Misc data processing. */
7338 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
7339 if (op < 4 && (insn & 0xf000) != 0xf000)
7340 goto illegal_op;
7341 switch (op) {
7342 case 0: /* Register controlled shift. */
8984bd2e
PB
7343 tmp = load_reg(s, rn);
7344 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
7345 if ((insn & 0x70) != 0)
7346 goto illegal_op;
7347 op = (insn >> 21) & 3;
8984bd2e
PB
7348 logic_cc = (insn & (1 << 20)) != 0;
7349 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
7350 if (logic_cc)
7351 gen_logic_CC(tmp);
21aeb343 7352 store_reg_bx(env, s, rd, tmp);
9ee6e8bb
PB
7353 break;
7354 case 1: /* Sign/zero extend. */
5e3f878a 7355 tmp = load_reg(s, rm);
9ee6e8bb
PB
7356 shift = (insn >> 4) & 3;
7357 /* ??? In many cases it's not neccessary to do a
7358 rotate, a shift is sufficient. */
7359 if (shift != 0)
5e3f878a 7360 tcg_gen_rori_i32(tmp, tmp, shift * 8);
9ee6e8bb
PB
7361 op = (insn >> 20) & 7;
7362 switch (op) {
5e3f878a
PB
7363 case 0: gen_sxth(tmp); break;
7364 case 1: gen_uxth(tmp); break;
7365 case 2: gen_sxtb16(tmp); break;
7366 case 3: gen_uxtb16(tmp); break;
7367 case 4: gen_sxtb(tmp); break;
7368 case 5: gen_uxtb(tmp); break;
9ee6e8bb
PB
7369 default: goto illegal_op;
7370 }
7371 if (rn != 15) {
5e3f878a 7372 tmp2 = load_reg(s, rn);
9ee6e8bb 7373 if ((op >> 1) == 1) {
5e3f878a 7374 gen_add16(tmp, tmp2);
9ee6e8bb 7375 } else {
5e3f878a
PB
7376 tcg_gen_add_i32(tmp, tmp, tmp2);
7377 dead_tmp(tmp2);
9ee6e8bb
PB
7378 }
7379 }
5e3f878a 7380 store_reg(s, rd, tmp);
9ee6e8bb
PB
7381 break;
7382 case 2: /* SIMD add/subtract. */
7383 op = (insn >> 20) & 7;
7384 shift = (insn >> 4) & 7;
7385 if ((op & 3) == 3 || (shift & 3) == 3)
7386 goto illegal_op;
6ddbc6e4
PB
7387 tmp = load_reg(s, rn);
7388 tmp2 = load_reg(s, rm);
7389 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
7390 dead_tmp(tmp2);
7391 store_reg(s, rd, tmp);
9ee6e8bb
PB
7392 break;
7393 case 3: /* Other data processing. */
7394 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
7395 if (op < 4) {
7396 /* Saturating add/subtract. */
d9ba4830
PB
7397 tmp = load_reg(s, rn);
7398 tmp2 = load_reg(s, rm);
9ee6e8bb 7399 if (op & 2)
d9ba4830 7400 gen_helper_double_saturate(tmp, tmp);
9ee6e8bb 7401 if (op & 1)
d9ba4830 7402 gen_helper_sub_saturate(tmp, tmp2, tmp);
9ee6e8bb 7403 else
d9ba4830
PB
7404 gen_helper_add_saturate(tmp, tmp, tmp2);
7405 dead_tmp(tmp2);
9ee6e8bb 7406 } else {
d9ba4830 7407 tmp = load_reg(s, rn);
9ee6e8bb
PB
7408 switch (op) {
7409 case 0x0a: /* rbit */
d9ba4830 7410 gen_helper_rbit(tmp, tmp);
9ee6e8bb
PB
7411 break;
7412 case 0x08: /* rev */
66896cb8 7413 tcg_gen_bswap32_i32(tmp, tmp);
9ee6e8bb
PB
7414 break;
7415 case 0x09: /* rev16 */
d9ba4830 7416 gen_rev16(tmp);
9ee6e8bb
PB
7417 break;
7418 case 0x0b: /* revsh */
d9ba4830 7419 gen_revsh(tmp);
9ee6e8bb
PB
7420 break;
7421 case 0x10: /* sel */
d9ba4830 7422 tmp2 = load_reg(s, rm);
6ddbc6e4
PB
7423 tmp3 = new_tmp();
7424 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
d9ba4830 7425 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
6ddbc6e4 7426 dead_tmp(tmp3);
d9ba4830 7427 dead_tmp(tmp2);
9ee6e8bb
PB
7428 break;
7429 case 0x18: /* clz */
d9ba4830 7430 gen_helper_clz(tmp, tmp);
9ee6e8bb
PB
7431 break;
7432 default:
7433 goto illegal_op;
7434 }
7435 }
d9ba4830 7436 store_reg(s, rd, tmp);
9ee6e8bb
PB
7437 break;
7438 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7439 op = (insn >> 4) & 0xf;
d9ba4830
PB
7440 tmp = load_reg(s, rn);
7441 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
7442 switch ((insn >> 20) & 7) {
7443 case 0: /* 32 x 32 -> 32 */
d9ba4830
PB
7444 tcg_gen_mul_i32(tmp, tmp, tmp2);
7445 dead_tmp(tmp2);
9ee6e8bb 7446 if (rs != 15) {
d9ba4830 7447 tmp2 = load_reg(s, rs);
9ee6e8bb 7448 if (op)
d9ba4830 7449 tcg_gen_sub_i32(tmp, tmp2, tmp);
9ee6e8bb 7450 else
d9ba4830
PB
7451 tcg_gen_add_i32(tmp, tmp, tmp2);
7452 dead_tmp(tmp2);
9ee6e8bb 7453 }
9ee6e8bb
PB
7454 break;
7455 case 1: /* 16 x 16 -> 32 */
d9ba4830
PB
7456 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7457 dead_tmp(tmp2);
9ee6e8bb 7458 if (rs != 15) {
d9ba4830
PB
7459 tmp2 = load_reg(s, rs);
7460 gen_helper_add_setq(tmp, tmp, tmp2);
7461 dead_tmp(tmp2);
9ee6e8bb 7462 }
9ee6e8bb
PB
7463 break;
7464 case 2: /* Dual multiply add. */
7465 case 4: /* Dual multiply subtract. */
7466 if (op)
d9ba4830
PB
7467 gen_swap_half(tmp2);
7468 gen_smul_dual(tmp, tmp2);
9ee6e8bb
PB
7469 /* This addition cannot overflow. */
7470 if (insn & (1 << 22)) {
d9ba4830 7471 tcg_gen_sub_i32(tmp, tmp, tmp2);
9ee6e8bb 7472 } else {
d9ba4830 7473 tcg_gen_add_i32(tmp, tmp, tmp2);
9ee6e8bb 7474 }
d9ba4830 7475 dead_tmp(tmp2);
9ee6e8bb
PB
7476 if (rs != 15)
7477 {
d9ba4830
PB
7478 tmp2 = load_reg(s, rs);
7479 gen_helper_add_setq(tmp, tmp, tmp2);
7480 dead_tmp(tmp2);
9ee6e8bb 7481 }
9ee6e8bb
PB
7482 break;
7483 case 3: /* 32 * 16 -> 32msb */
7484 if (op)
d9ba4830 7485 tcg_gen_sari_i32(tmp2, tmp2, 16);
9ee6e8bb 7486 else
d9ba4830 7487 gen_sxth(tmp2);
a7812ae4
PB
7488 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7489 tcg_gen_shri_i64(tmp64, tmp64, 16);
5e3f878a 7490 tmp = new_tmp();
a7812ae4 7491 tcg_gen_trunc_i64_i32(tmp, tmp64);
9ee6e8bb
PB
7492 if (rs != 15)
7493 {
d9ba4830
PB
7494 tmp2 = load_reg(s, rs);
7495 gen_helper_add_setq(tmp, tmp, tmp2);
7496 dead_tmp(tmp2);
9ee6e8bb 7497 }
9ee6e8bb
PB
7498 break;
7499 case 5: case 6: /* 32 * 32 -> 32msb */
d9ba4830
PB
7500 gen_imull(tmp, tmp2);
7501 if (insn & (1 << 5)) {
7502 gen_roundqd(tmp, tmp2);
7503 dead_tmp(tmp2);
7504 } else {
7505 dead_tmp(tmp);
7506 tmp = tmp2;
7507 }
9ee6e8bb 7508 if (rs != 15) {
d9ba4830 7509 tmp2 = load_reg(s, rs);
9ee6e8bb 7510 if (insn & (1 << 21)) {
d9ba4830 7511 tcg_gen_add_i32(tmp, tmp, tmp2);
99c475ab 7512 } else {
d9ba4830 7513 tcg_gen_sub_i32(tmp, tmp2, tmp);
99c475ab 7514 }
d9ba4830 7515 dead_tmp(tmp2);
2c0262af 7516 }
9ee6e8bb
PB
7517 break;
7518 case 7: /* Unsigned sum of absolute differences. */
d9ba4830
PB
7519 gen_helper_usad8(tmp, tmp, tmp2);
7520 dead_tmp(tmp2);
9ee6e8bb 7521 if (rs != 15) {
d9ba4830
PB
7522 tmp2 = load_reg(s, rs);
7523 tcg_gen_add_i32(tmp, tmp, tmp2);
7524 dead_tmp(tmp2);
5fd46862 7525 }
9ee6e8bb 7526 break;
2c0262af 7527 }
d9ba4830 7528 store_reg(s, rd, tmp);
2c0262af 7529 break;
9ee6e8bb
PB
7530 case 6: case 7: /* 64-bit multiply, Divide. */
7531 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
5e3f878a
PB
7532 tmp = load_reg(s, rn);
7533 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
7534 if ((op & 0x50) == 0x10) {
7535 /* sdiv, udiv */
7536 if (!arm_feature(env, ARM_FEATURE_DIV))
7537 goto illegal_op;
7538 if (op & 0x20)
5e3f878a 7539 gen_helper_udiv(tmp, tmp, tmp2);
2c0262af 7540 else
5e3f878a
PB
7541 gen_helper_sdiv(tmp, tmp, tmp2);
7542 dead_tmp(tmp2);
7543 store_reg(s, rd, tmp);
9ee6e8bb
PB
7544 } else if ((op & 0xe) == 0xc) {
7545 /* Dual multiply accumulate long. */
7546 if (op & 1)
5e3f878a
PB
7547 gen_swap_half(tmp2);
7548 gen_smul_dual(tmp, tmp2);
9ee6e8bb 7549 if (op & 0x10) {
5e3f878a 7550 tcg_gen_sub_i32(tmp, tmp, tmp2);
b5ff1b31 7551 } else {
5e3f878a 7552 tcg_gen_add_i32(tmp, tmp, tmp2);
b5ff1b31 7553 }
5e3f878a 7554 dead_tmp(tmp2);
a7812ae4
PB
7555 /* BUGFIX */
7556 tmp64 = tcg_temp_new_i64();
7557 tcg_gen_ext_i32_i64(tmp64, tmp);
7558 dead_tmp(tmp);
7559 gen_addq(s, tmp64, rs, rd);
7560 gen_storeq_reg(s, rs, rd, tmp64);
2c0262af 7561 } else {
9ee6e8bb
PB
7562 if (op & 0x20) {
7563 /* Unsigned 64-bit multiply */
a7812ae4 7564 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
b5ff1b31 7565 } else {
9ee6e8bb
PB
7566 if (op & 8) {
7567 /* smlalxy */
5e3f878a
PB
7568 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7569 dead_tmp(tmp2);
a7812ae4
PB
7570 tmp64 = tcg_temp_new_i64();
7571 tcg_gen_ext_i32_i64(tmp64, tmp);
5e3f878a 7572 dead_tmp(tmp);
9ee6e8bb
PB
7573 } else {
7574 /* Signed 64-bit multiply */
a7812ae4 7575 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9ee6e8bb 7576 }
b5ff1b31 7577 }
9ee6e8bb
PB
7578 if (op & 4) {
7579 /* umaal */
a7812ae4
PB
7580 gen_addq_lo(s, tmp64, rs);
7581 gen_addq_lo(s, tmp64, rd);
9ee6e8bb
PB
7582 } else if (op & 0x40) {
7583 /* 64-bit accumulate. */
a7812ae4 7584 gen_addq(s, tmp64, rs, rd);
9ee6e8bb 7585 }
a7812ae4 7586 gen_storeq_reg(s, rs, rd, tmp64);
5fd46862 7587 }
2c0262af 7588 break;
9ee6e8bb
PB
7589 }
7590 break;
7591 case 6: case 7: case 14: case 15:
7592 /* Coprocessor. */
7593 if (((insn >> 24) & 3) == 3) {
7594 /* Translate into the equivalent ARM encoding. */
7595 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4);
7596 if (disas_neon_data_insn(env, s, insn))
7597 goto illegal_op;
7598 } else {
7599 if (insn & (1 << 28))
7600 goto illegal_op;
7601 if (disas_coproc_insn (env, s, insn))
7602 goto illegal_op;
7603 }
7604 break;
7605 case 8: case 9: case 10: case 11:
7606 if (insn & (1 << 15)) {
7607 /* Branches, misc control. */
7608 if (insn & 0x5000) {
7609 /* Unconditional branch. */
7610 /* signextend(hw1[10:0]) -> offset[:12]. */
7611 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
7612 /* hw1[10:0] -> offset[11:1]. */
7613 offset |= (insn & 0x7ff) << 1;
7614 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7615 offset[24:22] already have the same value because of the
7616 sign extension above. */
7617 offset ^= ((~insn) & (1 << 13)) << 10;
7618 offset ^= ((~insn) & (1 << 11)) << 11;
7619
9ee6e8bb
PB
7620 if (insn & (1 << 14)) {
7621 /* Branch and link. */
b0109805 7622 gen_op_movl_T1_im(s->pc | 1);
9ee6e8bb 7623 gen_movl_reg_T1(s, 14);
b5ff1b31 7624 }
3b46e624 7625
b0109805 7626 offset += s->pc;
9ee6e8bb
PB
7627 if (insn & (1 << 12)) {
7628 /* b/bl */
b0109805 7629 gen_jmp(s, offset);
9ee6e8bb
PB
7630 } else {
7631 /* blx */
b0109805
PB
7632 offset &= ~(uint32_t)2;
7633 gen_bx_im(s, offset);
2c0262af 7634 }
9ee6e8bb
PB
7635 } else if (((insn >> 23) & 7) == 7) {
7636 /* Misc control */
7637 if (insn & (1 << 13))
7638 goto illegal_op;
7639
7640 if (insn & (1 << 26)) {
7641 /* Secure monitor call (v6Z) */
7642 goto illegal_op; /* not implemented. */
2c0262af 7643 } else {
9ee6e8bb
PB
7644 op = (insn >> 20) & 7;
7645 switch (op) {
7646 case 0: /* msr cpsr. */
7647 if (IS_M(env)) {
8984bd2e
PB
7648 tmp = load_reg(s, rn);
7649 addr = tcg_const_i32(insn & 0xff);
7650 gen_helper_v7m_msr(cpu_env, addr, tmp);
9ee6e8bb
PB
7651 gen_lookup_tb(s);
7652 break;
7653 }
7654 /* fall through */
7655 case 1: /* msr spsr. */
7656 if (IS_M(env))
7657 goto illegal_op;
2fbac54b
FN
7658 tmp = load_reg(s, rn);
7659 if (gen_set_psr(s,
9ee6e8bb 7660 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
2fbac54b 7661 op == 1, tmp))
9ee6e8bb
PB
7662 goto illegal_op;
7663 break;
7664 case 2: /* cps, nop-hint. */
7665 if (((insn >> 8) & 7) == 0) {
7666 gen_nop_hint(s, insn & 0xff);
7667 }
7668 /* Implemented as NOP in user mode. */
7669 if (IS_USER(s))
7670 break;
7671 offset = 0;
7672 imm = 0;
7673 if (insn & (1 << 10)) {
7674 if (insn & (1 << 7))
7675 offset |= CPSR_A;
7676 if (insn & (1 << 6))
7677 offset |= CPSR_I;
7678 if (insn & (1 << 5))
7679 offset |= CPSR_F;
7680 if (insn & (1 << 9))
7681 imm = CPSR_A | CPSR_I | CPSR_F;
7682 }
7683 if (insn & (1 << 8)) {
7684 offset |= 0x1f;
7685 imm |= (insn & 0x1f);
7686 }
7687 if (offset) {
2fbac54b 7688 gen_set_psr_im(s, offset, 0, imm);
9ee6e8bb
PB
7689 }
7690 break;
7691 case 3: /* Special control operations. */
7692 op = (insn >> 4) & 0xf;
7693 switch (op) {
7694 case 2: /* clrex */
8f8e3aa4 7695 gen_helper_clrex(cpu_env);
9ee6e8bb
PB
7696 break;
7697 case 4: /* dsb */
7698 case 5: /* dmb */
7699 case 6: /* isb */
7700 /* These execute as NOPs. */
7701 ARCH(7);
7702 break;
7703 default:
7704 goto illegal_op;
7705 }
7706 break;
7707 case 4: /* bxj */
7708 /* Trivial implementation equivalent to bx. */
d9ba4830
PB
7709 tmp = load_reg(s, rn);
7710 gen_bx(s, tmp);
9ee6e8bb
PB
7711 break;
7712 case 5: /* Exception return. */
7713 /* Unpredictable in user mode. */
7714 goto illegal_op;
7715 case 6: /* mrs cpsr. */
8984bd2e 7716 tmp = new_tmp();
9ee6e8bb 7717 if (IS_M(env)) {
8984bd2e
PB
7718 addr = tcg_const_i32(insn & 0xff);
7719 gen_helper_v7m_mrs(tmp, cpu_env, addr);
9ee6e8bb 7720 } else {
8984bd2e 7721 gen_helper_cpsr_read(tmp);
9ee6e8bb 7722 }
8984bd2e 7723 store_reg(s, rd, tmp);
9ee6e8bb
PB
7724 break;
7725 case 7: /* mrs spsr. */
7726 /* Not accessible in user mode. */
7727 if (IS_USER(s) || IS_M(env))
7728 goto illegal_op;
d9ba4830
PB
7729 tmp = load_cpu_field(spsr);
7730 store_reg(s, rd, tmp);
9ee6e8bb 7731 break;
2c0262af
FB
7732 }
7733 }
9ee6e8bb
PB
7734 } else {
7735 /* Conditional branch. */
7736 op = (insn >> 22) & 0xf;
7737 /* Generate a conditional jump to next instruction. */
7738 s->condlabel = gen_new_label();
d9ba4830 7739 gen_test_cc(op ^ 1, s->condlabel);
9ee6e8bb
PB
7740 s->condjmp = 1;
7741
7742 /* offset[11:1] = insn[10:0] */
7743 offset = (insn & 0x7ff) << 1;
7744 /* offset[17:12] = insn[21:16]. */
7745 offset |= (insn & 0x003f0000) >> 4;
7746 /* offset[31:20] = insn[26]. */
7747 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
7748 /* offset[18] = insn[13]. */
7749 offset |= (insn & (1 << 13)) << 5;
7750 /* offset[19] = insn[11]. */
7751 offset |= (insn & (1 << 11)) << 8;
7752
7753 /* jump to the offset */
b0109805 7754 gen_jmp(s, s->pc + offset);
9ee6e8bb
PB
7755 }
7756 } else {
7757 /* Data processing immediate. */
7758 if (insn & (1 << 25)) {
7759 if (insn & (1 << 24)) {
7760 if (insn & (1 << 20))
7761 goto illegal_op;
7762 /* Bitfield/Saturate. */
7763 op = (insn >> 21) & 7;
7764 imm = insn & 0x1f;
7765 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
6ddbc6e4
PB
7766 if (rn == 15) {
7767 tmp = new_tmp();
7768 tcg_gen_movi_i32(tmp, 0);
7769 } else {
7770 tmp = load_reg(s, rn);
7771 }
9ee6e8bb
PB
7772 switch (op) {
7773 case 2: /* Signed bitfield extract. */
7774 imm++;
7775 if (shift + imm > 32)
7776 goto illegal_op;
7777 if (imm < 32)
6ddbc6e4 7778 gen_sbfx(tmp, shift, imm);
9ee6e8bb
PB
7779 break;
7780 case 6: /* Unsigned bitfield extract. */
7781 imm++;
7782 if (shift + imm > 32)
7783 goto illegal_op;
7784 if (imm < 32)
6ddbc6e4 7785 gen_ubfx(tmp, shift, (1u << imm) - 1);
9ee6e8bb
PB
7786 break;
7787 case 3: /* Bitfield insert/clear. */
7788 if (imm < shift)
7789 goto illegal_op;
7790 imm = imm + 1 - shift;
7791 if (imm != 32) {
6ddbc6e4 7792 tmp2 = load_reg(s, rd);
8f8e3aa4 7793 gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
6ddbc6e4 7794 dead_tmp(tmp2);
9ee6e8bb
PB
7795 }
7796 break;
7797 case 7:
7798 goto illegal_op;
7799 default: /* Saturate. */
9ee6e8bb
PB
7800 if (shift) {
7801 if (op & 1)
6ddbc6e4 7802 tcg_gen_sari_i32(tmp, tmp, shift);
9ee6e8bb 7803 else
6ddbc6e4 7804 tcg_gen_shli_i32(tmp, tmp, shift);
9ee6e8bb 7805 }
6ddbc6e4 7806 tmp2 = tcg_const_i32(imm);
9ee6e8bb
PB
7807 if (op & 4) {
7808 /* Unsigned. */
9ee6e8bb 7809 if ((op & 1) && shift == 0)
6ddbc6e4 7810 gen_helper_usat16(tmp, tmp, tmp2);
9ee6e8bb 7811 else
6ddbc6e4 7812 gen_helper_usat(tmp, tmp, tmp2);
2c0262af 7813 } else {
9ee6e8bb 7814 /* Signed. */
9ee6e8bb 7815 if ((op & 1) && shift == 0)
6ddbc6e4 7816 gen_helper_ssat16(tmp, tmp, tmp2);
9ee6e8bb 7817 else
6ddbc6e4 7818 gen_helper_ssat(tmp, tmp, tmp2);
2c0262af 7819 }
9ee6e8bb 7820 break;
2c0262af 7821 }
6ddbc6e4 7822 store_reg(s, rd, tmp);
9ee6e8bb
PB
7823 } else {
7824 imm = ((insn & 0x04000000) >> 15)
7825 | ((insn & 0x7000) >> 4) | (insn & 0xff);
7826 if (insn & (1 << 22)) {
7827 /* 16-bit immediate. */
7828 imm |= (insn >> 4) & 0xf000;
7829 if (insn & (1 << 23)) {
7830 /* movt */
5e3f878a 7831 tmp = load_reg(s, rd);
86831435 7832 tcg_gen_ext16u_i32(tmp, tmp);
5e3f878a 7833 tcg_gen_ori_i32(tmp, tmp, imm << 16);
2c0262af 7834 } else {
9ee6e8bb 7835 /* movw */
5e3f878a
PB
7836 tmp = new_tmp();
7837 tcg_gen_movi_i32(tmp, imm);
2c0262af
FB
7838 }
7839 } else {
9ee6e8bb
PB
7840 /* Add/sub 12-bit immediate. */
7841 if (rn == 15) {
b0109805 7842 offset = s->pc & ~(uint32_t)3;
9ee6e8bb 7843 if (insn & (1 << 23))
b0109805 7844 offset -= imm;
9ee6e8bb 7845 else
b0109805 7846 offset += imm;
5e3f878a
PB
7847 tmp = new_tmp();
7848 tcg_gen_movi_i32(tmp, offset);
2c0262af 7849 } else {
5e3f878a 7850 tmp = load_reg(s, rn);
9ee6e8bb 7851 if (insn & (1 << 23))
5e3f878a 7852 tcg_gen_subi_i32(tmp, tmp, imm);
9ee6e8bb 7853 else
5e3f878a 7854 tcg_gen_addi_i32(tmp, tmp, imm);
2c0262af 7855 }
9ee6e8bb 7856 }
5e3f878a 7857 store_reg(s, rd, tmp);
191abaa2 7858 }
9ee6e8bb
PB
7859 } else {
7860 int shifter_out = 0;
7861 /* modified 12-bit immediate. */
7862 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
7863 imm = (insn & 0xff);
7864 switch (shift) {
7865 case 0: /* XY */
7866 /* Nothing to do. */
7867 break;
7868 case 1: /* 00XY00XY */
7869 imm |= imm << 16;
7870 break;
7871 case 2: /* XY00XY00 */
7872 imm |= imm << 16;
7873 imm <<= 8;
7874 break;
7875 case 3: /* XYXYXYXY */
7876 imm |= imm << 16;
7877 imm |= imm << 8;
7878 break;
7879 default: /* Rotated constant. */
7880 shift = (shift << 1) | (imm >> 7);
7881 imm |= 0x80;
7882 imm = imm << (32 - shift);
7883 shifter_out = 1;
7884 break;
b5ff1b31 7885 }
9ee6e8bb
PB
7886 gen_op_movl_T1_im(imm);
7887 rn = (insn >> 16) & 0xf;
7888 if (rn == 15)
7889 gen_op_movl_T0_im(0);
7890 else
7891 gen_movl_T0_reg(s, rn);
7892 op = (insn >> 21) & 0xf;
7893 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
7894 shifter_out))
7895 goto illegal_op;
7896 rd = (insn >> 8) & 0xf;
7897 if (rd != 15) {
7898 gen_movl_reg_T0(s, rd);
2c0262af 7899 }
2c0262af 7900 }
9ee6e8bb
PB
7901 }
7902 break;
7903 case 12: /* Load/store single data item. */
7904 {
7905 int postinc = 0;
7906 int writeback = 0;
b0109805 7907 int user;
9ee6e8bb
PB
7908 if ((insn & 0x01100000) == 0x01000000) {
7909 if (disas_neon_ls_insn(env, s, insn))
c1713132 7910 goto illegal_op;
9ee6e8bb
PB
7911 break;
7912 }
b0109805 7913 user = IS_USER(s);
9ee6e8bb 7914 if (rn == 15) {
b0109805 7915 addr = new_tmp();
9ee6e8bb
PB
7916 /* PC relative. */
7917 /* s->pc has already been incremented by 4. */
7918 imm = s->pc & 0xfffffffc;
7919 if (insn & (1 << 23))
7920 imm += insn & 0xfff;
7921 else
7922 imm -= insn & 0xfff;
b0109805 7923 tcg_gen_movi_i32(addr, imm);
9ee6e8bb 7924 } else {
b0109805 7925 addr = load_reg(s, rn);
9ee6e8bb
PB
7926 if (insn & (1 << 23)) {
7927 /* Positive offset. */
7928 imm = insn & 0xfff;
b0109805 7929 tcg_gen_addi_i32(addr, addr, imm);
9ee6e8bb
PB
7930 } else {
7931 op = (insn >> 8) & 7;
7932 imm = insn & 0xff;
7933 switch (op) {
7934 case 0: case 8: /* Shifted Register. */
7935 shift = (insn >> 4) & 0xf;
7936 if (shift > 3)
18c9b560 7937 goto illegal_op;
b26eefb6 7938 tmp = load_reg(s, rm);
9ee6e8bb 7939 if (shift)
b26eefb6 7940 tcg_gen_shli_i32(tmp, tmp, shift);
b0109805 7941 tcg_gen_add_i32(addr, addr, tmp);
b26eefb6 7942 dead_tmp(tmp);
9ee6e8bb
PB
7943 break;
7944 case 4: /* Negative offset. */
b0109805 7945 tcg_gen_addi_i32(addr, addr, -imm);
9ee6e8bb
PB
7946 break;
7947 case 6: /* User privilege. */
b0109805
PB
7948 tcg_gen_addi_i32(addr, addr, imm);
7949 user = 1;
9ee6e8bb
PB
7950 break;
7951 case 1: /* Post-decrement. */
7952 imm = -imm;
7953 /* Fall through. */
7954 case 3: /* Post-increment. */
9ee6e8bb
PB
7955 postinc = 1;
7956 writeback = 1;
7957 break;
7958 case 5: /* Pre-decrement. */
7959 imm = -imm;
7960 /* Fall through. */
7961 case 7: /* Pre-increment. */
b0109805 7962 tcg_gen_addi_i32(addr, addr, imm);
9ee6e8bb
PB
7963 writeback = 1;
7964 break;
7965 default:
b7bcbe95 7966 goto illegal_op;
9ee6e8bb
PB
7967 }
7968 }
7969 }
7970 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
7971 if (insn & (1 << 20)) {
7972 /* Load. */
7973 if (rs == 15 && op != 2) {
7974 if (op & 2)
b5ff1b31 7975 goto illegal_op;
9ee6e8bb
PB
7976 /* Memory hint. Implemented as NOP. */
7977 } else {
7978 switch (op) {
b0109805
PB
7979 case 0: tmp = gen_ld8u(addr, user); break;
7980 case 4: tmp = gen_ld8s(addr, user); break;
7981 case 1: tmp = gen_ld16u(addr, user); break;
7982 case 5: tmp = gen_ld16s(addr, user); break;
7983 case 2: tmp = gen_ld32(addr, user); break;
9ee6e8bb
PB
7984 default: goto illegal_op;
7985 }
7986 if (rs == 15) {
b0109805 7987 gen_bx(s, tmp);
9ee6e8bb 7988 } else {
b0109805 7989 store_reg(s, rs, tmp);
9ee6e8bb
PB
7990 }
7991 }
7992 } else {
7993 /* Store. */
7994 if (rs == 15)
b7bcbe95 7995 goto illegal_op;
b0109805 7996 tmp = load_reg(s, rs);
9ee6e8bb 7997 switch (op) {
b0109805
PB
7998 case 0: gen_st8(tmp, addr, user); break;
7999 case 1: gen_st16(tmp, addr, user); break;
8000 case 2: gen_st32(tmp, addr, user); break;
9ee6e8bb 8001 default: goto illegal_op;
b7bcbe95 8002 }
2c0262af 8003 }
9ee6e8bb 8004 if (postinc)
b0109805
PB
8005 tcg_gen_addi_i32(addr, addr, imm);
8006 if (writeback) {
8007 store_reg(s, rn, addr);
8008 } else {
8009 dead_tmp(addr);
8010 }
9ee6e8bb
PB
8011 }
8012 break;
8013 default:
8014 goto illegal_op;
2c0262af 8015 }
9ee6e8bb
PB
8016 return 0;
8017illegal_op:
8018 return 1;
2c0262af
FB
8019}
8020
9ee6e8bb 8021static void disas_thumb_insn(CPUState *env, DisasContext *s)
99c475ab
FB
8022{
8023 uint32_t val, insn, op, rm, rn, rd, shift, cond;
8024 int32_t offset;
8025 int i;
b26eefb6 8026 TCGv tmp;
d9ba4830 8027 TCGv tmp2;
b0109805 8028 TCGv addr;
99c475ab 8029
9ee6e8bb
PB
8030 if (s->condexec_mask) {
8031 cond = s->condexec_cond;
8032 s->condlabel = gen_new_label();
d9ba4830 8033 gen_test_cc(cond ^ 1, s->condlabel);
9ee6e8bb
PB
8034 s->condjmp = 1;
8035 }
8036
b5ff1b31 8037 insn = lduw_code(s->pc);
99c475ab 8038 s->pc += 2;
b5ff1b31 8039
99c475ab
FB
8040 switch (insn >> 12) {
8041 case 0: case 1:
8042 rd = insn & 7;
8043 op = (insn >> 11) & 3;
8044 if (op == 3) {
8045 /* add/subtract */
8046 rn = (insn >> 3) & 7;
8047 gen_movl_T0_reg(s, rn);
8048 if (insn & (1 << 10)) {
8049 /* immediate */
8050 gen_op_movl_T1_im((insn >> 6) & 7);
8051 } else {
8052 /* reg */
8053 rm = (insn >> 6) & 7;
8054 gen_movl_T1_reg(s, rm);
8055 }
9ee6e8bb
PB
8056 if (insn & (1 << 9)) {
8057 if (s->condexec_mask)
8058 gen_op_subl_T0_T1();
8059 else
8060 gen_op_subl_T0_T1_cc();
8061 } else {
8062 if (s->condexec_mask)
8063 gen_op_addl_T0_T1();
8064 else
8065 gen_op_addl_T0_T1_cc();
8066 }
99c475ab
FB
8067 gen_movl_reg_T0(s, rd);
8068 } else {
8069 /* shift immediate */
8070 rm = (insn >> 3) & 7;
8071 shift = (insn >> 6) & 0x1f;
9a119ff6
PB
8072 tmp = load_reg(s, rm);
8073 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
8074 if (!s->condexec_mask)
8075 gen_logic_CC(tmp);
8076 store_reg(s, rd, tmp);
99c475ab
FB
8077 }
8078 break;
8079 case 2: case 3:
8080 /* arithmetic large immediate */
8081 op = (insn >> 11) & 3;
8082 rd = (insn >> 8) & 0x7;
8083 if (op == 0) {
8084 gen_op_movl_T0_im(insn & 0xff);
8085 } else {
8086 gen_movl_T0_reg(s, rd);
8087 gen_op_movl_T1_im(insn & 0xff);
8088 }
8089 switch (op) {
8090 case 0: /* mov */
9ee6e8bb
PB
8091 if (!s->condexec_mask)
8092 gen_op_logic_T0_cc();
99c475ab
FB
8093 break;
8094 case 1: /* cmp */
8095 gen_op_subl_T0_T1_cc();
8096 break;
8097 case 2: /* add */
9ee6e8bb
PB
8098 if (s->condexec_mask)
8099 gen_op_addl_T0_T1();
8100 else
8101 gen_op_addl_T0_T1_cc();
99c475ab
FB
8102 break;
8103 case 3: /* sub */
9ee6e8bb
PB
8104 if (s->condexec_mask)
8105 gen_op_subl_T0_T1();
8106 else
8107 gen_op_subl_T0_T1_cc();
99c475ab
FB
8108 break;
8109 }
8110 if (op != 1)
8111 gen_movl_reg_T0(s, rd);
8112 break;
8113 case 4:
8114 if (insn & (1 << 11)) {
8115 rd = (insn >> 8) & 7;
5899f386
FB
8116 /* load pc-relative. Bit 1 of PC is ignored. */
8117 val = s->pc + 2 + ((insn & 0xff) * 4);
8118 val &= ~(uint32_t)2;
b0109805
PB
8119 addr = new_tmp();
8120 tcg_gen_movi_i32(addr, val);
8121 tmp = gen_ld32(addr, IS_USER(s));
8122 dead_tmp(addr);
8123 store_reg(s, rd, tmp);
99c475ab
FB
8124 break;
8125 }
8126 if (insn & (1 << 10)) {
8127 /* data processing extended or blx */
8128 rd = (insn & 7) | ((insn >> 4) & 8);
8129 rm = (insn >> 3) & 0xf;
8130 op = (insn >> 8) & 3;
8131 switch (op) {
8132 case 0: /* add */
8133 gen_movl_T0_reg(s, rd);
8134 gen_movl_T1_reg(s, rm);
8135 gen_op_addl_T0_T1();
8136 gen_movl_reg_T0(s, rd);
8137 break;
8138 case 1: /* cmp */
8139 gen_movl_T0_reg(s, rd);
8140 gen_movl_T1_reg(s, rm);
8141 gen_op_subl_T0_T1_cc();
8142 break;
8143 case 2: /* mov/cpy */
8144 gen_movl_T0_reg(s, rm);
8145 gen_movl_reg_T0(s, rd);
8146 break;
8147 case 3:/* branch [and link] exchange thumb register */
b0109805 8148 tmp = load_reg(s, rm);
99c475ab
FB
8149 if (insn & (1 << 7)) {
8150 val = (uint32_t)s->pc | 1;
b0109805
PB
8151 tmp2 = new_tmp();
8152 tcg_gen_movi_i32(tmp2, val);
8153 store_reg(s, 14, tmp2);
99c475ab 8154 }
d9ba4830 8155 gen_bx(s, tmp);
99c475ab
FB
8156 break;
8157 }
8158 break;
8159 }
8160
8161 /* data processing register */
8162 rd = insn & 7;
8163 rm = (insn >> 3) & 7;
8164 op = (insn >> 6) & 0xf;
8165 if (op == 2 || op == 3 || op == 4 || op == 7) {
8166 /* the shift/rotate ops want the operands backwards */
8167 val = rm;
8168 rm = rd;
8169 rd = val;
8170 val = 1;
8171 } else {
8172 val = 0;
8173 }
8174
8175 if (op == 9) /* neg */
8176 gen_op_movl_T0_im(0);
8177 else if (op != 0xf) /* mvn doesn't read its first operand */
8178 gen_movl_T0_reg(s, rd);
8179
8180 gen_movl_T1_reg(s, rm);
5899f386 8181 switch (op) {
99c475ab
FB
8182 case 0x0: /* and */
8183 gen_op_andl_T0_T1();
9ee6e8bb
PB
8184 if (!s->condexec_mask)
8185 gen_op_logic_T0_cc();
99c475ab
FB
8186 break;
8187 case 0x1: /* eor */
8188 gen_op_xorl_T0_T1();
9ee6e8bb
PB
8189 if (!s->condexec_mask)
8190 gen_op_logic_T0_cc();
99c475ab
FB
8191 break;
8192 case 0x2: /* lsl */
9ee6e8bb 8193 if (s->condexec_mask) {
8984bd2e 8194 gen_helper_shl(cpu_T[1], cpu_T[1], cpu_T[0]);
9ee6e8bb 8195 } else {
8984bd2e 8196 gen_helper_shl_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
9ee6e8bb
PB
8197 gen_op_logic_T1_cc();
8198 }
99c475ab
FB
8199 break;
8200 case 0x3: /* lsr */
9ee6e8bb 8201 if (s->condexec_mask) {
8984bd2e 8202 gen_helper_shr(cpu_T[1], cpu_T[1], cpu_T[0]);
9ee6e8bb 8203 } else {
8984bd2e 8204 gen_helper_shr_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
9ee6e8bb
PB
8205 gen_op_logic_T1_cc();
8206 }
99c475ab
FB
8207 break;
8208 case 0x4: /* asr */
9ee6e8bb 8209 if (s->condexec_mask) {
8984bd2e 8210 gen_helper_sar(cpu_T[1], cpu_T[1], cpu_T[0]);
9ee6e8bb 8211 } else {
8984bd2e 8212 gen_helper_sar_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
9ee6e8bb
PB
8213 gen_op_logic_T1_cc();
8214 }
99c475ab
FB
8215 break;
8216 case 0x5: /* adc */
9ee6e8bb 8217 if (s->condexec_mask)
b26eefb6 8218 gen_adc_T0_T1();
9ee6e8bb
PB
8219 else
8220 gen_op_adcl_T0_T1_cc();
99c475ab
FB
8221 break;
8222 case 0x6: /* sbc */
9ee6e8bb 8223 if (s->condexec_mask)
3670669c 8224 gen_sbc_T0_T1();
9ee6e8bb
PB
8225 else
8226 gen_op_sbcl_T0_T1_cc();
99c475ab
FB
8227 break;
8228 case 0x7: /* ror */
9ee6e8bb 8229 if (s->condexec_mask) {
8984bd2e 8230 gen_helper_ror(cpu_T[1], cpu_T[1], cpu_T[0]);
9ee6e8bb 8231 } else {
8984bd2e 8232 gen_helper_ror_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
9ee6e8bb
PB
8233 gen_op_logic_T1_cc();
8234 }
99c475ab
FB
8235 break;
8236 case 0x8: /* tst */
8237 gen_op_andl_T0_T1();
8238 gen_op_logic_T0_cc();
8239 rd = 16;
5899f386 8240 break;
99c475ab 8241 case 0x9: /* neg */
9ee6e8bb 8242 if (s->condexec_mask)
390efc54 8243 tcg_gen_neg_i32(cpu_T[0], cpu_T[1]);
9ee6e8bb
PB
8244 else
8245 gen_op_subl_T0_T1_cc();
99c475ab
FB
8246 break;
8247 case 0xa: /* cmp */
8248 gen_op_subl_T0_T1_cc();
8249 rd = 16;
8250 break;
8251 case 0xb: /* cmn */
8252 gen_op_addl_T0_T1_cc();
8253 rd = 16;
8254 break;
8255 case 0xc: /* orr */
8256 gen_op_orl_T0_T1();
9ee6e8bb
PB
8257 if (!s->condexec_mask)
8258 gen_op_logic_T0_cc();
99c475ab
FB
8259 break;
8260 case 0xd: /* mul */
8261 gen_op_mull_T0_T1();
9ee6e8bb
PB
8262 if (!s->condexec_mask)
8263 gen_op_logic_T0_cc();
99c475ab
FB
8264 break;
8265 case 0xe: /* bic */
8266 gen_op_bicl_T0_T1();
9ee6e8bb
PB
8267 if (!s->condexec_mask)
8268 gen_op_logic_T0_cc();
99c475ab
FB
8269 break;
8270 case 0xf: /* mvn */
8271 gen_op_notl_T1();
9ee6e8bb
PB
8272 if (!s->condexec_mask)
8273 gen_op_logic_T1_cc();
99c475ab 8274 val = 1;
5899f386 8275 rm = rd;
99c475ab
FB
8276 break;
8277 }
8278 if (rd != 16) {
8279 if (val)
5899f386 8280 gen_movl_reg_T1(s, rm);
99c475ab
FB
8281 else
8282 gen_movl_reg_T0(s, rd);
8283 }
8284 break;
8285
8286 case 5:
8287 /* load/store register offset. */
8288 rd = insn & 7;
8289 rn = (insn >> 3) & 7;
8290 rm = (insn >> 6) & 7;
8291 op = (insn >> 9) & 7;
b0109805 8292 addr = load_reg(s, rn);
b26eefb6 8293 tmp = load_reg(s, rm);
b0109805 8294 tcg_gen_add_i32(addr, addr, tmp);
b26eefb6 8295 dead_tmp(tmp);
99c475ab
FB
8296
8297 if (op < 3) /* store */
b0109805 8298 tmp = load_reg(s, rd);
99c475ab
FB
8299
8300 switch (op) {
8301 case 0: /* str */
b0109805 8302 gen_st32(tmp, addr, IS_USER(s));
99c475ab
FB
8303 break;
8304 case 1: /* strh */
b0109805 8305 gen_st16(tmp, addr, IS_USER(s));
99c475ab
FB
8306 break;
8307 case 2: /* strb */
b0109805 8308 gen_st8(tmp, addr, IS_USER(s));
99c475ab
FB
8309 break;
8310 case 3: /* ldrsb */
b0109805 8311 tmp = gen_ld8s(addr, IS_USER(s));
99c475ab
FB
8312 break;
8313 case 4: /* ldr */
b0109805 8314 tmp = gen_ld32(addr, IS_USER(s));
99c475ab
FB
8315 break;
8316 case 5: /* ldrh */
b0109805 8317 tmp = gen_ld16u(addr, IS_USER(s));
99c475ab
FB
8318 break;
8319 case 6: /* ldrb */
b0109805 8320 tmp = gen_ld8u(addr, IS_USER(s));
99c475ab
FB
8321 break;
8322 case 7: /* ldrsh */
b0109805 8323 tmp = gen_ld16s(addr, IS_USER(s));
99c475ab
FB
8324 break;
8325 }
8326 if (op >= 3) /* load */
b0109805
PB
8327 store_reg(s, rd, tmp);
8328 dead_tmp(addr);
99c475ab
FB
8329 break;
8330
8331 case 6:
8332 /* load/store word immediate offset */
8333 rd = insn & 7;
8334 rn = (insn >> 3) & 7;
b0109805 8335 addr = load_reg(s, rn);
99c475ab 8336 val = (insn >> 4) & 0x7c;
b0109805 8337 tcg_gen_addi_i32(addr, addr, val);
99c475ab
FB
8338
8339 if (insn & (1 << 11)) {
8340 /* load */
b0109805
PB
8341 tmp = gen_ld32(addr, IS_USER(s));
8342 store_reg(s, rd, tmp);
99c475ab
FB
8343 } else {
8344 /* store */
b0109805
PB
8345 tmp = load_reg(s, rd);
8346 gen_st32(tmp, addr, IS_USER(s));
99c475ab 8347 }
b0109805 8348 dead_tmp(addr);
99c475ab
FB
8349 break;
8350
8351 case 7:
8352 /* load/store byte immediate offset */
8353 rd = insn & 7;
8354 rn = (insn >> 3) & 7;
b0109805 8355 addr = load_reg(s, rn);
99c475ab 8356 val = (insn >> 6) & 0x1f;
b0109805 8357 tcg_gen_addi_i32(addr, addr, val);
99c475ab
FB
8358
8359 if (insn & (1 << 11)) {
8360 /* load */
b0109805
PB
8361 tmp = gen_ld8u(addr, IS_USER(s));
8362 store_reg(s, rd, tmp);
99c475ab
FB
8363 } else {
8364 /* store */
b0109805
PB
8365 tmp = load_reg(s, rd);
8366 gen_st8(tmp, addr, IS_USER(s));
99c475ab 8367 }
b0109805 8368 dead_tmp(addr);
99c475ab
FB
8369 break;
8370
8371 case 8:
8372 /* load/store halfword immediate offset */
8373 rd = insn & 7;
8374 rn = (insn >> 3) & 7;
b0109805 8375 addr = load_reg(s, rn);
99c475ab 8376 val = (insn >> 5) & 0x3e;
b0109805 8377 tcg_gen_addi_i32(addr, addr, val);
99c475ab
FB
8378
8379 if (insn & (1 << 11)) {
8380 /* load */
b0109805
PB
8381 tmp = gen_ld16u(addr, IS_USER(s));
8382 store_reg(s, rd, tmp);
99c475ab
FB
8383 } else {
8384 /* store */
b0109805
PB
8385 tmp = load_reg(s, rd);
8386 gen_st16(tmp, addr, IS_USER(s));
99c475ab 8387 }
b0109805 8388 dead_tmp(addr);
99c475ab
FB
8389 break;
8390
8391 case 9:
8392 /* load/store from stack */
8393 rd = (insn >> 8) & 7;
b0109805 8394 addr = load_reg(s, 13);
99c475ab 8395 val = (insn & 0xff) * 4;
b0109805 8396 tcg_gen_addi_i32(addr, addr, val);
99c475ab
FB
8397
8398 if (insn & (1 << 11)) {
8399 /* load */
b0109805
PB
8400 tmp = gen_ld32(addr, IS_USER(s));
8401 store_reg(s, rd, tmp);
99c475ab
FB
8402 } else {
8403 /* store */
b0109805
PB
8404 tmp = load_reg(s, rd);
8405 gen_st32(tmp, addr, IS_USER(s));
99c475ab 8406 }
b0109805 8407 dead_tmp(addr);
99c475ab
FB
8408 break;
8409
8410 case 10:
8411 /* add to high reg */
8412 rd = (insn >> 8) & 7;
5899f386
FB
8413 if (insn & (1 << 11)) {
8414 /* SP */
5e3f878a 8415 tmp = load_reg(s, 13);
5899f386
FB
8416 } else {
8417 /* PC. bit 1 is ignored. */
5e3f878a
PB
8418 tmp = new_tmp();
8419 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
5899f386 8420 }
99c475ab 8421 val = (insn & 0xff) * 4;
5e3f878a
PB
8422 tcg_gen_addi_i32(tmp, tmp, val);
8423 store_reg(s, rd, tmp);
99c475ab
FB
8424 break;
8425
8426 case 11:
8427 /* misc */
8428 op = (insn >> 8) & 0xf;
8429 switch (op) {
8430 case 0:
8431 /* adjust stack pointer */
b26eefb6 8432 tmp = load_reg(s, 13);
99c475ab
FB
8433 val = (insn & 0x7f) * 4;
8434 if (insn & (1 << 7))
6a0d8a1d 8435 val = -(int32_t)val;
b26eefb6
PB
8436 tcg_gen_addi_i32(tmp, tmp, val);
8437 store_reg(s, 13, tmp);
99c475ab
FB
8438 break;
8439
9ee6e8bb
PB
8440 case 2: /* sign/zero extend. */
8441 ARCH(6);
8442 rd = insn & 7;
8443 rm = (insn >> 3) & 7;
b0109805 8444 tmp = load_reg(s, rm);
9ee6e8bb 8445 switch ((insn >> 6) & 3) {
b0109805
PB
8446 case 0: gen_sxth(tmp); break;
8447 case 1: gen_sxtb(tmp); break;
8448 case 2: gen_uxth(tmp); break;
8449 case 3: gen_uxtb(tmp); break;
9ee6e8bb 8450 }
b0109805 8451 store_reg(s, rd, tmp);
9ee6e8bb 8452 break;
99c475ab
FB
8453 case 4: case 5: case 0xc: case 0xd:
8454 /* push/pop */
b0109805 8455 addr = load_reg(s, 13);
5899f386
FB
8456 if (insn & (1 << 8))
8457 offset = 4;
99c475ab 8458 else
5899f386
FB
8459 offset = 0;
8460 for (i = 0; i < 8; i++) {
8461 if (insn & (1 << i))
8462 offset += 4;
8463 }
8464 if ((insn & (1 << 11)) == 0) {
b0109805 8465 tcg_gen_addi_i32(addr, addr, -offset);
5899f386 8466 }
99c475ab
FB
8467 for (i = 0; i < 8; i++) {
8468 if (insn & (1 << i)) {
8469 if (insn & (1 << 11)) {
8470 /* pop */
b0109805
PB
8471 tmp = gen_ld32(addr, IS_USER(s));
8472 store_reg(s, i, tmp);
99c475ab
FB
8473 } else {
8474 /* push */
b0109805
PB
8475 tmp = load_reg(s, i);
8476 gen_st32(tmp, addr, IS_USER(s));
99c475ab 8477 }
5899f386 8478 /* advance to the next address. */
b0109805 8479 tcg_gen_addi_i32(addr, addr, 4);
99c475ab
FB
8480 }
8481 }
a50f5b91 8482 TCGV_UNUSED(tmp);
99c475ab
FB
8483 if (insn & (1 << 8)) {
8484 if (insn & (1 << 11)) {
8485 /* pop pc */
b0109805 8486 tmp = gen_ld32(addr, IS_USER(s));
99c475ab
FB
8487 /* don't set the pc until the rest of the instruction
8488 has completed */
8489 } else {
8490 /* push lr */
b0109805
PB
8491 tmp = load_reg(s, 14);
8492 gen_st32(tmp, addr, IS_USER(s));
99c475ab 8493 }
b0109805 8494 tcg_gen_addi_i32(addr, addr, 4);
99c475ab 8495 }
5899f386 8496 if ((insn & (1 << 11)) == 0) {
b0109805 8497 tcg_gen_addi_i32(addr, addr, -offset);
5899f386 8498 }
99c475ab 8499 /* write back the new stack pointer */
b0109805 8500 store_reg(s, 13, addr);
99c475ab
FB
8501 /* set the new PC value */
8502 if ((insn & 0x0900) == 0x0900)
b0109805 8503 gen_bx(s, tmp);
99c475ab
FB
8504 break;
8505
9ee6e8bb
PB
8506 case 1: case 3: case 9: case 11: /* czb */
8507 rm = insn & 7;
d9ba4830 8508 tmp = load_reg(s, rm);
9ee6e8bb
PB
8509 s->condlabel = gen_new_label();
8510 s->condjmp = 1;
8511 if (insn & (1 << 11))
cb63669a 8512 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
9ee6e8bb 8513 else
cb63669a 8514 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
d9ba4830 8515 dead_tmp(tmp);
9ee6e8bb
PB
8516 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
8517 val = (uint32_t)s->pc + 2;
8518 val += offset;
8519 gen_jmp(s, val);
8520 break;
8521
8522 case 15: /* IT, nop-hint. */
8523 if ((insn & 0xf) == 0) {
8524 gen_nop_hint(s, (insn >> 4) & 0xf);
8525 break;
8526 }
8527 /* If Then. */
8528 s->condexec_cond = (insn >> 4) & 0xe;
8529 s->condexec_mask = insn & 0x1f;
8530 /* No actual code generated for this insn, just setup state. */
8531 break;
8532
06c949e6 8533 case 0xe: /* bkpt */
9ee6e8bb 8534 gen_set_condexec(s);
5e3f878a 8535 gen_set_pc_im(s->pc - 2);
d9ba4830 8536 gen_exception(EXCP_BKPT);
06c949e6
PB
8537 s->is_jmp = DISAS_JUMP;
8538 break;
8539
9ee6e8bb
PB
8540 case 0xa: /* rev */
8541 ARCH(6);
8542 rn = (insn >> 3) & 0x7;
8543 rd = insn & 0x7;
b0109805 8544 tmp = load_reg(s, rn);
9ee6e8bb 8545 switch ((insn >> 6) & 3) {
66896cb8 8546 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
b0109805
PB
8547 case 1: gen_rev16(tmp); break;
8548 case 3: gen_revsh(tmp); break;
9ee6e8bb
PB
8549 default: goto illegal_op;
8550 }
b0109805 8551 store_reg(s, rd, tmp);
9ee6e8bb
PB
8552 break;
8553
8554 case 6: /* cps */
8555 ARCH(6);
8556 if (IS_USER(s))
8557 break;
8558 if (IS_M(env)) {
8984bd2e 8559 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
9ee6e8bb 8560 /* PRIMASK */
8984bd2e
PB
8561 if (insn & 1) {
8562 addr = tcg_const_i32(16);
8563 gen_helper_v7m_msr(cpu_env, addr, tmp);
8564 }
9ee6e8bb 8565 /* FAULTMASK */
8984bd2e
PB
8566 if (insn & 2) {
8567 addr = tcg_const_i32(17);
8568 gen_helper_v7m_msr(cpu_env, addr, tmp);
8569 }
9ee6e8bb
PB
8570 gen_lookup_tb(s);
8571 } else {
8572 if (insn & (1 << 4))
8573 shift = CPSR_A | CPSR_I | CPSR_F;
8574 else
8575 shift = 0;
2fbac54b 8576 gen_set_psr_im(s, shift, 0, ((insn & 7) << 6) & shift);
9ee6e8bb
PB
8577 }
8578 break;
8579
99c475ab
FB
8580 default:
8581 goto undef;
8582 }
8583 break;
8584
8585 case 12:
8586 /* load/store multiple */
8587 rn = (insn >> 8) & 0x7;
b0109805 8588 addr = load_reg(s, rn);
99c475ab
FB
8589 for (i = 0; i < 8; i++) {
8590 if (insn & (1 << i)) {
99c475ab
FB
8591 if (insn & (1 << 11)) {
8592 /* load */
b0109805
PB
8593 tmp = gen_ld32(addr, IS_USER(s));
8594 store_reg(s, i, tmp);
99c475ab
FB
8595 } else {
8596 /* store */
b0109805
PB
8597 tmp = load_reg(s, i);
8598 gen_st32(tmp, addr, IS_USER(s));
99c475ab 8599 }
5899f386 8600 /* advance to the next address */
b0109805 8601 tcg_gen_addi_i32(addr, addr, 4);
99c475ab
FB
8602 }
8603 }
5899f386 8604 /* Base register writeback. */
b0109805
PB
8605 if ((insn & (1 << rn)) == 0) {
8606 store_reg(s, rn, addr);
8607 } else {
8608 dead_tmp(addr);
8609 }
99c475ab
FB
8610 break;
8611
8612 case 13:
8613 /* conditional branch or swi */
8614 cond = (insn >> 8) & 0xf;
8615 if (cond == 0xe)
8616 goto undef;
8617
8618 if (cond == 0xf) {
8619 /* swi */
9ee6e8bb 8620 gen_set_condexec(s);
422ebf69 8621 gen_set_pc_im(s->pc);
9ee6e8bb 8622 s->is_jmp = DISAS_SWI;
99c475ab
FB
8623 break;
8624 }
8625 /* generate a conditional jump to next instruction */
e50e6a20 8626 s->condlabel = gen_new_label();
d9ba4830 8627 gen_test_cc(cond ^ 1, s->condlabel);
e50e6a20 8628 s->condjmp = 1;
99c475ab
FB
8629
8630 /* jump to the offset */
5899f386 8631 val = (uint32_t)s->pc + 2;
99c475ab 8632 offset = ((int32_t)insn << 24) >> 24;
5899f386 8633 val += offset << 1;
8aaca4c0 8634 gen_jmp(s, val);
99c475ab
FB
8635 break;
8636
8637 case 14:
358bf29e 8638 if (insn & (1 << 11)) {
9ee6e8bb
PB
8639 if (disas_thumb2_insn(env, s, insn))
8640 goto undef32;
358bf29e
PB
8641 break;
8642 }
9ee6e8bb 8643 /* unconditional branch */
99c475ab
FB
8644 val = (uint32_t)s->pc;
8645 offset = ((int32_t)insn << 21) >> 21;
8646 val += (offset << 1) + 2;
8aaca4c0 8647 gen_jmp(s, val);
99c475ab
FB
8648 break;
8649
8650 case 15:
9ee6e8bb 8651 if (disas_thumb2_insn(env, s, insn))
6a0d8a1d 8652 goto undef32;
9ee6e8bb 8653 break;
99c475ab
FB
8654 }
8655 return;
9ee6e8bb
PB
8656undef32:
8657 gen_set_condexec(s);
5e3f878a 8658 gen_set_pc_im(s->pc - 4);
d9ba4830 8659 gen_exception(EXCP_UDEF);
9ee6e8bb
PB
8660 s->is_jmp = DISAS_JUMP;
8661 return;
8662illegal_op:
99c475ab 8663undef:
9ee6e8bb 8664 gen_set_condexec(s);
5e3f878a 8665 gen_set_pc_im(s->pc - 2);
d9ba4830 8666 gen_exception(EXCP_UDEF);
99c475ab
FB
8667 s->is_jmp = DISAS_JUMP;
8668}
8669
2c0262af
FB
8670/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8671 basic block 'tb'. If search_pc is TRUE, also generate PC
8672 information for each intermediate instruction. */
2cfc5f17
TS
8673static inline void gen_intermediate_code_internal(CPUState *env,
8674 TranslationBlock *tb,
8675 int search_pc)
2c0262af
FB
8676{
8677 DisasContext dc1, *dc = &dc1;
a1d1bb31 8678 CPUBreakpoint *bp;
2c0262af
FB
8679 uint16_t *gen_opc_end;
8680 int j, lj;
0fa85d43 8681 target_ulong pc_start;
b5ff1b31 8682 uint32_t next_page_start;
2e70f6ef
PB
8683 int num_insns;
8684 int max_insns;
3b46e624 8685
2c0262af 8686 /* generate intermediate code */
b26eefb6 8687 num_temps = 0;
b26eefb6 8688
0fa85d43 8689 pc_start = tb->pc;
3b46e624 8690
2c0262af
FB
8691 dc->tb = tb;
8692
2c0262af 8693 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2c0262af
FB
8694
8695 dc->is_jmp = DISAS_NEXT;
8696 dc->pc = pc_start;
8aaca4c0 8697 dc->singlestep_enabled = env->singlestep_enabled;
e50e6a20 8698 dc->condjmp = 0;
5899f386 8699 dc->thumb = env->thumb;
9ee6e8bb
PB
8700 dc->condexec_mask = (env->condexec_bits & 0xf) << 1;
8701 dc->condexec_cond = env->condexec_bits >> 4;
b5ff1b31 8702#if !defined(CONFIG_USER_ONLY)
9ee6e8bb
PB
8703 if (IS_M(env)) {
8704 dc->user = ((env->v7m.exception == 0) && (env->v7m.control & 1));
8705 } else {
8706 dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
8707 }
b5ff1b31 8708#endif
a7812ae4
PB
8709 cpu_F0s = tcg_temp_new_i32();
8710 cpu_F1s = tcg_temp_new_i32();
8711 cpu_F0d = tcg_temp_new_i64();
8712 cpu_F1d = tcg_temp_new_i64();
ad69471c
PB
8713 cpu_V0 = cpu_F0d;
8714 cpu_V1 = cpu_F1d;
e677137d 8715 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
a7812ae4 8716 cpu_M0 = tcg_temp_new_i64();
b5ff1b31 8717 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
2c0262af 8718 lj = -1;
2e70f6ef
PB
8719 num_insns = 0;
8720 max_insns = tb->cflags & CF_COUNT_MASK;
8721 if (max_insns == 0)
8722 max_insns = CF_COUNT_MASK;
8723
8724 gen_icount_start();
9ee6e8bb
PB
8725 /* Reset the conditional execution bits immediately. This avoids
8726 complications trying to do it at the end of the block. */
8727 if (env->condexec_bits)
8f01245e
PB
8728 {
8729 TCGv tmp = new_tmp();
8730 tcg_gen_movi_i32(tmp, 0);
d9ba4830 8731 store_cpu_field(tmp, condexec_bits);
8f01245e 8732 }
2c0262af 8733 do {
fbb4a2e3
PB
8734#ifdef CONFIG_USER_ONLY
8735 /* Intercept jump to the magic kernel page. */
8736 if (dc->pc >= 0xffff0000) {
8737 /* We always get here via a jump, so know we are not in a
8738 conditional execution block. */
8739 gen_exception(EXCP_KERNEL_TRAP);
8740 dc->is_jmp = DISAS_UPDATE;
8741 break;
8742 }
8743#else
9ee6e8bb
PB
8744 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
8745 /* We always get here via a jump, so know we are not in a
8746 conditional execution block. */
d9ba4830 8747 gen_exception(EXCP_EXCEPTION_EXIT);
d60bb01c
PB
8748 dc->is_jmp = DISAS_UPDATE;
8749 break;
9ee6e8bb
PB
8750 }
8751#endif
8752
72cf2d4f
BS
8753 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
8754 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
a1d1bb31 8755 if (bp->pc == dc->pc) {
9ee6e8bb 8756 gen_set_condexec(dc);
5e3f878a 8757 gen_set_pc_im(dc->pc);
d9ba4830 8758 gen_exception(EXCP_DEBUG);
1fddef4b 8759 dc->is_jmp = DISAS_JUMP;
9ee6e8bb
PB
8760 /* Advance PC so that clearing the breakpoint will
8761 invalidate this TB. */
8762 dc->pc += 2;
8763 goto done_generating;
1fddef4b
FB
8764 break;
8765 }
8766 }
8767 }
2c0262af
FB
8768 if (search_pc) {
8769 j = gen_opc_ptr - gen_opc_buf;
8770 if (lj < j) {
8771 lj++;
8772 while (lj < j)
8773 gen_opc_instr_start[lj++] = 0;
8774 }
0fa85d43 8775 gen_opc_pc[lj] = dc->pc;
2c0262af 8776 gen_opc_instr_start[lj] = 1;
2e70f6ef 8777 gen_opc_icount[lj] = num_insns;
2c0262af 8778 }
e50e6a20 8779
2e70f6ef
PB
8780 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8781 gen_io_start();
8782
9ee6e8bb
PB
8783 if (env->thumb) {
8784 disas_thumb_insn(env, dc);
8785 if (dc->condexec_mask) {
8786 dc->condexec_cond = (dc->condexec_cond & 0xe)
8787 | ((dc->condexec_mask >> 4) & 1);
8788 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
8789 if (dc->condexec_mask == 0) {
8790 dc->condexec_cond = 0;
8791 }
8792 }
8793 } else {
8794 disas_arm_insn(env, dc);
8795 }
b26eefb6
PB
8796 if (num_temps) {
8797 fprintf(stderr, "Internal resource leak before %08x\n", dc->pc);
8798 num_temps = 0;
8799 }
e50e6a20
FB
8800
8801 if (dc->condjmp && !dc->is_jmp) {
8802 gen_set_label(dc->condlabel);
8803 dc->condjmp = 0;
8804 }
aaf2d97d 8805 /* Translation stops when a conditional branch is encountered.
e50e6a20 8806 * Otherwise the subsequent code could get translated several times.
b5ff1b31 8807 * Also stop translation when a page boundary is reached. This
bf20dc07 8808 * ensures prefetch aborts occur at the right place. */
2e70f6ef 8809 num_insns ++;
1fddef4b
FB
8810 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
8811 !env->singlestep_enabled &&
1b530a6d 8812 !singlestep &&
2e70f6ef
PB
8813 dc->pc < next_page_start &&
8814 num_insns < max_insns);
8815
8816 if (tb->cflags & CF_LAST_IO) {
8817 if (dc->condjmp) {
8818 /* FIXME: This can theoretically happen with self-modifying
8819 code. */
8820 cpu_abort(env, "IO on conditional branch instruction");
8821 }
8822 gen_io_end();
8823 }
9ee6e8bb 8824
b5ff1b31 8825 /* At this stage dc->condjmp will only be set when the skipped
9ee6e8bb
PB
8826 instruction was a conditional branch or trap, and the PC has
8827 already been written. */
551bd27f 8828 if (unlikely(env->singlestep_enabled)) {
8aaca4c0 8829 /* Make sure the pc is updated, and raise a debug exception. */
e50e6a20 8830 if (dc->condjmp) {
9ee6e8bb
PB
8831 gen_set_condexec(dc);
8832 if (dc->is_jmp == DISAS_SWI) {
d9ba4830 8833 gen_exception(EXCP_SWI);
9ee6e8bb 8834 } else {
d9ba4830 8835 gen_exception(EXCP_DEBUG);
9ee6e8bb 8836 }
e50e6a20
FB
8837 gen_set_label(dc->condlabel);
8838 }
8839 if (dc->condjmp || !dc->is_jmp) {
5e3f878a 8840 gen_set_pc_im(dc->pc);
e50e6a20 8841 dc->condjmp = 0;
8aaca4c0 8842 }
9ee6e8bb
PB
8843 gen_set_condexec(dc);
8844 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
d9ba4830 8845 gen_exception(EXCP_SWI);
9ee6e8bb
PB
8846 } else {
8847 /* FIXME: Single stepping a WFI insn will not halt
8848 the CPU. */
d9ba4830 8849 gen_exception(EXCP_DEBUG);
9ee6e8bb 8850 }
8aaca4c0 8851 } else {
9ee6e8bb
PB
8852 /* While branches must always occur at the end of an IT block,
8853 there are a few other things that can cause us to terminate
8854 the TB in the middel of an IT block:
8855 - Exception generating instructions (bkpt, swi, undefined).
8856 - Page boundaries.
8857 - Hardware watchpoints.
8858 Hardware breakpoints have already been handled and skip this code.
8859 */
8860 gen_set_condexec(dc);
8aaca4c0 8861 switch(dc->is_jmp) {
8aaca4c0 8862 case DISAS_NEXT:
6e256c93 8863 gen_goto_tb(dc, 1, dc->pc);
8aaca4c0
FB
8864 break;
8865 default:
8866 case DISAS_JUMP:
8867 case DISAS_UPDATE:
8868 /* indicate that the hash table must be used to find the next TB */
57fec1fe 8869 tcg_gen_exit_tb(0);
8aaca4c0
FB
8870 break;
8871 case DISAS_TB_JUMP:
8872 /* nothing more to generate */
8873 break;
9ee6e8bb 8874 case DISAS_WFI:
d9ba4830 8875 gen_helper_wfi();
9ee6e8bb
PB
8876 break;
8877 case DISAS_SWI:
d9ba4830 8878 gen_exception(EXCP_SWI);
9ee6e8bb 8879 break;
8aaca4c0 8880 }
e50e6a20
FB
8881 if (dc->condjmp) {
8882 gen_set_label(dc->condlabel);
9ee6e8bb 8883 gen_set_condexec(dc);
6e256c93 8884 gen_goto_tb(dc, 1, dc->pc);
e50e6a20
FB
8885 dc->condjmp = 0;
8886 }
2c0262af 8887 }
2e70f6ef 8888
9ee6e8bb 8889done_generating:
2e70f6ef 8890 gen_icount_end(tb, num_insns);
2c0262af
FB
8891 *gen_opc_ptr = INDEX_op_end;
8892
8893#ifdef DEBUG_DISAS
8fec2b8c 8894 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
93fcfe39
AL
8895 qemu_log("----------------\n");
8896 qemu_log("IN: %s\n", lookup_symbol(pc_start));
8897 log_target_disas(pc_start, dc->pc - pc_start, env->thumb);
8898 qemu_log("\n");
2c0262af
FB
8899 }
8900#endif
b5ff1b31
FB
8901 if (search_pc) {
8902 j = gen_opc_ptr - gen_opc_buf;
8903 lj++;
8904 while (lj <= j)
8905 gen_opc_instr_start[lj++] = 0;
b5ff1b31 8906 } else {
2c0262af 8907 tb->size = dc->pc - pc_start;
2e70f6ef 8908 tb->icount = num_insns;
b5ff1b31 8909 }
2c0262af
FB
8910}
8911
2cfc5f17 8912void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
2c0262af 8913{
2cfc5f17 8914 gen_intermediate_code_internal(env, tb, 0);
2c0262af
FB
8915}
8916
2cfc5f17 8917void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
2c0262af 8918{
2cfc5f17 8919 gen_intermediate_code_internal(env, tb, 1);
2c0262af
FB
8920}
8921
b5ff1b31
FB
8922static const char *cpu_mode_names[16] = {
8923 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
8924 "???", "???", "???", "und", "???", "???", "???", "sys"
8925};
9ee6e8bb 8926
5fafdf24 8927void cpu_dump_state(CPUState *env, FILE *f,
7fe48483
FB
8928 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8929 int flags)
2c0262af
FB
8930{
8931 int i;
06e80fc9 8932#if 0
bc380d17 8933 union {
b7bcbe95
FB
8934 uint32_t i;
8935 float s;
8936 } s0, s1;
8937 CPU_DoubleU d;
a94a6abf
PB
8938 /* ??? This assumes float64 and double have the same layout.
8939 Oh well, it's only debug dumps. */
8940 union {
8941 float64 f64;
8942 double d;
8943 } d0;
06e80fc9 8944#endif
b5ff1b31 8945 uint32_t psr;
2c0262af
FB
8946
8947 for(i=0;i<16;i++) {
7fe48483 8948 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
2c0262af 8949 if ((i % 4) == 3)
7fe48483 8950 cpu_fprintf(f, "\n");
2c0262af 8951 else
7fe48483 8952 cpu_fprintf(f, " ");
2c0262af 8953 }
b5ff1b31 8954 psr = cpsr_read(env);
687fa640
TS
8955 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
8956 psr,
b5ff1b31
FB
8957 psr & (1 << 31) ? 'N' : '-',
8958 psr & (1 << 30) ? 'Z' : '-',
8959 psr & (1 << 29) ? 'C' : '-',
8960 psr & (1 << 28) ? 'V' : '-',
5fafdf24 8961 psr & CPSR_T ? 'T' : 'A',
b5ff1b31 8962 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
b7bcbe95 8963
5e3f878a 8964#if 0
b7bcbe95 8965 for (i = 0; i < 16; i++) {
8e96005d
FB
8966 d.d = env->vfp.regs[i];
8967 s0.i = d.l.lower;
8968 s1.i = d.l.upper;
a94a6abf
PB
8969 d0.f64 = d.d;
8970 cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
b7bcbe95 8971 i * 2, (int)s0.i, s0.s,
a94a6abf 8972 i * 2 + 1, (int)s1.i, s1.s,
b7bcbe95 8973 i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
a94a6abf 8974 d0.d);
b7bcbe95 8975 }
40f137e1 8976 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
5e3f878a 8977#endif
2c0262af 8978}
a6b025d3 8979
d2856f1a
AJ
8980void gen_pc_load(CPUState *env, TranslationBlock *tb,
8981 unsigned long searched_pc, int pc_pos, void *puc)
8982{
8983 env->regs[15] = gen_opc_pc[pc_pos];
8984}