xref: /illumos-kvm-cmd/target-arm/translate.c (revision 68396ea9)
1 /*
2  *  ARM translation
3  *
4  *  Copyright (c) 2003 Fabrice Bellard
5  *  Copyright (c) 2005-2007 CodeSourcery
6  *  Copyright (c) 2007 OpenedHand, Ltd.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20  */
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <inttypes.h>
26 
27 #include "cpu.h"
28 #include "exec-all.h"
29 #include "disas.h"
30 #include "tcg-op.h"
31 #include "qemu-log.h"
32 
33 #include "helpers.h"
34 #define GEN_HELPER 1
35 #include "helpers.h"
36 
37 #define ENABLE_ARCH_5J    0
38 #define ENABLE_ARCH_6     arm_feature(env, ARM_FEATURE_V6)
39 #define ENABLE_ARCH_6K   arm_feature(env, ARM_FEATURE_V6K)
40 #define ENABLE_ARCH_6T2   arm_feature(env, ARM_FEATURE_THUMB2)
41 #define ENABLE_ARCH_7     arm_feature(env, ARM_FEATURE_V7)
42 
43 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
44 
45 /* internal defines */
46 typedef struct DisasContext {
47     target_ulong pc;
48     int is_jmp;
49     /* Nonzero if this instruction has been conditionally skipped.  */
50     int condjmp;
51     /* The label that will be jumped to when the instruction is skipped.  */
52     int condlabel;
53     /* Thumb-2 condtional execution bits.  */
54     int condexec_mask;
55     int condexec_cond;
56     struct TranslationBlock *tb;
57     int singlestep_enabled;
58     int thumb;
59 #if !defined(CONFIG_USER_ONLY)
60     int user;
61 #endif
62     int vfp_enabled;
63     int vec_len;
64     int vec_stride;
65 } DisasContext;
66 
67 static uint32_t gen_opc_condexec_bits[OPC_BUF_SIZE];
68 
69 #if defined(CONFIG_USER_ONLY)
70 #define IS_USER(s) 1
71 #else
72 #define IS_USER(s) (s->user)
73 #endif
74 
75 /* These instructions trap after executing, so defer them until after the
76    conditional executions state has been updated.  */
77 #define DISAS_WFI 4
78 #define DISAS_SWI 5
79 
80 static TCGv_ptr cpu_env;
81 /* We reuse the same 64-bit temporaries for efficiency.  */
82 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
83 static TCGv_i32 cpu_R[16];
84 static TCGv_i32 cpu_exclusive_addr;
85 static TCGv_i32 cpu_exclusive_val;
86 static TCGv_i32 cpu_exclusive_high;
87 #ifdef CONFIG_USER_ONLY
88 static TCGv_i32 cpu_exclusive_test;
89 static TCGv_i32 cpu_exclusive_info;
90 #endif
91 
92 /* FIXME:  These should be removed.  */
93 static TCGv cpu_F0s, cpu_F1s;
94 static TCGv_i64 cpu_F0d, cpu_F1d;
95 
96 #include "gen-icount.h"
97 
98 static const char *regnames[] =
99     { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
100       "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
101 
102 /* initialize TCG globals.  */
arm_translate_init(void)103 void arm_translate_init(void)
104 {
105     int i;
106 
107     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
108 
109     for (i = 0; i < 16; i++) {
110         cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
111                                           offsetof(CPUState, regs[i]),
112                                           regnames[i]);
113     }
114     cpu_exclusive_addr = tcg_global_mem_new_i32(TCG_AREG0,
115         offsetof(CPUState, exclusive_addr), "exclusive_addr");
116     cpu_exclusive_val = tcg_global_mem_new_i32(TCG_AREG0,
117         offsetof(CPUState, exclusive_val), "exclusive_val");
118     cpu_exclusive_high = tcg_global_mem_new_i32(TCG_AREG0,
119         offsetof(CPUState, exclusive_high), "exclusive_high");
120 #ifdef CONFIG_USER_ONLY
121     cpu_exclusive_test = tcg_global_mem_new_i32(TCG_AREG0,
122         offsetof(CPUState, exclusive_test), "exclusive_test");
123     cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0,
124         offsetof(CPUState, exclusive_info), "exclusive_info");
125 #endif
126 
127 #define GEN_HELPER 2
128 #include "helpers.h"
129 }
130 
131 static int num_temps;
132 
133 /* Allocate a temporary variable.  */
new_tmp(void)134 static TCGv_i32 new_tmp(void)
135 {
136     num_temps++;
137     return tcg_temp_new_i32();
138 }
139 
140 /* Release a temporary variable.  */
dead_tmp(TCGv tmp)141 static void dead_tmp(TCGv tmp)
142 {
143     tcg_temp_free(tmp);
144     num_temps--;
145 }
146 
load_cpu_offset(int offset)147 static inline TCGv load_cpu_offset(int offset)
148 {
149     TCGv tmp = new_tmp();
150     tcg_gen_ld_i32(tmp, cpu_env, offset);
151     return tmp;
152 }
153 
154 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
155 
store_cpu_offset(TCGv var,int offset)156 static inline void store_cpu_offset(TCGv var, int offset)
157 {
158     tcg_gen_st_i32(var, cpu_env, offset);
159     dead_tmp(var);
160 }
161 
162 #define store_cpu_field(var, name) \
163     store_cpu_offset(var, offsetof(CPUState, name))
164 
165 /* Set a variable to the value of a CPU register.  */
load_reg_var(DisasContext * s,TCGv var,int reg)166 static void load_reg_var(DisasContext *s, TCGv var, int reg)
167 {
168     if (reg == 15) {
169         uint32_t addr;
170         /* normaly, since we updated PC, we need only to add one insn */
171         if (s->thumb)
172             addr = (long)s->pc + 2;
173         else
174             addr = (long)s->pc + 4;
175         tcg_gen_movi_i32(var, addr);
176     } else {
177         tcg_gen_mov_i32(var, cpu_R[reg]);
178     }
179 }
180 
181 /* Create a new temporary and set it to the value of a CPU register.  */
load_reg(DisasContext * s,int reg)182 static inline TCGv load_reg(DisasContext *s, int reg)
183 {
184     TCGv tmp = new_tmp();
185     load_reg_var(s, tmp, reg);
186     return tmp;
187 }
188 
189 /* Set a CPU register.  The source must be a temporary and will be
190    marked as dead.  */
store_reg(DisasContext * s,int reg,TCGv var)191 static void store_reg(DisasContext *s, int reg, TCGv var)
192 {
193     if (reg == 15) {
194         tcg_gen_andi_i32(var, var, ~1);
195         s->is_jmp = DISAS_JUMP;
196     }
197     tcg_gen_mov_i32(cpu_R[reg], var);
198     dead_tmp(var);
199 }
200 
201 /* Value extensions.  */
202 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
203 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
204 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
205 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
206 
207 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
208 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
209 
210 
gen_set_cpsr(TCGv var,uint32_t mask)211 static inline void gen_set_cpsr(TCGv var, uint32_t mask)
212 {
213     TCGv tmp_mask = tcg_const_i32(mask);
214     gen_helper_cpsr_write(var, tmp_mask);
215     tcg_temp_free_i32(tmp_mask);
216 }
217 /* Set NZCV flags from the high 4 bits of var.  */
218 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
219 
gen_exception(int excp)220 static void gen_exception(int excp)
221 {
222     TCGv tmp = new_tmp();
223     tcg_gen_movi_i32(tmp, excp);
224     gen_helper_exception(tmp);
225     dead_tmp(tmp);
226 }
227 
gen_smul_dual(TCGv a,TCGv b)228 static void gen_smul_dual(TCGv a, TCGv b)
229 {
230     TCGv tmp1 = new_tmp();
231     TCGv tmp2 = new_tmp();
232     tcg_gen_ext16s_i32(tmp1, a);
233     tcg_gen_ext16s_i32(tmp2, b);
234     tcg_gen_mul_i32(tmp1, tmp1, tmp2);
235     dead_tmp(tmp2);
236     tcg_gen_sari_i32(a, a, 16);
237     tcg_gen_sari_i32(b, b, 16);
238     tcg_gen_mul_i32(b, b, a);
239     tcg_gen_mov_i32(a, tmp1);
240     dead_tmp(tmp1);
241 }
242 
243 /* Byteswap each halfword.  */
gen_rev16(TCGv var)244 static void gen_rev16(TCGv var)
245 {
246     TCGv tmp = new_tmp();
247     tcg_gen_shri_i32(tmp, var, 8);
248     tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
249     tcg_gen_shli_i32(var, var, 8);
250     tcg_gen_andi_i32(var, var, 0xff00ff00);
251     tcg_gen_or_i32(var, var, tmp);
252     dead_tmp(tmp);
253 }
254 
255 /* Byteswap low halfword and sign extend.  */
gen_revsh(TCGv var)256 static void gen_revsh(TCGv var)
257 {
258     tcg_gen_ext16u_i32(var, var);
259     tcg_gen_bswap16_i32(var, var);
260     tcg_gen_ext16s_i32(var, var);
261 }
262 
263 /* Unsigned bitfield extract.  */
gen_ubfx(TCGv var,int shift,uint32_t mask)264 static void gen_ubfx(TCGv var, int shift, uint32_t mask)
265 {
266     if (shift)
267         tcg_gen_shri_i32(var, var, shift);
268     tcg_gen_andi_i32(var, var, mask);
269 }
270 
271 /* Signed bitfield extract.  */
gen_sbfx(TCGv var,int shift,int width)272 static void gen_sbfx(TCGv var, int shift, int width)
273 {
274     uint32_t signbit;
275 
276     if (shift)
277         tcg_gen_sari_i32(var, var, shift);
278     if (shift + width < 32) {
279         signbit = 1u << (width - 1);
280         tcg_gen_andi_i32(var, var, (1u << width) - 1);
281         tcg_gen_xori_i32(var, var, signbit);
282         tcg_gen_subi_i32(var, var, signbit);
283     }
284 }
285 
286 /* Bitfield insertion.  Insert val into base.  Clobbers base and val.  */
gen_bfi(TCGv dest,TCGv base,TCGv val,int shift,uint32_t mask)287 static void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask)
288 {
289     tcg_gen_andi_i32(val, val, mask);
290     tcg_gen_shli_i32(val, val, shift);
291     tcg_gen_andi_i32(base, base, ~(mask << shift));
292     tcg_gen_or_i32(dest, base, val);
293 }
294 
295 /* Return (b << 32) + a. Mark inputs as dead */
gen_addq_msw(TCGv_i64 a,TCGv b)296 static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv b)
297 {
298     TCGv_i64 tmp64 = tcg_temp_new_i64();
299 
300     tcg_gen_extu_i32_i64(tmp64, b);
301     dead_tmp(b);
302     tcg_gen_shli_i64(tmp64, tmp64, 32);
303     tcg_gen_add_i64(a, tmp64, a);
304 
305     tcg_temp_free_i64(tmp64);
306     return a;
307 }
308 
309 /* Return (b << 32) - a. Mark inputs as dead. */
gen_subq_msw(TCGv_i64 a,TCGv b)310 static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv b)
311 {
312     TCGv_i64 tmp64 = tcg_temp_new_i64();
313 
314     tcg_gen_extu_i32_i64(tmp64, b);
315     dead_tmp(b);
316     tcg_gen_shli_i64(tmp64, tmp64, 32);
317     tcg_gen_sub_i64(a, tmp64, a);
318 
319     tcg_temp_free_i64(tmp64);
320     return a;
321 }
322 
323 /* FIXME: Most targets have native widening multiplication.
324    It would be good to use that instead of a full wide multiply.  */
325 /* 32x32->64 multiply.  Marks inputs as dead.  */
gen_mulu_i64_i32(TCGv a,TCGv b)326 static TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b)
327 {
328     TCGv_i64 tmp1 = tcg_temp_new_i64();
329     TCGv_i64 tmp2 = tcg_temp_new_i64();
330 
331     tcg_gen_extu_i32_i64(tmp1, a);
332     dead_tmp(a);
333     tcg_gen_extu_i32_i64(tmp2, b);
334     dead_tmp(b);
335     tcg_gen_mul_i64(tmp1, tmp1, tmp2);
336     tcg_temp_free_i64(tmp2);
337     return tmp1;
338 }
339 
gen_muls_i64_i32(TCGv a,TCGv b)340 static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b)
341 {
342     TCGv_i64 tmp1 = tcg_temp_new_i64();
343     TCGv_i64 tmp2 = tcg_temp_new_i64();
344 
345     tcg_gen_ext_i32_i64(tmp1, a);
346     dead_tmp(a);
347     tcg_gen_ext_i32_i64(tmp2, b);
348     dead_tmp(b);
349     tcg_gen_mul_i64(tmp1, tmp1, tmp2);
350     tcg_temp_free_i64(tmp2);
351     return tmp1;
352 }
353 
354 /* Swap low and high halfwords.  */
gen_swap_half(TCGv var)355 static void gen_swap_half(TCGv var)
356 {
357     TCGv tmp = new_tmp();
358     tcg_gen_shri_i32(tmp, var, 16);
359     tcg_gen_shli_i32(var, var, 16);
360     tcg_gen_or_i32(var, var, tmp);
361     dead_tmp(tmp);
362 }
363 
364 /* Dual 16-bit add.  Result placed in t0 and t1 is marked as dead.
365     tmp = (t0 ^ t1) & 0x8000;
366     t0 &= ~0x8000;
367     t1 &= ~0x8000;
368     t0 = (t0 + t1) ^ tmp;
369  */
370 
gen_add16(TCGv t0,TCGv t1)371 static void gen_add16(TCGv t0, TCGv t1)
372 {
373     TCGv tmp = new_tmp();
374     tcg_gen_xor_i32(tmp, t0, t1);
375     tcg_gen_andi_i32(tmp, tmp, 0x8000);
376     tcg_gen_andi_i32(t0, t0, ~0x8000);
377     tcg_gen_andi_i32(t1, t1, ~0x8000);
378     tcg_gen_add_i32(t0, t0, t1);
379     tcg_gen_xor_i32(t0, t0, tmp);
380     dead_tmp(tmp);
381     dead_tmp(t1);
382 }
383 
384 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
385 
386 /* Set CF to the top bit of var.  */
gen_set_CF_bit31(TCGv var)387 static void gen_set_CF_bit31(TCGv var)
388 {
389     TCGv tmp = new_tmp();
390     tcg_gen_shri_i32(tmp, var, 31);
391     gen_set_CF(tmp);
392     dead_tmp(tmp);
393 }
394 
395 /* Set N and Z flags from var.  */
gen_logic_CC(TCGv var)396 static inline void gen_logic_CC(TCGv var)
397 {
398     tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NF));
399     tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, ZF));
400 }
401 
402 /* T0 += T1 + CF.  */
gen_adc(TCGv t0,TCGv t1)403 static void gen_adc(TCGv t0, TCGv t1)
404 {
405     TCGv tmp;
406     tcg_gen_add_i32(t0, t0, t1);
407     tmp = load_cpu_field(CF);
408     tcg_gen_add_i32(t0, t0, tmp);
409     dead_tmp(tmp);
410 }
411 
412 /* dest = T0 + T1 + CF. */
gen_add_carry(TCGv dest,TCGv t0,TCGv t1)413 static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1)
414 {
415     TCGv tmp;
416     tcg_gen_add_i32(dest, t0, t1);
417     tmp = load_cpu_field(CF);
418     tcg_gen_add_i32(dest, dest, tmp);
419     dead_tmp(tmp);
420 }
421 
422 /* dest = T0 - T1 + CF - 1.  */
gen_sub_carry(TCGv dest,TCGv t0,TCGv t1)423 static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
424 {
425     TCGv tmp;
426     tcg_gen_sub_i32(dest, t0, t1);
427     tmp = load_cpu_field(CF);
428     tcg_gen_add_i32(dest, dest, tmp);
429     tcg_gen_subi_i32(dest, dest, 1);
430     dead_tmp(tmp);
431 }
432 
433 /* FIXME:  Implement this natively.  */
434 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
435 
shifter_out_im(TCGv var,int shift)436 static void shifter_out_im(TCGv var, int shift)
437 {
438     TCGv tmp = new_tmp();
439     if (shift == 0) {
440         tcg_gen_andi_i32(tmp, var, 1);
441     } else {
442         tcg_gen_shri_i32(tmp, var, shift);
443         if (shift != 31)
444             tcg_gen_andi_i32(tmp, tmp, 1);
445     }
446     gen_set_CF(tmp);
447     dead_tmp(tmp);
448 }
449 
450 /* Shift by immediate.  Includes special handling for shift == 0.  */
gen_arm_shift_im(TCGv var,int shiftop,int shift,int flags)451 static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
452 {
453     switch (shiftop) {
454     case 0: /* LSL */
455         if (shift != 0) {
456             if (flags)
457                 shifter_out_im(var, 32 - shift);
458             tcg_gen_shli_i32(var, var, shift);
459         }
460         break;
461     case 1: /* LSR */
462         if (shift == 0) {
463             if (flags) {
464                 tcg_gen_shri_i32(var, var, 31);
465                 gen_set_CF(var);
466             }
467             tcg_gen_movi_i32(var, 0);
468         } else {
469             if (flags)
470                 shifter_out_im(var, shift - 1);
471             tcg_gen_shri_i32(var, var, shift);
472         }
473         break;
474     case 2: /* ASR */
475         if (shift == 0)
476             shift = 32;
477         if (flags)
478             shifter_out_im(var, shift - 1);
479         if (shift == 32)
480           shift = 31;
481         tcg_gen_sari_i32(var, var, shift);
482         break;
483     case 3: /* ROR/RRX */
484         if (shift != 0) {
485             if (flags)
486                 shifter_out_im(var, shift - 1);
487             tcg_gen_rotri_i32(var, var, shift); break;
488         } else {
489             TCGv tmp = load_cpu_field(CF);
490             if (flags)
491                 shifter_out_im(var, 0);
492             tcg_gen_shri_i32(var, var, 1);
493             tcg_gen_shli_i32(tmp, tmp, 31);
494             tcg_gen_or_i32(var, var, tmp);
495             dead_tmp(tmp);
496         }
497     }
498 };
499 
gen_arm_shift_reg(TCGv var,int shiftop,TCGv shift,int flags)500 static inline void gen_arm_shift_reg(TCGv var, int shiftop,
501                                      TCGv shift, int flags)
502 {
503     if (flags) {
504         switch (shiftop) {
505         case 0: gen_helper_shl_cc(var, var, shift); break;
506         case 1: gen_helper_shr_cc(var, var, shift); break;
507         case 2: gen_helper_sar_cc(var, var, shift); break;
508         case 3: gen_helper_ror_cc(var, var, shift); break;
509         }
510     } else {
511         switch (shiftop) {
512         case 0: gen_helper_shl(var, var, shift); break;
513         case 1: gen_helper_shr(var, var, shift); break;
514         case 2: gen_helper_sar(var, var, shift); break;
515         case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
516                 tcg_gen_rotr_i32(var, var, shift); break;
517         }
518     }
519     dead_tmp(shift);
520 }
521 
522 #define PAS_OP(pfx) \
523     switch (op2) {  \
524     case 0: gen_pas_helper(glue(pfx,add16)); break; \
525     case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
526     case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
527     case 3: gen_pas_helper(glue(pfx,sub16)); break; \
528     case 4: gen_pas_helper(glue(pfx,add8)); break; \
529     case 7: gen_pas_helper(glue(pfx,sub8)); break; \
530     }
gen_arm_parallel_addsub(int op1,int op2,TCGv a,TCGv b)531 static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
532 {
533     TCGv_ptr tmp;
534 
535     switch (op1) {
536 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
537     case 1:
538         tmp = tcg_temp_new_ptr();
539         tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
540         PAS_OP(s)
541         tcg_temp_free_ptr(tmp);
542         break;
543     case 5:
544         tmp = tcg_temp_new_ptr();
545         tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
546         PAS_OP(u)
547         tcg_temp_free_ptr(tmp);
548         break;
549 #undef gen_pas_helper
550 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
551     case 2:
552         PAS_OP(q);
553         break;
554     case 3:
555         PAS_OP(sh);
556         break;
557     case 6:
558         PAS_OP(uq);
559         break;
560     case 7:
561         PAS_OP(uh);
562         break;
563 #undef gen_pas_helper
564     }
565 }
566 #undef PAS_OP
567 
568 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings.  */
569 #define PAS_OP(pfx) \
570     switch (op1) {  \
571     case 0: gen_pas_helper(glue(pfx,add8)); break; \
572     case 1: gen_pas_helper(glue(pfx,add16)); break; \
573     case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
574     case 4: gen_pas_helper(glue(pfx,sub8)); break; \
575     case 5: gen_pas_helper(glue(pfx,sub16)); break; \
576     case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
577     }
gen_thumb2_parallel_addsub(int op1,int op2,TCGv a,TCGv b)578 static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
579 {
580     TCGv_ptr tmp;
581 
582     switch (op2) {
583 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
584     case 0:
585         tmp = tcg_temp_new_ptr();
586         tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
587         PAS_OP(s)
588         tcg_temp_free_ptr(tmp);
589         break;
590     case 4:
591         tmp = tcg_temp_new_ptr();
592         tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
593         PAS_OP(u)
594         tcg_temp_free_ptr(tmp);
595         break;
596 #undef gen_pas_helper
597 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
598     case 1:
599         PAS_OP(q);
600         break;
601     case 2:
602         PAS_OP(sh);
603         break;
604     case 5:
605         PAS_OP(uq);
606         break;
607     case 6:
608         PAS_OP(uh);
609         break;
610 #undef gen_pas_helper
611     }
612 }
613 #undef PAS_OP
614 
gen_test_cc(int cc,int label)615 static void gen_test_cc(int cc, int label)
616 {
617     TCGv tmp;
618     TCGv tmp2;
619     int inv;
620 
621     switch (cc) {
622     case 0: /* eq: Z */
623         tmp = load_cpu_field(ZF);
624         tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
625         break;
626     case 1: /* ne: !Z */
627         tmp = load_cpu_field(ZF);
628         tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
629         break;
630     case 2: /* cs: C */
631         tmp = load_cpu_field(CF);
632         tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
633         break;
634     case 3: /* cc: !C */
635         tmp = load_cpu_field(CF);
636         tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
637         break;
638     case 4: /* mi: N */
639         tmp = load_cpu_field(NF);
640         tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
641         break;
642     case 5: /* pl: !N */
643         tmp = load_cpu_field(NF);
644         tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
645         break;
646     case 6: /* vs: V */
647         tmp = load_cpu_field(VF);
648         tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
649         break;
650     case 7: /* vc: !V */
651         tmp = load_cpu_field(VF);
652         tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
653         break;
654     case 8: /* hi: C && !Z */
655         inv = gen_new_label();
656         tmp = load_cpu_field(CF);
657         tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
658         dead_tmp(tmp);
659         tmp = load_cpu_field(ZF);
660         tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
661         gen_set_label(inv);
662         break;
663     case 9: /* ls: !C || Z */
664         tmp = load_cpu_field(CF);
665         tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
666         dead_tmp(tmp);
667         tmp = load_cpu_field(ZF);
668         tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
669         break;
670     case 10: /* ge: N == V -> N ^ V == 0 */
671         tmp = load_cpu_field(VF);
672         tmp2 = load_cpu_field(NF);
673         tcg_gen_xor_i32(tmp, tmp, tmp2);
674         dead_tmp(tmp2);
675         tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
676         break;
677     case 11: /* lt: N != V -> N ^ V != 0 */
678         tmp = load_cpu_field(VF);
679         tmp2 = load_cpu_field(NF);
680         tcg_gen_xor_i32(tmp, tmp, tmp2);
681         dead_tmp(tmp2);
682         tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
683         break;
684     case 12: /* gt: !Z && N == V */
685         inv = gen_new_label();
686         tmp = load_cpu_field(ZF);
687         tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
688         dead_tmp(tmp);
689         tmp = load_cpu_field(VF);
690         tmp2 = load_cpu_field(NF);
691         tcg_gen_xor_i32(tmp, tmp, tmp2);
692         dead_tmp(tmp2);
693         tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
694         gen_set_label(inv);
695         break;
696     case 13: /* le: Z || N != V */
697         tmp = load_cpu_field(ZF);
698         tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
699         dead_tmp(tmp);
700         tmp = load_cpu_field(VF);
701         tmp2 = load_cpu_field(NF);
702         tcg_gen_xor_i32(tmp, tmp, tmp2);
703         dead_tmp(tmp2);
704         tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
705         break;
706     default:
707         fprintf(stderr, "Bad condition code 0x%x\n", cc);
708         abort();
709     }
710     dead_tmp(tmp);
711 }
712 
713 static const uint8_t table_logic_cc[16] = {
714     1, /* and */
715     1, /* xor */
716     0, /* sub */
717     0, /* rsb */
718     0, /* add */
719     0, /* adc */
720     0, /* sbc */
721     0, /* rsc */
722     1, /* andl */
723     1, /* xorl */
724     0, /* cmp */
725     0, /* cmn */
726     1, /* orr */
727     1, /* mov */
728     1, /* bic */
729     1, /* mvn */
730 };
731 
732 /* Set PC and Thumb state from an immediate address.  */
gen_bx_im(DisasContext * s,uint32_t addr)733 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
734 {
735     TCGv tmp;
736 
737     s->is_jmp = DISAS_UPDATE;
738     if (s->thumb != (addr & 1)) {
739         tmp = new_tmp();
740         tcg_gen_movi_i32(tmp, addr & 1);
741         tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
742         dead_tmp(tmp);
743     }
744     tcg_gen_movi_i32(cpu_R[15], addr & ~1);
745 }
746 
747 /* Set PC and Thumb state from var.  var is marked as dead.  */
gen_bx(DisasContext * s,TCGv var)748 static inline void gen_bx(DisasContext *s, TCGv var)
749 {
750     s->is_jmp = DISAS_UPDATE;
751     tcg_gen_andi_i32(cpu_R[15], var, ~1);
752     tcg_gen_andi_i32(var, var, 1);
753     store_cpu_field(var, thumb);
754 }
755 
756 /* Variant of store_reg which uses branch&exchange logic when storing
757    to r15 in ARM architecture v7 and above. The source must be a temporary
758    and will be marked as dead. */
store_reg_bx(CPUState * env,DisasContext * s,int reg,TCGv var)759 static inline void store_reg_bx(CPUState *env, DisasContext *s,
760                                 int reg, TCGv var)
761 {
762     if (reg == 15 && ENABLE_ARCH_7) {
763         gen_bx(s, var);
764     } else {
765         store_reg(s, reg, var);
766     }
767 }
768 
gen_ld8s(TCGv addr,int index)769 static inline TCGv gen_ld8s(TCGv addr, int index)
770 {
771     TCGv tmp = new_tmp();
772     tcg_gen_qemu_ld8s(tmp, addr, index);
773     return tmp;
774 }
gen_ld8u(TCGv addr,int index)775 static inline TCGv gen_ld8u(TCGv addr, int index)
776 {
777     TCGv tmp = new_tmp();
778     tcg_gen_qemu_ld8u(tmp, addr, index);
779     return tmp;
780 }
gen_ld16s(TCGv addr,int index)781 static inline TCGv gen_ld16s(TCGv addr, int index)
782 {
783     TCGv tmp = new_tmp();
784     tcg_gen_qemu_ld16s(tmp, addr, index);
785     return tmp;
786 }
gen_ld16u(TCGv addr,int index)787 static inline TCGv gen_ld16u(TCGv addr, int index)
788 {
789     TCGv tmp = new_tmp();
790     tcg_gen_qemu_ld16u(tmp, addr, index);
791     return tmp;
792 }
gen_ld32(TCGv addr,int index)793 static inline TCGv gen_ld32(TCGv addr, int index)
794 {
795     TCGv tmp = new_tmp();
796     tcg_gen_qemu_ld32u(tmp, addr, index);
797     return tmp;
798 }
gen_ld64(TCGv addr,int index)799 static inline TCGv_i64 gen_ld64(TCGv addr, int index)
800 {
801     TCGv_i64 tmp = tcg_temp_new_i64();
802     tcg_gen_qemu_ld64(tmp, addr, index);
803     return tmp;
804 }
gen_st8(TCGv val,TCGv addr,int index)805 static inline void gen_st8(TCGv val, TCGv addr, int index)
806 {
807     tcg_gen_qemu_st8(val, addr, index);
808     dead_tmp(val);
809 }
gen_st16(TCGv val,TCGv addr,int index)810 static inline void gen_st16(TCGv val, TCGv addr, int index)
811 {
812     tcg_gen_qemu_st16(val, addr, index);
813     dead_tmp(val);
814 }
gen_st32(TCGv val,TCGv addr,int index)815 static inline void gen_st32(TCGv val, TCGv addr, int index)
816 {
817     tcg_gen_qemu_st32(val, addr, index);
818     dead_tmp(val);
819 }
gen_st64(TCGv_i64 val,TCGv addr,int index)820 static inline void gen_st64(TCGv_i64 val, TCGv addr, int index)
821 {
822     tcg_gen_qemu_st64(val, addr, index);
823     tcg_temp_free_i64(val);
824 }
825 
gen_set_pc_im(uint32_t val)826 static inline void gen_set_pc_im(uint32_t val)
827 {
828     tcg_gen_movi_i32(cpu_R[15], val);
829 }
830 
831 /* Force a TB lookup after an instruction that changes the CPU state.  */
gen_lookup_tb(DisasContext * s)832 static inline void gen_lookup_tb(DisasContext *s)
833 {
834     tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
835     s->is_jmp = DISAS_UPDATE;
836 }
837 
gen_add_data_offset(DisasContext * s,unsigned int insn,TCGv var)838 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
839                                        TCGv var)
840 {
841     int val, rm, shift, shiftop;
842     TCGv offset;
843 
844     if (!(insn & (1 << 25))) {
845         /* immediate */
846         val = insn & 0xfff;
847         if (!(insn & (1 << 23)))
848             val = -val;
849         if (val != 0)
850             tcg_gen_addi_i32(var, var, val);
851     } else {
852         /* shift/register */
853         rm = (insn) & 0xf;
854         shift = (insn >> 7) & 0x1f;
855         shiftop = (insn >> 5) & 3;
856         offset = load_reg(s, rm);
857         gen_arm_shift_im(offset, shiftop, shift, 0);
858         if (!(insn & (1 << 23)))
859             tcg_gen_sub_i32(var, var, offset);
860         else
861             tcg_gen_add_i32(var, var, offset);
862         dead_tmp(offset);
863     }
864 }
865 
gen_add_datah_offset(DisasContext * s,unsigned int insn,int extra,TCGv var)866 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
867                                         int extra, TCGv var)
868 {
869     int val, rm;
870     TCGv offset;
871 
872     if (insn & (1 << 22)) {
873         /* immediate */
874         val = (insn & 0xf) | ((insn >> 4) & 0xf0);
875         if (!(insn & (1 << 23)))
876             val = -val;
877         val += extra;
878         if (val != 0)
879             tcg_gen_addi_i32(var, var, val);
880     } else {
881         /* register */
882         if (extra)
883             tcg_gen_addi_i32(var, var, extra);
884         rm = (insn) & 0xf;
885         offset = load_reg(s, rm);
886         if (!(insn & (1 << 23)))
887             tcg_gen_sub_i32(var, var, offset);
888         else
889             tcg_gen_add_i32(var, var, offset);
890         dead_tmp(offset);
891     }
892 }
893 
894 #define VFP_OP2(name)                                                 \
895 static inline void gen_vfp_##name(int dp)                             \
896 {                                                                     \
897     if (dp)                                                           \
898         gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
899     else                                                              \
900         gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
901 }
902 
903 VFP_OP2(add)
VFP_OP2(sub)904 VFP_OP2(sub)
905 VFP_OP2(mul)
906 VFP_OP2(div)
907 
908 #undef VFP_OP2
909 
910 static inline void gen_vfp_abs(int dp)
911 {
912     if (dp)
913         gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
914     else
915         gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
916 }
917 
gen_vfp_neg(int dp)918 static inline void gen_vfp_neg(int dp)
919 {
920     if (dp)
921         gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
922     else
923         gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
924 }
925 
gen_vfp_sqrt(int dp)926 static inline void gen_vfp_sqrt(int dp)
927 {
928     if (dp)
929         gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
930     else
931         gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
932 }
933 
gen_vfp_cmp(int dp)934 static inline void gen_vfp_cmp(int dp)
935 {
936     if (dp)
937         gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
938     else
939         gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
940 }
941 
gen_vfp_cmpe(int dp)942 static inline void gen_vfp_cmpe(int dp)
943 {
944     if (dp)
945         gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
946     else
947         gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
948 }
949 
gen_vfp_F1_ld0(int dp)950 static inline void gen_vfp_F1_ld0(int dp)
951 {
952     if (dp)
953         tcg_gen_movi_i64(cpu_F1d, 0);
954     else
955         tcg_gen_movi_i32(cpu_F1s, 0);
956 }
957 
gen_vfp_uito(int dp)958 static inline void gen_vfp_uito(int dp)
959 {
960     if (dp)
961         gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env);
962     else
963         gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env);
964 }
965 
gen_vfp_sito(int dp)966 static inline void gen_vfp_sito(int dp)
967 {
968     if (dp)
969         gen_helper_vfp_sitod(cpu_F0d, cpu_F0s, cpu_env);
970     else
971         gen_helper_vfp_sitos(cpu_F0s, cpu_F0s, cpu_env);
972 }
973 
gen_vfp_toui(int dp)974 static inline void gen_vfp_toui(int dp)
975 {
976     if (dp)
977         gen_helper_vfp_touid(cpu_F0s, cpu_F0d, cpu_env);
978     else
979         gen_helper_vfp_touis(cpu_F0s, cpu_F0s, cpu_env);
980 }
981 
gen_vfp_touiz(int dp)982 static inline void gen_vfp_touiz(int dp)
983 {
984     if (dp)
985         gen_helper_vfp_touizd(cpu_F0s, cpu_F0d, cpu_env);
986     else
987         gen_helper_vfp_touizs(cpu_F0s, cpu_F0s, cpu_env);
988 }
989 
gen_vfp_tosi(int dp)990 static inline void gen_vfp_tosi(int dp)
991 {
992     if (dp)
993         gen_helper_vfp_tosid(cpu_F0s, cpu_F0d, cpu_env);
994     else
995         gen_helper_vfp_tosis(cpu_F0s, cpu_F0s, cpu_env);
996 }
997 
gen_vfp_tosiz(int dp)998 static inline void gen_vfp_tosiz(int dp)
999 {
1000     if (dp)
1001         gen_helper_vfp_tosizd(cpu_F0s, cpu_F0d, cpu_env);
1002     else
1003         gen_helper_vfp_tosizs(cpu_F0s, cpu_F0s, cpu_env);
1004 }
1005 
1006 #define VFP_GEN_FIX(name) \
1007 static inline void gen_vfp_##name(int dp, int shift) \
1008 { \
1009     TCGv tmp_shift = tcg_const_i32(shift); \
1010     if (dp) \
1011         gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, cpu_env);\
1012     else \
1013         gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, cpu_env);\
1014     tcg_temp_free_i32(tmp_shift); \
1015 }
1016 VFP_GEN_FIX(tosh)
VFP_GEN_FIX(tosl)1017 VFP_GEN_FIX(tosl)
1018 VFP_GEN_FIX(touh)
1019 VFP_GEN_FIX(toul)
1020 VFP_GEN_FIX(shto)
1021 VFP_GEN_FIX(slto)
1022 VFP_GEN_FIX(uhto)
1023 VFP_GEN_FIX(ulto)
1024 #undef VFP_GEN_FIX
1025 
1026 static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv addr)
1027 {
1028     if (dp)
1029         tcg_gen_qemu_ld64(cpu_F0d, addr, IS_USER(s));
1030     else
1031         tcg_gen_qemu_ld32u(cpu_F0s, addr, IS_USER(s));
1032 }
1033 
gen_vfp_st(DisasContext * s,int dp,TCGv addr)1034 static inline void gen_vfp_st(DisasContext *s, int dp, TCGv addr)
1035 {
1036     if (dp)
1037         tcg_gen_qemu_st64(cpu_F0d, addr, IS_USER(s));
1038     else
1039         tcg_gen_qemu_st32(cpu_F0s, addr, IS_USER(s));
1040 }
1041 
1042 static inline long
vfp_reg_offset(int dp,int reg)1043 vfp_reg_offset (int dp, int reg)
1044 {
1045     if (dp)
1046         return offsetof(CPUARMState, vfp.regs[reg]);
1047     else if (reg & 1) {
1048         return offsetof(CPUARMState, vfp.regs[reg >> 1])
1049           + offsetof(CPU_DoubleU, l.upper);
1050     } else {
1051         return offsetof(CPUARMState, vfp.regs[reg >> 1])
1052           + offsetof(CPU_DoubleU, l.lower);
1053     }
1054 }
1055 
1056 /* Return the offset of a 32-bit piece of a NEON register.
1057    zero is the least significant end of the register.  */
1058 static inline long
neon_reg_offset(int reg,int n)1059 neon_reg_offset (int reg, int n)
1060 {
1061     int sreg;
1062     sreg = reg * 2 + n;
1063     return vfp_reg_offset(0, sreg);
1064 }
1065 
neon_load_reg(int reg,int pass)1066 static TCGv neon_load_reg(int reg, int pass)
1067 {
1068     TCGv tmp = new_tmp();
1069     tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1070     return tmp;
1071 }
1072 
neon_store_reg(int reg,int pass,TCGv var)1073 static void neon_store_reg(int reg, int pass, TCGv var)
1074 {
1075     tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1076     dead_tmp(var);
1077 }
1078 
neon_load_reg64(TCGv_i64 var,int reg)1079 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1080 {
1081     tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1082 }
1083 
neon_store_reg64(TCGv_i64 var,int reg)1084 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1085 {
1086     tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1087 }
1088 
1089 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1090 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1091 #define tcg_gen_st_f32 tcg_gen_st_i32
1092 #define tcg_gen_st_f64 tcg_gen_st_i64
1093 
gen_mov_F0_vreg(int dp,int reg)1094 static inline void gen_mov_F0_vreg(int dp, int reg)
1095 {
1096     if (dp)
1097         tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1098     else
1099         tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1100 }
1101 
gen_mov_F1_vreg(int dp,int reg)1102 static inline void gen_mov_F1_vreg(int dp, int reg)
1103 {
1104     if (dp)
1105         tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1106     else
1107         tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1108 }
1109 
gen_mov_vreg_F0(int dp,int reg)1110 static inline void gen_mov_vreg_F0(int dp, int reg)
1111 {
1112     if (dp)
1113         tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1114     else
1115         tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1116 }
1117 
1118 #define ARM_CP_RW_BIT	(1 << 20)
1119 
iwmmxt_load_reg(TCGv_i64 var,int reg)1120 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1121 {
1122     tcg_gen_ld_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1123 }
1124 
iwmmxt_store_reg(TCGv_i64 var,int reg)1125 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1126 {
1127     tcg_gen_st_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1128 }
1129 
iwmmxt_load_creg(int reg)1130 static inline TCGv iwmmxt_load_creg(int reg)
1131 {
1132     TCGv var = new_tmp();
1133     tcg_gen_ld_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1134     return var;
1135 }
1136 
iwmmxt_store_creg(int reg,TCGv var)1137 static inline void iwmmxt_store_creg(int reg, TCGv var)
1138 {
1139     tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1140     dead_tmp(var);
1141 }
1142 
gen_op_iwmmxt_movq_wRn_M0(int rn)1143 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1144 {
1145     iwmmxt_store_reg(cpu_M0, rn);
1146 }
1147 
gen_op_iwmmxt_movq_M0_wRn(int rn)1148 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1149 {
1150     iwmmxt_load_reg(cpu_M0, rn);
1151 }
1152 
gen_op_iwmmxt_orq_M0_wRn(int rn)1153 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1154 {
1155     iwmmxt_load_reg(cpu_V1, rn);
1156     tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1157 }
1158 
gen_op_iwmmxt_andq_M0_wRn(int rn)1159 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1160 {
1161     iwmmxt_load_reg(cpu_V1, rn);
1162     tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1163 }
1164 
gen_op_iwmmxt_xorq_M0_wRn(int rn)1165 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1166 {
1167     iwmmxt_load_reg(cpu_V1, rn);
1168     tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1169 }
1170 
1171 #define IWMMXT_OP(name) \
1172 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1173 { \
1174     iwmmxt_load_reg(cpu_V1, rn); \
1175     gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1176 }
1177 
1178 #define IWMMXT_OP_ENV(name) \
1179 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1180 { \
1181     iwmmxt_load_reg(cpu_V1, rn); \
1182     gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1183 }
1184 
1185 #define IWMMXT_OP_ENV_SIZE(name) \
1186 IWMMXT_OP_ENV(name##b) \
1187 IWMMXT_OP_ENV(name##w) \
1188 IWMMXT_OP_ENV(name##l)
1189 
1190 #define IWMMXT_OP_ENV1(name) \
1191 static inline void gen_op_iwmmxt_##name##_M0(void) \
1192 { \
1193     gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1194 }
1195 
1196 IWMMXT_OP(maddsq)
IWMMXT_OP(madduq)1197 IWMMXT_OP(madduq)
1198 IWMMXT_OP(sadb)
1199 IWMMXT_OP(sadw)
1200 IWMMXT_OP(mulslw)
1201 IWMMXT_OP(mulshw)
1202 IWMMXT_OP(mululw)
1203 IWMMXT_OP(muluhw)
1204 IWMMXT_OP(macsw)
1205 IWMMXT_OP(macuw)
1206 
1207 IWMMXT_OP_ENV_SIZE(unpackl)
1208 IWMMXT_OP_ENV_SIZE(unpackh)
1209 
1210 IWMMXT_OP_ENV1(unpacklub)
1211 IWMMXT_OP_ENV1(unpackluw)
1212 IWMMXT_OP_ENV1(unpacklul)
1213 IWMMXT_OP_ENV1(unpackhub)
1214 IWMMXT_OP_ENV1(unpackhuw)
1215 IWMMXT_OP_ENV1(unpackhul)
1216 IWMMXT_OP_ENV1(unpacklsb)
1217 IWMMXT_OP_ENV1(unpacklsw)
1218 IWMMXT_OP_ENV1(unpacklsl)
1219 IWMMXT_OP_ENV1(unpackhsb)
1220 IWMMXT_OP_ENV1(unpackhsw)
1221 IWMMXT_OP_ENV1(unpackhsl)
1222 
1223 IWMMXT_OP_ENV_SIZE(cmpeq)
1224 IWMMXT_OP_ENV_SIZE(cmpgtu)
1225 IWMMXT_OP_ENV_SIZE(cmpgts)
1226 
1227 IWMMXT_OP_ENV_SIZE(mins)
1228 IWMMXT_OP_ENV_SIZE(minu)
1229 IWMMXT_OP_ENV_SIZE(maxs)
1230 IWMMXT_OP_ENV_SIZE(maxu)
1231 
1232 IWMMXT_OP_ENV_SIZE(subn)
1233 IWMMXT_OP_ENV_SIZE(addn)
1234 IWMMXT_OP_ENV_SIZE(subu)
1235 IWMMXT_OP_ENV_SIZE(addu)
1236 IWMMXT_OP_ENV_SIZE(subs)
1237 IWMMXT_OP_ENV_SIZE(adds)
1238 
1239 IWMMXT_OP_ENV(avgb0)
1240 IWMMXT_OP_ENV(avgb1)
1241 IWMMXT_OP_ENV(avgw0)
1242 IWMMXT_OP_ENV(avgw1)
1243 
1244 IWMMXT_OP(msadb)
1245 
1246 IWMMXT_OP_ENV(packuw)
1247 IWMMXT_OP_ENV(packul)
1248 IWMMXT_OP_ENV(packuq)
1249 IWMMXT_OP_ENV(packsw)
1250 IWMMXT_OP_ENV(packsl)
1251 IWMMXT_OP_ENV(packsq)
1252 
1253 static void gen_op_iwmmxt_set_mup(void)
1254 {
1255     TCGv tmp;
1256     tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1257     tcg_gen_ori_i32(tmp, tmp, 2);
1258     store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1259 }
1260 
gen_op_iwmmxt_set_cup(void)1261 static void gen_op_iwmmxt_set_cup(void)
1262 {
1263     TCGv tmp;
1264     tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1265     tcg_gen_ori_i32(tmp, tmp, 1);
1266     store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1267 }
1268 
gen_op_iwmmxt_setpsr_nz(void)1269 static void gen_op_iwmmxt_setpsr_nz(void)
1270 {
1271     TCGv tmp = new_tmp();
1272     gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1273     store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1274 }
1275 
gen_op_iwmmxt_addl_M0_wRn(int rn)1276 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1277 {
1278     iwmmxt_load_reg(cpu_V1, rn);
1279     tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1280     tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1281 }
1282 
gen_iwmmxt_address(DisasContext * s,uint32_t insn,TCGv dest)1283 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn, TCGv dest)
1284 {
1285     int rd;
1286     uint32_t offset;
1287     TCGv tmp;
1288 
1289     rd = (insn >> 16) & 0xf;
1290     tmp = load_reg(s, rd);
1291 
1292     offset = (insn & 0xff) << ((insn >> 7) & 2);
1293     if (insn & (1 << 24)) {
1294         /* Pre indexed */
1295         if (insn & (1 << 23))
1296             tcg_gen_addi_i32(tmp, tmp, offset);
1297         else
1298             tcg_gen_addi_i32(tmp, tmp, -offset);
1299         tcg_gen_mov_i32(dest, tmp);
1300         if (insn & (1 << 21))
1301             store_reg(s, rd, tmp);
1302         else
1303             dead_tmp(tmp);
1304     } else if (insn & (1 << 21)) {
1305         /* Post indexed */
1306         tcg_gen_mov_i32(dest, tmp);
1307         if (insn & (1 << 23))
1308             tcg_gen_addi_i32(tmp, tmp, offset);
1309         else
1310             tcg_gen_addi_i32(tmp, tmp, -offset);
1311         store_reg(s, rd, tmp);
1312     } else if (!(insn & (1 << 23)))
1313         return 1;
1314     return 0;
1315 }
1316 
gen_iwmmxt_shift(uint32_t insn,uint32_t mask,TCGv dest)1317 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv dest)
1318 {
1319     int rd = (insn >> 0) & 0xf;
1320     TCGv tmp;
1321 
1322     if (insn & (1 << 8)) {
1323         if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1324             return 1;
1325         } else {
1326             tmp = iwmmxt_load_creg(rd);
1327         }
1328     } else {
1329         tmp = new_tmp();
1330         iwmmxt_load_reg(cpu_V0, rd);
1331         tcg_gen_trunc_i64_i32(tmp, cpu_V0);
1332     }
1333     tcg_gen_andi_i32(tmp, tmp, mask);
1334     tcg_gen_mov_i32(dest, tmp);
1335     dead_tmp(tmp);
1336     return 0;
1337 }
1338 
1339 /* Disassemble an iwMMXt instruction.  Returns nonzero if an error occured
1340    (ie. an undefined instruction).  */
disas_iwmmxt_insn(CPUState * env,DisasContext * s,uint32_t insn)1341 static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
1342 {
1343     int rd, wrd;
1344     int rdhi, rdlo, rd0, rd1, i;
1345     TCGv addr;
1346     TCGv tmp, tmp2, tmp3;
1347 
1348     if ((insn & 0x0e000e00) == 0x0c000000) {
1349         if ((insn & 0x0fe00ff0) == 0x0c400000) {
1350             wrd = insn & 0xf;
1351             rdlo = (insn >> 12) & 0xf;
1352             rdhi = (insn >> 16) & 0xf;
1353             if (insn & ARM_CP_RW_BIT) {			/* TMRRC */
1354                 iwmmxt_load_reg(cpu_V0, wrd);
1355                 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
1356                 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1357                 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
1358             } else {					/* TMCRR */
1359                 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1360                 iwmmxt_store_reg(cpu_V0, wrd);
1361                 gen_op_iwmmxt_set_mup();
1362             }
1363             return 0;
1364         }
1365 
1366         wrd = (insn >> 12) & 0xf;
1367         addr = new_tmp();
1368         if (gen_iwmmxt_address(s, insn, addr)) {
1369             dead_tmp(addr);
1370             return 1;
1371         }
1372         if (insn & ARM_CP_RW_BIT) {
1373             if ((insn >> 28) == 0xf) {			/* WLDRW wCx */
1374                 tmp = new_tmp();
1375                 tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s));
1376                 iwmmxt_store_creg(wrd, tmp);
1377             } else {
1378                 i = 1;
1379                 if (insn & (1 << 8)) {
1380                     if (insn & (1 << 22)) {		/* WLDRD */
1381                         tcg_gen_qemu_ld64(cpu_M0, addr, IS_USER(s));
1382                         i = 0;
1383                     } else {				/* WLDRW wRd */
1384                         tmp = gen_ld32(addr, IS_USER(s));
1385                     }
1386                 } else {
1387                     if (insn & (1 << 22)) {		/* WLDRH */
1388                         tmp = gen_ld16u(addr, IS_USER(s));
1389                     } else {				/* WLDRB */
1390                         tmp = gen_ld8u(addr, IS_USER(s));
1391                     }
1392                 }
1393                 if (i) {
1394                     tcg_gen_extu_i32_i64(cpu_M0, tmp);
1395                     dead_tmp(tmp);
1396                 }
1397                 gen_op_iwmmxt_movq_wRn_M0(wrd);
1398             }
1399         } else {
1400             if ((insn >> 28) == 0xf) {			/* WSTRW wCx */
1401                 tmp = iwmmxt_load_creg(wrd);
1402                 gen_st32(tmp, addr, IS_USER(s));
1403             } else {
1404                 gen_op_iwmmxt_movq_M0_wRn(wrd);
1405                 tmp = new_tmp();
1406                 if (insn & (1 << 8)) {
1407                     if (insn & (1 << 22)) {		/* WSTRD */
1408                         dead_tmp(tmp);
1409                         tcg_gen_qemu_st64(cpu_M0, addr, IS_USER(s));
1410                     } else {				/* WSTRW wRd */
1411                         tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1412                         gen_st32(tmp, addr, IS_USER(s));
1413                     }
1414                 } else {
1415                     if (insn & (1 << 22)) {		/* WSTRH */
1416                         tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1417                         gen_st16(tmp, addr, IS_USER(s));
1418                     } else {				/* WSTRB */
1419                         tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1420                         gen_st8(tmp, addr, IS_USER(s));
1421                     }
1422                 }
1423             }
1424         }
1425         dead_tmp(addr);
1426         return 0;
1427     }
1428 
1429     if ((insn & 0x0f000000) != 0x0e000000)
1430         return 1;
1431 
1432     switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1433     case 0x000:						/* WOR */
1434         wrd = (insn >> 12) & 0xf;
1435         rd0 = (insn >> 0) & 0xf;
1436         rd1 = (insn >> 16) & 0xf;
1437         gen_op_iwmmxt_movq_M0_wRn(rd0);
1438         gen_op_iwmmxt_orq_M0_wRn(rd1);
1439         gen_op_iwmmxt_setpsr_nz();
1440         gen_op_iwmmxt_movq_wRn_M0(wrd);
1441         gen_op_iwmmxt_set_mup();
1442         gen_op_iwmmxt_set_cup();
1443         break;
1444     case 0x011:						/* TMCR */
1445         if (insn & 0xf)
1446             return 1;
1447         rd = (insn >> 12) & 0xf;
1448         wrd = (insn >> 16) & 0xf;
1449         switch (wrd) {
1450         case ARM_IWMMXT_wCID:
1451         case ARM_IWMMXT_wCASF:
1452             break;
1453         case ARM_IWMMXT_wCon:
1454             gen_op_iwmmxt_set_cup();
1455             /* Fall through.  */
1456         case ARM_IWMMXT_wCSSF:
1457             tmp = iwmmxt_load_creg(wrd);
1458             tmp2 = load_reg(s, rd);
1459             tcg_gen_andc_i32(tmp, tmp, tmp2);
1460             dead_tmp(tmp2);
1461             iwmmxt_store_creg(wrd, tmp);
1462             break;
1463         case ARM_IWMMXT_wCGR0:
1464         case ARM_IWMMXT_wCGR1:
1465         case ARM_IWMMXT_wCGR2:
1466         case ARM_IWMMXT_wCGR3:
1467             gen_op_iwmmxt_set_cup();
1468             tmp = load_reg(s, rd);
1469             iwmmxt_store_creg(wrd, tmp);
1470             break;
1471         default:
1472             return 1;
1473         }
1474         break;
1475     case 0x100:						/* WXOR */
1476         wrd = (insn >> 12) & 0xf;
1477         rd0 = (insn >> 0) & 0xf;
1478         rd1 = (insn >> 16) & 0xf;
1479         gen_op_iwmmxt_movq_M0_wRn(rd0);
1480         gen_op_iwmmxt_xorq_M0_wRn(rd1);
1481         gen_op_iwmmxt_setpsr_nz();
1482         gen_op_iwmmxt_movq_wRn_M0(wrd);
1483         gen_op_iwmmxt_set_mup();
1484         gen_op_iwmmxt_set_cup();
1485         break;
1486     case 0x111:						/* TMRC */
1487         if (insn & 0xf)
1488             return 1;
1489         rd = (insn >> 12) & 0xf;
1490         wrd = (insn >> 16) & 0xf;
1491         tmp = iwmmxt_load_creg(wrd);
1492         store_reg(s, rd, tmp);
1493         break;
1494     case 0x300:						/* WANDN */
1495         wrd = (insn >> 12) & 0xf;
1496         rd0 = (insn >> 0) & 0xf;
1497         rd1 = (insn >> 16) & 0xf;
1498         gen_op_iwmmxt_movq_M0_wRn(rd0);
1499         tcg_gen_neg_i64(cpu_M0, cpu_M0);
1500         gen_op_iwmmxt_andq_M0_wRn(rd1);
1501         gen_op_iwmmxt_setpsr_nz();
1502         gen_op_iwmmxt_movq_wRn_M0(wrd);
1503         gen_op_iwmmxt_set_mup();
1504         gen_op_iwmmxt_set_cup();
1505         break;
1506     case 0x200:						/* WAND */
1507         wrd = (insn >> 12) & 0xf;
1508         rd0 = (insn >> 0) & 0xf;
1509         rd1 = (insn >> 16) & 0xf;
1510         gen_op_iwmmxt_movq_M0_wRn(rd0);
1511         gen_op_iwmmxt_andq_M0_wRn(rd1);
1512         gen_op_iwmmxt_setpsr_nz();
1513         gen_op_iwmmxt_movq_wRn_M0(wrd);
1514         gen_op_iwmmxt_set_mup();
1515         gen_op_iwmmxt_set_cup();
1516         break;
1517     case 0x810: case 0xa10:				/* WMADD */
1518         wrd = (insn >> 12) & 0xf;
1519         rd0 = (insn >> 0) & 0xf;
1520         rd1 = (insn >> 16) & 0xf;
1521         gen_op_iwmmxt_movq_M0_wRn(rd0);
1522         if (insn & (1 << 21))
1523             gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1524         else
1525             gen_op_iwmmxt_madduq_M0_wRn(rd1);
1526         gen_op_iwmmxt_movq_wRn_M0(wrd);
1527         gen_op_iwmmxt_set_mup();
1528         break;
1529     case 0x10e: case 0x50e: case 0x90e: case 0xd0e:	/* WUNPCKIL */
1530         wrd = (insn >> 12) & 0xf;
1531         rd0 = (insn >> 16) & 0xf;
1532         rd1 = (insn >> 0) & 0xf;
1533         gen_op_iwmmxt_movq_M0_wRn(rd0);
1534         switch ((insn >> 22) & 3) {
1535         case 0:
1536             gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1537             break;
1538         case 1:
1539             gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1540             break;
1541         case 2:
1542             gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1543             break;
1544         case 3:
1545             return 1;
1546         }
1547         gen_op_iwmmxt_movq_wRn_M0(wrd);
1548         gen_op_iwmmxt_set_mup();
1549         gen_op_iwmmxt_set_cup();
1550         break;
1551     case 0x10c: case 0x50c: case 0x90c: case 0xd0c:	/* WUNPCKIH */
1552         wrd = (insn >> 12) & 0xf;
1553         rd0 = (insn >> 16) & 0xf;
1554         rd1 = (insn >> 0) & 0xf;
1555         gen_op_iwmmxt_movq_M0_wRn(rd0);
1556         switch ((insn >> 22) & 3) {
1557         case 0:
1558             gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1559             break;
1560         case 1:
1561             gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1562             break;
1563         case 2:
1564             gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1565             break;
1566         case 3:
1567             return 1;
1568         }
1569         gen_op_iwmmxt_movq_wRn_M0(wrd);
1570         gen_op_iwmmxt_set_mup();
1571         gen_op_iwmmxt_set_cup();
1572         break;
1573     case 0x012: case 0x112: case 0x412: case 0x512:	/* WSAD */
1574         wrd = (insn >> 12) & 0xf;
1575         rd0 = (insn >> 16) & 0xf;
1576         rd1 = (insn >> 0) & 0xf;
1577         gen_op_iwmmxt_movq_M0_wRn(rd0);
1578         if (insn & (1 << 22))
1579             gen_op_iwmmxt_sadw_M0_wRn(rd1);
1580         else
1581             gen_op_iwmmxt_sadb_M0_wRn(rd1);
1582         if (!(insn & (1 << 20)))
1583             gen_op_iwmmxt_addl_M0_wRn(wrd);
1584         gen_op_iwmmxt_movq_wRn_M0(wrd);
1585         gen_op_iwmmxt_set_mup();
1586         break;
1587     case 0x010: case 0x110: case 0x210: case 0x310:	/* WMUL */
1588         wrd = (insn >> 12) & 0xf;
1589         rd0 = (insn >> 16) & 0xf;
1590         rd1 = (insn >> 0) & 0xf;
1591         gen_op_iwmmxt_movq_M0_wRn(rd0);
1592         if (insn & (1 << 21)) {
1593             if (insn & (1 << 20))
1594                 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1595             else
1596                 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1597         } else {
1598             if (insn & (1 << 20))
1599                 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1600             else
1601                 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1602         }
1603         gen_op_iwmmxt_movq_wRn_M0(wrd);
1604         gen_op_iwmmxt_set_mup();
1605         break;
1606     case 0x410: case 0x510: case 0x610: case 0x710:	/* WMAC */
1607         wrd = (insn >> 12) & 0xf;
1608         rd0 = (insn >> 16) & 0xf;
1609         rd1 = (insn >> 0) & 0xf;
1610         gen_op_iwmmxt_movq_M0_wRn(rd0);
1611         if (insn & (1 << 21))
1612             gen_op_iwmmxt_macsw_M0_wRn(rd1);
1613         else
1614             gen_op_iwmmxt_macuw_M0_wRn(rd1);
1615         if (!(insn & (1 << 20))) {
1616             iwmmxt_load_reg(cpu_V1, wrd);
1617             tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1618         }
1619         gen_op_iwmmxt_movq_wRn_M0(wrd);
1620         gen_op_iwmmxt_set_mup();
1621         break;
1622     case 0x006: case 0x406: case 0x806: case 0xc06:	/* WCMPEQ */
1623         wrd = (insn >> 12) & 0xf;
1624         rd0 = (insn >> 16) & 0xf;
1625         rd1 = (insn >> 0) & 0xf;
1626         gen_op_iwmmxt_movq_M0_wRn(rd0);
1627         switch ((insn >> 22) & 3) {
1628         case 0:
1629             gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1630             break;
1631         case 1:
1632             gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1633             break;
1634         case 2:
1635             gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1636             break;
1637         case 3:
1638             return 1;
1639         }
1640         gen_op_iwmmxt_movq_wRn_M0(wrd);
1641         gen_op_iwmmxt_set_mup();
1642         gen_op_iwmmxt_set_cup();
1643         break;
1644     case 0x800: case 0x900: case 0xc00: case 0xd00:	/* WAVG2 */
1645         wrd = (insn >> 12) & 0xf;
1646         rd0 = (insn >> 16) & 0xf;
1647         rd1 = (insn >> 0) & 0xf;
1648         gen_op_iwmmxt_movq_M0_wRn(rd0);
1649         if (insn & (1 << 22)) {
1650             if (insn & (1 << 20))
1651                 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1652             else
1653                 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1654         } else {
1655             if (insn & (1 << 20))
1656                 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1657             else
1658                 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1659         }
1660         gen_op_iwmmxt_movq_wRn_M0(wrd);
1661         gen_op_iwmmxt_set_mup();
1662         gen_op_iwmmxt_set_cup();
1663         break;
1664     case 0x802: case 0x902: case 0xa02: case 0xb02:	/* WALIGNR */
1665         wrd = (insn >> 12) & 0xf;
1666         rd0 = (insn >> 16) & 0xf;
1667         rd1 = (insn >> 0) & 0xf;
1668         gen_op_iwmmxt_movq_M0_wRn(rd0);
1669         tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1670         tcg_gen_andi_i32(tmp, tmp, 7);
1671         iwmmxt_load_reg(cpu_V1, rd1);
1672         gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
1673         dead_tmp(tmp);
1674         gen_op_iwmmxt_movq_wRn_M0(wrd);
1675         gen_op_iwmmxt_set_mup();
1676         break;
1677     case 0x601: case 0x605: case 0x609: case 0x60d:	/* TINSR */
1678         if (((insn >> 6) & 3) == 3)
1679             return 1;
1680         rd = (insn >> 12) & 0xf;
1681         wrd = (insn >> 16) & 0xf;
1682         tmp = load_reg(s, rd);
1683         gen_op_iwmmxt_movq_M0_wRn(wrd);
1684         switch ((insn >> 6) & 3) {
1685         case 0:
1686             tmp2 = tcg_const_i32(0xff);
1687             tmp3 = tcg_const_i32((insn & 7) << 3);
1688             break;
1689         case 1:
1690             tmp2 = tcg_const_i32(0xffff);
1691             tmp3 = tcg_const_i32((insn & 3) << 4);
1692             break;
1693         case 2:
1694             tmp2 = tcg_const_i32(0xffffffff);
1695             tmp3 = tcg_const_i32((insn & 1) << 5);
1696             break;
1697         default:
1698             TCGV_UNUSED(tmp2);
1699             TCGV_UNUSED(tmp3);
1700         }
1701         gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
1702         tcg_temp_free(tmp3);
1703         tcg_temp_free(tmp2);
1704         dead_tmp(tmp);
1705         gen_op_iwmmxt_movq_wRn_M0(wrd);
1706         gen_op_iwmmxt_set_mup();
1707         break;
1708     case 0x107: case 0x507: case 0x907: case 0xd07:	/* TEXTRM */
1709         rd = (insn >> 12) & 0xf;
1710         wrd = (insn >> 16) & 0xf;
1711         if (rd == 15 || ((insn >> 22) & 3) == 3)
1712             return 1;
1713         gen_op_iwmmxt_movq_M0_wRn(wrd);
1714         tmp = new_tmp();
1715         switch ((insn >> 22) & 3) {
1716         case 0:
1717             tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
1718             tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1719             if (insn & 8) {
1720                 tcg_gen_ext8s_i32(tmp, tmp);
1721             } else {
1722                 tcg_gen_andi_i32(tmp, tmp, 0xff);
1723             }
1724             break;
1725         case 1:
1726             tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
1727             tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1728             if (insn & 8) {
1729                 tcg_gen_ext16s_i32(tmp, tmp);
1730             } else {
1731                 tcg_gen_andi_i32(tmp, tmp, 0xffff);
1732             }
1733             break;
1734         case 2:
1735             tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
1736             tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1737             break;
1738         }
1739         store_reg(s, rd, tmp);
1740         break;
1741     case 0x117: case 0x517: case 0x917: case 0xd17:	/* TEXTRC */
1742         if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1743             return 1;
1744         tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1745         switch ((insn >> 22) & 3) {
1746         case 0:
1747             tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
1748             break;
1749         case 1:
1750             tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
1751             break;
1752         case 2:
1753             tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
1754             break;
1755         }
1756         tcg_gen_shli_i32(tmp, tmp, 28);
1757         gen_set_nzcv(tmp);
1758         dead_tmp(tmp);
1759         break;
1760     case 0x401: case 0x405: case 0x409: case 0x40d:	/* TBCST */
1761         if (((insn >> 6) & 3) == 3)
1762             return 1;
1763         rd = (insn >> 12) & 0xf;
1764         wrd = (insn >> 16) & 0xf;
1765         tmp = load_reg(s, rd);
1766         switch ((insn >> 6) & 3) {
1767         case 0:
1768             gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
1769             break;
1770         case 1:
1771             gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
1772             break;
1773         case 2:
1774             gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
1775             break;
1776         }
1777         dead_tmp(tmp);
1778         gen_op_iwmmxt_movq_wRn_M0(wrd);
1779         gen_op_iwmmxt_set_mup();
1780         break;
1781     case 0x113: case 0x513: case 0x913: case 0xd13:	/* TANDC */
1782         if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1783             return 1;
1784         tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1785         tmp2 = new_tmp();
1786         tcg_gen_mov_i32(tmp2, tmp);
1787         switch ((insn >> 22) & 3) {
1788         case 0:
1789             for (i = 0; i < 7; i ++) {
1790                 tcg_gen_shli_i32(tmp2, tmp2, 4);
1791                 tcg_gen_and_i32(tmp, tmp, tmp2);
1792             }
1793             break;
1794         case 1:
1795             for (i = 0; i < 3; i ++) {
1796                 tcg_gen_shli_i32(tmp2, tmp2, 8);
1797                 tcg_gen_and_i32(tmp, tmp, tmp2);
1798             }
1799             break;
1800         case 2:
1801             tcg_gen_shli_i32(tmp2, tmp2, 16);
1802             tcg_gen_and_i32(tmp, tmp, tmp2);
1803             break;
1804         }
1805         gen_set_nzcv(tmp);
1806         dead_tmp(tmp2);
1807         dead_tmp(tmp);
1808         break;
1809     case 0x01c: case 0x41c: case 0x81c: case 0xc1c:	/* WACC */
1810         wrd = (insn >> 12) & 0xf;
1811         rd0 = (insn >> 16) & 0xf;
1812         gen_op_iwmmxt_movq_M0_wRn(rd0);
1813         switch ((insn >> 22) & 3) {
1814         case 0:
1815             gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1816             break;
1817         case 1:
1818             gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1819             break;
1820         case 2:
1821             gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1822             break;
1823         case 3:
1824             return 1;
1825         }
1826         gen_op_iwmmxt_movq_wRn_M0(wrd);
1827         gen_op_iwmmxt_set_mup();
1828         break;
1829     case 0x115: case 0x515: case 0x915: case 0xd15:	/* TORC */
1830         if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1831             return 1;
1832         tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1833         tmp2 = new_tmp();
1834         tcg_gen_mov_i32(tmp2, tmp);
1835         switch ((insn >> 22) & 3) {
1836         case 0:
1837             for (i = 0; i < 7; i ++) {
1838                 tcg_gen_shli_i32(tmp2, tmp2, 4);
1839                 tcg_gen_or_i32(tmp, tmp, tmp2);
1840             }
1841             break;
1842         case 1:
1843             for (i = 0; i < 3; i ++) {
1844                 tcg_gen_shli_i32(tmp2, tmp2, 8);
1845                 tcg_gen_or_i32(tmp, tmp, tmp2);
1846             }
1847             break;
1848         case 2:
1849             tcg_gen_shli_i32(tmp2, tmp2, 16);
1850             tcg_gen_or_i32(tmp, tmp, tmp2);
1851             break;
1852         }
1853         gen_set_nzcv(tmp);
1854         dead_tmp(tmp2);
1855         dead_tmp(tmp);
1856         break;
1857     case 0x103: case 0x503: case 0x903: case 0xd03:	/* TMOVMSK */
1858         rd = (insn >> 12) & 0xf;
1859         rd0 = (insn >> 16) & 0xf;
1860         if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
1861             return 1;
1862         gen_op_iwmmxt_movq_M0_wRn(rd0);
1863         tmp = new_tmp();
1864         switch ((insn >> 22) & 3) {
1865         case 0:
1866             gen_helper_iwmmxt_msbb(tmp, cpu_M0);
1867             break;
1868         case 1:
1869             gen_helper_iwmmxt_msbw(tmp, cpu_M0);
1870             break;
1871         case 2:
1872             gen_helper_iwmmxt_msbl(tmp, cpu_M0);
1873             break;
1874         }
1875         store_reg(s, rd, tmp);
1876         break;
1877     case 0x106: case 0x306: case 0x506: case 0x706:	/* WCMPGT */
1878     case 0x906: case 0xb06: case 0xd06: case 0xf06:
1879         wrd = (insn >> 12) & 0xf;
1880         rd0 = (insn >> 16) & 0xf;
1881         rd1 = (insn >> 0) & 0xf;
1882         gen_op_iwmmxt_movq_M0_wRn(rd0);
1883         switch ((insn >> 22) & 3) {
1884         case 0:
1885             if (insn & (1 << 21))
1886                 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
1887             else
1888                 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
1889             break;
1890         case 1:
1891             if (insn & (1 << 21))
1892                 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
1893             else
1894                 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
1895             break;
1896         case 2:
1897             if (insn & (1 << 21))
1898                 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
1899             else
1900                 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
1901             break;
1902         case 3:
1903             return 1;
1904         }
1905         gen_op_iwmmxt_movq_wRn_M0(wrd);
1906         gen_op_iwmmxt_set_mup();
1907         gen_op_iwmmxt_set_cup();
1908         break;
1909     case 0x00e: case 0x20e: case 0x40e: case 0x60e:	/* WUNPCKEL */
1910     case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1911         wrd = (insn >> 12) & 0xf;
1912         rd0 = (insn >> 16) & 0xf;
1913         gen_op_iwmmxt_movq_M0_wRn(rd0);
1914         switch ((insn >> 22) & 3) {
1915         case 0:
1916             if (insn & (1 << 21))
1917                 gen_op_iwmmxt_unpacklsb_M0();
1918             else
1919                 gen_op_iwmmxt_unpacklub_M0();
1920             break;
1921         case 1:
1922             if (insn & (1 << 21))
1923                 gen_op_iwmmxt_unpacklsw_M0();
1924             else
1925                 gen_op_iwmmxt_unpackluw_M0();
1926             break;
1927         case 2:
1928             if (insn & (1 << 21))
1929                 gen_op_iwmmxt_unpacklsl_M0();
1930             else
1931                 gen_op_iwmmxt_unpacklul_M0();
1932             break;
1933         case 3:
1934             return 1;
1935         }
1936         gen_op_iwmmxt_movq_wRn_M0(wrd);
1937         gen_op_iwmmxt_set_mup();
1938         gen_op_iwmmxt_set_cup();
1939         break;
1940     case 0x00c: case 0x20c: case 0x40c: case 0x60c:	/* WUNPCKEH */
1941     case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1942         wrd = (insn >> 12) & 0xf;
1943         rd0 = (insn >> 16) & 0xf;
1944         gen_op_iwmmxt_movq_M0_wRn(rd0);
1945         switch ((insn >> 22) & 3) {
1946         case 0:
1947             if (insn & (1 << 21))
1948                 gen_op_iwmmxt_unpackhsb_M0();
1949             else
1950                 gen_op_iwmmxt_unpackhub_M0();
1951             break;
1952         case 1:
1953             if (insn & (1 << 21))
1954                 gen_op_iwmmxt_unpackhsw_M0();
1955             else
1956                 gen_op_iwmmxt_unpackhuw_M0();
1957             break;
1958         case 2:
1959             if (insn & (1 << 21))
1960                 gen_op_iwmmxt_unpackhsl_M0();
1961             else
1962                 gen_op_iwmmxt_unpackhul_M0();
1963             break;
1964         case 3:
1965             return 1;
1966         }
1967         gen_op_iwmmxt_movq_wRn_M0(wrd);
1968         gen_op_iwmmxt_set_mup();
1969         gen_op_iwmmxt_set_cup();
1970         break;
1971     case 0x204: case 0x604: case 0xa04: case 0xe04:	/* WSRL */
1972     case 0x214: case 0x614: case 0xa14: case 0xe14:
1973         if (((insn >> 22) & 3) == 0)
1974             return 1;
1975         wrd = (insn >> 12) & 0xf;
1976         rd0 = (insn >> 16) & 0xf;
1977         gen_op_iwmmxt_movq_M0_wRn(rd0);
1978         tmp = new_tmp();
1979         if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
1980             dead_tmp(tmp);
1981             return 1;
1982         }
1983         switch ((insn >> 22) & 3) {
1984         case 1:
1985             gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
1986             break;
1987         case 2:
1988             gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
1989             break;
1990         case 3:
1991             gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
1992             break;
1993         }
1994         dead_tmp(tmp);
1995         gen_op_iwmmxt_movq_wRn_M0(wrd);
1996         gen_op_iwmmxt_set_mup();
1997         gen_op_iwmmxt_set_cup();
1998         break;
1999     case 0x004: case 0x404: case 0x804: case 0xc04:	/* WSRA */
2000     case 0x014: case 0x414: case 0x814: case 0xc14:
2001         if (((insn >> 22) & 3) == 0)
2002             return 1;
2003         wrd = (insn >> 12) & 0xf;
2004         rd0 = (insn >> 16) & 0xf;
2005         gen_op_iwmmxt_movq_M0_wRn(rd0);
2006         tmp = new_tmp();
2007         if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2008             dead_tmp(tmp);
2009             return 1;
2010         }
2011         switch ((insn >> 22) & 3) {
2012         case 1:
2013             gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
2014             break;
2015         case 2:
2016             gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
2017             break;
2018         case 3:
2019             gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
2020             break;
2021         }
2022         dead_tmp(tmp);
2023         gen_op_iwmmxt_movq_wRn_M0(wrd);
2024         gen_op_iwmmxt_set_mup();
2025         gen_op_iwmmxt_set_cup();
2026         break;
2027     case 0x104: case 0x504: case 0x904: case 0xd04:	/* WSLL */
2028     case 0x114: case 0x514: case 0x914: case 0xd14:
2029         if (((insn >> 22) & 3) == 0)
2030             return 1;
2031         wrd = (insn >> 12) & 0xf;
2032         rd0 = (insn >> 16) & 0xf;
2033         gen_op_iwmmxt_movq_M0_wRn(rd0);
2034         tmp = new_tmp();
2035         if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2036             dead_tmp(tmp);
2037             return 1;
2038         }
2039         switch ((insn >> 22) & 3) {
2040         case 1:
2041             gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2042             break;
2043         case 2:
2044             gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2045             break;
2046         case 3:
2047             gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2048             break;
2049         }
2050         dead_tmp(tmp);
2051         gen_op_iwmmxt_movq_wRn_M0(wrd);
2052         gen_op_iwmmxt_set_mup();
2053         gen_op_iwmmxt_set_cup();
2054         break;
2055     case 0x304: case 0x704: case 0xb04: case 0xf04:	/* WROR */
2056     case 0x314: case 0x714: case 0xb14: case 0xf14:
2057         if (((insn >> 22) & 3) == 0)
2058             return 1;
2059         wrd = (insn >> 12) & 0xf;
2060         rd0 = (insn >> 16) & 0xf;
2061         gen_op_iwmmxt_movq_M0_wRn(rd0);
2062         tmp = new_tmp();
2063         switch ((insn >> 22) & 3) {
2064         case 1:
2065             if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2066                 dead_tmp(tmp);
2067                 return 1;
2068             }
2069             gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2070             break;
2071         case 2:
2072             if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2073                 dead_tmp(tmp);
2074                 return 1;
2075             }
2076             gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2077             break;
2078         case 3:
2079             if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2080                 dead_tmp(tmp);
2081                 return 1;
2082             }
2083             gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2084             break;
2085         }
2086         dead_tmp(tmp);
2087         gen_op_iwmmxt_movq_wRn_M0(wrd);
2088         gen_op_iwmmxt_set_mup();
2089         gen_op_iwmmxt_set_cup();
2090         break;
2091     case 0x116: case 0x316: case 0x516: case 0x716:	/* WMIN */
2092     case 0x916: case 0xb16: case 0xd16: case 0xf16:
2093         wrd = (insn >> 12) & 0xf;
2094         rd0 = (insn >> 16) & 0xf;
2095         rd1 = (insn >> 0) & 0xf;
2096         gen_op_iwmmxt_movq_M0_wRn(rd0);
2097         switch ((insn >> 22) & 3) {
2098         case 0:
2099             if (insn & (1 << 21))
2100                 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2101             else
2102                 gen_op_iwmmxt_minub_M0_wRn(rd1);
2103             break;
2104         case 1:
2105             if (insn & (1 << 21))
2106                 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2107             else
2108                 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2109             break;
2110         case 2:
2111             if (insn & (1 << 21))
2112                 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2113             else
2114                 gen_op_iwmmxt_minul_M0_wRn(rd1);
2115             break;
2116         case 3:
2117             return 1;
2118         }
2119         gen_op_iwmmxt_movq_wRn_M0(wrd);
2120         gen_op_iwmmxt_set_mup();
2121         break;
2122     case 0x016: case 0x216: case 0x416: case 0x616:	/* WMAX */
2123     case 0x816: case 0xa16: case 0xc16: case 0xe16:
2124         wrd = (insn >> 12) & 0xf;
2125         rd0 = (insn >> 16) & 0xf;
2126         rd1 = (insn >> 0) & 0xf;
2127         gen_op_iwmmxt_movq_M0_wRn(rd0);
2128         switch ((insn >> 22) & 3) {
2129         case 0:
2130             if (insn & (1 << 21))
2131                 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2132             else
2133                 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2134             break;
2135         case 1:
2136             if (insn & (1 << 21))
2137                 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2138             else
2139                 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2140             break;
2141         case 2:
2142             if (insn & (1 << 21))
2143                 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2144             else
2145                 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2146             break;
2147         case 3:
2148             return 1;
2149         }
2150         gen_op_iwmmxt_movq_wRn_M0(wrd);
2151         gen_op_iwmmxt_set_mup();
2152         break;
2153     case 0x002: case 0x102: case 0x202: case 0x302:	/* WALIGNI */
2154     case 0x402: case 0x502: case 0x602: case 0x702:
2155         wrd = (insn >> 12) & 0xf;
2156         rd0 = (insn >> 16) & 0xf;
2157         rd1 = (insn >> 0) & 0xf;
2158         gen_op_iwmmxt_movq_M0_wRn(rd0);
2159         tmp = tcg_const_i32((insn >> 20) & 3);
2160         iwmmxt_load_reg(cpu_V1, rd1);
2161         gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2162         tcg_temp_free(tmp);
2163         gen_op_iwmmxt_movq_wRn_M0(wrd);
2164         gen_op_iwmmxt_set_mup();
2165         break;
2166     case 0x01a: case 0x11a: case 0x21a: case 0x31a:	/* WSUB */
2167     case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2168     case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2169     case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2170         wrd = (insn >> 12) & 0xf;
2171         rd0 = (insn >> 16) & 0xf;
2172         rd1 = (insn >> 0) & 0xf;
2173         gen_op_iwmmxt_movq_M0_wRn(rd0);
2174         switch ((insn >> 20) & 0xf) {
2175         case 0x0:
2176             gen_op_iwmmxt_subnb_M0_wRn(rd1);
2177             break;
2178         case 0x1:
2179             gen_op_iwmmxt_subub_M0_wRn(rd1);
2180             break;
2181         case 0x3:
2182             gen_op_iwmmxt_subsb_M0_wRn(rd1);
2183             break;
2184         case 0x4:
2185             gen_op_iwmmxt_subnw_M0_wRn(rd1);
2186             break;
2187         case 0x5:
2188             gen_op_iwmmxt_subuw_M0_wRn(rd1);
2189             break;
2190         case 0x7:
2191             gen_op_iwmmxt_subsw_M0_wRn(rd1);
2192             break;
2193         case 0x8:
2194             gen_op_iwmmxt_subnl_M0_wRn(rd1);
2195             break;
2196         case 0x9:
2197             gen_op_iwmmxt_subul_M0_wRn(rd1);
2198             break;
2199         case 0xb:
2200             gen_op_iwmmxt_subsl_M0_wRn(rd1);
2201             break;
2202         default:
2203             return 1;
2204         }
2205         gen_op_iwmmxt_movq_wRn_M0(wrd);
2206         gen_op_iwmmxt_set_mup();
2207         gen_op_iwmmxt_set_cup();
2208         break;
2209     case 0x01e: case 0x11e: case 0x21e: case 0x31e:	/* WSHUFH */
2210     case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2211     case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2212     case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2213         wrd = (insn >> 12) & 0xf;
2214         rd0 = (insn >> 16) & 0xf;
2215         gen_op_iwmmxt_movq_M0_wRn(rd0);
2216         tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2217         gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2218         tcg_temp_free(tmp);
2219         gen_op_iwmmxt_movq_wRn_M0(wrd);
2220         gen_op_iwmmxt_set_mup();
2221         gen_op_iwmmxt_set_cup();
2222         break;
2223     case 0x018: case 0x118: case 0x218: case 0x318:	/* WADD */
2224     case 0x418: case 0x518: case 0x618: case 0x718:
2225     case 0x818: case 0x918: case 0xa18: case 0xb18:
2226     case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2227         wrd = (insn >> 12) & 0xf;
2228         rd0 = (insn >> 16) & 0xf;
2229         rd1 = (insn >> 0) & 0xf;
2230         gen_op_iwmmxt_movq_M0_wRn(rd0);
2231         switch ((insn >> 20) & 0xf) {
2232         case 0x0:
2233             gen_op_iwmmxt_addnb_M0_wRn(rd1);
2234             break;
2235         case 0x1:
2236             gen_op_iwmmxt_addub_M0_wRn(rd1);
2237             break;
2238         case 0x3:
2239             gen_op_iwmmxt_addsb_M0_wRn(rd1);
2240             break;
2241         case 0x4:
2242             gen_op_iwmmxt_addnw_M0_wRn(rd1);
2243             break;
2244         case 0x5:
2245             gen_op_iwmmxt_adduw_M0_wRn(rd1);
2246             break;
2247         case 0x7:
2248             gen_op_iwmmxt_addsw_M0_wRn(rd1);
2249             break;
2250         case 0x8:
2251             gen_op_iwmmxt_addnl_M0_wRn(rd1);
2252             break;
2253         case 0x9:
2254             gen_op_iwmmxt_addul_M0_wRn(rd1);
2255             break;
2256         case 0xb:
2257             gen_op_iwmmxt_addsl_M0_wRn(rd1);
2258             break;
2259         default:
2260             return 1;
2261         }
2262         gen_op_iwmmxt_movq_wRn_M0(wrd);
2263         gen_op_iwmmxt_set_mup();
2264         gen_op_iwmmxt_set_cup();
2265         break;
2266     case 0x008: case 0x108: case 0x208: case 0x308:	/* WPACK */
2267     case 0x408: case 0x508: case 0x608: case 0x708:
2268     case 0x808: case 0x908: case 0xa08: case 0xb08:
2269     case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2270         if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2271             return 1;
2272         wrd = (insn >> 12) & 0xf;
2273         rd0 = (insn >> 16) & 0xf;
2274         rd1 = (insn >> 0) & 0xf;
2275         gen_op_iwmmxt_movq_M0_wRn(rd0);
2276         switch ((insn >> 22) & 3) {
2277         case 1:
2278             if (insn & (1 << 21))
2279                 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2280             else
2281                 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2282             break;
2283         case 2:
2284             if (insn & (1 << 21))
2285                 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2286             else
2287                 gen_op_iwmmxt_packul_M0_wRn(rd1);
2288             break;
2289         case 3:
2290             if (insn & (1 << 21))
2291                 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2292             else
2293                 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2294             break;
2295         }
2296         gen_op_iwmmxt_movq_wRn_M0(wrd);
2297         gen_op_iwmmxt_set_mup();
2298         gen_op_iwmmxt_set_cup();
2299         break;
2300     case 0x201: case 0x203: case 0x205: case 0x207:
2301     case 0x209: case 0x20b: case 0x20d: case 0x20f:
2302     case 0x211: case 0x213: case 0x215: case 0x217:
2303     case 0x219: case 0x21b: case 0x21d: case 0x21f:
2304         wrd = (insn >> 5) & 0xf;
2305         rd0 = (insn >> 12) & 0xf;
2306         rd1 = (insn >> 0) & 0xf;
2307         if (rd0 == 0xf || rd1 == 0xf)
2308             return 1;
2309         gen_op_iwmmxt_movq_M0_wRn(wrd);
2310         tmp = load_reg(s, rd0);
2311         tmp2 = load_reg(s, rd1);
2312         switch ((insn >> 16) & 0xf) {
2313         case 0x0:					/* TMIA */
2314             gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2315             break;
2316         case 0x8:					/* TMIAPH */
2317             gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2318             break;
2319         case 0xc: case 0xd: case 0xe: case 0xf:		/* TMIAxy */
2320             if (insn & (1 << 16))
2321                 tcg_gen_shri_i32(tmp, tmp, 16);
2322             if (insn & (1 << 17))
2323                 tcg_gen_shri_i32(tmp2, tmp2, 16);
2324             gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2325             break;
2326         default:
2327             dead_tmp(tmp2);
2328             dead_tmp(tmp);
2329             return 1;
2330         }
2331         dead_tmp(tmp2);
2332         dead_tmp(tmp);
2333         gen_op_iwmmxt_movq_wRn_M0(wrd);
2334         gen_op_iwmmxt_set_mup();
2335         break;
2336     default:
2337         return 1;
2338     }
2339 
2340     return 0;
2341 }
2342 
2343 /* Disassemble an XScale DSP instruction.  Returns nonzero if an error occured
2344    (ie. an undefined instruction).  */
disas_dsp_insn(CPUState * env,DisasContext * s,uint32_t insn)2345 static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2346 {
2347     int acc, rd0, rd1, rdhi, rdlo;
2348     TCGv tmp, tmp2;
2349 
2350     if ((insn & 0x0ff00f10) == 0x0e200010) {
2351         /* Multiply with Internal Accumulate Format */
2352         rd0 = (insn >> 12) & 0xf;
2353         rd1 = insn & 0xf;
2354         acc = (insn >> 5) & 7;
2355 
2356         if (acc != 0)
2357             return 1;
2358 
2359         tmp = load_reg(s, rd0);
2360         tmp2 = load_reg(s, rd1);
2361         switch ((insn >> 16) & 0xf) {
2362         case 0x0:					/* MIA */
2363             gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2364             break;
2365         case 0x8:					/* MIAPH */
2366             gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2367             break;
2368         case 0xc:					/* MIABB */
2369         case 0xd:					/* MIABT */
2370         case 0xe:					/* MIATB */
2371         case 0xf:					/* MIATT */
2372             if (insn & (1 << 16))
2373                 tcg_gen_shri_i32(tmp, tmp, 16);
2374             if (insn & (1 << 17))
2375                 tcg_gen_shri_i32(tmp2, tmp2, 16);
2376             gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2377             break;
2378         default:
2379             return 1;
2380         }
2381         dead_tmp(tmp2);
2382         dead_tmp(tmp);
2383 
2384         gen_op_iwmmxt_movq_wRn_M0(acc);
2385         return 0;
2386     }
2387 
2388     if ((insn & 0x0fe00ff8) == 0x0c400000) {
2389         /* Internal Accumulator Access Format */
2390         rdhi = (insn >> 16) & 0xf;
2391         rdlo = (insn >> 12) & 0xf;
2392         acc = insn & 7;
2393 
2394         if (acc != 0)
2395             return 1;
2396 
2397         if (insn & ARM_CP_RW_BIT) {			/* MRA */
2398             iwmmxt_load_reg(cpu_V0, acc);
2399             tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
2400             tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
2401             tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
2402             tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
2403         } else {					/* MAR */
2404             tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2405             iwmmxt_store_reg(cpu_V0, acc);
2406         }
2407         return 0;
2408     }
2409 
2410     return 1;
2411 }
2412 
2413 /* Disassemble system coprocessor instruction.  Return nonzero if
2414    instruction is not defined.  */
disas_cp_insn(CPUState * env,DisasContext * s,uint32_t insn)2415 static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2416 {
2417     TCGv tmp, tmp2;
2418     uint32_t rd = (insn >> 12) & 0xf;
2419     uint32_t cp = (insn >> 8) & 0xf;
2420     if (IS_USER(s)) {
2421         return 1;
2422     }
2423 
2424     if (insn & ARM_CP_RW_BIT) {
2425         if (!env->cp[cp].cp_read)
2426             return 1;
2427         gen_set_pc_im(s->pc);
2428         tmp = new_tmp();
2429         tmp2 = tcg_const_i32(insn);
2430         gen_helper_get_cp(tmp, cpu_env, tmp2);
2431         tcg_temp_free(tmp2);
2432         store_reg(s, rd, tmp);
2433     } else {
2434         if (!env->cp[cp].cp_write)
2435             return 1;
2436         gen_set_pc_im(s->pc);
2437         tmp = load_reg(s, rd);
2438         tmp2 = tcg_const_i32(insn);
2439         gen_helper_set_cp(cpu_env, tmp2, tmp);
2440         tcg_temp_free(tmp2);
2441         dead_tmp(tmp);
2442     }
2443     return 0;
2444 }
2445 
cp15_user_ok(uint32_t insn)2446 static int cp15_user_ok(uint32_t insn)
2447 {
2448     int cpn = (insn >> 16) & 0xf;
2449     int cpm = insn & 0xf;
2450     int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2451 
2452     if (cpn == 13 && cpm == 0) {
2453         /* TLS register.  */
2454         if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
2455             return 1;
2456     }
2457     if (cpn == 7) {
2458         /* ISB, DSB, DMB.  */
2459         if ((cpm == 5 && op == 4)
2460                 || (cpm == 10 && (op == 4 || op == 5)))
2461             return 1;
2462     }
2463     return 0;
2464 }
2465 
cp15_tls_load_store(CPUState * env,DisasContext * s,uint32_t insn,uint32_t rd)2466 static int cp15_tls_load_store(CPUState *env, DisasContext *s, uint32_t insn, uint32_t rd)
2467 {
2468     TCGv tmp;
2469     int cpn = (insn >> 16) & 0xf;
2470     int cpm = insn & 0xf;
2471     int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2472 
2473     if (!arm_feature(env, ARM_FEATURE_V6K))
2474         return 0;
2475 
2476     if (!(cpn == 13 && cpm == 0))
2477         return 0;
2478 
2479     if (insn & ARM_CP_RW_BIT) {
2480         switch (op) {
2481         case 2:
2482             tmp = load_cpu_field(cp15.c13_tls1);
2483             break;
2484         case 3:
2485             tmp = load_cpu_field(cp15.c13_tls2);
2486             break;
2487         case 4:
2488             tmp = load_cpu_field(cp15.c13_tls3);
2489             break;
2490         default:
2491             return 0;
2492         }
2493         store_reg(s, rd, tmp);
2494 
2495     } else {
2496         tmp = load_reg(s, rd);
2497         switch (op) {
2498         case 2:
2499             store_cpu_field(tmp, cp15.c13_tls1);
2500             break;
2501         case 3:
2502             store_cpu_field(tmp, cp15.c13_tls2);
2503             break;
2504         case 4:
2505             store_cpu_field(tmp, cp15.c13_tls3);
2506             break;
2507         default:
2508             dead_tmp(tmp);
2509             return 0;
2510         }
2511     }
2512     return 1;
2513 }
2514 
2515 /* Disassemble system coprocessor (cp15) instruction.  Return nonzero if
2516    instruction is not defined.  */
disas_cp15_insn(CPUState * env,DisasContext * s,uint32_t insn)2517 static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
2518 {
2519     uint32_t rd;
2520     TCGv tmp, tmp2;
2521 
2522     /* M profile cores use memory mapped registers instead of cp15.  */
2523     if (arm_feature(env, ARM_FEATURE_M))
2524 	return 1;
2525 
2526     if ((insn & (1 << 25)) == 0) {
2527         if (insn & (1 << 20)) {
2528             /* mrrc */
2529             return 1;
2530         }
2531         /* mcrr.  Used for block cache operations, so implement as no-op.  */
2532         return 0;
2533     }
2534     if ((insn & (1 << 4)) == 0) {
2535         /* cdp */
2536         return 1;
2537     }
2538     if (IS_USER(s) && !cp15_user_ok(insn)) {
2539         return 1;
2540     }
2541     if ((insn & 0x0fff0fff) == 0x0e070f90
2542         || (insn & 0x0fff0fff) == 0x0e070f58) {
2543         /* Wait for interrupt.  */
2544         gen_set_pc_im(s->pc);
2545         s->is_jmp = DISAS_WFI;
2546         return 0;
2547     }
2548     rd = (insn >> 12) & 0xf;
2549 
2550     if (cp15_tls_load_store(env, s, insn, rd))
2551         return 0;
2552 
2553     tmp2 = tcg_const_i32(insn);
2554     if (insn & ARM_CP_RW_BIT) {
2555         tmp = new_tmp();
2556         gen_helper_get_cp15(tmp, cpu_env, tmp2);
2557         /* If the destination register is r15 then sets condition codes.  */
2558         if (rd != 15)
2559             store_reg(s, rd, tmp);
2560         else
2561             dead_tmp(tmp);
2562     } else {
2563         tmp = load_reg(s, rd);
2564         gen_helper_set_cp15(cpu_env, tmp2, tmp);
2565         dead_tmp(tmp);
2566         /* Normally we would always end the TB here, but Linux
2567          * arch/arm/mach-pxa/sleep.S expects two instructions following
2568          * an MMU enable to execute from cache.  Imitate this behaviour.  */
2569         if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
2570                 (insn & 0x0fff0fff) != 0x0e010f10)
2571             gen_lookup_tb(s);
2572     }
2573     tcg_temp_free_i32(tmp2);
2574     return 0;
2575 }
2576 
2577 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2578 #define VFP_SREG(insn, bigbit, smallbit) \
2579   ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2580 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2581     if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2582         reg = (((insn) >> (bigbit)) & 0x0f) \
2583               | (((insn) >> ((smallbit) - 4)) & 0x10); \
2584     } else { \
2585         if (insn & (1 << (smallbit))) \
2586             return 1; \
2587         reg = ((insn) >> (bigbit)) & 0x0f; \
2588     }} while (0)
2589 
2590 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2591 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2592 #define VFP_SREG_N(insn) VFP_SREG(insn, 16,  7)
2593 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16,  7)
2594 #define VFP_SREG_M(insn) VFP_SREG(insn,  0,  5)
2595 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn,  0,  5)
2596 
2597 /* Move between integer and VFP cores.  */
gen_vfp_mrs(void)2598 static TCGv gen_vfp_mrs(void)
2599 {
2600     TCGv tmp = new_tmp();
2601     tcg_gen_mov_i32(tmp, cpu_F0s);
2602     return tmp;
2603 }
2604 
gen_vfp_msr(TCGv tmp)2605 static void gen_vfp_msr(TCGv tmp)
2606 {
2607     tcg_gen_mov_i32(cpu_F0s, tmp);
2608     dead_tmp(tmp);
2609 }
2610 
gen_neon_dup_u8(TCGv var,int shift)2611 static void gen_neon_dup_u8(TCGv var, int shift)
2612 {
2613     TCGv tmp = new_tmp();
2614     if (shift)
2615         tcg_gen_shri_i32(var, var, shift);
2616     tcg_gen_ext8u_i32(var, var);
2617     tcg_gen_shli_i32(tmp, var, 8);
2618     tcg_gen_or_i32(var, var, tmp);
2619     tcg_gen_shli_i32(tmp, var, 16);
2620     tcg_gen_or_i32(var, var, tmp);
2621     dead_tmp(tmp);
2622 }
2623 
gen_neon_dup_low16(TCGv var)2624 static void gen_neon_dup_low16(TCGv var)
2625 {
2626     TCGv tmp = new_tmp();
2627     tcg_gen_ext16u_i32(var, var);
2628     tcg_gen_shli_i32(tmp, var, 16);
2629     tcg_gen_or_i32(var, var, tmp);
2630     dead_tmp(tmp);
2631 }
2632 
gen_neon_dup_high16(TCGv var)2633 static void gen_neon_dup_high16(TCGv var)
2634 {
2635     TCGv tmp = new_tmp();
2636     tcg_gen_andi_i32(var, var, 0xffff0000);
2637     tcg_gen_shri_i32(tmp, var, 16);
2638     tcg_gen_or_i32(var, var, tmp);
2639     dead_tmp(tmp);
2640 }
2641 
2642 /* Disassemble a VFP instruction.  Returns nonzero if an error occured
2643    (ie. an undefined instruction).  */
disas_vfp_insn(CPUState * env,DisasContext * s,uint32_t insn)2644 static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2645 {
2646     uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2647     int dp, veclen;
2648     TCGv addr;
2649     TCGv tmp;
2650     TCGv tmp2;
2651 
2652     if (!arm_feature(env, ARM_FEATURE_VFP))
2653         return 1;
2654 
2655     if (!s->vfp_enabled) {
2656         /* VFP disabled.  Only allow fmxr/fmrx to/from some control regs.  */
2657         if ((insn & 0x0fe00fff) != 0x0ee00a10)
2658             return 1;
2659         rn = (insn >> 16) & 0xf;
2660         if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2661             && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2662             return 1;
2663     }
2664     dp = ((insn & 0xf00) == 0xb00);
2665     switch ((insn >> 24) & 0xf) {
2666     case 0xe:
2667         if (insn & (1 << 4)) {
2668             /* single register transfer */
2669             rd = (insn >> 12) & 0xf;
2670             if (dp) {
2671                 int size;
2672                 int pass;
2673 
2674                 VFP_DREG_N(rn, insn);
2675                 if (insn & 0xf)
2676                     return 1;
2677                 if (insn & 0x00c00060
2678                     && !arm_feature(env, ARM_FEATURE_NEON))
2679                     return 1;
2680 
2681                 pass = (insn >> 21) & 1;
2682                 if (insn & (1 << 22)) {
2683                     size = 0;
2684                     offset = ((insn >> 5) & 3) * 8;
2685                 } else if (insn & (1 << 5)) {
2686                     size = 1;
2687                     offset = (insn & (1 << 6)) ? 16 : 0;
2688                 } else {
2689                     size = 2;
2690                     offset = 0;
2691                 }
2692                 if (insn & ARM_CP_RW_BIT) {
2693                     /* vfp->arm */
2694                     tmp = neon_load_reg(rn, pass);
2695                     switch (size) {
2696                     case 0:
2697                         if (offset)
2698                             tcg_gen_shri_i32(tmp, tmp, offset);
2699                         if (insn & (1 << 23))
2700                             gen_uxtb(tmp);
2701                         else
2702                             gen_sxtb(tmp);
2703                         break;
2704                     case 1:
2705                         if (insn & (1 << 23)) {
2706                             if (offset) {
2707                                 tcg_gen_shri_i32(tmp, tmp, 16);
2708                             } else {
2709                                 gen_uxth(tmp);
2710                             }
2711                         } else {
2712                             if (offset) {
2713                                 tcg_gen_sari_i32(tmp, tmp, 16);
2714                             } else {
2715                                 gen_sxth(tmp);
2716                             }
2717                         }
2718                         break;
2719                     case 2:
2720                         break;
2721                     }
2722                     store_reg(s, rd, tmp);
2723                 } else {
2724                     /* arm->vfp */
2725                     tmp = load_reg(s, rd);
2726                     if (insn & (1 << 23)) {
2727                         /* VDUP */
2728                         if (size == 0) {
2729                             gen_neon_dup_u8(tmp, 0);
2730                         } else if (size == 1) {
2731                             gen_neon_dup_low16(tmp);
2732                         }
2733                         for (n = 0; n <= pass * 2; n++) {
2734                             tmp2 = new_tmp();
2735                             tcg_gen_mov_i32(tmp2, tmp);
2736                             neon_store_reg(rn, n, tmp2);
2737                         }
2738                         neon_store_reg(rn, n, tmp);
2739                     } else {
2740                         /* VMOV */
2741                         switch (size) {
2742                         case 0:
2743                             tmp2 = neon_load_reg(rn, pass);
2744                             gen_bfi(tmp, tmp2, tmp, offset, 0xff);
2745                             dead_tmp(tmp2);
2746                             break;
2747                         case 1:
2748                             tmp2 = neon_load_reg(rn, pass);
2749                             gen_bfi(tmp, tmp2, tmp, offset, 0xffff);
2750                             dead_tmp(tmp2);
2751                             break;
2752                         case 2:
2753                             break;
2754                         }
2755                         neon_store_reg(rn, pass, tmp);
2756                     }
2757                 }
2758             } else { /* !dp */
2759                 if ((insn & 0x6f) != 0x00)
2760                     return 1;
2761                 rn = VFP_SREG_N(insn);
2762                 if (insn & ARM_CP_RW_BIT) {
2763                     /* vfp->arm */
2764                     if (insn & (1 << 21)) {
2765                         /* system register */
2766                         rn >>= 1;
2767 
2768                         switch (rn) {
2769                         case ARM_VFP_FPSID:
2770                             /* VFP2 allows access to FSID from userspace.
2771                                VFP3 restricts all id registers to privileged
2772                                accesses.  */
2773                             if (IS_USER(s)
2774                                 && arm_feature(env, ARM_FEATURE_VFP3))
2775                                 return 1;
2776                             tmp = load_cpu_field(vfp.xregs[rn]);
2777                             break;
2778                         case ARM_VFP_FPEXC:
2779                             if (IS_USER(s))
2780                                 return 1;
2781                             tmp = load_cpu_field(vfp.xregs[rn]);
2782                             break;
2783                         case ARM_VFP_FPINST:
2784                         case ARM_VFP_FPINST2:
2785                             /* Not present in VFP3.  */
2786                             if (IS_USER(s)
2787                                 || arm_feature(env, ARM_FEATURE_VFP3))
2788                                 return 1;
2789                             tmp = load_cpu_field(vfp.xregs[rn]);
2790                             break;
2791                         case ARM_VFP_FPSCR:
2792                             if (rd == 15) {
2793                                 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2794                                 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2795                             } else {
2796                                 tmp = new_tmp();
2797                                 gen_helper_vfp_get_fpscr(tmp, cpu_env);
2798                             }
2799                             break;
2800                         case ARM_VFP_MVFR0:
2801                         case ARM_VFP_MVFR1:
2802                             if (IS_USER(s)
2803                                 || !arm_feature(env, ARM_FEATURE_VFP3))
2804                                 return 1;
2805                             tmp = load_cpu_field(vfp.xregs[rn]);
2806                             break;
2807                         default:
2808                             return 1;
2809                         }
2810                     } else {
2811                         gen_mov_F0_vreg(0, rn);
2812                         tmp = gen_vfp_mrs();
2813                     }
2814                     if (rd == 15) {
2815                         /* Set the 4 flag bits in the CPSR.  */
2816                         gen_set_nzcv(tmp);
2817                         dead_tmp(tmp);
2818                     } else {
2819                         store_reg(s, rd, tmp);
2820                     }
2821                 } else {
2822                     /* arm->vfp */
2823                     tmp = load_reg(s, rd);
2824                     if (insn & (1 << 21)) {
2825                         rn >>= 1;
2826                         /* system register */
2827                         switch (rn) {
2828                         case ARM_VFP_FPSID:
2829                         case ARM_VFP_MVFR0:
2830                         case ARM_VFP_MVFR1:
2831                             /* Writes are ignored.  */
2832                             break;
2833                         case ARM_VFP_FPSCR:
2834                             gen_helper_vfp_set_fpscr(cpu_env, tmp);
2835                             dead_tmp(tmp);
2836                             gen_lookup_tb(s);
2837                             break;
2838                         case ARM_VFP_FPEXC:
2839                             if (IS_USER(s))
2840                                 return 1;
2841                             /* TODO: VFP subarchitecture support.
2842                              * For now, keep the EN bit only */
2843                             tcg_gen_andi_i32(tmp, tmp, 1 << 30);
2844                             store_cpu_field(tmp, vfp.xregs[rn]);
2845                             gen_lookup_tb(s);
2846                             break;
2847                         case ARM_VFP_FPINST:
2848                         case ARM_VFP_FPINST2:
2849                             store_cpu_field(tmp, vfp.xregs[rn]);
2850                             break;
2851                         default:
2852                             return 1;
2853                         }
2854                     } else {
2855                         gen_vfp_msr(tmp);
2856                         gen_mov_vreg_F0(0, rn);
2857                     }
2858                 }
2859             }
2860         } else {
2861             /* data processing */
2862             /* The opcode is in bits 23, 21, 20 and 6.  */
2863             op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2864             if (dp) {
2865                 if (op == 15) {
2866                     /* rn is opcode */
2867                     rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2868                 } else {
2869                     /* rn is register number */
2870                     VFP_DREG_N(rn, insn);
2871                 }
2872 
2873                 if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18))) {
2874                     /* Integer or single precision destination.  */
2875                     rd = VFP_SREG_D(insn);
2876                 } else {
2877                     VFP_DREG_D(rd, insn);
2878                 }
2879                 if (op == 15 &&
2880                     (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14))) {
2881                     /* VCVT from int is always from S reg regardless of dp bit.
2882                      * VCVT with immediate frac_bits has same format as SREG_M
2883                      */
2884                     rm = VFP_SREG_M(insn);
2885                 } else {
2886                     VFP_DREG_M(rm, insn);
2887                 }
2888             } else {
2889                 rn = VFP_SREG_N(insn);
2890                 if (op == 15 && rn == 15) {
2891                     /* Double precision destination.  */
2892                     VFP_DREG_D(rd, insn);
2893                 } else {
2894                     rd = VFP_SREG_D(insn);
2895                 }
2896                 /* NB that we implicitly rely on the encoding for the frac_bits
2897                  * in VCVT of fixed to float being the same as that of an SREG_M
2898                  */
2899                 rm = VFP_SREG_M(insn);
2900             }
2901 
2902             veclen = s->vec_len;
2903             if (op == 15 && rn > 3)
2904                 veclen = 0;
2905 
2906             /* Shut up compiler warnings.  */
2907             delta_m = 0;
2908             delta_d = 0;
2909             bank_mask = 0;
2910 
2911             if (veclen > 0) {
2912                 if (dp)
2913                     bank_mask = 0xc;
2914                 else
2915                     bank_mask = 0x18;
2916 
2917                 /* Figure out what type of vector operation this is.  */
2918                 if ((rd & bank_mask) == 0) {
2919                     /* scalar */
2920                     veclen = 0;
2921                 } else {
2922                     if (dp)
2923                         delta_d = (s->vec_stride >> 1) + 1;
2924                     else
2925                         delta_d = s->vec_stride + 1;
2926 
2927                     if ((rm & bank_mask) == 0) {
2928                         /* mixed scalar/vector */
2929                         delta_m = 0;
2930                     } else {
2931                         /* vector */
2932                         delta_m = delta_d;
2933                     }
2934                 }
2935             }
2936 
2937             /* Load the initial operands.  */
2938             if (op == 15) {
2939                 switch (rn) {
2940                 case 16:
2941                 case 17:
2942                     /* Integer source */
2943                     gen_mov_F0_vreg(0, rm);
2944                     break;
2945                 case 8:
2946                 case 9:
2947                     /* Compare */
2948                     gen_mov_F0_vreg(dp, rd);
2949                     gen_mov_F1_vreg(dp, rm);
2950                     break;
2951                 case 10:
2952                 case 11:
2953                     /* Compare with zero */
2954                     gen_mov_F0_vreg(dp, rd);
2955                     gen_vfp_F1_ld0(dp);
2956                     break;
2957                 case 20:
2958                 case 21:
2959                 case 22:
2960                 case 23:
2961                 case 28:
2962                 case 29:
2963                 case 30:
2964                 case 31:
2965                     /* Source and destination the same.  */
2966                     gen_mov_F0_vreg(dp, rd);
2967                     break;
2968                 default:
2969                     /* One source operand.  */
2970                     gen_mov_F0_vreg(dp, rm);
2971                     break;
2972                 }
2973             } else {
2974                 /* Two source operands.  */
2975                 gen_mov_F0_vreg(dp, rn);
2976                 gen_mov_F1_vreg(dp, rm);
2977             }
2978 
2979             for (;;) {
2980                 /* Perform the calculation.  */
2981                 switch (op) {
2982                 case 0: /* mac: fd + (fn * fm) */
2983                     gen_vfp_mul(dp);
2984                     gen_mov_F1_vreg(dp, rd);
2985                     gen_vfp_add(dp);
2986                     break;
2987                 case 1: /* nmac: fd - (fn * fm) */
2988                     gen_vfp_mul(dp);
2989                     gen_vfp_neg(dp);
2990                     gen_mov_F1_vreg(dp, rd);
2991                     gen_vfp_add(dp);
2992                     break;
2993                 case 2: /* msc: -fd + (fn * fm) */
2994                     gen_vfp_mul(dp);
2995                     gen_mov_F1_vreg(dp, rd);
2996                     gen_vfp_sub(dp);
2997                     break;
2998                 case 3: /* nmsc: -fd - (fn * fm)  */
2999                     gen_vfp_mul(dp);
3000                     gen_vfp_neg(dp);
3001                     gen_mov_F1_vreg(dp, rd);
3002                     gen_vfp_sub(dp);
3003                     break;
3004                 case 4: /* mul: fn * fm */
3005                     gen_vfp_mul(dp);
3006                     break;
3007                 case 5: /* nmul: -(fn * fm) */
3008                     gen_vfp_mul(dp);
3009                     gen_vfp_neg(dp);
3010                     break;
3011                 case 6: /* add: fn + fm */
3012                     gen_vfp_add(dp);
3013                     break;
3014                 case 7: /* sub: fn - fm */
3015                     gen_vfp_sub(dp);
3016                     break;
3017                 case 8: /* div: fn / fm */
3018                     gen_vfp_div(dp);
3019                     break;
3020                 case 14: /* fconst */
3021                     if (!arm_feature(env, ARM_FEATURE_VFP3))
3022                       return 1;
3023 
3024                     n = (insn << 12) & 0x80000000;
3025                     i = ((insn >> 12) & 0x70) | (insn & 0xf);
3026                     if (dp) {
3027                         if (i & 0x40)
3028                             i |= 0x3f80;
3029                         else
3030                             i |= 0x4000;
3031                         n |= i << 16;
3032                         tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3033                     } else {
3034                         if (i & 0x40)
3035                             i |= 0x780;
3036                         else
3037                             i |= 0x800;
3038                         n |= i << 19;
3039                         tcg_gen_movi_i32(cpu_F0s, n);
3040                     }
3041                     break;
3042                 case 15: /* extension space */
3043                     switch (rn) {
3044                     case 0: /* cpy */
3045                         /* no-op */
3046                         break;
3047                     case 1: /* abs */
3048                         gen_vfp_abs(dp);
3049                         break;
3050                     case 2: /* neg */
3051                         gen_vfp_neg(dp);
3052                         break;
3053                     case 3: /* sqrt */
3054                         gen_vfp_sqrt(dp);
3055                         break;
3056                     case 4: /* vcvtb.f32.f16 */
3057                         if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3058                           return 1;
3059                         tmp = gen_vfp_mrs();
3060                         tcg_gen_ext16u_i32(tmp, tmp);
3061                         gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3062                         dead_tmp(tmp);
3063                         break;
3064                     case 5: /* vcvtt.f32.f16 */
3065                         if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3066                           return 1;
3067                         tmp = gen_vfp_mrs();
3068                         tcg_gen_shri_i32(tmp, tmp, 16);
3069                         gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3070                         dead_tmp(tmp);
3071                         break;
3072                     case 6: /* vcvtb.f16.f32 */
3073                         if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3074                           return 1;
3075                         tmp = new_tmp();
3076                         gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3077                         gen_mov_F0_vreg(0, rd);
3078                         tmp2 = gen_vfp_mrs();
3079                         tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
3080                         tcg_gen_or_i32(tmp, tmp, tmp2);
3081                         dead_tmp(tmp2);
3082                         gen_vfp_msr(tmp);
3083                         break;
3084                     case 7: /* vcvtt.f16.f32 */
3085                         if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3086                           return 1;
3087                         tmp = new_tmp();
3088                         gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3089                         tcg_gen_shli_i32(tmp, tmp, 16);
3090                         gen_mov_F0_vreg(0, rd);
3091                         tmp2 = gen_vfp_mrs();
3092                         tcg_gen_ext16u_i32(tmp2, tmp2);
3093                         tcg_gen_or_i32(tmp, tmp, tmp2);
3094                         dead_tmp(tmp2);
3095                         gen_vfp_msr(tmp);
3096                         break;
3097                     case 8: /* cmp */
3098                         gen_vfp_cmp(dp);
3099                         break;
3100                     case 9: /* cmpe */
3101                         gen_vfp_cmpe(dp);
3102                         break;
3103                     case 10: /* cmpz */
3104                         gen_vfp_cmp(dp);
3105                         break;
3106                     case 11: /* cmpez */
3107                         gen_vfp_F1_ld0(dp);
3108                         gen_vfp_cmpe(dp);
3109                         break;
3110                     case 15: /* single<->double conversion */
3111                         if (dp)
3112                             gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3113                         else
3114                             gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3115                         break;
3116                     case 16: /* fuito */
3117                         gen_vfp_uito(dp);
3118                         break;
3119                     case 17: /* fsito */
3120                         gen_vfp_sito(dp);
3121                         break;
3122                     case 20: /* fshto */
3123                         if (!arm_feature(env, ARM_FEATURE_VFP3))
3124                           return 1;
3125                         gen_vfp_shto(dp, 16 - rm);
3126                         break;
3127                     case 21: /* fslto */
3128                         if (!arm_feature(env, ARM_FEATURE_VFP3))
3129                           return 1;
3130                         gen_vfp_slto(dp, 32 - rm);
3131                         break;
3132                     case 22: /* fuhto */
3133                         if (!arm_feature(env, ARM_FEATURE_VFP3))
3134                           return 1;
3135                         gen_vfp_uhto(dp, 16 - rm);
3136                         break;
3137                     case 23: /* fulto */
3138                         if (!arm_feature(env, ARM_FEATURE_VFP3))
3139                           return 1;
3140                         gen_vfp_ulto(dp, 32 - rm);
3141                         break;
3142                     case 24: /* ftoui */
3143                         gen_vfp_toui(dp);
3144                         break;
3145                     case 25: /* ftouiz */
3146                         gen_vfp_touiz(dp);
3147                         break;
3148                     case 26: /* ftosi */
3149                         gen_vfp_tosi(dp);
3150                         break;
3151                     case 27: /* ftosiz */
3152                         gen_vfp_tosiz(dp);
3153                         break;
3154                     case 28: /* ftosh */
3155                         if (!arm_feature(env, ARM_FEATURE_VFP3))
3156                           return 1;
3157                         gen_vfp_tosh(