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