1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include "qemu/osdep.h"
22
23#include "cpu.h"
24#include "internals.h"
25#include "disas/disas.h"
26#include "exec/exec-all.h"
27#include "tcg-op.h"
28#include "qemu/log.h"
29#include "qemu/bitops.h"
30#include "arm_ldst.h"
31
32#include "exec/helper-proto.h"
33#include "exec/helper-gen.h"
34
35#include "trace-tcg.h"
36#include "exec/log.h"
37
38
39#define ENABLE_ARCH_4T arm_dc_feature(s, ARM_FEATURE_V4T)
40#define ENABLE_ARCH_5 arm_dc_feature(s, ARM_FEATURE_V5)
41
42#define ENABLE_ARCH_5TE arm_dc_feature(s, ARM_FEATURE_V5)
43#define ENABLE_ARCH_5J 0
44#define ENABLE_ARCH_6 arm_dc_feature(s, ARM_FEATURE_V6)
45#define ENABLE_ARCH_6K arm_dc_feature(s, ARM_FEATURE_V6K)
46#define ENABLE_ARCH_6T2 arm_dc_feature(s, ARM_FEATURE_THUMB2)
47#define ENABLE_ARCH_7 arm_dc_feature(s, ARM_FEATURE_V7)
48#define ENABLE_ARCH_8 arm_dc_feature(s, ARM_FEATURE_V8)
49
50#define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
51
52#include "translate.h"
53
54#if defined(CONFIG_USER_ONLY)
55#define IS_USER(s) 1
56#else
57#define IS_USER(s) (s->user)
58#endif
59
60TCGv_env cpu_env;
61
62static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
63static TCGv_i32 cpu_R[16];
64TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
65TCGv_i64 cpu_exclusive_addr;
66TCGv_i64 cpu_exclusive_val;
67#ifdef CONFIG_USER_ONLY
68TCGv_i64 cpu_exclusive_test;
69TCGv_i32 cpu_exclusive_info;
70#endif
71
72
73static TCGv_i32 cpu_F0s, cpu_F1s;
74static TCGv_i64 cpu_F0d, cpu_F1d;
75
76#include "exec/gen-icount.h"
77
78static const char *regnames[] =
79 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
80 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
81
82
83void arm_translate_init(void)
84{
85 int i;
86
87 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
88
89 for (i = 0; i < 16; i++) {
90 cpu_R[i] = tcg_global_mem_new_i32(cpu_env,
91 offsetof(CPUARMState, regs[i]),
92 regnames[i]);
93 }
94 cpu_CF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, CF), "CF");
95 cpu_NF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, NF), "NF");
96 cpu_VF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, VF), "VF");
97 cpu_ZF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, ZF), "ZF");
98
99 cpu_exclusive_addr = tcg_global_mem_new_i64(cpu_env,
100 offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
101 cpu_exclusive_val = tcg_global_mem_new_i64(cpu_env,
102 offsetof(CPUARMState, exclusive_val), "exclusive_val");
103#ifdef CONFIG_USER_ONLY
104 cpu_exclusive_test = tcg_global_mem_new_i64(cpu_env,
105 offsetof(CPUARMState, exclusive_test), "exclusive_test");
106 cpu_exclusive_info = tcg_global_mem_new_i32(cpu_env,
107 offsetof(CPUARMState, exclusive_info), "exclusive_info");
108#endif
109
110 a64_translate_init();
111}
112
113static inline ARMMMUIdx get_a32_user_mem_index(DisasContext *s)
114{
115
116
117
118
119
120 switch (s->mmu_idx) {
121 case ARMMMUIdx_S1E2:
122 case ARMMMUIdx_S12NSE0:
123 case ARMMMUIdx_S12NSE1:
124 return ARMMMUIdx_S12NSE0;
125 case ARMMMUIdx_S1E3:
126 case ARMMMUIdx_S1SE0:
127 case ARMMMUIdx_S1SE1:
128 return ARMMMUIdx_S1SE0;
129 case ARMMMUIdx_S2NS:
130 default:
131 g_assert_not_reached();
132 }
133}
134
135static inline TCGv_i32 load_cpu_offset(int offset)
136{
137 TCGv_i32 tmp = tcg_temp_new_i32();
138 tcg_gen_ld_i32(tmp, cpu_env, offset);
139 return tmp;
140}
141
142#define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
143
144static inline void store_cpu_offset(TCGv_i32 var, int offset)
145{
146 tcg_gen_st_i32(var, cpu_env, offset);
147 tcg_temp_free_i32(var);
148}
149
150#define store_cpu_field(var, name) \
151 store_cpu_offset(var, offsetof(CPUARMState, name))
152
153
154static void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
155{
156 if (reg == 15) {
157 uint32_t addr;
158
159 if (s->thumb)
160 addr = (long)s->pc + 2;
161 else
162 addr = (long)s->pc + 4;
163 tcg_gen_movi_i32(var, addr);
164 } else {
165 tcg_gen_mov_i32(var, cpu_R[reg]);
166 }
167}
168
169
170static inline TCGv_i32 load_reg(DisasContext *s, int reg)
171{
172 TCGv_i32 tmp = tcg_temp_new_i32();
173 load_reg_var(s, tmp, reg);
174 return tmp;
175}
176
177
178
179static void store_reg(DisasContext *s, int reg, TCGv_i32 var)
180{
181 if (reg == 15) {
182 tcg_gen_andi_i32(var, var, ~1);
183 s->is_jmp = DISAS_JUMP;
184 }
185 tcg_gen_mov_i32(cpu_R[reg], var);
186 tcg_temp_free_i32(var);
187}
188
189
190#define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
191#define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
192#define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
193#define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
194
195#define gen_sxtb16(var) gen_helper_sxtb16(var, var)
196#define gen_uxtb16(var) gen_helper_uxtb16(var, var)
197
198
199static inline void gen_set_cpsr(TCGv_i32 var, uint32_t mask)
200{
201 TCGv_i32 tmp_mask = tcg_const_i32(mask);
202 gen_helper_cpsr_write(cpu_env, var, tmp_mask);
203 tcg_temp_free_i32(tmp_mask);
204}
205
206#define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
207
208static void gen_exception_internal(int excp)
209{
210 TCGv_i32 tcg_excp = tcg_const_i32(excp);
211
212 assert(excp_is_internal(excp));
213 gen_helper_exception_internal(cpu_env, tcg_excp);
214 tcg_temp_free_i32(tcg_excp);
215}
216
217static void gen_exception(int excp, uint32_t syndrome, uint32_t target_el)
218{
219 TCGv_i32 tcg_excp = tcg_const_i32(excp);
220 TCGv_i32 tcg_syn = tcg_const_i32(syndrome);
221 TCGv_i32 tcg_el = tcg_const_i32(target_el);
222
223 gen_helper_exception_with_syndrome(cpu_env, tcg_excp,
224 tcg_syn, tcg_el);
225
226 tcg_temp_free_i32(tcg_el);
227 tcg_temp_free_i32(tcg_syn);
228 tcg_temp_free_i32(tcg_excp);
229}
230
231static void gen_ss_advance(DisasContext *s)
232{
233
234
235
236 if (s->ss_active) {
237 s->pstate_ss = 0;
238 gen_helper_clear_pstate_ss(cpu_env);
239 }
240}
241
242static void gen_step_complete_exception(DisasContext *s)
243{
244
245
246
247
248
249
250
251
252
253 gen_ss_advance(s);
254 gen_exception(EXCP_UDEF, syn_swstep(s->ss_same_el, 1, s->is_ldex),
255 default_exception_el(s));
256 s->is_jmp = DISAS_EXC;
257}
258
259static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
260{
261 TCGv_i32 tmp1 = tcg_temp_new_i32();
262 TCGv_i32 tmp2 = tcg_temp_new_i32();
263 tcg_gen_ext16s_i32(tmp1, a);
264 tcg_gen_ext16s_i32(tmp2, b);
265 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
266 tcg_temp_free_i32(tmp2);
267 tcg_gen_sari_i32(a, a, 16);
268 tcg_gen_sari_i32(b, b, 16);
269 tcg_gen_mul_i32(b, b, a);
270 tcg_gen_mov_i32(a, tmp1);
271 tcg_temp_free_i32(tmp1);
272}
273
274
275static void gen_rev16(TCGv_i32 var)
276{
277 TCGv_i32 tmp = tcg_temp_new_i32();
278 tcg_gen_shri_i32(tmp, var, 8);
279 tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
280 tcg_gen_shli_i32(var, var, 8);
281 tcg_gen_andi_i32(var, var, 0xff00ff00);
282 tcg_gen_or_i32(var, var, tmp);
283 tcg_temp_free_i32(tmp);
284}
285
286
287static void gen_revsh(TCGv_i32 var)
288{
289 tcg_gen_ext16u_i32(var, var);
290 tcg_gen_bswap16_i32(var, var);
291 tcg_gen_ext16s_i32(var, var);
292}
293
294
295static void gen_ubfx(TCGv_i32 var, int shift, uint32_t mask)
296{
297 if (shift)
298 tcg_gen_shri_i32(var, var, shift);
299 tcg_gen_andi_i32(var, var, mask);
300}
301
302
303static void gen_sbfx(TCGv_i32 var, int shift, int width)
304{
305 uint32_t signbit;
306
307 if (shift)
308 tcg_gen_sari_i32(var, var, shift);
309 if (shift + width < 32) {
310 signbit = 1u << (width - 1);
311 tcg_gen_andi_i32(var, var, (1u << width) - 1);
312 tcg_gen_xori_i32(var, var, signbit);
313 tcg_gen_subi_i32(var, var, signbit);
314 }
315}
316
317
318static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv_i32 b)
319{
320 TCGv_i64 tmp64 = tcg_temp_new_i64();
321
322 tcg_gen_extu_i32_i64(tmp64, b);
323 tcg_temp_free_i32(b);
324 tcg_gen_shli_i64(tmp64, tmp64, 32);
325 tcg_gen_add_i64(a, tmp64, a);
326
327 tcg_temp_free_i64(tmp64);
328 return a;
329}
330
331
332static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv_i32 b)
333{
334 TCGv_i64 tmp64 = tcg_temp_new_i64();
335
336 tcg_gen_extu_i32_i64(tmp64, b);
337 tcg_temp_free_i32(b);
338 tcg_gen_shli_i64(tmp64, tmp64, 32);
339 tcg_gen_sub_i64(a, tmp64, a);
340
341 tcg_temp_free_i64(tmp64);
342 return a;
343}
344
345
346static TCGv_i64 gen_mulu_i64_i32(TCGv_i32 a, TCGv_i32 b)
347{
348 TCGv_i32 lo = tcg_temp_new_i32();
349 TCGv_i32 hi = tcg_temp_new_i32();
350 TCGv_i64 ret;
351
352 tcg_gen_mulu2_i32(lo, hi, a, b);
353 tcg_temp_free_i32(a);
354 tcg_temp_free_i32(b);
355
356 ret = tcg_temp_new_i64();
357 tcg_gen_concat_i32_i64(ret, lo, hi);
358 tcg_temp_free_i32(lo);
359 tcg_temp_free_i32(hi);
360
361 return ret;
362}
363
364static TCGv_i64 gen_muls_i64_i32(TCGv_i32 a, TCGv_i32 b)
365{
366 TCGv_i32 lo = tcg_temp_new_i32();
367 TCGv_i32 hi = tcg_temp_new_i32();
368 TCGv_i64 ret;
369
370 tcg_gen_muls2_i32(lo, hi, a, b);
371 tcg_temp_free_i32(a);
372 tcg_temp_free_i32(b);
373
374 ret = tcg_temp_new_i64();
375 tcg_gen_concat_i32_i64(ret, lo, hi);
376 tcg_temp_free_i32(lo);
377 tcg_temp_free_i32(hi);
378
379 return ret;
380}
381
382
383static void gen_swap_half(TCGv_i32 var)
384{
385 TCGv_i32 tmp = tcg_temp_new_i32();
386 tcg_gen_shri_i32(tmp, var, 16);
387 tcg_gen_shli_i32(var, var, 16);
388 tcg_gen_or_i32(var, var, tmp);
389 tcg_temp_free_i32(tmp);
390}
391
392
393
394
395
396
397
398
399static void gen_add16(TCGv_i32 t0, TCGv_i32 t1)
400{
401 TCGv_i32 tmp = tcg_temp_new_i32();
402 tcg_gen_xor_i32(tmp, t0, t1);
403 tcg_gen_andi_i32(tmp, tmp, 0x8000);
404 tcg_gen_andi_i32(t0, t0, ~0x8000);
405 tcg_gen_andi_i32(t1, t1, ~0x8000);
406 tcg_gen_add_i32(t0, t0, t1);
407 tcg_gen_xor_i32(t0, t0, tmp);
408 tcg_temp_free_i32(tmp);
409 tcg_temp_free_i32(t1);
410}
411
412
413static void gen_set_CF_bit31(TCGv_i32 var)
414{
415 tcg_gen_shri_i32(cpu_CF, var, 31);
416}
417
418
419static inline void gen_logic_CC(TCGv_i32 var)
420{
421 tcg_gen_mov_i32(cpu_NF, var);
422 tcg_gen_mov_i32(cpu_ZF, var);
423}
424
425
426static void gen_adc(TCGv_i32 t0, TCGv_i32 t1)
427{
428 tcg_gen_add_i32(t0, t0, t1);
429 tcg_gen_add_i32(t0, t0, cpu_CF);
430}
431
432
433static void gen_add_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
434{
435 tcg_gen_add_i32(dest, t0, t1);
436 tcg_gen_add_i32(dest, dest, cpu_CF);
437}
438
439
440static void gen_sub_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
441{
442 tcg_gen_sub_i32(dest, t0, t1);
443 tcg_gen_add_i32(dest, dest, cpu_CF);
444 tcg_gen_subi_i32(dest, dest, 1);
445}
446
447
448static void gen_add_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
449{
450 TCGv_i32 tmp = tcg_temp_new_i32();
451 tcg_gen_movi_i32(tmp, 0);
452 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, t1, tmp);
453 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
454 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
455 tcg_gen_xor_i32(tmp, t0, t1);
456 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
457 tcg_temp_free_i32(tmp);
458 tcg_gen_mov_i32(dest, cpu_NF);
459}
460
461
462static void gen_adc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
463{
464 TCGv_i32 tmp = tcg_temp_new_i32();
465 if (TCG_TARGET_HAS_add2_i32) {
466 tcg_gen_movi_i32(tmp, 0);
467 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, cpu_CF, tmp);
468 tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1, tmp);
469 } else {
470 TCGv_i64 q0 = tcg_temp_new_i64();
471 TCGv_i64 q1 = tcg_temp_new_i64();
472 tcg_gen_extu_i32_i64(q0, t0);
473 tcg_gen_extu_i32_i64(q1, t1);
474 tcg_gen_add_i64(q0, q0, q1);
475 tcg_gen_extu_i32_i64(q1, cpu_CF);
476 tcg_gen_add_i64(q0, q0, q1);
477 tcg_gen_extr_i64_i32(cpu_NF, cpu_CF, q0);
478 tcg_temp_free_i64(q0);
479 tcg_temp_free_i64(q1);
480 }
481 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
482 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
483 tcg_gen_xor_i32(tmp, t0, t1);
484 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
485 tcg_temp_free_i32(tmp);
486 tcg_gen_mov_i32(dest, cpu_NF);
487}
488
489
490static void gen_sub_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
491{
492 TCGv_i32 tmp;
493 tcg_gen_sub_i32(cpu_NF, t0, t1);
494 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
495 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0, t1);
496 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
497 tmp = tcg_temp_new_i32();
498 tcg_gen_xor_i32(tmp, t0, t1);
499 tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
500 tcg_temp_free_i32(tmp);
501 tcg_gen_mov_i32(dest, cpu_NF);
502}
503
504
505static void gen_sbc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
506{
507 TCGv_i32 tmp = tcg_temp_new_i32();
508 tcg_gen_not_i32(tmp, t1);
509 gen_adc_CC(dest, t0, tmp);
510 tcg_temp_free_i32(tmp);
511}
512
513#define GEN_SHIFT(name) \
514static void gen_##name(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) \
515{ \
516 TCGv_i32 tmp1, tmp2, tmp3; \
517 tmp1 = tcg_temp_new_i32(); \
518 tcg_gen_andi_i32(tmp1, t1, 0xff); \
519 tmp2 = tcg_const_i32(0); \
520 tmp3 = tcg_const_i32(0x1f); \
521 tcg_gen_movcond_i32(TCG_COND_GTU, tmp2, tmp1, tmp3, tmp2, t0); \
522 tcg_temp_free_i32(tmp3); \
523 tcg_gen_andi_i32(tmp1, tmp1, 0x1f); \
524 tcg_gen_##name##_i32(dest, tmp2, tmp1); \
525 tcg_temp_free_i32(tmp2); \
526 tcg_temp_free_i32(tmp1); \
527}
528GEN_SHIFT(shl)
529GEN_SHIFT(shr)
530#undef GEN_SHIFT
531
532static void gen_sar(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
533{
534 TCGv_i32 tmp1, tmp2;
535 tmp1 = tcg_temp_new_i32();
536 tcg_gen_andi_i32(tmp1, t1, 0xff);
537 tmp2 = tcg_const_i32(0x1f);
538 tcg_gen_movcond_i32(TCG_COND_GTU, tmp1, tmp1, tmp2, tmp2, tmp1);
539 tcg_temp_free_i32(tmp2);
540 tcg_gen_sar_i32(dest, t0, tmp1);
541 tcg_temp_free_i32(tmp1);
542}
543
544static void tcg_gen_abs_i32(TCGv_i32 dest, TCGv_i32 src)
545{
546 TCGv_i32 c0 = tcg_const_i32(0);
547 TCGv_i32 tmp = tcg_temp_new_i32();
548 tcg_gen_neg_i32(tmp, src);
549 tcg_gen_movcond_i32(TCG_COND_GT, dest, src, c0, src, tmp);
550 tcg_temp_free_i32(c0);
551 tcg_temp_free_i32(tmp);
552}
553
554static void shifter_out_im(TCGv_i32 var, int shift)
555{
556 if (shift == 0) {
557 tcg_gen_andi_i32(cpu_CF, var, 1);
558 } else {
559 tcg_gen_shri_i32(cpu_CF, var, shift);
560 if (shift != 31) {
561 tcg_gen_andi_i32(cpu_CF, cpu_CF, 1);
562 }
563 }
564}
565
566
567static inline void gen_arm_shift_im(TCGv_i32 var, int shiftop,
568 int shift, int flags)
569{
570 switch (shiftop) {
571 case 0:
572 if (shift != 0) {
573 if (flags)
574 shifter_out_im(var, 32 - shift);
575 tcg_gen_shli_i32(var, var, shift);
576 }
577 break;
578 case 1:
579 if (shift == 0) {
580 if (flags) {
581 tcg_gen_shri_i32(cpu_CF, var, 31);
582 }
583 tcg_gen_movi_i32(var, 0);
584 } else {
585 if (flags)
586 shifter_out_im(var, shift - 1);
587 tcg_gen_shri_i32(var, var, shift);
588 }
589 break;
590 case 2:
591 if (shift == 0)
592 shift = 32;
593 if (flags)
594 shifter_out_im(var, shift - 1);
595 if (shift == 32)
596 shift = 31;
597 tcg_gen_sari_i32(var, var, shift);
598 break;
599 case 3:
600 if (shift != 0) {
601 if (flags)
602 shifter_out_im(var, shift - 1);
603 tcg_gen_rotri_i32(var, var, shift); break;
604 } else {
605 TCGv_i32 tmp = tcg_temp_new_i32();
606 tcg_gen_shli_i32(tmp, cpu_CF, 31);
607 if (flags)
608 shifter_out_im(var, 0);
609 tcg_gen_shri_i32(var, var, 1);
610 tcg_gen_or_i32(var, var, tmp);
611 tcg_temp_free_i32(tmp);
612 }
613 }
614};
615
616static inline void gen_arm_shift_reg(TCGv_i32 var, int shiftop,
617 TCGv_i32 shift, int flags)
618{
619 if (flags) {
620 switch (shiftop) {
621 case 0: gen_helper_shl_cc(var, cpu_env, var, shift); break;
622 case 1: gen_helper_shr_cc(var, cpu_env, var, shift); break;
623 case 2: gen_helper_sar_cc(var, cpu_env, var, shift); break;
624 case 3: gen_helper_ror_cc(var, cpu_env, var, shift); break;
625 }
626 } else {
627 switch (shiftop) {
628 case 0:
629 gen_shl(var, var, shift);
630 break;
631 case 1:
632 gen_shr(var, var, shift);
633 break;
634 case 2:
635 gen_sar(var, var, shift);
636 break;
637 case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
638 tcg_gen_rotr_i32(var, var, shift); break;
639 }
640 }
641 tcg_temp_free_i32(shift);
642}
643
644#define PAS_OP(pfx) \
645 switch (op2) { \
646 case 0: gen_pas_helper(glue(pfx,add16)); break; \
647 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
648 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
649 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
650 case 4: gen_pas_helper(glue(pfx,add8)); break; \
651 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
652 }
653static void gen_arm_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
654{
655 TCGv_ptr tmp;
656
657 switch (op1) {
658#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
659 case 1:
660 tmp = tcg_temp_new_ptr();
661 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
662 PAS_OP(s)
663 tcg_temp_free_ptr(tmp);
664 break;
665 case 5:
666 tmp = tcg_temp_new_ptr();
667 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
668 PAS_OP(u)
669 tcg_temp_free_ptr(tmp);
670 break;
671#undef gen_pas_helper
672#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
673 case 2:
674 PAS_OP(q);
675 break;
676 case 3:
677 PAS_OP(sh);
678 break;
679 case 6:
680 PAS_OP(uq);
681 break;
682 case 7:
683 PAS_OP(uh);
684 break;
685#undef gen_pas_helper
686 }
687}
688#undef PAS_OP
689
690
691#define PAS_OP(pfx) \
692 switch (op1) { \
693 case 0: gen_pas_helper(glue(pfx,add8)); break; \
694 case 1: gen_pas_helper(glue(pfx,add16)); break; \
695 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
696 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
697 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
698 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
699 }
700static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
701{
702 TCGv_ptr tmp;
703
704 switch (op2) {
705#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
706 case 0:
707 tmp = tcg_temp_new_ptr();
708 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
709 PAS_OP(s)
710 tcg_temp_free_ptr(tmp);
711 break;
712 case 4:
713 tmp = tcg_temp_new_ptr();
714 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
715 PAS_OP(u)
716 tcg_temp_free_ptr(tmp);
717 break;
718#undef gen_pas_helper
719#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
720 case 1:
721 PAS_OP(q);
722 break;
723 case 2:
724 PAS_OP(sh);
725 break;
726 case 5:
727 PAS_OP(uq);
728 break;
729 case 6:
730 PAS_OP(uh);
731 break;
732#undef gen_pas_helper
733 }
734}
735#undef PAS_OP
736
737
738
739
740
741void arm_test_cc(DisasCompare *cmp, int cc)
742{
743 TCGv_i32 value;
744 TCGCond cond;
745 bool global = true;
746
747 switch (cc) {
748 case 0:
749 case 1:
750 cond = TCG_COND_EQ;
751 value = cpu_ZF;
752 break;
753
754 case 2:
755 case 3:
756 cond = TCG_COND_NE;
757 value = cpu_CF;
758 break;
759
760 case 4:
761 case 5:
762 cond = TCG_COND_LT;
763 value = cpu_NF;
764 break;
765
766 case 6:
767 case 7:
768 cond = TCG_COND_LT;
769 value = cpu_VF;
770 break;
771
772 case 8:
773 case 9:
774 cond = TCG_COND_NE;
775 value = tcg_temp_new_i32();
776 global = false;
777
778
779 tcg_gen_neg_i32(value, cpu_CF);
780 tcg_gen_and_i32(value, value, cpu_ZF);
781 break;
782
783 case 10:
784 case 11:
785
786 cond = TCG_COND_GE;
787 value = tcg_temp_new_i32();
788 global = false;
789 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
790 break;
791
792 case 12:
793 case 13:
794 cond = TCG_COND_NE;
795 value = tcg_temp_new_i32();
796 global = false;
797
798
799 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
800 tcg_gen_sari_i32(value, value, 31);
801 tcg_gen_andc_i32(value, cpu_ZF, value);
802 break;
803
804 case 14:
805 case 15:
806
807
808 cond = TCG_COND_ALWAYS;
809 value = cpu_ZF;
810 goto no_invert;
811
812 default:
813 fprintf(stderr, "Bad condition code 0x%x\n", cc);
814 abort();
815 }
816
817 if (cc & 1) {
818 cond = tcg_invert_cond(cond);
819 }
820
821 no_invert:
822 cmp->cond = cond;
823 cmp->value = value;
824 cmp->value_global = global;
825}
826
827void arm_free_cc(DisasCompare *cmp)
828{
829 if (!cmp->value_global) {
830 tcg_temp_free_i32(cmp->value);
831 }
832}
833
834void arm_jump_cc(DisasCompare *cmp, TCGLabel *label)
835{
836 tcg_gen_brcondi_i32(cmp->cond, cmp->value, 0, label);
837}
838
839void arm_gen_test_cc(int cc, TCGLabel *label)
840{
841 DisasCompare cmp;
842 arm_test_cc(&cmp, cc);
843 arm_jump_cc(&cmp, label);
844 arm_free_cc(&cmp);
845}
846
847static const uint8_t table_logic_cc[16] = {
848 1,
849 1,
850 0,
851 0,
852 0,
853 0,
854 0,
855 0,
856 1,
857 1,
858 0,
859 0,
860 1,
861 1,
862 1,
863 1,
864};
865
866
867static inline void gen_bx_im(DisasContext *s, uint32_t addr)
868{
869 TCGv_i32 tmp;
870
871 s->is_jmp = DISAS_JUMP;
872 if (s->thumb != (addr & 1)) {
873 tmp = tcg_temp_new_i32();
874 tcg_gen_movi_i32(tmp, addr & 1);
875 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUARMState, thumb));
876 tcg_temp_free_i32(tmp);
877 }
878 tcg_gen_movi_i32(cpu_R[15], addr & ~1);
879}
880
881
882static inline void gen_bx(DisasContext *s, TCGv_i32 var)
883{
884 s->is_jmp = DISAS_JUMP;
885 tcg_gen_andi_i32(cpu_R[15], var, ~1);
886 tcg_gen_andi_i32(var, var, 1);
887 store_cpu_field(var, thumb);
888}
889
890
891
892
893static inline void store_reg_bx(DisasContext *s, int reg, TCGv_i32 var)
894{
895 if (reg == 15 && ENABLE_ARCH_7) {
896 gen_bx(s, var);
897 } else {
898 store_reg(s, reg, var);
899 }
900}
901
902
903
904
905
906static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
907{
908 if (reg == 15 && ENABLE_ARCH_5) {
909 gen_bx(s, var);
910 } else {
911 store_reg(s, reg, var);
912 }
913}
914
915#ifdef CONFIG_USER_ONLY
916#define IS_USER_ONLY 1
917#else
918#define IS_USER_ONLY 0
919#endif
920
921
922
923
924
925
926
927
928#if TARGET_LONG_BITS == 32
929
930#define DO_GEN_LD(SUFF, OPC, BE32_XOR) \
931static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \
932 TCGv_i32 addr, int index) \
933{ \
934 TCGMemOp opc = (OPC) | s->be_data; \
935 \
936 if (!IS_USER_ONLY && s->sctlr_b && BE32_XOR) { \
937 TCGv addr_be = tcg_temp_new(); \
938 tcg_gen_xori_i32(addr_be, addr, BE32_XOR); \
939 tcg_gen_qemu_ld_i32(val, addr_be, index, opc); \
940 tcg_temp_free(addr_be); \
941 return; \
942 } \
943 tcg_gen_qemu_ld_i32(val, addr, index, opc); \
944}
945
946#define DO_GEN_ST(SUFF, OPC, BE32_XOR) \
947static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, \
948 TCGv_i32 addr, int index) \
949{ \
950 TCGMemOp opc = (OPC) | s->be_data; \
951 \
952 if (!IS_USER_ONLY && s->sctlr_b && BE32_XOR) { \
953 TCGv addr_be = tcg_temp_new(); \
954 tcg_gen_xori_i32(addr_be, addr, BE32_XOR); \
955 tcg_gen_qemu_st_i32(val, addr_be, index, opc); \
956 tcg_temp_free(addr_be); \
957 return; \
958 } \
959 tcg_gen_qemu_st_i32(val, addr, index, opc); \
960}
961
962static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
963 TCGv_i32 addr, int index)
964{
965 TCGMemOp opc = MO_Q | s->be_data;
966 tcg_gen_qemu_ld_i64(val, addr, index, opc);
967
968 if (!IS_USER_ONLY && s->sctlr_b) {
969 tcg_gen_rotri_i64(val, val, 32);
970 }
971}
972
973static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
974 TCGv_i32 addr, int index)
975{
976 TCGMemOp opc = MO_Q | s->be_data;
977
978 if (!IS_USER_ONLY && s->sctlr_b) {
979 TCGv_i64 tmp = tcg_temp_new_i64();
980 tcg_gen_rotri_i64(tmp, val, 32);
981 tcg_gen_qemu_st_i64(tmp, addr, index, opc);
982 tcg_temp_free_i64(tmp);
983 return;
984 }
985 tcg_gen_qemu_st_i64(val, addr, index, opc);
986}
987
988#else
989
990#define DO_GEN_LD(SUFF, OPC, BE32_XOR) \
991static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \
992 TCGv_i32 addr, int index) \
993{ \
994 TCGMemOp opc = (OPC) | s->be_data; \
995 TCGv addr64 = tcg_temp_new(); \
996 tcg_gen_extu_i32_i64(addr64, addr); \
997 \
998 if (!IS_USER_ONLY && s->sctlr_b && BE32_XOR) { \
999 tcg_gen_xori_i64(addr64, addr64, BE32_XOR); \
1000 } \
1001 tcg_gen_qemu_ld_i32(val, addr64, index, opc); \
1002 tcg_temp_free(addr64); \
1003}
1004
1005#define DO_GEN_ST(SUFF, OPC, BE32_XOR) \
1006static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, \
1007 TCGv_i32 addr, int index) \
1008{ \
1009 TCGMemOp opc = (OPC) | s->be_data; \
1010 TCGv addr64 = tcg_temp_new(); \
1011 tcg_gen_extu_i32_i64(addr64, addr); \
1012 \
1013 if (!IS_USER_ONLY && s->sctlr_b && BE32_XOR) { \
1014 tcg_gen_xori_i64(addr64, addr64, BE32_XOR); \
1015 } \
1016 tcg_gen_qemu_st_i32(val, addr64, index, opc); \
1017 tcg_temp_free(addr64); \
1018}
1019
1020static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
1021 TCGv_i32 addr, int index)
1022{
1023 TCGMemOp opc = MO_Q | s->be_data;
1024 TCGv addr64 = tcg_temp_new();
1025 tcg_gen_extu_i32_i64(addr64, addr);
1026 tcg_gen_qemu_ld_i64(val, addr64, index, opc);
1027
1028
1029 if (!IS_USER_ONLY && s->sctlr_b) {
1030 tcg_gen_rotri_i64(val, val, 32);
1031 }
1032 tcg_temp_free(addr64);
1033}
1034
1035static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
1036 TCGv_i32 addr, int index)
1037{
1038 TCGMemOp opc = MO_Q | s->be_data;
1039 TCGv addr64 = tcg_temp_new();
1040 tcg_gen_extu_i32_i64(addr64, addr);
1041
1042
1043 if (!IS_USER_ONLY && s->sctlr_b) {
1044 TCGv tmp = tcg_temp_new();
1045 tcg_gen_rotri_i64(tmp, val, 32);
1046 tcg_gen_qemu_st_i64(tmp, addr64, index, opc);
1047 tcg_temp_free(tmp);
1048 } else {
1049 tcg_gen_qemu_st_i64(val, addr64, index, opc);
1050 }
1051 tcg_temp_free(addr64);
1052}
1053
1054#endif
1055
1056DO_GEN_LD(8s, MO_SB, 3)
1057DO_GEN_LD(8u, MO_UB, 3)
1058DO_GEN_LD(16s, MO_SW, 2)
1059DO_GEN_LD(16u, MO_UW, 2)
1060DO_GEN_LD(32u, MO_UL, 0)
1061
1062DO_GEN_LD(16ua, MO_UW | MO_ALIGN, 2)
1063DO_GEN_LD(32ua, MO_UL | MO_ALIGN, 0)
1064DO_GEN_ST(8, MO_UB, 3)
1065DO_GEN_ST(16, MO_UW, 2)
1066DO_GEN_ST(32, MO_UL, 0)
1067
1068static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
1069{
1070 tcg_gen_movi_i32(cpu_R[15], val);
1071}
1072
1073static inline void gen_hvc(DisasContext *s, int imm16)
1074{
1075
1076
1077
1078
1079 gen_set_pc_im(s, s->pc - 4);
1080 gen_helper_pre_hvc(cpu_env);
1081
1082
1083
1084
1085
1086 s->svc_imm = imm16;
1087 gen_set_pc_im(s, s->pc);
1088 s->is_jmp = DISAS_HVC;
1089}
1090
1091static inline void gen_smc(DisasContext *s)
1092{
1093
1094
1095
1096 TCGv_i32 tmp;
1097
1098 gen_set_pc_im(s, s->pc - 4);
1099 tmp = tcg_const_i32(syn_aa32_smc());
1100 gen_helper_pre_smc(cpu_env, tmp);
1101 tcg_temp_free_i32(tmp);
1102 gen_set_pc_im(s, s->pc);
1103 s->is_jmp = DISAS_SMC;
1104}
1105
1106static inline void
1107gen_set_condexec (DisasContext *s)
1108{
1109 if (s->condexec_mask) {
1110 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
1111 TCGv_i32 tmp = tcg_temp_new_i32();
1112 tcg_gen_movi_i32(tmp, val);
1113 store_cpu_field(tmp, condexec_bits);
1114 }
1115}
1116
1117static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
1118{
1119 gen_set_condexec(s);
1120 gen_set_pc_im(s, s->pc - offset);
1121 gen_exception_internal(excp);
1122 s->is_jmp = DISAS_JUMP;
1123}
1124
1125static void gen_exception_insn(DisasContext *s, int offset, int excp,
1126 int syn, uint32_t target_el)
1127{
1128 gen_set_condexec(s);
1129 gen_set_pc_im(s, s->pc - offset);
1130 gen_exception(excp, syn, target_el);
1131 s->is_jmp = DISAS_JUMP;
1132}
1133
1134
1135static inline void gen_lookup_tb(DisasContext *s)
1136{
1137 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
1138 s->is_jmp = DISAS_JUMP;
1139}
1140
1141static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
1142 TCGv_i32 var)
1143{
1144 int val, rm, shift, shiftop;
1145 TCGv_i32 offset;
1146
1147 if (!(insn & (1 << 25))) {
1148
1149 val = insn & 0xfff;
1150 if (!(insn & (1 << 23)))
1151 val = -val;
1152 if (val != 0)
1153 tcg_gen_addi_i32(var, var, val);
1154 } else {
1155
1156 rm = (insn) & 0xf;
1157 shift = (insn >> 7) & 0x1f;
1158 shiftop = (insn >> 5) & 3;
1159 offset = load_reg(s, rm);
1160 gen_arm_shift_im(offset, shiftop, shift, 0);
1161 if (!(insn & (1 << 23)))
1162 tcg_gen_sub_i32(var, var, offset);
1163 else
1164 tcg_gen_add_i32(var, var, offset);
1165 tcg_temp_free_i32(offset);
1166 }
1167}
1168
1169static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
1170 int extra, TCGv_i32 var)
1171{
1172 int val, rm;
1173 TCGv_i32 offset;
1174
1175 if (insn & (1 << 22)) {
1176
1177 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
1178 if (!(insn & (1 << 23)))
1179 val = -val;
1180 val += extra;
1181 if (val != 0)
1182 tcg_gen_addi_i32(var, var, val);
1183 } else {
1184
1185 if (extra)
1186 tcg_gen_addi_i32(var, var, extra);
1187 rm = (insn) & 0xf;
1188 offset = load_reg(s, rm);
1189 if (!(insn & (1 << 23)))
1190 tcg_gen_sub_i32(var, var, offset);
1191 else
1192 tcg_gen_add_i32(var, var, offset);
1193 tcg_temp_free_i32(offset);
1194 }
1195}
1196
1197static TCGv_ptr get_fpstatus_ptr(int neon)
1198{
1199 TCGv_ptr statusptr = tcg_temp_new_ptr();
1200 int offset;
1201 if (neon) {
1202 offset = offsetof(CPUARMState, vfp.standard_fp_status);
1203 } else {
1204 offset = offsetof(CPUARMState, vfp.fp_status);
1205 }
1206 tcg_gen_addi_ptr(statusptr, cpu_env, offset);
1207 return statusptr;
1208}
1209
1210#define VFP_OP2(name) \
1211static inline void gen_vfp_##name(int dp) \
1212{ \
1213 TCGv_ptr fpst = get_fpstatus_ptr(0); \
1214 if (dp) { \
1215 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, fpst); \
1216 } else { \
1217 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, fpst); \
1218 } \
1219 tcg_temp_free_ptr(fpst); \
1220}
1221
1222VFP_OP2(add)
1223VFP_OP2(sub)
1224VFP_OP2(mul)
1225VFP_OP2(div)
1226
1227#undef VFP_OP2
1228
1229static inline void gen_vfp_F1_mul(int dp)
1230{
1231
1232 TCGv_ptr fpst = get_fpstatus_ptr(0);
1233 if (dp) {
1234 gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, fpst);
1235 } else {
1236 gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, fpst);
1237 }
1238 tcg_temp_free_ptr(fpst);
1239}
1240
1241static inline void gen_vfp_F1_neg(int dp)
1242{
1243
1244 if (dp) {
1245 gen_helper_vfp_negd(cpu_F1d, cpu_F0d);
1246 } else {
1247 gen_helper_vfp_negs(cpu_F1s, cpu_F0s);
1248 }
1249}
1250
1251static inline void gen_vfp_abs(int dp)
1252{
1253 if (dp)
1254 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
1255 else
1256 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
1257}
1258
1259static inline void gen_vfp_neg(int dp)
1260{
1261 if (dp)
1262 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
1263 else
1264 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
1265}
1266
1267static inline void gen_vfp_sqrt(int dp)
1268{
1269 if (dp)
1270 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
1271 else
1272 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1273}
1274
1275static inline void gen_vfp_cmp(int dp)
1276{
1277 if (dp)
1278 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1279 else
1280 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1281}
1282
1283static inline void gen_vfp_cmpe(int dp)
1284{
1285 if (dp)
1286 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1287 else
1288 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1289}
1290
1291static inline void gen_vfp_F1_ld0(int dp)
1292{
1293 if (dp)
1294 tcg_gen_movi_i64(cpu_F1d, 0);
1295 else
1296 tcg_gen_movi_i32(cpu_F1s, 0);
1297}
1298
1299#define VFP_GEN_ITOF(name) \
1300static inline void gen_vfp_##name(int dp, int neon) \
1301{ \
1302 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1303 if (dp) { \
1304 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \
1305 } else { \
1306 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1307 } \
1308 tcg_temp_free_ptr(statusptr); \
1309}
1310
1311VFP_GEN_ITOF(uito)
1312VFP_GEN_ITOF(sito)
1313#undef VFP_GEN_ITOF
1314
1315#define VFP_GEN_FTOI(name) \
1316static inline void gen_vfp_##name(int dp, int neon) \
1317{ \
1318 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1319 if (dp) { \
1320 gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \
1321 } else { \
1322 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1323 } \
1324 tcg_temp_free_ptr(statusptr); \
1325}
1326
1327VFP_GEN_FTOI(toui)
1328VFP_GEN_FTOI(touiz)
1329VFP_GEN_FTOI(tosi)
1330VFP_GEN_FTOI(tosiz)
1331#undef VFP_GEN_FTOI
1332
1333#define VFP_GEN_FIX(name, round) \
1334static inline void gen_vfp_##name(int dp, int shift, int neon) \
1335{ \
1336 TCGv_i32 tmp_shift = tcg_const_i32(shift); \
1337 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1338 if (dp) { \
1339 gen_helper_vfp_##name##d##round(cpu_F0d, cpu_F0d, tmp_shift, \
1340 statusptr); \
1341 } else { \
1342 gen_helper_vfp_##name##s##round(cpu_F0s, cpu_F0s, tmp_shift, \
1343 statusptr); \
1344 } \
1345 tcg_temp_free_i32(tmp_shift); \
1346 tcg_temp_free_ptr(statusptr); \
1347}
1348VFP_GEN_FIX(tosh, _round_to_zero)
1349VFP_GEN_FIX(tosl, _round_to_zero)
1350VFP_GEN_FIX(touh, _round_to_zero)
1351VFP_GEN_FIX(toul, _round_to_zero)
1352VFP_GEN_FIX(shto, )
1353VFP_GEN_FIX(slto, )
1354VFP_GEN_FIX(uhto, )
1355VFP_GEN_FIX(ulto, )
1356#undef VFP_GEN_FIX
1357
1358static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv_i32 addr)
1359{
1360 if (dp) {
1361 gen_aa32_ld64(s, cpu_F0d, addr, get_mem_index(s));
1362 } else {
1363 gen_aa32_ld32u(s, cpu_F0s, addr, get_mem_index(s));
1364 }
1365}
1366
1367static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
1368{
1369 if (dp) {
1370 gen_aa32_st64(s, cpu_F0d, addr, get_mem_index(s));
1371 } else {
1372 gen_aa32_st32(s, cpu_F0s, addr, get_mem_index(s));
1373 }
1374}
1375
1376static inline long
1377vfp_reg_offset (int dp, int reg)
1378{
1379 if (dp)
1380 return offsetof(CPUARMState, vfp.regs[reg]);
1381 else if (reg & 1) {
1382 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1383 + offsetof(CPU_DoubleU, l.upper);
1384 } else {
1385 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1386 + offsetof(CPU_DoubleU, l.lower);
1387 }
1388}
1389
1390
1391
1392static inline long
1393neon_reg_offset (int reg, int n)
1394{
1395 int sreg;
1396 sreg = reg * 2 + n;
1397 return vfp_reg_offset(0, sreg);
1398}
1399
1400static TCGv_i32 neon_load_reg(int reg, int pass)
1401{
1402 TCGv_i32 tmp = tcg_temp_new_i32();
1403 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1404 return tmp;
1405}
1406
1407static void neon_store_reg(int reg, int pass, TCGv_i32 var)
1408{
1409 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1410 tcg_temp_free_i32(var);
1411}
1412
1413static inline void neon_load_reg64(TCGv_i64 var, int reg)
1414{
1415 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1416}
1417
1418static inline void neon_store_reg64(TCGv_i64 var, int reg)
1419{
1420 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1421}
1422
1423#define tcg_gen_ld_f32 tcg_gen_ld_i32
1424#define tcg_gen_ld_f64 tcg_gen_ld_i64
1425#define tcg_gen_st_f32 tcg_gen_st_i32
1426#define tcg_gen_st_f64 tcg_gen_st_i64
1427
1428static inline void gen_mov_F0_vreg(int dp, int reg)
1429{
1430 if (dp)
1431 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1432 else
1433 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1434}
1435
1436static inline void gen_mov_F1_vreg(int dp, int reg)
1437{
1438 if (dp)
1439 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1440 else
1441 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1442}
1443
1444static inline void gen_mov_vreg_F0(int dp, int reg)
1445{
1446 if (dp)
1447 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1448 else
1449 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1450}
1451
1452#define ARM_CP_RW_BIT (1 << 20)
1453
1454static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1455{
1456 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1457}
1458
1459static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1460{
1461 tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1462}
1463
1464static inline TCGv_i32 iwmmxt_load_creg(int reg)
1465{
1466 TCGv_i32 var = tcg_temp_new_i32();
1467 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1468 return var;
1469}
1470
1471static inline void iwmmxt_store_creg(int reg, TCGv_i32 var)
1472{
1473 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1474 tcg_temp_free_i32(var);
1475}
1476
1477static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1478{
1479 iwmmxt_store_reg(cpu_M0, rn);
1480}
1481
1482static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1483{
1484 iwmmxt_load_reg(cpu_M0, rn);
1485}
1486
1487static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1488{
1489 iwmmxt_load_reg(cpu_V1, rn);
1490 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1491}
1492
1493static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1494{
1495 iwmmxt_load_reg(cpu_V1, rn);
1496 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1497}
1498
1499static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1500{
1501 iwmmxt_load_reg(cpu_V1, rn);
1502 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1503}
1504
1505#define IWMMXT_OP(name) \
1506static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1507{ \
1508 iwmmxt_load_reg(cpu_V1, rn); \
1509 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1510}
1511
1512#define IWMMXT_OP_ENV(name) \
1513static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1514{ \
1515 iwmmxt_load_reg(cpu_V1, rn); \
1516 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1517}
1518
1519#define IWMMXT_OP_ENV_SIZE(name) \
1520IWMMXT_OP_ENV(name##b) \
1521IWMMXT_OP_ENV(name##w) \
1522IWMMXT_OP_ENV(name##l)
1523
1524#define IWMMXT_OP_ENV1(name) \
1525static inline void gen_op_iwmmxt_##name##_M0(void) \
1526{ \
1527 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1528}
1529
1530IWMMXT_OP(maddsq)
1531IWMMXT_OP(madduq)
1532IWMMXT_OP(sadb)
1533IWMMXT_OP(sadw)
1534IWMMXT_OP(mulslw)
1535IWMMXT_OP(mulshw)
1536IWMMXT_OP(mululw)
1537IWMMXT_OP(muluhw)
1538IWMMXT_OP(macsw)
1539IWMMXT_OP(macuw)
1540
1541IWMMXT_OP_ENV_SIZE(unpackl)
1542IWMMXT_OP_ENV_SIZE(unpackh)
1543
1544IWMMXT_OP_ENV1(unpacklub)
1545IWMMXT_OP_ENV1(unpackluw)
1546IWMMXT_OP_ENV1(unpacklul)
1547IWMMXT_OP_ENV1(unpackhub)
1548IWMMXT_OP_ENV1(unpackhuw)
1549IWMMXT_OP_ENV1(unpackhul)
1550IWMMXT_OP_ENV1(unpacklsb)
1551IWMMXT_OP_ENV1(unpacklsw)
1552IWMMXT_OP_ENV1(unpacklsl)
1553IWMMXT_OP_ENV1(unpackhsb)
1554IWMMXT_OP_ENV1(unpackhsw)
1555IWMMXT_OP_ENV1(unpackhsl)
1556
1557IWMMXT_OP_ENV_SIZE(cmpeq)
1558IWMMXT_OP_ENV_SIZE(cmpgtu)
1559IWMMXT_OP_ENV_SIZE(cmpgts)
1560
1561IWMMXT_OP_ENV_SIZE(mins)
1562IWMMXT_OP_ENV_SIZE(minu)
1563IWMMXT_OP_ENV_SIZE(maxs)
1564IWMMXT_OP_ENV_SIZE(maxu)
1565
1566IWMMXT_OP_ENV_SIZE(subn)
1567IWMMXT_OP_ENV_SIZE(addn)
1568IWMMXT_OP_ENV_SIZE(subu)
1569IWMMXT_OP_ENV_SIZE(addu)
1570IWMMXT_OP_ENV_SIZE(subs)
1571IWMMXT_OP_ENV_SIZE(adds)
1572
1573IWMMXT_OP_ENV(avgb0)
1574IWMMXT_OP_ENV(avgb1)
1575IWMMXT_OP_ENV(avgw0)
1576IWMMXT_OP_ENV(avgw1)
1577
1578IWMMXT_OP_ENV(packuw)
1579IWMMXT_OP_ENV(packul)
1580IWMMXT_OP_ENV(packuq)
1581IWMMXT_OP_ENV(packsw)
1582IWMMXT_OP_ENV(packsl)
1583IWMMXT_OP_ENV(packsq)
1584
1585static void gen_op_iwmmxt_set_mup(void)
1586{
1587 TCGv_i32 tmp;
1588 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1589 tcg_gen_ori_i32(tmp, tmp, 2);
1590 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1591}
1592
1593static void gen_op_iwmmxt_set_cup(void)
1594{
1595 TCGv_i32 tmp;
1596 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1597 tcg_gen_ori_i32(tmp, tmp, 1);
1598 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1599}
1600
1601static void gen_op_iwmmxt_setpsr_nz(void)
1602{
1603 TCGv_i32 tmp = tcg_temp_new_i32();
1604 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1605 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1606}
1607
1608static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1609{
1610 iwmmxt_load_reg(cpu_V1, rn);
1611 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1612 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1613}
1614
1615static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn,
1616 TCGv_i32 dest)
1617{
1618 int rd;
1619 uint32_t offset;
1620 TCGv_i32 tmp;
1621
1622 rd = (insn >> 16) & 0xf;
1623 tmp = load_reg(s, rd);
1624
1625 offset = (insn & 0xff) << ((insn >> 7) & 2);
1626 if (insn & (1 << 24)) {
1627
1628 if (insn & (1 << 23))
1629 tcg_gen_addi_i32(tmp, tmp, offset);
1630 else
1631 tcg_gen_addi_i32(tmp, tmp, -offset);
1632 tcg_gen_mov_i32(dest, tmp);
1633 if (insn & (1 << 21))
1634 store_reg(s, rd, tmp);
1635 else
1636 tcg_temp_free_i32(tmp);
1637 } else if (insn & (1 << 21)) {
1638
1639 tcg_gen_mov_i32(dest, tmp);
1640 if (insn & (1 << 23))
1641 tcg_gen_addi_i32(tmp, tmp, offset);
1642 else
1643 tcg_gen_addi_i32(tmp, tmp, -offset);
1644 store_reg(s, rd, tmp);
1645 } else if (!(insn & (1 << 23)))
1646 return 1;
1647 return 0;
1648}
1649
1650static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv_i32 dest)
1651{
1652 int rd = (insn >> 0) & 0xf;
1653 TCGv_i32 tmp;
1654
1655 if (insn & (1 << 8)) {
1656 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1657 return 1;
1658 } else {
1659 tmp = iwmmxt_load_creg(rd);
1660 }
1661 } else {
1662 tmp = tcg_temp_new_i32();
1663 iwmmxt_load_reg(cpu_V0, rd);
1664 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
1665 }
1666 tcg_gen_andi_i32(tmp, tmp, mask);
1667 tcg_gen_mov_i32(dest, tmp);
1668 tcg_temp_free_i32(tmp);
1669 return 0;
1670}
1671
1672
1673
1674static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
1675{
1676 int rd, wrd;
1677 int rdhi, rdlo, rd0, rd1, i;
1678 TCGv_i32 addr;
1679 TCGv_i32 tmp, tmp2, tmp3;
1680
1681 if ((insn & 0x0e000e00) == 0x0c000000) {
1682 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1683 wrd = insn & 0xf;
1684 rdlo = (insn >> 12) & 0xf;
1685 rdhi = (insn >> 16) & 0xf;
1686 if (insn & ARM_CP_RW_BIT) {
1687 iwmmxt_load_reg(cpu_V0, wrd);
1688 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
1689 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1690 tcg_gen_extrl_i64_i32(cpu_R[rdhi], cpu_V0);
1691 } else {
1692 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1693 iwmmxt_store_reg(cpu_V0, wrd);
1694 gen_op_iwmmxt_set_mup();
1695 }
1696 return 0;
1697 }
1698
1699 wrd = (insn >> 12) & 0xf;
1700 addr = tcg_temp_new_i32();
1701 if (gen_iwmmxt_address(s, insn, addr)) {
1702 tcg_temp_free_i32(addr);
1703 return 1;
1704 }
1705 if (insn & ARM_CP_RW_BIT) {
1706 if ((insn >> 28) == 0xf) {
1707 tmp = tcg_temp_new_i32();
1708 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
1709 iwmmxt_store_creg(wrd, tmp);
1710 } else {
1711 i = 1;
1712 if (insn & (1 << 8)) {
1713 if (insn & (1 << 22)) {
1714 gen_aa32_ld64(s, cpu_M0, addr, get_mem_index(s));
1715 i = 0;
1716 } else {
1717 tmp = tcg_temp_new_i32();
1718 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
1719 }
1720 } else {
1721 tmp = tcg_temp_new_i32();
1722 if (insn & (1 << 22)) {
1723 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
1724 } else {
1725 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
1726 }
1727 }
1728 if (i) {
1729 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1730 tcg_temp_free_i32(tmp);
1731 }
1732 gen_op_iwmmxt_movq_wRn_M0(wrd);
1733 }
1734 } else {
1735 if ((insn >> 28) == 0xf) {
1736 tmp = iwmmxt_load_creg(wrd);
1737 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
1738 } else {
1739 gen_op_iwmmxt_movq_M0_wRn(wrd);
1740 tmp = tcg_temp_new_i32();
1741 if (insn & (1 << 8)) {
1742 if (insn & (1 << 22)) {
1743 gen_aa32_st64(s, cpu_M0, addr, get_mem_index(s));
1744 } else {
1745 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1746 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
1747 }
1748 } else {
1749 if (insn & (1 << 22)) {
1750 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1751 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
1752 } else {
1753 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1754 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
1755 }
1756 }
1757 }
1758 tcg_temp_free_i32(tmp);
1759 }
1760 tcg_temp_free_i32(addr);
1761 return 0;
1762 }
1763
1764 if ((insn & 0x0f000000) != 0x0e000000)
1765 return 1;
1766
1767 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1768 case 0x000:
1769 wrd = (insn >> 12) & 0xf;
1770 rd0 = (insn >> 0) & 0xf;
1771 rd1 = (insn >> 16) & 0xf;
1772 gen_op_iwmmxt_movq_M0_wRn(rd0);
1773 gen_op_iwmmxt_orq_M0_wRn(rd1);
1774 gen_op_iwmmxt_setpsr_nz();
1775 gen_op_iwmmxt_movq_wRn_M0(wrd);
1776 gen_op_iwmmxt_set_mup();
1777 gen_op_iwmmxt_set_cup();
1778 break;
1779 case 0x011:
1780 if (insn & 0xf)
1781 return 1;
1782 rd = (insn >> 12) & 0xf;
1783 wrd = (insn >> 16) & 0xf;
1784 switch (wrd) {
1785 case ARM_IWMMXT_wCID:
1786 case ARM_IWMMXT_wCASF:
1787 break;
1788 case ARM_IWMMXT_wCon:
1789 gen_op_iwmmxt_set_cup();
1790
1791 case ARM_IWMMXT_wCSSF:
1792 tmp = iwmmxt_load_creg(wrd);
1793 tmp2 = load_reg(s, rd);
1794 tcg_gen_andc_i32(tmp, tmp, tmp2);
1795 tcg_temp_free_i32(tmp2);
1796 iwmmxt_store_creg(wrd, tmp);
1797 break;
1798 case ARM_IWMMXT_wCGR0:
1799 case ARM_IWMMXT_wCGR1:
1800 case ARM_IWMMXT_wCGR2:
1801 case ARM_IWMMXT_wCGR3:
1802 gen_op_iwmmxt_set_cup();
1803 tmp = load_reg(s, rd);
1804 iwmmxt_store_creg(wrd, tmp);
1805 break;
1806 default:
1807 return 1;
1808 }
1809 break;
1810 case 0x100:
1811 wrd = (insn >> 12) & 0xf;
1812 rd0 = (insn >> 0) & 0xf;
1813 rd1 = (insn >> 16) & 0xf;
1814 gen_op_iwmmxt_movq_M0_wRn(rd0);
1815 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1816 gen_op_iwmmxt_setpsr_nz();
1817 gen_op_iwmmxt_movq_wRn_M0(wrd);
1818 gen_op_iwmmxt_set_mup();
1819 gen_op_iwmmxt_set_cup();
1820 break;
1821 case 0x111:
1822 if (insn & 0xf)
1823 return 1;
1824 rd = (insn >> 12) & 0xf;
1825 wrd = (insn >> 16) & 0xf;
1826 tmp = iwmmxt_load_creg(wrd);
1827 store_reg(s, rd, tmp);
1828 break;
1829 case 0x300:
1830 wrd = (insn >> 12) & 0xf;
1831 rd0 = (insn >> 0) & 0xf;
1832 rd1 = (insn >> 16) & 0xf;
1833 gen_op_iwmmxt_movq_M0_wRn(rd0);
1834 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1835 gen_op_iwmmxt_andq_M0_wRn(rd1);
1836 gen_op_iwmmxt_setpsr_nz();
1837 gen_op_iwmmxt_movq_wRn_M0(wrd);
1838 gen_op_iwmmxt_set_mup();
1839 gen_op_iwmmxt_set_cup();
1840 break;
1841 case 0x200:
1842 wrd = (insn >> 12) & 0xf;
1843 rd0 = (insn >> 0) & 0xf;
1844 rd1 = (insn >> 16) & 0xf;
1845 gen_op_iwmmxt_movq_M0_wRn(rd0);
1846 gen_op_iwmmxt_andq_M0_wRn(rd1);
1847 gen_op_iwmmxt_setpsr_nz();
1848 gen_op_iwmmxt_movq_wRn_M0(wrd);
1849 gen_op_iwmmxt_set_mup();
1850 gen_op_iwmmxt_set_cup();
1851 break;
1852 case 0x810: case 0xa10:
1853 wrd = (insn >> 12) & 0xf;
1854 rd0 = (insn >> 0) & 0xf;
1855 rd1 = (insn >> 16) & 0xf;
1856 gen_op_iwmmxt_movq_M0_wRn(rd0);
1857 if (insn & (1 << 21))
1858 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1859 else
1860 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1861 gen_op_iwmmxt_movq_wRn_M0(wrd);
1862 gen_op_iwmmxt_set_mup();
1863 break;
1864 case 0x10e: case 0x50e: case 0x90e: case 0xd0e:
1865 wrd = (insn >> 12) & 0xf;
1866 rd0 = (insn >> 16) & 0xf;
1867 rd1 = (insn >> 0) & 0xf;
1868 gen_op_iwmmxt_movq_M0_wRn(rd0);
1869 switch ((insn >> 22) & 3) {
1870 case 0:
1871 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1872 break;
1873 case 1:
1874 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1875 break;
1876 case 2:
1877 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1878 break;
1879 case 3:
1880 return 1;
1881 }
1882 gen_op_iwmmxt_movq_wRn_M0(wrd);
1883 gen_op_iwmmxt_set_mup();
1884 gen_op_iwmmxt_set_cup();
1885 break;
1886 case 0x10c: case 0x50c: case 0x90c: case 0xd0c:
1887 wrd = (insn >> 12) & 0xf;
1888 rd0 = (insn >> 16) & 0xf;
1889 rd1 = (insn >> 0) & 0xf;
1890 gen_op_iwmmxt_movq_M0_wRn(rd0);
1891 switch ((insn >> 22) & 3) {
1892 case 0:
1893 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1894 break;
1895 case 1:
1896 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1897 break;
1898 case 2:
1899 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1900 break;
1901 case 3:
1902 return 1;
1903 }
1904 gen_op_iwmmxt_movq_wRn_M0(wrd);
1905 gen_op_iwmmxt_set_mup();
1906 gen_op_iwmmxt_set_cup();
1907 break;
1908 case 0x012: case 0x112: case 0x412: case 0x512:
1909 wrd = (insn >> 12) & 0xf;
1910 rd0 = (insn >> 16) & 0xf;
1911 rd1 = (insn >> 0) & 0xf;
1912 gen_op_iwmmxt_movq_M0_wRn(rd0);
1913 if (insn & (1 << 22))
1914 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1915 else
1916 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1917 if (!(insn & (1 << 20)))
1918 gen_op_iwmmxt_addl_M0_wRn(wrd);
1919 gen_op_iwmmxt_movq_wRn_M0(wrd);
1920 gen_op_iwmmxt_set_mup();
1921 break;
1922 case 0x010: case 0x110: case 0x210: case 0x310:
1923 wrd = (insn >> 12) & 0xf;
1924 rd0 = (insn >> 16) & 0xf;
1925 rd1 = (insn >> 0) & 0xf;
1926 gen_op_iwmmxt_movq_M0_wRn(rd0);
1927 if (insn & (1 << 21)) {
1928 if (insn & (1 << 20))
1929 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1930 else
1931 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1932 } else {
1933 if (insn & (1 << 20))
1934 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1935 else
1936 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1937 }
1938 gen_op_iwmmxt_movq_wRn_M0(wrd);
1939 gen_op_iwmmxt_set_mup();
1940 break;
1941 case 0x410: case 0x510: case 0x610: case 0x710:
1942 wrd = (insn >> 12) & 0xf;
1943 rd0 = (insn >> 16) & 0xf;
1944 rd1 = (insn >> 0) & 0xf;
1945 gen_op_iwmmxt_movq_M0_wRn(rd0);
1946 if (insn & (1 << 21))
1947 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1948 else
1949 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1950 if (!(insn & (1 << 20))) {
1951 iwmmxt_load_reg(cpu_V1, wrd);
1952 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1953 }
1954 gen_op_iwmmxt_movq_wRn_M0(wrd);
1955 gen_op_iwmmxt_set_mup();
1956 break;
1957 case 0x006: case 0x406: case 0x806: case 0xc06:
1958 wrd = (insn >> 12) & 0xf;
1959 rd0 = (insn >> 16) & 0xf;
1960 rd1 = (insn >> 0) & 0xf;
1961 gen_op_iwmmxt_movq_M0_wRn(rd0);
1962 switch ((insn >> 22) & 3) {
1963 case 0:
1964 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1965 break;
1966 case 1:
1967 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1968 break;
1969 case 2:
1970 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1971 break;
1972 case 3:
1973 return 1;
1974 }
1975 gen_op_iwmmxt_movq_wRn_M0(wrd);
1976 gen_op_iwmmxt_set_mup();
1977 gen_op_iwmmxt_set_cup();
1978 break;
1979 case 0x800: case 0x900: case 0xc00: case 0xd00:
1980 wrd = (insn >> 12) & 0xf;
1981 rd0 = (insn >> 16) & 0xf;
1982 rd1 = (insn >> 0) & 0xf;
1983 gen_op_iwmmxt_movq_M0_wRn(rd0);
1984 if (insn & (1 << 22)) {
1985 if (insn & (1 << 20))
1986 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1987 else
1988 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1989 } else {
1990 if (insn & (1 << 20))
1991 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1992 else
1993 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1994 }
1995 gen_op_iwmmxt_movq_wRn_M0(wrd);
1996 gen_op_iwmmxt_set_mup();
1997 gen_op_iwmmxt_set_cup();
1998 break;
1999 case 0x802: case 0x902: case 0xa02: case 0xb02:
2000 wrd = (insn >> 12) & 0xf;
2001 rd0 = (insn >> 16) & 0xf;
2002 rd1 = (insn >> 0) & 0xf;
2003 gen_op_iwmmxt_movq_M0_wRn(rd0);
2004 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
2005 tcg_gen_andi_i32(tmp, tmp, 7);
2006 iwmmxt_load_reg(cpu_V1, rd1);
2007 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2008 tcg_temp_free_i32(tmp);
2009 gen_op_iwmmxt_movq_wRn_M0(wrd);
2010 gen_op_iwmmxt_set_mup();
2011 break;
2012 case 0x601: case 0x605: case 0x609: case 0x60d:
2013 if (((insn >> 6) & 3) == 3)
2014 return 1;
2015 rd = (insn >> 12) & 0xf;
2016 wrd = (insn >> 16) & 0xf;
2017 tmp = load_reg(s, rd);
2018 gen_op_iwmmxt_movq_M0_wRn(wrd);
2019 switch ((insn >> 6) & 3) {
2020 case 0:
2021 tmp2 = tcg_const_i32(0xff);
2022 tmp3 = tcg_const_i32((insn & 7) << 3);
2023 break;
2024 case 1:
2025 tmp2 = tcg_const_i32(0xffff);
2026 tmp3 = tcg_const_i32((insn & 3) << 4);
2027 break;
2028 case 2:
2029 tmp2 = tcg_const_i32(0xffffffff);
2030 tmp3 = tcg_const_i32((insn & 1) << 5);
2031 break;
2032 default:
2033 TCGV_UNUSED_I32(tmp2);
2034 TCGV_UNUSED_I32(tmp3);
2035 }
2036 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
2037 tcg_temp_free_i32(tmp3);
2038 tcg_temp_free_i32(tmp2);
2039 tcg_temp_free_i32(tmp);
2040 gen_op_iwmmxt_movq_wRn_M0(wrd);
2041 gen_op_iwmmxt_set_mup();
2042 break;
2043 case 0x107: case 0x507: case 0x907: case 0xd07:
2044 rd = (insn >> 12) & 0xf;
2045 wrd = (insn >> 16) & 0xf;
2046 if (rd == 15 || ((insn >> 22) & 3) == 3)
2047 return 1;
2048 gen_op_iwmmxt_movq_M0_wRn(wrd);
2049 tmp = tcg_temp_new_i32();
2050 switch ((insn >> 22) & 3) {
2051 case 0:
2052 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
2053 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2054 if (insn & 8) {
2055 tcg_gen_ext8s_i32(tmp, tmp);
2056 } else {
2057 tcg_gen_andi_i32(tmp, tmp, 0xff);
2058 }
2059 break;
2060 case 1:
2061 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
2062 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2063 if (insn & 8) {
2064 tcg_gen_ext16s_i32(tmp, tmp);
2065 } else {
2066 tcg_gen_andi_i32(tmp, tmp, 0xffff);
2067 }
2068 break;
2069 case 2:
2070 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
2071 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2072 break;
2073 }
2074 store_reg(s, rd, tmp);
2075 break;
2076 case 0x117: case 0x517: case 0x917: case 0xd17:
2077 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
2078 return 1;
2079 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
2080 switch ((insn >> 22) & 3) {
2081 case 0:
2082 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
2083 break;
2084 case 1:
2085 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
2086 break;
2087 case 2:
2088 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
2089 break;
2090 }
2091 tcg_gen_shli_i32(tmp, tmp, 28);
2092 gen_set_nzcv(tmp);
2093 tcg_temp_free_i32(tmp);
2094 break;
2095 case 0x401: case 0x405: case 0x409: case 0x40d:
2096 if (((insn >> 6) & 3) == 3)
2097 return 1;
2098 rd = (insn >> 12) & 0xf;
2099 wrd = (insn >> 16) & 0xf;
2100 tmp = load_reg(s, rd);
2101 switch ((insn >> 6) & 3) {
2102 case 0:
2103 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
2104 break;
2105 case 1:
2106 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
2107 break;
2108 case 2:
2109 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
2110 break;
2111 }
2112 tcg_temp_free_i32(tmp);
2113 gen_op_iwmmxt_movq_wRn_M0(wrd);
2114 gen_op_iwmmxt_set_mup();
2115 break;
2116 case 0x113: case 0x513: case 0x913: case 0xd13:
2117 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
2118 return 1;
2119 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
2120 tmp2 = tcg_temp_new_i32();
2121 tcg_gen_mov_i32(tmp2, tmp);
2122 switch ((insn >> 22) & 3) {
2123 case 0:
2124 for (i = 0; i < 7; i ++) {
2125 tcg_gen_shli_i32(tmp2, tmp2, 4);
2126 tcg_gen_and_i32(tmp, tmp, tmp2);
2127 }
2128 break;
2129 case 1:
2130 for (i = 0; i < 3; i ++) {
2131 tcg_gen_shli_i32(tmp2, tmp2, 8);
2132 tcg_gen_and_i32(tmp, tmp, tmp2);
2133 }
2134 break;
2135 case 2:
2136 tcg_gen_shli_i32(tmp2, tmp2, 16);
2137 tcg_gen_and_i32(tmp, tmp, tmp2);
2138 break;
2139 }
2140 gen_set_nzcv(tmp);
2141 tcg_temp_free_i32(tmp2);
2142 tcg_temp_free_i32(tmp);
2143 break;
2144 case 0x01c: case 0x41c: case 0x81c: case 0xc1c:
2145 wrd = (insn >> 12) & 0xf;
2146 rd0 = (insn >> 16) & 0xf;
2147 gen_op_iwmmxt_movq_M0_wRn(rd0);
2148 switch ((insn >> 22) & 3) {
2149 case 0:
2150 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
2151 break;
2152 case 1:
2153 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
2154 break;
2155 case 2:
2156 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
2157 break;
2158 case 3:
2159 return 1;
2160 }
2161 gen_op_iwmmxt_movq_wRn_M0(wrd);
2162 gen_op_iwmmxt_set_mup();
2163 break;
2164 case 0x115: case 0x515: case 0x915: case 0xd15:
2165 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
2166 return 1;
2167 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
2168 tmp2 = tcg_temp_new_i32();
2169 tcg_gen_mov_i32(tmp2, tmp);
2170 switch ((insn >> 22) & 3) {
2171 case 0:
2172 for (i = 0; i < 7; i ++) {
2173 tcg_gen_shli_i32(tmp2, tmp2, 4);
2174 tcg_gen_or_i32(tmp, tmp, tmp2);
2175 }
2176 break;
2177 case 1:
2178 for (i = 0; i < 3; i ++) {
2179 tcg_gen_shli_i32(tmp2, tmp2, 8);
2180 tcg_gen_or_i32(tmp, tmp, tmp2);
2181 }
2182 break;
2183 case 2:
2184 tcg_gen_shli_i32(tmp2, tmp2, 16);
2185 tcg_gen_or_i32(tmp, tmp, tmp2);
2186 break;
2187 }
2188 gen_set_nzcv(tmp);
2189 tcg_temp_free_i32(tmp2);
2190 tcg_temp_free_i32(tmp);
2191 break;
2192 case 0x103: case 0x503: case 0x903: case 0xd03:
2193 rd = (insn >> 12) & 0xf;
2194 rd0 = (insn >> 16) & 0xf;
2195 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
2196 return 1;
2197 gen_op_iwmmxt_movq_M0_wRn(rd0);
2198 tmp = tcg_temp_new_i32();
2199 switch ((insn >> 22) & 3) {
2200 case 0:
2201 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
2202 break;
2203 case 1:
2204 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
2205 break;
2206 case 2:
2207 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
2208 break;
2209 }
2210 store_reg(s, rd, tmp);
2211 break;
2212 case 0x106: case 0x306: case 0x506: case 0x706:
2213 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2214 wrd = (insn >> 12) & 0xf;
2215 rd0 = (insn >> 16) & 0xf;
2216 rd1 = (insn >> 0) & 0xf;
2217 gen_op_iwmmxt_movq_M0_wRn(rd0);
2218 switch ((insn >> 22) & 3) {
2219 case 0:
2220 if (insn & (1 << 21))
2221 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
2222 else
2223 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
2224 break;
2225 case 1:
2226 if (insn & (1 << 21))
2227 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
2228 else
2229 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2230 break;
2231 case 2:
2232 if (insn & (1 << 21))
2233 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2234 else
2235 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2236 break;
2237 case 3:
2238 return 1;
2239 }
2240 gen_op_iwmmxt_movq_wRn_M0(wrd);
2241 gen_op_iwmmxt_set_mup();
2242 gen_op_iwmmxt_set_cup();
2243 break;
2244 case 0x00e: case 0x20e: case 0x40e: case 0x60e:
2245 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2246 wrd = (insn >> 12) & 0xf;
2247 rd0 = (insn >> 16) & 0xf;
2248 gen_op_iwmmxt_movq_M0_wRn(rd0);
2249 switch ((insn >> 22) & 3) {
2250 case 0:
2251 if (insn & (1 << 21))
2252 gen_op_iwmmxt_unpacklsb_M0();
2253 else
2254 gen_op_iwmmxt_unpacklub_M0();
2255 break;
2256 case 1:
2257 if (insn & (1 << 21))
2258 gen_op_iwmmxt_unpacklsw_M0();
2259 else
2260 gen_op_iwmmxt_unpackluw_M0();
2261 break;
2262 case 2:
2263 if (insn & (1 << 21))
2264 gen_op_iwmmxt_unpacklsl_M0();
2265 else
2266 gen_op_iwmmxt_unpacklul_M0();
2267 break;
2268 case 3:
2269 return 1;
2270 }
2271 gen_op_iwmmxt_movq_wRn_M0(wrd);
2272 gen_op_iwmmxt_set_mup();
2273 gen_op_iwmmxt_set_cup();
2274 break;
2275 case 0x00c: case 0x20c: case 0x40c: case 0x60c:
2276 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2277 wrd = (insn >> 12) & 0xf;
2278 rd0 = (insn >> 16) & 0xf;
2279 gen_op_iwmmxt_movq_M0_wRn(rd0);
2280 switch ((insn >> 22) & 3) {
2281 case 0:
2282 if (insn & (1 << 21))
2283 gen_op_iwmmxt_unpackhsb_M0();
2284 else
2285 gen_op_iwmmxt_unpackhub_M0();
2286 break;
2287 case 1:
2288 if (insn & (1 << 21))
2289 gen_op_iwmmxt_unpackhsw_M0();
2290 else
2291 gen_op_iwmmxt_unpackhuw_M0();
2292 break;
2293 case 2:
2294 if (insn & (1 << 21))
2295 gen_op_iwmmxt_unpackhsl_M0();
2296 else
2297 gen_op_iwmmxt_unpackhul_M0();
2298 break;
2299 case 3:
2300 return 1;
2301 }
2302 gen_op_iwmmxt_movq_wRn_M0(wrd);
2303 gen_op_iwmmxt_set_mup();
2304 gen_op_iwmmxt_set_cup();
2305 break;
2306 case 0x204: case 0x604: case 0xa04: case 0xe04:
2307 case 0x214: case 0x614: case 0xa14: case 0xe14:
2308 if (((insn >> 22) & 3) == 0)
2309 return 1;
2310 wrd = (insn >> 12) & 0xf;
2311 rd0 = (insn >> 16) & 0xf;
2312 gen_op_iwmmxt_movq_M0_wRn(rd0);
2313 tmp = tcg_temp_new_i32();
2314 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2315 tcg_temp_free_i32(tmp);
2316 return 1;
2317 }
2318 switch ((insn >> 22) & 3) {
2319 case 1:
2320 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
2321 break;
2322 case 2:
2323 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
2324 break;
2325 case 3:
2326 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
2327 break;
2328 }
2329 tcg_temp_free_i32(tmp);
2330 gen_op_iwmmxt_movq_wRn_M0(wrd);
2331 gen_op_iwmmxt_set_mup();
2332 gen_op_iwmmxt_set_cup();
2333 break;
2334 case 0x004: case 0x404: case 0x804: case 0xc04:
2335 case 0x014: case 0x414: case 0x814: case 0xc14:
2336 if (((insn >> 22) & 3) == 0)
2337 return 1;
2338 wrd = (insn >> 12) & 0xf;
2339 rd0 = (insn >> 16) & 0xf;
2340 gen_op_iwmmxt_movq_M0_wRn(rd0);
2341 tmp = tcg_temp_new_i32();
2342 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2343 tcg_temp_free_i32(tmp);
2344 return 1;
2345 }
2346 switch ((insn >> 22) & 3) {
2347 case 1:
2348 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
2349 break;
2350 case 2:
2351 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
2352 break;
2353 case 3:
2354 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
2355 break;
2356 }
2357 tcg_temp_free_i32(tmp);
2358 gen_op_iwmmxt_movq_wRn_M0(wrd);
2359 gen_op_iwmmxt_set_mup();
2360 gen_op_iwmmxt_set_cup();
2361 break;
2362 case 0x104: case 0x504: case 0x904: case 0xd04:
2363 case 0x114: case 0x514: case 0x914: case 0xd14:
2364 if (((insn >> 22) & 3) == 0)
2365 return 1;
2366 wrd = (insn >> 12) & 0xf;
2367 rd0 = (insn >> 16) & 0xf;
2368 gen_op_iwmmxt_movq_M0_wRn(rd0);
2369 tmp = tcg_temp_new_i32();
2370 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2371 tcg_temp_free_i32(tmp);
2372 return 1;
2373 }
2374 switch ((insn >> 22) & 3) {
2375 case 1:
2376 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2377 break;
2378 case 2:
2379 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2380 break;
2381 case 3:
2382 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2383 break;
2384 }
2385 tcg_temp_free_i32(tmp);
2386 gen_op_iwmmxt_movq_wRn_M0(wrd);
2387 gen_op_iwmmxt_set_mup();
2388 gen_op_iwmmxt_set_cup();
2389 break;
2390 case 0x304: case 0x704: case 0xb04: case 0xf04:
2391 case 0x314: case 0x714: case 0xb14: case 0xf14:
2392 if (((insn >> 22) & 3) == 0)
2393 return 1;
2394 wrd = (insn >> 12) & 0xf;
2395 rd0 = (insn >> 16) & 0xf;
2396 gen_op_iwmmxt_movq_M0_wRn(rd0);
2397 tmp = tcg_temp_new_i32();
2398 switch ((insn >> 22) & 3) {
2399 case 1:
2400 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2401 tcg_temp_free_i32(tmp);
2402 return 1;
2403 }
2404 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2405 break;
2406 case 2:
2407 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2408 tcg_temp_free_i32(tmp);
2409 return 1;
2410 }
2411 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2412 break;
2413 case 3:
2414 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2415 tcg_temp_free_i32(tmp);
2416 return 1;
2417 }
2418 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2419 break;
2420 }
2421 tcg_temp_free_i32(tmp);
2422 gen_op_iwmmxt_movq_wRn_M0(wrd);
2423 gen_op_iwmmxt_set_mup();
2424 gen_op_iwmmxt_set_cup();
2425 break;
2426 case 0x116: case 0x316: case 0x516: case 0x716:
2427 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2428 wrd = (insn >> 12) & 0xf;
2429 rd0 = (insn >> 16) & 0xf;
2430 rd1 = (insn >> 0) & 0xf;
2431 gen_op_iwmmxt_movq_M0_wRn(rd0);
2432 switch ((insn >> 22) & 3) {
2433 case 0:
2434 if (insn & (1 << 21))
2435 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2436 else
2437 gen_op_iwmmxt_minub_M0_wRn(rd1);
2438 break;
2439 case 1:
2440 if (insn & (1 << 21))
2441 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2442 else
2443 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2444 break;
2445 case 2:
2446 if (insn & (1 << 21))
2447 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2448 else
2449 gen_op_iwmmxt_minul_M0_wRn(rd1);
2450 break;
2451 case 3:
2452 return 1;
2453 }
2454 gen_op_iwmmxt_movq_wRn_M0(wrd);
2455 gen_op_iwmmxt_set_mup();
2456 break;
2457 case 0x016: case 0x216: case 0x416: case 0x616:
2458 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2459 wrd = (insn >> 12) & 0xf;
2460 rd0 = (insn >> 16) & 0xf;
2461 rd1 = (insn >> 0) & 0xf;
2462 gen_op_iwmmxt_movq_M0_wRn(rd0);
2463 switch ((insn >> 22) & 3) {
2464 case 0:
2465 if (insn & (1 << 21))
2466 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2467 else
2468 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2469 break;
2470 case 1:
2471 if (insn & (1 << 21))
2472 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2473 else
2474 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2475 break;
2476 case 2:
2477 if (insn & (1 << 21))
2478 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2479 else
2480 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2481 break;
2482 case 3:
2483 return 1;
2484 }
2485 gen_op_iwmmxt_movq_wRn_M0(wrd);
2486 gen_op_iwmmxt_set_mup();
2487 break;
2488 case 0x002: case 0x102: case 0x202: case 0x302:
2489 case 0x402: case 0x502: case 0x602: case 0x702:
2490 wrd = (insn >> 12) & 0xf;
2491 rd0 = (insn >> 16) & 0xf;
2492 rd1 = (insn >> 0) & 0xf;
2493 gen_op_iwmmxt_movq_M0_wRn(rd0);
2494 tmp = tcg_const_i32((insn >> 20) & 3);
2495 iwmmxt_load_reg(cpu_V1, rd1);
2496 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2497 tcg_temp_free_i32(tmp);
2498 gen_op_iwmmxt_movq_wRn_M0(wrd);
2499 gen_op_iwmmxt_set_mup();
2500 break;
2501 case 0x01a: case 0x11a: case 0x21a: case 0x31a:
2502 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2503 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2504 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2505 wrd = (insn >> 12) & 0xf;
2506 rd0 = (insn >> 16) & 0xf;
2507 rd1 = (insn >> 0) & 0xf;
2508 gen_op_iwmmxt_movq_M0_wRn(rd0);
2509 switch ((insn >> 20) & 0xf) {
2510 case 0x0:
2511 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2512 break;
2513 case 0x1:
2514 gen_op_iwmmxt_subub_M0_wRn(rd1);
2515 break;
2516 case 0x3:
2517 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2518 break;
2519 case 0x4:
2520 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2521 break;
2522 case 0x5:
2523 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2524 break;
2525 case 0x7:
2526 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2527 break;
2528 case 0x8:
2529 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2530 break;
2531 case 0x9:
2532 gen_op_iwmmxt_subul_M0_wRn(rd1);
2533 break;
2534 case 0xb:
2535 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2536 break;
2537 default:
2538 return 1;
2539 }
2540 gen_op_iwmmxt_movq_wRn_M0(wrd);
2541 gen_op_iwmmxt_set_mup();
2542 gen_op_iwmmxt_set_cup();
2543 break;
2544 case 0x01e: case 0x11e: case 0x21e: case 0x31e:
2545 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2546 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2547 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2548 wrd = (insn >> 12) & 0xf;
2549 rd0 = (insn >> 16) & 0xf;
2550 gen_op_iwmmxt_movq_M0_wRn(rd0);
2551 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2552 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2553 tcg_temp_free_i32(tmp);
2554 gen_op_iwmmxt_movq_wRn_M0(wrd);
2555 gen_op_iwmmxt_set_mup();
2556 gen_op_iwmmxt_set_cup();
2557 break;
2558 case 0x018: case 0x118: case 0x218: case 0x318:
2559 case 0x418: case 0x518: case 0x618: case 0x718:
2560 case 0x818: case 0x918: case 0xa18: case 0xb18:
2561 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2562 wrd = (insn >> 12) & 0xf;
2563 rd0 = (insn >> 16) & 0xf;
2564 rd1 = (insn >> 0) & 0xf;
2565 gen_op_iwmmxt_movq_M0_wRn(rd0);
2566 switch ((insn >> 20) & 0xf) {
2567 case 0x0:
2568 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2569 break;
2570 case 0x1:
2571 gen_op_iwmmxt_addub_M0_wRn(rd1);
2572 break;
2573 case 0x3:
2574 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2575 break;
2576 case 0x4:
2577 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2578 break;
2579 case 0x5:
2580 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2581 break;
2582 case 0x7:
2583 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2584 break;
2585 case 0x8:
2586 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2587 break;
2588 case 0x9:
2589 gen_op_iwmmxt_addul_M0_wRn(rd1);
2590 break;
2591 case 0xb:
2592 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2593 break;
2594 default:
2595 return 1;
2596 }
2597 gen_op_iwmmxt_movq_wRn_M0(wrd);
2598 gen_op_iwmmxt_set_mup();
2599 gen_op_iwmmxt_set_cup();
2600 break;
2601 case 0x008: case 0x108: case 0x208: case 0x308:
2602 case 0x408: case 0x508: case 0x608: case 0x708:
2603 case 0x808: case 0x908: case 0xa08: case 0xb08:
2604 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2605 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2606 return 1;
2607 wrd = (insn >> 12) & 0xf;
2608 rd0 = (insn >> 16) & 0xf;
2609 rd1 = (insn >> 0) & 0xf;
2610 gen_op_iwmmxt_movq_M0_wRn(rd0);
2611 switch ((insn >> 22) & 3) {
2612 case 1:
2613 if (insn & (1 << 21))
2614 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2615 else
2616 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2617 break;
2618 case 2:
2619 if (insn & (1 << 21))
2620 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2621 else
2622 gen_op_iwmmxt_packul_M0_wRn(rd1);
2623 break;
2624 case 3:
2625 if (insn & (1 << 21))
2626 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2627 else
2628 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2629 break;
2630 }
2631 gen_op_iwmmxt_movq_wRn_M0(wrd);
2632 gen_op_iwmmxt_set_mup();
2633 gen_op_iwmmxt_set_cup();
2634 break;
2635 case 0x201: case 0x203: case 0x205: case 0x207:
2636 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2637 case 0x211: case 0x213: case 0x215: case 0x217:
2638 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2639 wrd = (insn >> 5) & 0xf;
2640 rd0 = (insn >> 12) & 0xf;
2641 rd1 = (insn >> 0) & 0xf;
2642 if (rd0 == 0xf || rd1 == 0xf)
2643 return 1;
2644 gen_op_iwmmxt_movq_M0_wRn(wrd);
2645 tmp = load_reg(s, rd0);
2646 tmp2 = load_reg(s, rd1);
2647 switch ((insn >> 16) & 0xf) {
2648 case 0x0:
2649 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2650 break;
2651 case 0x8:
2652 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2653 break;
2654 case 0xc: case 0xd: case 0xe: case 0xf:
2655 if (insn & (1 << 16))
2656 tcg_gen_shri_i32(tmp, tmp, 16);
2657 if (insn & (1 << 17))
2658 tcg_gen_shri_i32(tmp2, tmp2, 16);
2659 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2660 break;
2661 default:
2662 tcg_temp_free_i32(tmp2);
2663 tcg_temp_free_i32(tmp);
2664 return 1;
2665 }
2666 tcg_temp_free_i32(tmp2);
2667 tcg_temp_free_i32(tmp);
2668 gen_op_iwmmxt_movq_wRn_M0(wrd);
2669 gen_op_iwmmxt_set_mup();
2670 break;
2671 default:
2672 return 1;
2673 }
2674
2675 return 0;
2676}
2677
2678
2679
2680static int disas_dsp_insn(DisasContext *s, uint32_t insn)
2681{
2682 int acc, rd0, rd1, rdhi, rdlo;
2683 TCGv_i32 tmp, tmp2;
2684
2685 if ((insn & 0x0ff00f10) == 0x0e200010) {
2686
2687 rd0 = (insn >> 12) & 0xf;
2688 rd1 = insn & 0xf;
2689 acc = (insn >> 5) & 7;
2690
2691 if (acc != 0)
2692 return 1;
2693
2694 tmp = load_reg(s, rd0);
2695 tmp2 = load_reg(s, rd1);
2696 switch ((insn >> 16) & 0xf) {
2697 case 0x0:
2698 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2699 break;
2700 case 0x8:
2701 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2702 break;
2703 case 0xc:
2704 case 0xd:
2705 case 0xe:
2706 case 0xf:
2707 if (insn & (1 << 16))
2708 tcg_gen_shri_i32(tmp, tmp, 16);
2709 if (insn & (1 << 17))
2710 tcg_gen_shri_i32(tmp2, tmp2, 16);
2711 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2712 break;
2713 default:
2714 return 1;
2715 }
2716 tcg_temp_free_i32(tmp2);
2717 tcg_temp_free_i32(tmp);
2718
2719 gen_op_iwmmxt_movq_wRn_M0(acc);
2720 return 0;
2721 }
2722
2723 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2724
2725 rdhi = (insn >> 16) & 0xf;
2726 rdlo = (insn >> 12) & 0xf;
2727 acc = insn & 7;
2728
2729 if (acc != 0)
2730 return 1;
2731
2732 if (insn & ARM_CP_RW_BIT) {
2733 iwmmxt_load_reg(cpu_V0, acc);
2734 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
2735 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
2736 tcg_gen_extrl_i64_i32(cpu_R[rdhi], cpu_V0);
2737 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
2738 } else {
2739 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2740 iwmmxt_store_reg(cpu_V0, acc);
2741 }
2742 return 0;
2743 }
2744
2745 return 1;
2746}
2747
2748#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2749#define VFP_SREG(insn, bigbit, smallbit) \
2750 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2751#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2752 if (arm_dc_feature(s, ARM_FEATURE_VFP3)) { \
2753 reg = (((insn) >> (bigbit)) & 0x0f) \
2754 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2755 } else { \
2756 if (insn & (1 << (smallbit))) \
2757 return 1; \
2758 reg = ((insn) >> (bigbit)) & 0x0f; \
2759 }} while (0)
2760
2761#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2762#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2763#define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2764#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2765#define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2766#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2767
2768
2769static TCGv_i32 gen_vfp_mrs(void)
2770{
2771 TCGv_i32 tmp = tcg_temp_new_i32();
2772 tcg_gen_mov_i32(tmp, cpu_F0s);
2773 return tmp;
2774}
2775
2776static void gen_vfp_msr(TCGv_i32 tmp)
2777{
2778 tcg_gen_mov_i32(cpu_F0s, tmp);
2779 tcg_temp_free_i32(tmp);
2780}
2781
2782static void gen_neon_dup_u8(TCGv_i32 var, int shift)
2783{
2784 TCGv_i32 tmp = tcg_temp_new_i32();
2785 if (shift)
2786 tcg_gen_shri_i32(var, var, shift);
2787 tcg_gen_ext8u_i32(var, var);
2788 tcg_gen_shli_i32(tmp, var, 8);
2789 tcg_gen_or_i32(var, var, tmp);
2790 tcg_gen_shli_i32(tmp, var, 16);
2791 tcg_gen_or_i32(var, var, tmp);
2792 tcg_temp_free_i32(tmp);
2793}
2794
2795static void gen_neon_dup_low16(TCGv_i32 var)
2796{
2797 TCGv_i32 tmp = tcg_temp_new_i32();
2798 tcg_gen_ext16u_i32(var, var);
2799 tcg_gen_shli_i32(tmp, var, 16);
2800 tcg_gen_or_i32(var, var, tmp);
2801 tcg_temp_free_i32(tmp);
2802}
2803
2804static void gen_neon_dup_high16(TCGv_i32 var)
2805{
2806 TCGv_i32 tmp = tcg_temp_new_i32();
2807 tcg_gen_andi_i32(var, var, 0xffff0000);
2808 tcg_gen_shri_i32(tmp, var, 16);
2809 tcg_gen_or_i32(var, var, tmp);
2810 tcg_temp_free_i32(tmp);
2811}
2812
2813static TCGv_i32 gen_load_and_replicate(DisasContext *s, TCGv_i32 addr, int size)
2814{
2815
2816 TCGv_i32 tmp = tcg_temp_new_i32();
2817 switch (size) {
2818 case 0:
2819 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
2820 gen_neon_dup_u8(tmp, 0);
2821 break;
2822 case 1:
2823 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
2824 gen_neon_dup_low16(tmp);
2825 break;
2826 case 2:
2827 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
2828 break;
2829 default:
2830 abort();
2831 }
2832 return tmp;
2833}
2834
2835static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm,
2836 uint32_t dp)
2837{
2838 uint32_t cc = extract32(insn, 20, 2);
2839
2840 if (dp) {
2841 TCGv_i64 frn, frm, dest;
2842 TCGv_i64 tmp, zero, zf, nf, vf;
2843
2844 zero = tcg_const_i64(0);
2845
2846 frn = tcg_temp_new_i64();
2847 frm = tcg_temp_new_i64();
2848 dest = tcg_temp_new_i64();
2849
2850 zf = tcg_temp_new_i64();
2851 nf = tcg_temp_new_i64();
2852 vf = tcg_temp_new_i64();
2853
2854 tcg_gen_extu_i32_i64(zf, cpu_ZF);
2855 tcg_gen_ext_i32_i64(nf, cpu_NF);
2856 tcg_gen_ext_i32_i64(vf, cpu_VF);
2857
2858 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
2859 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
2860 switch (cc) {
2861 case 0:
2862 tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero,
2863 frn, frm);
2864 break;
2865 case 1:
2866 tcg_gen_movcond_i64(TCG_COND_LT, dest, vf, zero,
2867 frn, frm);
2868 break;
2869 case 2:
2870 tmp = tcg_temp_new_i64();
2871 tcg_gen_xor_i64(tmp, vf, nf);
2872 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
2873 frn, frm);
2874 tcg_temp_free_i64(tmp);
2875 break;
2876 case 3:
2877 tcg_gen_movcond_i64(TCG_COND_NE, dest, zf, zero,
2878 frn, frm);
2879 tmp = tcg_temp_new_i64();
2880 tcg_gen_xor_i64(tmp, vf, nf);
2881 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
2882 dest, frm);
2883 tcg_temp_free_i64(tmp);
2884 break;
2885 }
2886 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
2887 tcg_temp_free_i64(frn);
2888 tcg_temp_free_i64(frm);
2889 tcg_temp_free_i64(dest);
2890
2891 tcg_temp_free_i64(zf);
2892 tcg_temp_free_i64(nf);
2893 tcg_temp_free_i64(vf);
2894
2895 tcg_temp_free_i64(zero);
2896 } else {
2897 TCGv_i32 frn, frm, dest;
2898 TCGv_i32 tmp, zero;
2899
2900 zero = tcg_const_i32(0);
2901
2902 frn = tcg_temp_new_i32();
2903 frm = tcg_temp_new_i32();
2904 dest = tcg_temp_new_i32();
2905 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
2906 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
2907 switch (cc) {
2908 case 0:
2909 tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero,
2910 frn, frm);
2911 break;
2912 case 1:
2913 tcg_gen_movcond_i32(TCG_COND_LT, dest, cpu_VF, zero,
2914 frn, frm);
2915 break;
2916 case 2:
2917 tmp = tcg_temp_new_i32();
2918 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
2919 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
2920 frn, frm);
2921 tcg_temp_free_i32(tmp);
2922 break;
2923 case 3:
2924 tcg_gen_movcond_i32(TCG_COND_NE, dest, cpu_ZF, zero,
2925 frn, frm);
2926 tmp = tcg_temp_new_i32();
2927 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
2928 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
2929 dest, frm);
2930 tcg_temp_free_i32(tmp);
2931 break;
2932 }
2933 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
2934 tcg_temp_free_i32(frn);
2935 tcg_temp_free_i32(frm);
2936 tcg_temp_free_i32(dest);
2937
2938 tcg_temp_free_i32(zero);
2939 }
2940
2941 return 0;
2942}
2943
2944static int handle_vminmaxnm(uint32_t insn, uint32_t rd, uint32_t rn,
2945 uint32_t rm, uint32_t dp)
2946{
2947 uint32_t vmin = extract32(insn, 6, 1);
2948 TCGv_ptr fpst = get_fpstatus_ptr(0);
2949
2950 if (dp) {
2951 TCGv_i64 frn, frm, dest;
2952
2953 frn = tcg_temp_new_i64();
2954 frm = tcg_temp_new_i64();
2955 dest = tcg_temp_new_i64();
2956
2957 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
2958 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
2959 if (vmin) {
2960 gen_helper_vfp_minnumd(dest, frn, frm, fpst);
2961 } else {
2962 gen_helper_vfp_maxnumd(dest, frn, frm, fpst);
2963 }
2964 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
2965 tcg_temp_free_i64(frn);
2966 tcg_temp_free_i64(frm);
2967 tcg_temp_free_i64(dest);
2968 } else {
2969 TCGv_i32 frn, frm, dest;
2970
2971 frn = tcg_temp_new_i32();
2972 frm = tcg_temp_new_i32();
2973 dest = tcg_temp_new_i32();
2974
2975 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
2976 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
2977 if (vmin) {
2978 gen_helper_vfp_minnums(dest, frn, frm, fpst);
2979 } else {
2980 gen_helper_vfp_maxnums(dest, frn, frm, fpst);
2981 }
2982 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
2983 tcg_temp_free_i32(frn);
2984 tcg_temp_free_i32(frm);
2985 tcg_temp_free_i32(dest);
2986 }
2987
2988 tcg_temp_free_ptr(fpst);
2989 return 0;
2990}
2991
2992static int handle_vrint(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
2993 int rounding)
2994{
2995 TCGv_ptr fpst = get_fpstatus_ptr(0);
2996 TCGv_i32 tcg_rmode;
2997
2998 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
2999 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3000
3001 if (dp) {
3002 TCGv_i64 tcg_op;
3003 TCGv_i64 tcg_res;
3004 tcg_op = tcg_temp_new_i64();
3005 tcg_res = tcg_temp_new_i64();
3006 tcg_gen_ld_f64(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
3007 gen_helper_rintd(tcg_res, tcg_op, fpst);
3008 tcg_gen_st_f64(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
3009 tcg_temp_free_i64(tcg_op);
3010 tcg_temp_free_i64(tcg_res);
3011 } else {
3012 TCGv_i32 tcg_op;
3013 TCGv_i32 tcg_res;
3014 tcg_op = tcg_temp_new_i32();
3015 tcg_res = tcg_temp_new_i32();
3016 tcg_gen_ld_f32(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
3017 gen_helper_rints(tcg_res, tcg_op, fpst);
3018 tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
3019 tcg_temp_free_i32(tcg_op);
3020 tcg_temp_free_i32(tcg_res);
3021 }
3022
3023 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3024 tcg_temp_free_i32(tcg_rmode);
3025
3026 tcg_temp_free_ptr(fpst);
3027 return 0;
3028}
3029
3030static int handle_vcvt(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
3031 int rounding)
3032{
3033 bool is_signed = extract32(insn, 7, 1);
3034 TCGv_ptr fpst = get_fpstatus_ptr(0);
3035 TCGv_i32 tcg_rmode, tcg_shift;
3036
3037 tcg_shift = tcg_const_i32(0);
3038
3039 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
3040 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3041
3042 if (dp) {
3043 TCGv_i64 tcg_double, tcg_res;
3044 TCGv_i32 tcg_tmp;
3045
3046
3047
3048 rd = ((rd << 1) & 0x1e) | ((rd >> 4) & 0x1);
3049 tcg_double = tcg_temp_new_i64();
3050 tcg_res = tcg_temp_new_i64();
3051 tcg_tmp = tcg_temp_new_i32();
3052 tcg_gen_ld_f64(tcg_double, cpu_env, vfp_reg_offset(1, rm));
3053 if (is_signed) {
3054 gen_helper_vfp_tosld(tcg_res, tcg_double, tcg_shift, fpst);
3055 } else {
3056 gen_helper_vfp_tould(tcg_res, tcg_double, tcg_shift, fpst);
3057 }
3058 tcg_gen_extrl_i64_i32(tcg_tmp, tcg_res);
3059 tcg_gen_st_f32(tcg_tmp, cpu_env, vfp_reg_offset(0, rd));
3060 tcg_temp_free_i32(tcg_tmp);
3061 tcg_temp_free_i64(tcg_res);
3062 tcg_temp_free_i64(tcg_double);
3063 } else {
3064 TCGv_i32 tcg_single, tcg_res;
3065 tcg_single = tcg_temp_new_i32();
3066 tcg_res = tcg_temp_new_i32();
3067 tcg_gen_ld_f32(tcg_single, cpu_env, vfp_reg_offset(0, rm));
3068 if (is_signed) {
3069 gen_helper_vfp_tosls(tcg_res, tcg_single, tcg_shift, fpst);
3070 } else {
3071 gen_helper_vfp_touls(tcg_res, tcg_single, tcg_shift, fpst);
3072 }
3073 tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(0, rd));
3074 tcg_temp_free_i32(tcg_res);
3075 tcg_temp_free_i32(tcg_single);
3076 }
3077
3078 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3079 tcg_temp_free_i32(tcg_rmode);
3080
3081 tcg_temp_free_i32(tcg_shift);
3082
3083 tcg_temp_free_ptr(fpst);
3084
3085 return 0;
3086}
3087
3088
3089
3090
3091
3092static const uint8_t fp_decode_rm[] = {
3093 FPROUNDING_TIEAWAY,
3094 FPROUNDING_TIEEVEN,
3095 FPROUNDING_POSINF,
3096 FPROUNDING_NEGINF,
3097};
3098
3099static int disas_vfp_v8_insn(DisasContext *s, uint32_t insn)
3100{
3101 uint32_t rd, rn, rm, dp = extract32(insn, 8, 1);
3102
3103 if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
3104 return 1;
3105 }
3106
3107 if (dp) {
3108 VFP_DREG_D(rd, insn);
3109 VFP_DREG_N(rn, insn);
3110 VFP_DREG_M(rm, insn);
3111 } else {
3112 rd = VFP_SREG_D(insn);
3113 rn = VFP_SREG_N(insn);
3114 rm = VFP_SREG_M(insn);
3115 }
3116
3117 if ((insn & 0x0f800e50) == 0x0e000a00) {
3118 return handle_vsel(insn, rd, rn, rm, dp);
3119 } else if ((insn & 0x0fb00e10) == 0x0e800a00) {
3120 return handle_vminmaxnm(insn, rd, rn, rm, dp);
3121 } else if ((insn & 0x0fbc0ed0) == 0x0eb80a40) {
3122
3123 int rounding = fp_decode_rm[extract32(insn, 16, 2)];
3124 return handle_vrint(insn, rd, rm, dp, rounding);
3125 } else if ((insn & 0x0fbc0e50) == 0x0ebc0a40) {
3126
3127 int rounding = fp_decode_rm[extract32(insn, 16, 2)];
3128 return handle_vcvt(insn, rd, rm, dp, rounding);
3129 }
3130 return 1;
3131}
3132
3133
3134
3135static int disas_vfp_insn(DisasContext *s, uint32_t insn)
3136{
3137 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
3138 int dp, veclen;
3139 TCGv_i32 addr;
3140 TCGv_i32 tmp;
3141 TCGv_i32 tmp2;
3142
3143 if (!arm_dc_feature(s, ARM_FEATURE_VFP)) {
3144 return 1;
3145 }
3146
3147
3148
3149
3150
3151 if (s->fp_excp_el) {
3152 gen_exception_insn(s, 4, EXCP_UDEF,
3153 syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
3154 return 0;
3155 }
3156
3157 if (!s->vfp_enabled) {
3158
3159 if ((insn & 0x0fe00fff) != 0x0ee00a10)
3160 return 1;
3161 rn = (insn >> 16) & 0xf;
3162 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC && rn != ARM_VFP_MVFR2
3163 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0) {
3164 return 1;
3165 }
3166 }
3167
3168 if (extract32(insn, 28, 4) == 0xf) {
3169
3170
3171
3172 return disas_vfp_v8_insn(s, insn);
3173 }
3174
3175 dp = ((insn & 0xf00) == 0xb00);
3176 switch ((insn >> 24) & 0xf) {
3177 case 0xe:
3178 if (insn & (1 << 4)) {
3179
3180 rd = (insn >> 12) & 0xf;
3181 if (dp) {
3182 int size;
3183 int pass;
3184
3185 VFP_DREG_N(rn, insn);
3186 if (insn & 0xf)
3187 return 1;
3188 if (insn & 0x00c00060
3189 && !arm_dc_feature(s, ARM_FEATURE_NEON)) {
3190 return 1;
3191 }
3192
3193 pass = (insn >> 21) & 1;
3194 if (insn & (1 << 22)) {
3195 size = 0;
3196 offset = ((insn >> 5) & 3) * 8;
3197 } else if (insn & (1 << 5)) {
3198 size = 1;
3199 offset = (insn & (1 << 6)) ? 16 : 0;
3200 } else {
3201 size = 2;
3202 offset = 0;
3203 }
3204 if (insn & ARM_CP_RW_BIT) {
3205
3206 tmp = neon_load_reg(rn, pass);
3207 switch (size) {
3208 case 0:
3209 if (offset)
3210 tcg_gen_shri_i32(tmp, tmp, offset);
3211 if (insn & (1 << 23))
3212 gen_uxtb(tmp);
3213 else
3214 gen_sxtb(tmp);
3215 break;
3216 case 1:
3217 if (insn & (1 << 23)) {
3218 if (offset) {
3219 tcg_gen_shri_i32(tmp, tmp, 16);
3220 } else {
3221 gen_uxth(tmp);
3222 }
3223 } else {
3224 if (offset) {
3225 tcg_gen_sari_i32(tmp, tmp, 16);
3226 } else {
3227 gen_sxth(tmp);
3228 }
3229 }
3230 break;
3231 case 2:
3232 break;
3233 }
3234 store_reg(s, rd, tmp);
3235 } else {
3236
3237 tmp = load_reg(s, rd);
3238 if (insn & (1 << 23)) {
3239
3240 if (size == 0) {
3241 gen_neon_dup_u8(tmp, 0);
3242 } else if (size == 1) {
3243 gen_neon_dup_low16(tmp);
3244 }
3245 for (n = 0; n <= pass * 2; n++) {
3246 tmp2 = tcg_temp_new_i32();
3247 tcg_gen_mov_i32(tmp2, tmp);
3248 neon_store_reg(rn, n, tmp2);
3249 }
3250 neon_store_reg(rn, n, tmp);
3251 } else {
3252
3253 switch (size) {
3254 case 0:
3255 tmp2 = neon_load_reg(rn, pass);
3256 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 8);
3257 tcg_temp_free_i32(tmp2);
3258 break;
3259 case 1:
3260 tmp2 = neon_load_reg(rn, pass);
3261 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 16);
3262 tcg_temp_free_i32(tmp2);
3263 break;
3264 case 2:
3265 break;
3266 }
3267 neon_store_reg(rn, pass, tmp);
3268 }
3269 }
3270 } else {
3271 if ((insn & 0x6f) != 0x00)
3272 return 1;
3273 rn = VFP_SREG_N(insn);
3274 if (insn & ARM_CP_RW_BIT) {
3275
3276 if (insn & (1 << 21)) {
3277
3278 rn >>= 1;
3279
3280 switch (rn) {
3281 case ARM_VFP_FPSID:
3282
3283
3284
3285 if (IS_USER(s)
3286 && arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3287 return 1;
3288 }
3289 tmp = load_cpu_field(vfp.xregs[rn]);
3290 break;
3291 case ARM_VFP_FPEXC:
3292 if (IS_USER(s))
3293 return 1;
3294 tmp = load_cpu_field(vfp.xregs[rn]);
3295 break;
3296 case ARM_VFP_FPINST:
3297 case ARM_VFP_FPINST2:
3298
3299 if (IS_USER(s)
3300 || arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3301 return 1;
3302 }
3303 tmp = load_cpu_field(vfp.xregs[rn]);
3304 break;
3305 case ARM_VFP_FPSCR:
3306 if (rd == 15) {
3307 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
3308 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
3309 } else {
3310 tmp = tcg_temp_new_i32();
3311 gen_helper_vfp_get_fpscr(tmp, cpu_env);
3312 }
3313 break;
3314 case ARM_VFP_MVFR2:
3315 if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
3316 return 1;
3317 }
3318
3319 case ARM_VFP_MVFR0:
3320 case ARM_VFP_MVFR1:
3321 if (IS_USER(s)
3322 || !arm_dc_feature(s, ARM_FEATURE_MVFR)) {
3323 return 1;
3324 }
3325 tmp = load_cpu_field(vfp.xregs[rn]);
3326 break;
3327 default:
3328 return 1;
3329 }
3330 } else {
3331 gen_mov_F0_vreg(0, rn);
3332 tmp = gen_vfp_mrs();
3333 }
3334 if (rd == 15) {
3335
3336 gen_set_nzcv(tmp);
3337 tcg_temp_free_i32(tmp);
3338 } else {
3339 store_reg(s, rd, tmp);
3340 }
3341 } else {
3342
3343 if (insn & (1 << 21)) {
3344 rn >>= 1;
3345
3346 switch (rn) {
3347 case ARM_VFP_FPSID:
3348 case ARM_VFP_MVFR0:
3349 case ARM_VFP_MVFR1:
3350
3351 break;
3352 case ARM_VFP_FPSCR:
3353 tmp = load_reg(s, rd);
3354 gen_helper_vfp_set_fpscr(cpu_env, tmp);
3355 tcg_temp_free_i32(tmp);
3356 gen_lookup_tb(s);
3357 break;
3358 case ARM_VFP_FPEXC:
3359 if (IS_USER(s))
3360 return 1;
3361
3362
3363 tmp = load_reg(s, rd);
3364 tcg_gen_andi_i32(tmp, tmp, 1 << 30);
3365 store_cpu_field(tmp, vfp.xregs[rn]);
3366 gen_lookup_tb(s);
3367 break;
3368 case ARM_VFP_FPINST:
3369 case ARM_VFP_FPINST2:
3370 if (IS_USER(s)) {
3371 return 1;
3372 }
3373 tmp = load_reg(s, rd);
3374 store_cpu_field(tmp, vfp.xregs[rn]);
3375 break;
3376 default:
3377 return 1;
3378 }
3379 } else {
3380 tmp = load_reg(s, rd);
3381 gen_vfp_msr(tmp);
3382 gen_mov_vreg_F0(0, rn);
3383 }
3384 }
3385 }
3386 } else {
3387
3388
3389 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
3390 if (dp) {
3391 if (op == 15) {
3392
3393 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
3394 } else {
3395
3396 VFP_DREG_N(rn, insn);
3397 }
3398
3399 if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18) ||
3400 ((rn & 0x1e) == 0x6))) {
3401
3402 rd = VFP_SREG_D(insn);
3403 } else {
3404 VFP_DREG_D(rd, insn);
3405 }
3406 if (op == 15 &&
3407 (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14) ||
3408 ((rn & 0x1e) == 0x4))) {
3409
3410
3411
3412
3413 rm = VFP_SREG_M(insn);
3414 } else {
3415 VFP_DREG_M(rm, insn);
3416 }
3417 } else {
3418 rn = VFP_SREG_N(insn);
3419 if (op == 15 && rn == 15) {
3420
3421 VFP_DREG_D(rd, insn);
3422 } else {
3423 rd = VFP_SREG_D(insn);
3424 }
3425
3426
3427
3428 rm = VFP_SREG_M(insn);
3429 }
3430
3431 veclen = s->vec_len;
3432 if (op == 15 && rn > 3)
3433 veclen = 0;
3434
3435
3436 delta_m = 0;
3437 delta_d = 0;
3438 bank_mask = 0;
3439
3440 if (veclen > 0) {
3441 if (dp)
3442 bank_mask = 0xc;
3443 else
3444 bank_mask = 0x18;
3445
3446
3447 if ((rd & bank_mask) == 0) {
3448
3449 veclen = 0;
3450 } else {
3451 if (dp)
3452 delta_d = (s->vec_stride >> 1) + 1;
3453 else
3454 delta_d = s->vec_stride + 1;
3455
3456 if ((rm & bank_mask) == 0) {
3457
3458 delta_m = 0;
3459 } else {
3460
3461 delta_m = delta_d;
3462 }
3463 }
3464 }
3465
3466
3467 if (op == 15) {
3468 switch (rn) {
3469 case 16:
3470 case 17:
3471
3472 gen_mov_F0_vreg(0, rm);
3473 break;
3474 case 8:
3475 case 9:
3476
3477 gen_mov_F0_vreg(dp, rd);
3478 gen_mov_F1_vreg(dp, rm);
3479 break;
3480 case 10:
3481 case 11:
3482
3483 gen_mov_F0_vreg(dp, rd);
3484 gen_vfp_F1_ld0(dp);
3485 break;
3486 case 20:
3487 case 21:
3488 case 22:
3489 case 23:
3490 case 28:
3491 case 29:
3492 case 30:
3493 case 31:
3494
3495 gen_mov_F0_vreg(dp, rd);
3496 break;
3497 case 4:
3498 case 5:
3499 case 6:
3500 case 7:
3501
3502
3503
3504
3505 if ((dp && !arm_dc_feature(s, ARM_FEATURE_V8)) ||
3506 !arm_dc_feature(s, ARM_FEATURE_VFP_FP16)) {
3507 return 1;
3508 }
3509 if (!extract32(rn, 1, 1)) {
3510
3511 gen_mov_F0_vreg(0, rm);
3512 break;
3513 }
3514
3515 default:
3516
3517 gen_mov_F0_vreg(dp, rm);
3518 break;
3519 }
3520 } else {
3521
3522 gen_mov_F0_vreg(dp, rn);
3523 gen_mov_F1_vreg(dp, rm);
3524 }
3525
3526 for (;;) {
3527
3528 switch (op) {
3529 case 0:
3530
3531 gen_vfp_F1_mul(dp);
3532 gen_mov_F0_vreg(dp, rd);
3533 gen_vfp_add(dp);
3534 break;
3535 case 1:
3536 gen_vfp_mul(dp);
3537 gen_vfp_F1_neg(dp);
3538 gen_mov_F0_vreg(dp, rd);
3539 gen_vfp_add(dp);
3540 break;
3541 case 2:
3542
3543
3544
3545
3546 gen_vfp_F1_mul(dp);
3547 gen_mov_F0_vreg(dp, rd);
3548 gen_vfp_neg(dp);
3549 gen_vfp_add(dp);
3550 break;
3551 case 3:
3552 gen_vfp_mul(dp);
3553 gen_vfp_F1_neg(dp);
3554 gen_mov_F0_vreg(dp, rd);
3555 gen_vfp_neg(dp);
3556 gen_vfp_add(dp);
3557 break;
3558 case 4:
3559 gen_vfp_mul(dp);
3560 break;
3561 case 5:
3562 gen_vfp_mul(dp);
3563 gen_vfp_neg(dp);
3564 break;
3565 case 6:
3566 gen_vfp_add(dp);
3567 break;
3568 case 7:
3569 gen_vfp_sub(dp);
3570 break;
3571 case 8:
3572 gen_vfp_div(dp);
3573 break;
3574 case 10:
3575 case 11:
3576 case 12:
3577 case 13:
3578
3579
3580
3581
3582
3583
3584
3585 if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
3586 return 1;
3587 }
3588 if (dp) {
3589 TCGv_ptr fpst;
3590 TCGv_i64 frd;
3591 if (op & 1) {
3592
3593 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
3594 }
3595 frd = tcg_temp_new_i64();
3596 tcg_gen_ld_f64(frd, cpu_env, vfp_reg_offset(dp, rd));
3597 if (op & 2) {
3598
3599 gen_helper_vfp_negd(frd, frd);
3600 }
3601 fpst = get_fpstatus_ptr(0);
3602 gen_helper_vfp_muladdd(cpu_F0d, cpu_F0d,
3603 cpu_F1d, frd, fpst);
3604 tcg_temp_free_ptr(fpst);
3605 tcg_temp_free_i64(frd);
3606 } else {
3607 TCGv_ptr fpst;
3608 TCGv_i32 frd;
3609 if (op & 1) {
3610
3611 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
3612 }
3613 frd = tcg_temp_new_i32();
3614 tcg_gen_ld_f32(frd, cpu_env, vfp_reg_offset(dp, rd));
3615 if (op & 2) {
3616 gen_helper_vfp_negs(frd, frd);
3617 }
3618 fpst = get_fpstatus_ptr(0);
3619 gen_helper_vfp_muladds(cpu_F0s, cpu_F0s,
3620 cpu_F1s, frd, fpst);
3621 tcg_temp_free_ptr(fpst);
3622 tcg_temp_free_i32(frd);
3623 }
3624 break;
3625 case 14:
3626 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3627 return 1;
3628 }
3629
3630 n = (insn << 12) & 0x80000000;
3631 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3632 if (dp) {
3633 if (i & 0x40)
3634 i |= 0x3f80;
3635 else
3636 i |= 0x4000;
3637 n |= i << 16;
3638 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3639 } else {
3640 if (i & 0x40)
3641 i |= 0x780;
3642 else
3643 i |= 0x800;
3644 n |= i << 19;
3645 tcg_gen_movi_i32(cpu_F0s, n);
3646 }
3647 break;
3648 case 15:
3649 switch (rn) {
3650 case 0:
3651
3652 break;
3653 case 1:
3654 gen_vfp_abs(dp);
3655 break;
3656 case 2:
3657 gen_vfp_neg(dp);
3658 break;
3659 case 3:
3660 gen_vfp_sqrt(dp);
3661 break;
3662 case 4:
3663 tmp = gen_vfp_mrs();
3664 tcg_gen_ext16u_i32(tmp, tmp);
3665 if (dp) {
3666 gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
3667 cpu_env);
3668 } else {
3669 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
3670 cpu_env);
3671 }
3672 tcg_temp_free_i32(tmp);
3673 break;
3674 case 5:
3675 tmp = gen_vfp_mrs();
3676 tcg_gen_shri_i32(tmp, tmp, 16);
3677 if (dp) {
3678 gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
3679 cpu_env);
3680 } else {
3681 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
3682 cpu_env);
3683 }
3684 tcg_temp_free_i32(tmp);
3685 break;
3686 case 6:
3687 tmp = tcg_temp_new_i32();
3688 if (dp) {
3689 gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
3690 cpu_env);
3691 } else {
3692 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
3693 cpu_env);
3694 }
3695 gen_mov_F0_vreg(0, rd);
3696 tmp2 = gen_vfp_mrs();
3697 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
3698 tcg_gen_or_i32(tmp, tmp, tmp2);
3699 tcg_temp_free_i32(tmp2);
3700 gen_vfp_msr(tmp);
3701 break;
3702 case 7:
3703 tmp = tcg_temp_new_i32();
3704 if (dp) {
3705 gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
3706 cpu_env);
3707 } else {
3708 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
3709 cpu_env);
3710 }
3711 tcg_gen_shli_i32(tmp, tmp, 16);
3712 gen_mov_F0_vreg(0, rd);
3713 tmp2 = gen_vfp_mrs();
3714 tcg_gen_ext16u_i32(tmp2, tmp2);
3715 tcg_gen_or_i32(tmp, tmp, tmp2);
3716 tcg_temp_free_i32(tmp2);
3717 gen_vfp_msr(tmp);
3718 break;
3719 case 8:
3720 gen_vfp_cmp(dp);
3721 break;
3722 case 9:
3723 gen_vfp_cmpe(dp);
3724 break;
3725 case 10:
3726 gen_vfp_cmp(dp);
3727 break;
3728 case 11:
3729 gen_vfp_F1_ld0(dp);
3730 gen_vfp_cmpe(dp);
3731 break;
3732 case 12:
3733 {
3734 TCGv_ptr fpst = get_fpstatus_ptr(0);
3735 if (dp) {
3736 gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
3737 } else {
3738 gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
3739 }
3740 tcg_temp_free_ptr(fpst);
3741 break;
3742 }
3743 case 13:
3744 {
3745 TCGv_ptr fpst = get_fpstatus_ptr(0);
3746 TCGv_i32 tcg_rmode;
3747 tcg_rmode = tcg_const_i32(float_round_to_zero);
3748 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3749 if (dp) {
3750 gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
3751 } else {
3752 gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
3753 }
3754 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3755 tcg_temp_free_i32(tcg_rmode);
3756 tcg_temp_free_ptr(fpst);
3757 break;
3758 }
3759 case 14:
3760 {
3761 TCGv_ptr fpst = get_fpstatus_ptr(0);
3762 if (dp) {
3763 gen_helper_rintd_exact(cpu_F0d, cpu_F0d, fpst);
3764 } else {
3765 gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpst);
3766 }
3767 tcg_temp_free_ptr(fpst);
3768 break;
3769 }
3770 case 15:
3771 if (dp)
3772 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3773 else
3774 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3775 break;
3776 case 16:
3777 gen_vfp_uito(dp, 0);
3778 break;
3779 case 17:
3780 gen_vfp_sito(dp, 0);
3781 break;
3782 case 20:
3783 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3784 return 1;
3785 }
3786 gen_vfp_shto(dp, 16 - rm, 0);
3787 break;
3788 case 21:
3789 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3790 return 1;
3791 }
3792 gen_vfp_slto(dp, 32 - rm, 0);
3793 break;
3794 case 22:
3795 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3796 return 1;
3797 }
3798 gen_vfp_uhto(dp, 16 - rm, 0);
3799 break;
3800 case 23:
3801 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3802 return 1;
3803 }
3804 gen_vfp_ulto(dp, 32 - rm, 0);
3805 break;
3806 case 24:
3807 gen_vfp_toui(dp, 0);
3808 break;
3809 case 25:
3810 gen_vfp_touiz(dp, 0);
3811 break;
3812 case 26:
3813 gen_vfp_tosi(dp, 0);
3814 break;
3815 case 27:
3816 gen_vfp_tosiz(dp, 0);
3817 break;
3818 case 28:
3819 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3820 return 1;
3821 }
3822 gen_vfp_tosh(dp, 16 - rm, 0);
3823 break;
3824 case 29:
3825 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3826 return 1;
3827 }
3828 gen_vfp_tosl(dp, 32 - rm, 0);
3829 break;
3830 case 30:
3831 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3832 return 1;
3833 }
3834 gen_vfp_touh(dp, 16 - rm, 0);
3835 break;
3836 case 31:
3837 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3838 return 1;
3839 }
3840 gen_vfp_toul(dp, 32 - rm, 0);
3841 break;
3842 default:
3843 return 1;
3844 }
3845 break;
3846 default:
3847 return 1;
3848 }
3849
3850
3851 if (op == 15 && (rn >= 8 && rn <= 11)) {
3852
3853 } else if (op == 15 && dp && ((rn & 0x1c) == 0x18 ||
3854 (rn & 0x1e) == 0x6)) {
3855
3856
3857
3858
3859 gen_mov_vreg_F0(0, rd);
3860 } else if (op == 15 && rn == 15) {
3861
3862 gen_mov_vreg_F0(!dp, rd);
3863 } else {
3864 gen_mov_vreg_F0(dp, rd);
3865 }
3866
3867
3868 if (veclen == 0)
3869 break;
3870
3871 if (op == 15 && delta_m == 0) {
3872
3873 while (veclen--) {
3874 rd = ((rd + delta_d) & (bank_mask - 1))
3875 | (rd & bank_mask);
3876 gen_mov_vreg_F0(dp, rd);
3877 }
3878 break;
3879 }
3880
3881 veclen--;
3882 rd = ((rd + delta_d) & (bank_mask - 1))
3883 | (rd & bank_mask);
3884
3885 if (op == 15) {
3886
3887 rm = ((rm + delta_m) & (bank_mask - 1))
3888 | (rm & bank_mask);
3889 gen_mov_F0_vreg(dp, rm);
3890 } else {
3891
3892 rn = ((rn + delta_d) & (bank_mask - 1))
3893 | (rn & bank_mask);
3894 gen_mov_F0_vreg(dp, rn);
3895 if (delta_m) {
3896 rm = ((rm + delta_m) & (bank_mask - 1))
3897 | (rm & bank_mask);
3898 gen_mov_F1_vreg(dp, rm);
3899 }
3900 }
3901 }
3902 }
3903 break;
3904 case 0xc:
3905 case 0xd:
3906 if ((insn & 0x03e00000) == 0x00400000) {
3907
3908 rn = (insn >> 16) & 0xf;
3909 rd = (insn >> 12) & 0xf;
3910 if (dp) {
3911 VFP_DREG_M(rm, insn);
3912 } else {
3913 rm = VFP_SREG_M(insn);
3914 }
3915
3916 if (insn & ARM_CP_RW_BIT) {
3917
3918 if (dp) {
3919 gen_mov_F0_vreg(0, rm * 2);
3920 tmp = gen_vfp_mrs();
3921 store_reg(s, rd, tmp);
3922 gen_mov_F0_vreg(0, rm * 2 + 1);
3923 tmp = gen_vfp_mrs();
3924 store_reg(s, rn, tmp);
3925 } else {
3926 gen_mov_F0_vreg(0, rm);
3927 tmp = gen_vfp_mrs();
3928 store_reg(s, rd, tmp);
3929 gen_mov_F0_vreg(0, rm + 1);
3930 tmp = gen_vfp_mrs();
3931 store_reg(s, rn, tmp);
3932 }
3933 } else {
3934
3935 if (dp) {
3936 tmp = load_reg(s, rd);
3937 gen_vfp_msr(tmp);
3938 gen_mov_vreg_F0(0, rm * 2);
3939 tmp = load_reg(s, rn);
3940 gen_vfp_msr(tmp);
3941 gen_mov_vreg_F0(0, rm * 2 + 1);
3942 } else {
3943 tmp = load_reg(s, rd);
3944 gen_vfp_msr(tmp);
3945 gen_mov_vreg_F0(0, rm);
3946 tmp = load_reg(s, rn);
3947 gen_vfp_msr(tmp);
3948 gen_mov_vreg_F0(0, rm + 1);
3949 }
3950 }
3951 } else {
3952
3953 rn = (insn >> 16) & 0xf;
3954 if (dp)
3955 VFP_DREG_D(rd, insn);
3956 else
3957 rd = VFP_SREG_D(insn);
3958 if ((insn & 0x01200000) == 0x01000000) {
3959
3960 offset = (insn & 0xff) << 2;
3961 if ((insn & (1 << 23)) == 0)
3962 offset = -offset;
3963 if (s->thumb && rn == 15) {
3964
3965 addr = tcg_temp_new_i32();
3966 tcg_gen_movi_i32(addr, s->pc & ~2);
3967 } else {
3968 addr = load_reg(s, rn);
3969 }
3970 tcg_gen_addi_i32(addr, addr, offset);
3971 if (insn & (1 << 20)) {
3972 gen_vfp_ld(s, dp, addr);
3973 gen_mov_vreg_F0(dp, rd);
3974 } else {
3975 gen_mov_F0_vreg(dp, rd);
3976 gen_vfp_st(s, dp, addr);
3977 }
3978 tcg_temp_free_i32(addr);
3979 } else {
3980
3981 int w = insn & (1 << 21);
3982 if (dp)
3983 n = (insn >> 1) & 0x7f;
3984 else
3985 n = insn & 0xff;
3986
3987 if (w && !(((insn >> 23) ^ (insn >> 24)) & 1)) {
3988
3989 return 1;
3990 }
3991 if (n == 0 || (rd + n) > 32 || (dp && n > 16)) {
3992
3993
3994
3995 return 1;
3996 }
3997 if (rn == 15 && w) {
3998
3999 return 1;
4000 }
4001
4002 if (s->thumb && rn == 15) {
4003
4004 addr = tcg_temp_new_i32();
4005 tcg_gen_movi_i32(addr, s->pc & ~2);
4006 } else {
4007 addr = load_reg(s, rn);
4008 }
4009 if (insn & (1 << 24))
4010 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
4011
4012 if (dp)
4013 offset = 8;
4014 else
4015 offset = 4;
4016 for (i = 0; i < n; i++) {
4017 if (insn & ARM_CP_RW_BIT) {
4018
4019 gen_vfp_ld(s, dp, addr);
4020 gen_mov_vreg_F0(dp, rd + i);
4021 } else {
4022
4023 gen_mov_F0_vreg(dp, rd + i);
4024 gen_vfp_st(s, dp, addr);
4025 }
4026 tcg_gen_addi_i32(addr, addr, offset);
4027 }
4028 if (w) {
4029
4030 if (insn & (1 << 24))
4031 offset = -offset * n;
4032 else if (dp && (insn & 1))
4033 offset = 4;
4034 else
4035 offset = 0;
4036
4037 if (offset != 0)
4038 tcg_gen_addi_i32(addr, addr, offset);
4039 store_reg(s, rn, addr);
4040 } else {
4041 tcg_temp_free_i32(addr);
4042 }
4043 }
4044 }
4045 break;
4046 default:
4047
4048 return 1;
4049 }
4050 return 0;
4051}
4052
4053static inline bool use_goto_tb(DisasContext *s, target_ulong dest)
4054{
4055#ifndef CONFIG_USER_ONLY
4056 return (s->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
4057 ((s->pc - 1) & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
4058#else
4059 return true;
4060#endif
4061}
4062
4063static inline void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
4064{
4065 if (use_goto_tb(s, dest)) {
4066 tcg_gen_goto_tb(n);
4067 gen_set_pc_im(s, dest);
4068 tcg_gen_exit_tb((uintptr_t)s->tb + n);
4069 } else {
4070 gen_set_pc_im(s, dest);
4071 tcg_gen_exit_tb(0);
4072 }
4073}
4074
4075static inline void gen_jmp (DisasContext *s, uint32_t dest)
4076{
4077 if (unlikely(s->singlestep_enabled || s->ss_active)) {
4078
4079 if (s->thumb)
4080 dest |= 1;
4081 gen_bx_im(s, dest);
4082 } else {
4083 gen_goto_tb(s, 0, dest);
4084 s->is_jmp = DISAS_TB_JUMP;
4085 }
4086}
4087
4088static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
4089{
4090 if (x)
4091 tcg_gen_sari_i32(t0, t0, 16);
4092 else
4093 gen_sxth(t0);
4094 if (y)
4095 tcg_gen_sari_i32(t1, t1, 16);
4096 else
4097 gen_sxth(t1);
4098 tcg_gen_mul_i32(t0, t0, t1);
4099}
4100
4101
4102static uint32_t msr_mask(DisasContext *s, int flags, int spsr)
4103{
4104 uint32_t mask;
4105
4106 mask = 0;
4107 if (flags & (1 << 0))
4108 mask |= 0xff;
4109 if (flags & (1 << 1))
4110 mask |= 0xff00;
4111 if (flags & (1 << 2))
4112 mask |= 0xff0000;
4113 if (flags & (1 << 3))
4114 mask |= 0xff000000;
4115
4116
4117 mask &= ~CPSR_RESERVED;
4118 if (!arm_dc_feature(s, ARM_FEATURE_V4T)) {
4119 mask &= ~CPSR_T;
4120 }
4121 if (!arm_dc_feature(s, ARM_FEATURE_V5)) {
4122 mask &= ~CPSR_Q;
4123 }
4124 if (!arm_dc_feature(s, ARM_FEATURE_V6)) {
4125 mask &= ~(CPSR_E | CPSR_GE);
4126 }
4127 if (!arm_dc_feature(s, ARM_FEATURE_THUMB2)) {
4128 mask &= ~CPSR_IT;
4129 }
4130
4131 if (!spsr) {
4132 mask &= ~(CPSR_EXEC | CPSR_RESERVED);
4133 }
4134
4135 if (IS_USER(s))
4136 mask &= CPSR_USER;
4137 return mask;
4138}
4139
4140
4141static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv_i32 t0)
4142{
4143 TCGv_i32 tmp;
4144 if (spsr) {
4145
4146 if (IS_USER(s))
4147 return 1;
4148
4149 tmp = load_cpu_field(spsr);
4150 tcg_gen_andi_i32(tmp, tmp, ~mask);
4151 tcg_gen_andi_i32(t0, t0, mask);
4152 tcg_gen_or_i32(tmp, tmp, t0);
4153 store_cpu_field(tmp, spsr);
4154 } else {
4155 gen_set_cpsr(t0, mask);
4156 }
4157 tcg_temp_free_i32(t0);
4158 gen_lookup_tb(s);
4159 return 0;
4160}
4161
4162
4163static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
4164{
4165 TCGv_i32 tmp;
4166 tmp = tcg_temp_new_i32();
4167 tcg_gen_movi_i32(tmp, val);
4168 return gen_set_psr(s, mask, spsr, tmp);
4169}
4170
4171static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
4172 int *tgtmode, int *regno)
4173{
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193 int exc_target = default_exception_el(s);
4194
4195
4196
4197
4198 if (!arm_dc_feature(s, ARM_FEATURE_V8) &&
4199 !arm_dc_feature(s, ARM_FEATURE_EL2)) {
4200 goto undef;
4201 }
4202
4203 if (IS_USER(s) || rn == 15) {
4204 goto undef;
4205 }
4206
4207
4208
4209
4210 if (r) {
4211
4212 switch (sysm) {
4213 case 0xe:
4214 *tgtmode = ARM_CPU_MODE_FIQ;
4215 break;
4216 case 0x10:
4217 *tgtmode = ARM_CPU_MODE_IRQ;
4218 break;
4219 case 0x12:
4220 *tgtmode = ARM_CPU_MODE_SVC;
4221 break;
4222 case 0x14:
4223 *tgtmode = ARM_CPU_MODE_ABT;
4224 break;
4225 case 0x16:
4226 *tgtmode = ARM_CPU_MODE_UND;
4227 break;
4228 case 0x1c:
4229 *tgtmode = ARM_CPU_MODE_MON;
4230 break;
4231 case 0x1e:
4232 *tgtmode = ARM_CPU_MODE_HYP;
4233 break;
4234 default:
4235 goto undef;
4236 }
4237
4238 *regno = 16;
4239 } else {
4240
4241 switch (sysm) {
4242 case 0x0 ... 0x6:
4243 *tgtmode = ARM_CPU_MODE_USR;
4244 *regno = sysm + 8;
4245 break;
4246 case 0x8 ... 0xe:
4247 *tgtmode = ARM_CPU_MODE_FIQ;
4248 *regno = sysm;
4249 break;
4250 case 0x10 ... 0x11:
4251 *tgtmode = ARM_CPU_MODE_IRQ;
4252 *regno = sysm & 1 ? 13 : 14;
4253 break;
4254 case 0x12 ... 0x13:
4255 *tgtmode = ARM_CPU_MODE_SVC;
4256 *regno = sysm & 1 ? 13 : 14;
4257 break;
4258 case 0x14 ... 0x15:
4259 *tgtmode = ARM_CPU_MODE_ABT;
4260 *regno = sysm & 1 ? 13 : 14;
4261 break;
4262 case 0x16 ... 0x17:
4263 *tgtmode = ARM_CPU_MODE_UND;
4264 *regno = sysm & 1 ? 13 : 14;
4265 break;
4266 case 0x1c ... 0x1d:
4267 *tgtmode = ARM_CPU_MODE_MON;
4268 *regno = sysm & 1 ? 13 : 14;
4269 break;
4270 case 0x1e ... 0x1f:
4271 *tgtmode = ARM_CPU_MODE_HYP;
4272
4273 *regno = sysm & 1 ? 13 : 17;
4274 break;
4275 default:
4276 goto undef;
4277 }
4278 }
4279
4280
4281
4282
4283 switch (*tgtmode) {
4284 case ARM_CPU_MODE_MON:
4285 if (!arm_dc_feature(s, ARM_FEATURE_EL3) || s->ns) {
4286 goto undef;
4287 }
4288 if (s->current_el == 1) {
4289
4290
4291
4292 exc_target = 3;
4293 goto undef;
4294 }
4295 break;
4296 case ARM_CPU_MODE_HYP:
4297
4298
4299
4300 if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_el < 3) {
4301 goto undef;
4302 }
4303 break;
4304 default:
4305 break;
4306 }
4307
4308 return true;
4309
4310undef:
4311
4312 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(), exc_target);
4313 return false;
4314}
4315
4316static void gen_msr_banked(DisasContext *s, int r, int sysm, int rn)
4317{
4318 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
4319 int tgtmode = 0, regno = 0;
4320
4321 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, ®no)) {
4322 return;
4323 }
4324
4325
4326 gen_set_condexec(s);
4327 gen_set_pc_im(s, s->pc - 4);
4328 tcg_reg = load_reg(s, rn);
4329 tcg_tgtmode = tcg_const_i32(tgtmode);
4330 tcg_regno = tcg_const_i32(regno);
4331 gen_helper_msr_banked(cpu_env, tcg_reg, tcg_tgtmode, tcg_regno);
4332 tcg_temp_free_i32(tcg_tgtmode);
4333 tcg_temp_free_i32(tcg_regno);
4334 tcg_temp_free_i32(tcg_reg);
4335 s->is_jmp = DISAS_UPDATE;
4336}
4337
4338static void gen_mrs_banked(DisasContext *s, int r, int sysm, int rn)
4339{
4340 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
4341 int tgtmode = 0, regno = 0;
4342
4343 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, ®no)) {
4344 return;
4345 }
4346
4347
4348 gen_set_condexec(s);
4349 gen_set_pc_im(s, s->pc - 4);
4350 tcg_reg = tcg_temp_new_i32();
4351 tcg_tgtmode = tcg_const_i32(tgtmode);
4352 tcg_regno = tcg_const_i32(regno);
4353 gen_helper_mrs_banked(tcg_reg, cpu_env, tcg_tgtmode, tcg_regno);
4354 tcg_temp_free_i32(tcg_tgtmode);
4355 tcg_temp_free_i32(tcg_regno);
4356 store_reg(s, rn, tcg_reg);
4357 s->is_jmp = DISAS_UPDATE;
4358}
4359
4360
4361static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
4362{
4363 TCGv_i32 tmp;
4364 store_reg(s, 15, pc);
4365 tmp = load_cpu_field(spsr);
4366 gen_helper_cpsr_write_eret(cpu_env, tmp);
4367 tcg_temp_free_i32(tmp);
4368 s->is_jmp = DISAS_JUMP;
4369}
4370
4371
4372static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
4373{
4374 gen_helper_cpsr_write_eret(cpu_env, cpsr);
4375 tcg_temp_free_i32(cpsr);
4376 store_reg(s, 15, pc);
4377 s->is_jmp = DISAS_JUMP;
4378}
4379
4380static void gen_nop_hint(DisasContext *s, int val)
4381{
4382 switch (val) {
4383 case 1:
4384 gen_set_pc_im(s, s->pc);
4385 s->is_jmp = DISAS_YIELD;
4386 break;
4387 case 3:
4388 gen_set_pc_im(s, s->pc);
4389 s->is_jmp = DISAS_WFI;
4390 break;
4391 case 2:
4392 gen_set_pc_im(s, s->pc);
4393 s->is_jmp = DISAS_WFE;
4394 break;
4395 case 4:
4396 case 5:
4397
4398 default:
4399 break;
4400 }
4401}
4402
4403#define CPU_V001 cpu_V0, cpu_V0, cpu_V1
4404
4405static inline void gen_neon_add(int size, TCGv_i32 t0, TCGv_i32 t1)
4406{
4407 switch (size) {
4408 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
4409 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
4410 case 2: tcg_gen_add_i32(t0, t0, t1); break;
4411 default: abort();
4412 }
4413}
4414
4415static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1)
4416{
4417 switch (size) {
4418 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
4419 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
4420 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
4421 default: return;
4422 }
4423}
4424
4425
4426#define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
4427#define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
4428#define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
4429#define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
4430
4431#define GEN_NEON_INTEGER_OP_ENV(name) do { \
4432 switch ((size << 1) | u) { \
4433 case 0: \
4434 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
4435 break; \
4436 case 1: \
4437 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
4438 break; \
4439 case 2: \
4440 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
4441 break; \
4442 case 3: \
4443 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
4444 break; \
4445 case 4: \
4446 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
4447 break; \
4448 case 5: \
4449 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
4450 break; \
4451 default: return 1; \
4452 }} while (0)
4453
4454#define GEN_NEON_INTEGER_OP(name) do { \
4455 switch ((size << 1) | u) { \
4456 case 0: \
4457 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
4458 break; \
4459 case 1: \
4460 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
4461 break; \
4462 case 2: \
4463 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
4464 break; \
4465 case 3: \
4466 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
4467 break; \
4468 case 4: \
4469 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
4470 break; \
4471 case 5: \
4472 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
4473 break; \
4474 default: return 1; \
4475 }} while (0)
4476
4477static TCGv_i32 neon_load_scratch(int scratch)
4478{
4479 TCGv_i32 tmp = tcg_temp_new_i32();
4480 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
4481 return tmp;
4482}
4483
4484static void neon_store_scratch(int scratch, TCGv_i32 var)
4485{
4486 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
4487 tcg_temp_free_i32(var);
4488}
4489
4490static inline TCGv_i32 neon_get_scalar(int size, int reg)
4491{
4492 TCGv_i32 tmp;
4493 if (size == 1) {
4494 tmp = neon_load_reg(reg & 7, reg >> 4);
4495 if (reg & 8) {
4496 gen_neon_dup_high16(tmp);
4497 } else {
4498 gen_neon_dup_low16(tmp);
4499 }
4500 } else {
4501 tmp = neon_load_reg(reg & 15, reg >> 4);
4502 }
4503 return tmp;
4504}
4505
4506static int gen_neon_unzip(int rd, int rm, int size, int q)
4507{
4508 TCGv_i32 tmp, tmp2;
4509 if (!q && size == 2) {
4510 return 1;
4511 }
4512 tmp = tcg_const_i32(rd);
4513 tmp2 = tcg_const_i32(rm);
4514 if (q) {
4515 switch (size) {
4516 case 0:
4517 gen_helper_neon_qunzip8(cpu_env, tmp, tmp2);
4518 break;
4519 case 1:
4520 gen_helper_neon_qunzip16(cpu_env, tmp, tmp2);
4521 break;
4522 case 2:
4523 gen_helper_neon_qunzip32(cpu_env, tmp, tmp2);
4524 break;
4525 default:
4526 abort();
4527 }
4528 } else {
4529 switch (size) {
4530 case 0:
4531 gen_helper_neon_unzip8(cpu_env, tmp, tmp2);
4532 break;
4533 case 1:
4534 gen_helper_neon_unzip16(cpu_env, tmp, tmp2);
4535 break;
4536 default:
4537 abort();
4538 }
4539 }
4540 tcg_temp_free_i32(tmp);
4541 tcg_temp_free_i32(tmp2);
4542 return 0;
4543}
4544
4545static int gen_neon_zip(int rd, int rm, int size, int q)
4546{
4547 TCGv_i32 tmp, tmp2;
4548 if (!q && size == 2) {
4549 return 1;
4550 }
4551 tmp = tcg_const_i32(rd);
4552 tmp2 = tcg_const_i32(rm);
4553 if (q) {
4554 switch (size) {
4555 case 0:
4556 gen_helper_neon_qzip8(cpu_env, tmp, tmp2);
4557 break;
4558 case 1:
4559 gen_helper_neon_qzip16(cpu_env, tmp, tmp2);
4560 break;
4561 case 2:
4562 gen_helper_neon_qzip32(cpu_env, tmp, tmp2);
4563 break;
4564 default:
4565 abort();
4566 }
4567 } else {
4568 switch (size) {
4569 case 0:
4570 gen_helper_neon_zip8(cpu_env, tmp, tmp2);
4571 break;
4572 case 1:
4573 gen_helper_neon_zip16(cpu_env, tmp, tmp2);
4574 break;
4575 default:
4576 abort();
4577 }
4578 }
4579 tcg_temp_free_i32(tmp);
4580 tcg_temp_free_i32(tmp2);
4581 return 0;
4582}
4583
4584static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1)
4585{
4586 TCGv_i32 rd, tmp;
4587
4588 rd = tcg_temp_new_i32();
4589 tmp = tcg_temp_new_i32();
4590
4591 tcg_gen_shli_i32(rd, t0, 8);
4592 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
4593 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
4594 tcg_gen_or_i32(rd, rd, tmp);
4595
4596 tcg_gen_shri_i32(t1, t1, 8);
4597 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
4598 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
4599 tcg_gen_or_i32(t1, t1, tmp);
4600 tcg_gen_mov_i32(t0, rd);
4601
4602 tcg_temp_free_i32(tmp);
4603 tcg_temp_free_i32(rd);
4604}
4605
4606static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
4607{
4608 TCGv_i32 rd, tmp;
4609
4610 rd = tcg_temp_new_i32();
4611 tmp = tcg_temp_new_i32();
4612
4613 tcg_gen_shli_i32(rd, t0, 16);
4614 tcg_gen_andi_i32(tmp, t1, 0xffff);
4615 tcg_gen_or_i32(rd, rd, tmp);
4616 tcg_gen_shri_i32(t1, t1, 16);
4617 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
4618 tcg_gen_or_i32(t1, t1, tmp);
4619 tcg_gen_mov_i32(t0, rd);
4620
4621 tcg_temp_free_i32(tmp);
4622 tcg_temp_free_i32(rd);
4623}
4624
4625
4626static struct {
4627 int nregs;
4628 int interleave;
4629 int spacing;
4630} neon_ls_element_type[11] = {
4631 {4, 4, 1},
4632 {4, 4, 2},
4633 {4, 1, 1},
4634 {4, 2, 1},
4635 {3, 3, 1},
4636 {3, 3, 2},
4637 {3, 1, 1},
4638 {1, 1, 1},
4639 {2, 2, 1},
4640 {2, 2, 2},
4641 {2, 1, 1}
4642};
4643
4644
4645
4646static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
4647{
4648 int rd, rn, rm;
4649 int op;
4650 int nregs;
4651 int interleave;
4652 int spacing;
4653 int stride;
4654 int size;
4655 int reg;
4656 int pass;
4657 int load;
4658 int shift;
4659 int n;
4660 TCGv_i32 addr;
4661 TCGv_i32 tmp;
4662 TCGv_i32 tmp2;
4663 TCGv_i64 tmp64;
4664
4665
4666
4667
4668
4669 if (s->fp_excp_el) {
4670 gen_exception_insn(s, 4, EXCP_UDEF,
4671 syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
4672 return 0;
4673 }
4674
4675 if (!s->vfp_enabled)
4676 return 1;
4677 VFP_DREG_D(rd, insn);
4678 rn = (insn >> 16) & 0xf;
4679 rm = insn & 0xf;
4680 load = (insn & (1 << 21)) != 0;
4681 if ((insn & (1 << 23)) == 0) {
4682
4683 op = (insn >> 8) & 0xf;
4684 size = (insn >> 6) & 3;
4685 if (op > 10)
4686 return 1;
4687
4688 switch (op & 0xc) {
4689 case 4:
4690 if (((insn >> 5) & 1) == 1) {
4691 return 1;
4692 }
4693 break;
4694 case 8:
4695 if (((insn >> 4) & 3) == 3) {
4696 return 1;
4697 }
4698 break;
4699 default:
4700 break;
4701 }
4702 nregs = neon_ls_element_type[op].nregs;
4703 interleave = neon_ls_element_type[op].interleave;
4704 spacing = neon_ls_element_type[op].spacing;
4705 if (size == 3 && (interleave | spacing) != 1)
4706 return 1;
4707 addr = tcg_temp_new_i32();
4708 load_reg_var(s, addr, rn);
4709 stride = (1 << size) * interleave;
4710 for (reg = 0; reg < nregs; reg++) {
4711 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
4712 load_reg_var(s, addr, rn);
4713 tcg_gen_addi_i32(addr, addr, (1 << size) * reg);
4714 } else if (interleave == 2 && nregs == 4 && reg == 2) {
4715 load_reg_var(s, addr, rn);
4716 tcg_gen_addi_i32(addr, addr, 1 << size);
4717 }
4718 if (size == 3) {
4719 tmp64 = tcg_temp_new_i64();
4720 if (load) {
4721 gen_aa32_ld64(s, tmp64, addr, get_mem_index(s));
4722 neon_store_reg64(tmp64, rd);
4723 } else {
4724 neon_load_reg64(tmp64, rd);
4725 gen_aa32_st64(s, tmp64, addr, get_mem_index(s));
4726 }
4727 tcg_temp_free_i64(tmp64);
4728 tcg_gen_addi_i32(addr, addr, stride);
4729 } else {
4730 for (pass = 0; pass < 2; pass++) {
4731 if (size == 2) {
4732 if (load) {
4733 tmp = tcg_temp_new_i32();
4734 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
4735 neon_store_reg(rd, pass, tmp);
4736 } else {
4737 tmp = neon_load_reg(rd, pass);
4738 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
4739 tcg_temp_free_i32(tmp);
4740 }
4741 tcg_gen_addi_i32(addr, addr, stride);
4742 } else if (size == 1) {
4743 if (load) {
4744 tmp = tcg_temp_new_i32();
4745 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
4746 tcg_gen_addi_i32(addr, addr, stride);
4747 tmp2 = tcg_temp_new_i32();
4748 gen_aa32_ld16u(s, tmp2, addr, get_mem_index(s));
4749 tcg_gen_addi_i32(addr, addr, stride);
4750 tcg_gen_shli_i32(tmp2, tmp2, 16);
4751 tcg_gen_or_i32(tmp, tmp, tmp2);
4752 tcg_temp_free_i32(tmp2);
4753 neon_store_reg(rd, pass, tmp);
4754 } else {
4755 tmp = neon_load_reg(rd, pass);
4756 tmp2 = tcg_temp_new_i32();
4757 tcg_gen_shri_i32(tmp2, tmp, 16);
4758 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
4759 tcg_temp_free_i32(tmp);
4760 tcg_gen_addi_i32(addr, addr, stride);
4761 gen_aa32_st16(s, tmp2, addr, get_mem_index(s));
4762 tcg_temp_free_i32(tmp2);
4763 tcg_gen_addi_i32(addr, addr, stride);
4764 }
4765 } else {
4766 if (load) {
4767 TCGV_UNUSED_I32(tmp2);
4768 for (n = 0; n < 4; n++) {
4769 tmp = tcg_temp_new_i32();
4770 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
4771 tcg_gen_addi_i32(addr, addr, stride);
4772 if (n == 0) {
4773 tmp2 = tmp;
4774 } else {
4775 tcg_gen_shli_i32(tmp, tmp, n * 8);
4776 tcg_gen_or_i32(tmp2, tmp2, tmp);
4777 tcg_temp_free_i32(tmp);
4778 }
4779 }
4780 neon_store_reg(rd, pass, tmp2);
4781 } else {
4782 tmp2 = neon_load_reg(rd, pass);
4783 for (n = 0; n < 4; n++) {
4784 tmp = tcg_temp_new_i32();
4785 if (n == 0) {
4786 tcg_gen_mov_i32(tmp, tmp2);
4787 } else {
4788 tcg_gen_shri_i32(tmp, tmp2, n * 8);
4789 }
4790 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
4791 tcg_temp_free_i32(tmp);
4792 tcg_gen_addi_i32(addr, addr, stride);
4793 }
4794 tcg_temp_free_i32(tmp2);
4795 }
4796 }
4797 }
4798 }
4799 rd += spacing;
4800 }
4801 tcg_temp_free_i32(addr);
4802 stride = nregs * 8;
4803 } else {
4804 size = (insn >> 10) & 3;
4805 if (size == 3) {
4806
4807 int a = (insn >> 4) & 1;
4808 if (!load) {
4809 return 1;
4810 }
4811 size = (insn >> 6) & 3;
4812 nregs = ((insn >> 8) & 3) + 1;
4813
4814 if (size == 3) {
4815 if (nregs != 4 || a == 0) {
4816 return 1;
4817 }
4818
4819 size = 2;
4820 }
4821 if (nregs == 1 && a == 1 && size == 0) {
4822 return 1;
4823 }
4824 if (nregs == 3 && a == 1) {
4825 return 1;
4826 }
4827 addr = tcg_temp_new_i32();
4828 load_reg_var(s, addr, rn);
4829 if (nregs == 1) {
4830
4831 tmp = gen_load_and_replicate(s, addr, size);
4832 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
4833 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
4834 if (insn & (1 << 5)) {
4835 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 0));
4836 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 1));
4837 }
4838 tcg_temp_free_i32(tmp);
4839 } else {
4840
4841 stride = (insn & (1 << 5)) ? 2 : 1;
4842 for (reg = 0; reg < nregs; reg++) {
4843 tmp = gen_load_and_replicate(s, addr, size);
4844 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
4845 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
4846 tcg_temp_free_i32(tmp);
4847 tcg_gen_addi_i32(addr, addr, 1 << size);
4848 rd += stride;
4849 }
4850 }
4851 tcg_temp_free_i32(addr);
4852 stride = (1 << size) * nregs;
4853 } else {
4854
4855 int idx = (insn >> 4) & 0xf;
4856 pass = (insn >> 7) & 1;
4857 switch (size) {
4858 case 0:
4859 shift = ((insn >> 5) & 3) * 8;
4860 stride = 1;
4861 break;
4862 case 1:
4863 shift = ((insn >> 6) & 1) * 16;
4864 stride = (insn & (1 << 5)) ? 2 : 1;
4865 break;
4866 case 2:
4867 shift = 0;
4868 stride = (insn & (1 << 6)) ? 2 : 1;
4869 break;
4870 default:
4871 abort();
4872 }
4873 nregs = ((insn >> 8) & 3) + 1;
4874
4875 switch (nregs) {
4876 case 1:
4877 if (((idx & (1 << size)) != 0) ||
4878 (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
4879 return 1;
4880 }
4881 break;
4882 case 3:
4883 if ((idx & 1) != 0) {
4884 return 1;
4885 }
4886
4887 case 2:
4888 if (size == 2 && (idx & 2) != 0) {
4889 return 1;
4890 }
4891 break;
4892 case 4:
4893 if ((size == 2) && ((idx & 3) == 3)) {
4894 return 1;
4895 }
4896 break;
4897 default:
4898 abort();
4899 }
4900 if ((rd + stride * (nregs - 1)) > 31) {
4901
4902
4903
4904
4905 return 1;
4906 }
4907 addr = tcg_temp_new_i32();
4908 load_reg_var(s, addr, rn);
4909 for (reg = 0; reg < nregs; reg++) {
4910 if (load) {
4911 tmp = tcg_temp_new_i32();
4912 switch (size) {
4913 case 0:
4914 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
4915 break;
4916 case 1:
4917 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
4918 break;
4919 case 2:
4920 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
4921 break;
4922 default:
4923 abort();
4924 }
4925 if (size != 2) {
4926 tmp2 = neon_load_reg(rd, pass);
4927 tcg_gen_deposit_i32(tmp, tmp2, tmp,
4928 shift, size ? 16 : 8);
4929 tcg_temp_free_i32(tmp2);
4930 }
4931 neon_store_reg(rd, pass, tmp);
4932 } else {
4933 tmp = neon_load_reg(rd, pass);
4934 if (shift)
4935 tcg_gen_shri_i32(tmp, tmp, shift);
4936 switch (size) {
4937 case 0:
4938 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
4939 break;
4940 case 1:
4941 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
4942 break;
4943 case 2:
4944 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
4945 break;
4946 }
4947 tcg_temp_free_i32(tmp);
4948 }
4949 rd += stride;
4950 tcg_gen_addi_i32(addr, addr, 1 << size);
4951 }
4952 tcg_temp_free_i32(addr);
4953 stride = nregs * (1 << size);
4954 }
4955 }
4956 if (rm != 15) {
4957 TCGv_i32 base;
4958
4959 base = load_reg(s, rn);
4960 if (rm == 13) {
4961 tcg_gen_addi_i32(base, base, stride);
4962 } else {
4963 TCGv_i32 index;
4964 index = load_reg(s, rm);
4965 tcg_gen_add_i32(base, base, index);
4966 tcg_temp_free_i32(index);
4967 }
4968 store_reg(s, rn, base);
4969 }
4970 return 0;
4971}
4972
4973
4974static void gen_neon_bsl(TCGv_i32 dest, TCGv_i32 t, TCGv_i32 f, TCGv_i32 c)
4975{
4976 tcg_gen_and_i32(t, t, c);
4977 tcg_gen_andc_i32(f, f, c);
4978 tcg_gen_or_i32(dest, t, f);
4979}
4980
4981static inline void gen_neon_narrow(int size, TCGv_i32 dest, TCGv_i64 src)
4982{
4983 switch (size) {
4984 case 0: gen_helper_neon_narrow_u8(dest, src); break;
4985 case 1: gen_helper_neon_narrow_u16(dest, src); break;
4986 case 2: tcg_gen_extrl_i64_i32(dest, src); break;
4987 default: abort();
4988 }
4989}
4990
4991static inline void gen_neon_narrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
4992{
4993 switch (size) {
4994 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
4995 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
4996 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
4997 default: abort();
4998 }
4999}
5000
5001static inline void gen_neon_narrow_satu(int size, TCGv_i32 dest, TCGv_i64 src)
5002{
5003 switch (size) {
5004 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
5005 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
5006 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
5007 default: abort();
5008 }
5009}
5010
5011static inline void gen_neon_unarrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
5012{
5013 switch (size) {
5014 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
5015 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
5016 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
5017 default: abort();
5018 }
5019}
5020
5021static inline void gen_neon_shift_narrow(int size, TCGv_i32 var, TCGv_i32 shift,
5022 int q, int u)
5023{
5024 if (q) {
5025 if (u) {
5026 switch (size) {
5027 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
5028 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
5029 default: abort();
5030 }
5031 } else {
5032 switch (size) {
5033 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
5034 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
5035 default: abort();
5036 }
5037 }
5038 } else {
5039 if (u) {
5040 switch (size) {
5041 case 1: gen_helper_neon_shl_u16(var, var, shift); break;
5042 case 2: gen_helper_neon_shl_u32(var, var, shift); break;
5043 default: abort();
5044 }
5045 } else {
5046 switch (size) {
5047 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
5048 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
5049 default: abort();
5050 }
5051 }
5052 }
5053}
5054
5055static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
5056{
5057 if (u) {
5058 switch (size) {
5059 case 0: gen_helper_neon_widen_u8(dest, src); break;
5060 case 1: gen_helper_neon_widen_u16(dest, src); break;
5061 case 2: tcg_gen_extu_i32_i64(dest, src); break;
5062 default: abort();
5063 }
5064 } else {
5065 switch (size) {
5066 case 0: gen_helper_neon_widen_s8(dest, src); break;
5067 case 1: gen_helper_neon_widen_s16(dest, src); break;
5068 case 2: tcg_gen_ext_i32_i64(dest, src); break;
5069 default: abort();
5070 }
5071 }
5072 tcg_temp_free_i32(src);
5073}
5074
5075static inline void gen_neon_addl(int size)
5076{
5077 switch (size) {
5078 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
5079 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
5080 case 2: tcg_gen_add_i64(CPU_V001); break;
5081 default: abort();
5082 }
5083}
5084
5085static inline void gen_neon_subl(int size)
5086{
5087 switch (size) {
5088 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
5089 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
5090 case 2: tcg_gen_sub_i64(CPU_V001); break;
5091 default: abort();
5092 }
5093}
5094
5095static inline void gen_neon_negl(TCGv_i64 var, int size)
5096{
5097 switch (size) {
5098 case 0: gen_helper_neon_negl_u16(var, var); break;
5099 case 1: gen_helper_neon_negl_u32(var, var); break;
5100 case 2:
5101 tcg_gen_neg_i64(var, var);
5102 break;
5103 default: abort();
5104 }
5105}
5106
5107static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
5108{
5109 switch (size) {
5110 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
5111 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
5112 default: abort();
5113 }
5114}
5115
5116static inline void gen_neon_mull(TCGv_i64 dest, TCGv_i32 a, TCGv_i32 b,
5117 int size, int u)
5118{
5119 TCGv_i64 tmp;
5120
5121 switch ((size << 1) | u) {
5122 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
5123 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
5124 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
5125 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
5126 case 4:
5127 tmp = gen_muls_i64_i32(a, b);
5128 tcg_gen_mov_i64(dest, tmp);
5129 tcg_temp_free_i64(tmp);
5130 break;
5131 case 5:
5132 tmp = gen_mulu_i64_i32(a, b);
5133 tcg_gen_mov_i64(dest, tmp);
5134 tcg_temp_free_i64(tmp);
5135 break;
5136 default: abort();
5137 }
5138
5139
5140
5141 if (size < 2) {
5142 tcg_temp_free_i32(a);
5143 tcg_temp_free_i32(b);
5144 }
5145}
5146
5147static void gen_neon_narrow_op(int op, int u, int size,
5148 TCGv_i32 dest, TCGv_i64 src)
5149{
5150 if (op) {
5151 if (u) {
5152 gen_neon_unarrow_sats(size, dest, src);
5153 } else {
5154 gen_neon_narrow(size, dest, src);
5155 }
5156 } else {
5157 if (u) {
5158 gen_neon_narrow_satu(size, dest, src);
5159 } else {
5160 gen_neon_narrow_sats(size, dest, src);
5161 }
5162 }
5163}
5164
5165
5166
5167
5168
5169#define NEON_3R_VHADD 0
5170#define NEON_3R_VQADD 1
5171#define NEON_3R_VRHADD 2
5172#define NEON_3R_LOGIC 3
5173#define NEON_3R_VHSUB 4
5174#define NEON_3R_VQSUB 5
5175#define NEON_3R_VCGT 6
5176#define NEON_3R_VCGE 7
5177#define NEON_3R_VSHL 8
5178#define NEON_3R_VQSHL 9
5179#define NEON_3R_VRSHL 10
5180#define NEON_3R_VQRSHL 11
5181#define NEON_3R_VMAX 12
5182#define NEON_3R_VMIN 13
5183#define NEON_3R_VABD 14
5184#define NEON_3R_VABA 15
5185#define NEON_3R_VADD_VSUB 16
5186#define NEON_3R_VTST_VCEQ 17
5187#define NEON_3R_VML 18
5188#define NEON_3R_VMUL 19
5189#define NEON_3R_VPMAX 20
5190#define NEON_3R_VPMIN 21
5191#define NEON_3R_VQDMULH_VQRDMULH 22
5192#define NEON_3R_VPADD 23
5193#define NEON_3R_SHA 24
5194#define NEON_3R_VFM 25
5195#define NEON_3R_FLOAT_ARITH 26
5196#define NEON_3R_FLOAT_MULTIPLY 27
5197#define NEON_3R_FLOAT_CMP 28
5198#define NEON_3R_FLOAT_ACMP 29
5199#define NEON_3R_FLOAT_MINMAX 30
5200#define NEON_3R_FLOAT_MISC 31
5201
5202static const uint8_t neon_3r_sizes[] = {
5203 [NEON_3R_VHADD] = 0x7,
5204 [NEON_3R_VQADD] = 0xf,
5205 [NEON_3R_VRHADD] = 0x7,
5206 [NEON_3R_LOGIC] = 0xf,
5207 [NEON_3R_VHSUB] = 0x7,
5208 [NEON_3R_VQSUB] = 0xf,
5209 [NEON_3R_VCGT] = 0x7,
5210 [NEON_3R_VCGE] = 0x7,
5211 [NEON_3R_VSHL] = 0xf,
5212 [NEON_3R_VQSHL] = 0xf,
5213 [NEON_3R_VRSHL] = 0xf,
5214 [NEON_3R_VQRSHL] = 0xf,
5215 [NEON_3R_VMAX] = 0x7,
5216 [NEON_3R_VMIN] = 0x7,
5217 [NEON_3R_VABD] = 0x7,
5218 [NEON_3R_VABA] = 0x7,
5219 [NEON_3R_VADD_VSUB] = 0xf,
5220 [NEON_3R_VTST_VCEQ] = 0x7,
5221 [NEON_3R_VML] = 0x7,
5222 [NEON_3R_VMUL] = 0x7,
5223 [NEON_3R_VPMAX] = 0x7,
5224 [NEON_3R_VPMIN] = 0x7,
5225 [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
5226 [NEON_3R_VPADD] = 0x7,
5227 [NEON_3R_SHA] = 0xf,
5228 [NEON_3R_VFM] = 0x5,
5229 [NEON_3R_FLOAT_ARITH] = 0x5,
5230 [NEON_3R_FLOAT_MULTIPLY] = 0x5,
5231 [NEON_3R_FLOAT_CMP] = 0x5,
5232 [NEON_3R_FLOAT_ACMP] = 0x5,
5233 [NEON_3R_FLOAT_MINMAX] = 0x5,
5234 [NEON_3R_FLOAT_MISC] = 0x5,
5235};
5236
5237
5238
5239
5240
5241#define NEON_2RM_VREV64 0
5242#define NEON_2RM_VREV32 1
5243#define NEON_2RM_VREV16 2
5244#define NEON_2RM_VPADDL 4
5245#define NEON_2RM_VPADDL_U 5
5246#define NEON_2RM_AESE 6
5247#define NEON_2RM_AESMC 7
5248#define NEON_2RM_VCLS 8
5249#define NEON_2RM_VCLZ 9
5250#define NEON_2RM_VCNT 10
5251#define NEON_2RM_VMVN 11
5252#define NEON_2RM_VPADAL 12
5253#define NEON_2RM_VPADAL_U 13
5254#define NEON_2RM_VQABS 14
5255#define NEON_2RM_VQNEG 15
5256#define NEON_2RM_VCGT0 16
5257#define NEON_2RM_VCGE0 17
5258#define NEON_2RM_VCEQ0 18
5259#define NEON_2RM_VCLE0 19
5260#define NEON_2RM_VCLT0 20
5261#define NEON_2RM_SHA1H 21
5262#define NEON_2RM_VABS 22
5263#define NEON_2RM_VNEG 23
5264#define NEON_2RM_VCGT0_F 24
5265#define NEON_2RM_VCGE0_F 25
5266#define NEON_2RM_VCEQ0_F 26
5267#define NEON_2RM_VCLE0_F 27
5268#define NEON_2RM_VCLT0_F 28
5269#define NEON_2RM_VABS_F 30
5270#define NEON_2RM_VNEG_F 31
5271#define NEON_2RM_VSWP 32
5272#define NEON_2RM_VTRN 33
5273#define NEON_2RM_VUZP 34
5274#define NEON_2RM_VZIP 35
5275#define NEON_2RM_VMOVN 36
5276#define NEON_2RM_VQMOVN 37
5277#define NEON_2RM_VSHLL 38
5278#define NEON_2RM_SHA1SU1 39
5279#define NEON_2RM_VRINTN 40
5280#define NEON_2RM_VRINTX 41
5281#define NEON_2RM_VRINTA 42
5282#define NEON_2RM_VRINTZ 43
5283#define NEON_2RM_VCVT_F16_F32 44
5284#define NEON_2RM_VRINTM 45
5285#define NEON_2RM_VCVT_F32_F16 46
5286#define NEON_2RM_VRINTP 47
5287#define NEON_2RM_VCVTAU 48
5288#define NEON_2RM_VCVTAS 49
5289#define NEON_2RM_VCVTNU 50
5290#define NEON_2RM_VCVTNS 51
5291#define NEON_2RM_VCVTPU 52
5292#define NEON_2RM_VCVTPS 53
5293#define NEON_2RM_VCVTMU 54
5294#define NEON_2RM_VCVTMS 55
5295#define NEON_2RM_VRECPE 56
5296#define NEON_2RM_VRSQRTE 57
5297#define NEON_2RM_VRECPE_F 58
5298#define NEON_2RM_VRSQRTE_F 59
5299#define NEON_2RM_VCVT_FS 60
5300#define NEON_2RM_VCVT_FU 61
5301#define NEON_2RM_VCVT_SF 62
5302#define NEON_2RM_VCVT_UF 63
5303
5304static int neon_2rm_is_float_op(int op)
5305{
5306
5307 return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
5308 (op >= NEON_2RM_VRINTN && op <= NEON_2RM_VRINTZ) ||
5309 op == NEON_2RM_VRINTM ||
5310 (op >= NEON_2RM_VRINTP && op <= NEON_2RM_VCVTMS) ||
5311 op >= NEON_2RM_VRECPE_F);
5312}
5313
5314
5315
5316
5317
5318static const uint8_t neon_2rm_sizes[] = {
5319 [NEON_2RM_VREV64] = 0x7,
5320 [NEON_2RM_VREV32] = 0x3,
5321 [NEON_2RM_VREV16] = 0x1,
5322 [NEON_2RM_VPADDL] = 0x7,
5323 [NEON_2RM_VPADDL_U] = 0x7,
5324 [NEON_2RM_AESE] = 0x1,
5325 [NEON_2RM_AESMC] = 0x1,
5326 [NEON_2RM_VCLS] = 0x7,
5327 [NEON_2RM_VCLZ] = 0x7,
5328 [NEON_2RM_VCNT] = 0x1,
5329 [NEON_2RM_VMVN] = 0x1,
5330 [NEON_2RM_VPADAL] = 0x7,
5331 [NEON_2RM_VPADAL_U] = 0x7,
5332 [NEON_2RM_VQABS] = 0x7,
5333 [NEON_2RM_VQNEG] = 0x7,
5334 [NEON_2RM_VCGT0] = 0x7,
5335 [NEON_2RM_VCGE0] = 0x7,
5336 [NEON_2RM_VCEQ0] = 0x7,
5337 [NEON_2RM_VCLE0] = 0x7,
5338 [NEON_2RM_VCLT0] = 0x7,
5339 [NEON_2RM_SHA1H] = 0x4,
5340 [NEON_2RM_VABS] = 0x7,
5341 [NEON_2RM_VNEG] = 0x7,
5342 [NEON_2RM_VCGT0_F] = 0x4,
5343 [NEON_2RM_VCGE0_F] = 0x4,
5344 [NEON_2RM_VCEQ0_F] = 0x4,
5345 [NEON_2RM_VCLE0_F] = 0x4,
5346 [NEON_2RM_VCLT0_F] = 0x4,
5347 [NEON_2RM_VABS_F] = 0x4,
5348 [NEON_2RM_VNEG_F] = 0x4,
5349 [NEON_2RM_VSWP] = 0x1,
5350 [NEON_2RM_VTRN] = 0x7,
5351 [NEON_2RM_VUZP] = 0x7,
5352 [NEON_2RM_VZIP] = 0x7,
5353 [NEON_2RM_VMOVN] = 0x7,
5354 [NEON_2RM_VQMOVN] = 0x7,
5355 [NEON_2RM_VSHLL] = 0x7,
5356 [NEON_2RM_SHA1SU1] = 0x4,
5357 [NEON_2RM_VRINTN] = 0x4,
5358 [NEON_2RM_VRINTX] = 0x4,
5359 [NEON_2RM_VRINTA] = 0x4,
5360 [NEON_2RM_VRINTZ] = 0x4,
5361 [NEON_2RM_VCVT_F16_F32] = 0x2,
5362 [NEON_2RM_VRINTM] = 0x4,
5363 [NEON_2RM_VCVT_F32_F16] = 0x2,
5364 [NEON_2RM_VRINTP] = 0x4,
5365 [NEON_2RM_VCVTAU] = 0x4,
5366 [NEON_2RM_VCVTAS] = 0x4,
5367 [NEON_2RM_VCVTNU] = 0x4,
5368 [NEON_2RM_VCVTNS] = 0x4,
5369 [NEON_2RM_VCVTPU] = 0x4,
5370 [NEON_2RM_VCVTPS] = 0x4,
5371 [NEON_2RM_VCVTMU] = 0x4,
5372 [NEON_2RM_VCVTMS] = 0x4,
5373 [NEON_2RM_VRECPE] = 0x4,
5374 [NEON_2RM_VRSQRTE] = 0x4,
5375 [NEON_2RM_VRECPE_F] = 0x4,
5376 [NEON_2RM_VRSQRTE_F] = 0x4,
5377 [NEON_2RM_VCVT_FS] = 0x4,
5378 [NEON_2RM_VCVT_FU] = 0x4,
5379 [NEON_2RM_VCVT_SF] = 0x4,
5380 [NEON_2RM_VCVT_UF] = 0x4,
5381};
5382
5383
5384
5385
5386
5387
5388static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
5389{
5390 int op;
5391 int q;
5392 int rd, rn, rm;
5393 int size;
5394 int shift;
5395 int pass;
5396 int count;
5397 int pairwise;
5398 int u;
5399 uint32_t imm, mask;
5400 TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
5401 TCGv_i64 tmp64;
5402
5403
5404
5405
5406
5407 if (s->fp_excp_el) {
5408 gen_exception_insn(s, 4, EXCP_UDEF,
5409 syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
5410 return 0;
5411 }
5412
5413 if (!s->vfp_enabled)
5414 return 1;
5415 q = (insn & (1 << 6)) != 0;
5416 u = (insn >> 24) & 1;
5417 VFP_DREG_D(rd, insn);
5418 VFP_DREG_N(rn, insn);
5419 VFP_DREG_M(rm, insn);
5420 size = (insn >> 20) & 3;
5421 if ((insn & (1 << 23)) == 0) {
5422
5423 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
5424
5425 if ((neon_3r_sizes[op] & (1 << size)) == 0) {
5426 return 1;
5427 }
5428
5429
5430
5431 if (q && ((rd | rn | rm) & 1)) {
5432 return 1;
5433 }
5434
5435
5436
5437
5438
5439 if (op == NEON_3R_SHA) {
5440 if (!q) {
5441 return 1;
5442 }
5443 if (!u) {
5444 if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA1)) {
5445 return 1;
5446 }
5447 tmp = tcg_const_i32(rd);
5448 tmp2 = tcg_const_i32(rn);
5449 tmp3 = tcg_const_i32(rm);
5450 tmp4 = tcg_const_i32(size);
5451 gen_helper_crypto_sha1_3reg(cpu_env, tmp, tmp2, tmp3, tmp4);
5452 tcg_temp_free_i32(tmp4);
5453 } else {
5454 if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA256) || size == 3) {
5455 return 1;
5456 }
5457 tmp = tcg_const_i32(rd);
5458 tmp2 = tcg_const_i32(rn);
5459 tmp3 = tcg_const_i32(rm);
5460 switch (size) {
5461 case 0:
5462 gen_helper_crypto_sha256h(cpu_env, tmp, tmp2, tmp3);
5463 break;
5464 case 1:
5465 gen_helper_crypto_sha256h2(cpu_env, tmp, tmp2, tmp3);
5466 break;
5467 case 2:
5468 gen_helper_crypto_sha256su1(cpu_env, tmp, tmp2, tmp3);
5469 break;
5470 }
5471 }
5472 tcg_temp_free_i32(tmp);
5473 tcg_temp_free_i32(tmp2);
5474 tcg_temp_free_i32(tmp3);
5475 return 0;
5476 }
5477 if (size == 3 && op != NEON_3R_LOGIC) {
5478
5479 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5480 neon_load_reg64(cpu_V0, rn + pass);
5481 neon_load_reg64(cpu_V1, rm + pass);
5482 switch (op) {
5483 case NEON_3R_VQADD:
5484 if (u) {
5485 gen_helper_neon_qadd_u64(cpu_V0, cpu_env,
5486 cpu_V0, cpu_V1);
5487 } else {
5488 gen_helper_neon_qadd_s64(cpu_V0, cpu_env,
5489 cpu_V0, cpu_V1);
5490 }
5491 break;
5492 case NEON_3R_VQSUB:
5493 if (u) {
5494 gen_helper_neon_qsub_u64(cpu_V0, cpu_env,
5495 cpu_V0, cpu_V1);
5496 } else {
5497 gen_helper_neon_qsub_s64(cpu_V0, cpu_env,
5498 cpu_V0, cpu_V1);
5499 }
5500 break;
5501 case NEON_3R_VSHL:
5502 if (u) {
5503 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
5504 } else {
5505 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
5506 }
5507 break;
5508 case NEON_3R_VQSHL:
5509 if (u) {
5510 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
5511 cpu_V1, cpu_V0);
5512 } else {
5513 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
5514 cpu_V1, cpu_V0);
5515 }
5516 break;
5517 case NEON_3R_VRSHL:
5518 if (u) {
5519 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
5520 } else {
5521 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
5522 }
5523 break;
5524 case NEON_3R_VQRSHL:
5525 if (u) {
5526 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
5527 cpu_V1, cpu_V0);
5528 } else {
5529 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
5530 cpu_V1, cpu_V0);
5531 }
5532 break;
5533 case NEON_3R_VADD_VSUB:
5534 if (u) {
5535 tcg_gen_sub_i64(CPU_V001);
5536 } else {
5537 tcg_gen_add_i64(CPU_V001);
5538 }
5539 break;
5540 default:
5541 abort();
5542 }
5543 neon_store_reg64(cpu_V0, rd + pass);
5544 }
5545 return 0;
5546 }
5547 pairwise = 0;
5548 switch (op) {
5549 case NEON_3R_VSHL:
5550 case NEON_3R_VQSHL:
5551 case NEON_3R_VRSHL:
5552 case NEON_3R_VQRSHL:
5553 {
5554 int rtmp;
5555
5556 rtmp = rn;
5557 rn = rm;
5558 rm = rtmp;
5559 }
5560 break;
5561 case NEON_3R_VPADD:
5562 if (u) {
5563 return 1;
5564 }
5565
5566 case NEON_3R_VPMAX:
5567 case NEON_3R_VPMIN:
5568 pairwise = 1;
5569 break;
5570 case NEON_3R_FLOAT_ARITH:
5571 pairwise = (u && size < 2);
5572 break;
5573 case NEON_3R_FLOAT_MINMAX:
5574 pairwise = u;
5575 break;
5576 case NEON_3R_FLOAT_CMP:
5577 if (!u && size) {
5578
5579 return 1;
5580 }
5581 break;
5582 case NEON_3R_FLOAT_ACMP:
5583 if (!u) {
5584 return 1;
5585 }
5586 break;
5587 case NEON_3R_FLOAT_MISC:
5588
5589 if (u && !arm_dc_feature(s, ARM_FEATURE_V8)) {
5590 return 1;
5591 }
5592 break;
5593 case NEON_3R_VMUL:
5594 if (u && (size != 0)) {
5595
5596 return 1;
5597 }
5598 break;
5599 case NEON_3R_VFM:
5600 if (!arm_dc_feature(s, ARM_FEATURE_VFP4) || u) {
5601 return 1;
5602 }
5603 break;
5604 default:
5605 break;
5606 }
5607
5608 if (pairwise && q) {
5609
5610 return 1;
5611 }
5612
5613 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5614
5615 if (pairwise) {
5616
5617 if (pass < 1) {
5618 tmp = neon_load_reg(rn, 0);
5619 tmp2 = neon_load_reg(rn, 1);
5620 } else {
5621 tmp = neon_load_reg(rm, 0);
5622 tmp2 = neon_load_reg(rm, 1);
5623 }
5624 } else {
5625
5626 tmp = neon_load_reg(rn, pass);
5627 tmp2 = neon_load_reg(rm, pass);
5628 }
5629 switch (op) {
5630 case NEON_3R_VHADD:
5631 GEN_NEON_INTEGER_OP(hadd);
5632 break;
5633 case NEON_3R_VQADD:
5634 GEN_NEON_INTEGER_OP_ENV(qadd);
5635 break;
5636 case NEON_3R_VRHADD:
5637 GEN_NEON_INTEGER_OP(rhadd);
5638 break;
5639 case NEON_3R_LOGIC:
5640 switch ((u << 2) | size) {
5641 case 0:
5642 tcg_gen_and_i32(tmp, tmp, tmp2);
5643 break;
5644 case 1:
5645 tcg_gen_andc_i32(tmp, tmp, tmp2);
5646 break;
5647 case 2:
5648 tcg_gen_or_i32(tmp, tmp, tmp2);
5649 break;
5650 case 3:
5651 tcg_gen_orc_i32(tmp, tmp, tmp2);
5652 break;
5653 case 4:
5654 tcg_gen_xor_i32(tmp, tmp, tmp2);
5655 break;
5656 case 5:
5657 tmp3 = neon_load_reg(rd, pass);
5658 gen_neon_bsl(tmp, tmp, tmp2, tmp3);
5659 tcg_temp_free_i32(tmp3);
5660 break;
5661 case 6:
5662 tmp3 = neon_load_reg(rd, pass);
5663 gen_neon_bsl(tmp, tmp, tmp3, tmp2);
5664 tcg_temp_free_i32(tmp3);
5665 break;
5666 case 7:
5667 tmp3 = neon_load_reg(rd, pass);
5668 gen_neon_bsl(tmp, tmp3, tmp, tmp2);
5669 tcg_temp_free_i32(tmp3);
5670 break;
5671 }
5672 break;
5673 case NEON_3R_VHSUB:
5674 GEN_NEON_INTEGER_OP(hsub);
5675 break;
5676 case NEON_3R_VQSUB:
5677 GEN_NEON_INTEGER_OP_ENV(qsub);
5678 break;
5679 case NEON_3R_VCGT:
5680 GEN_NEON_INTEGER_OP(cgt);
5681 break;
5682 case NEON_3R_VCGE:
5683 GEN_NEON_INTEGER_OP(cge);
5684 break;
5685 case NEON_3R_VSHL:
5686 GEN_NEON_INTEGER_OP(shl);
5687 break;
5688 case NEON_3R_VQSHL:
5689 GEN_NEON_INTEGER_OP_ENV(qshl);
5690 break;
5691 case NEON_3R_VRSHL:
5692 GEN_NEON_INTEGER_OP(rshl);
5693 break;
5694 case NEON_3R_VQRSHL:
5695 GEN_NEON_INTEGER_OP_ENV(qrshl);
5696 break;
5697 case NEON_3R_VMAX:
5698 GEN_NEON_INTEGER_OP(max);
5699 break;
5700 case NEON_3R_VMIN:
5701 GEN_NEON_INTEGER_OP(min);
5702 break;
5703 case NEON_3R_VABD:
5704 GEN_NEON_INTEGER_OP(abd);
5705 break;
5706 case NEON_3R_VABA:
5707 GEN_NEON_INTEGER_OP(abd);
5708 tcg_temp_free_i32(tmp2);
5709 tmp2 = neon_load_reg(rd, pass);
5710 gen_neon_add(size, tmp, tmp2);
5711 break;
5712 case NEON_3R_VADD_VSUB:
5713 if (!u) {
5714 gen_neon_add(size, tmp, tmp2);
5715 } else {
5716 switch (size) {
5717 case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
5718 case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
5719 case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
5720 default: abort();
5721 }
5722 }
5723 break;
5724 case NEON_3R_VTST_VCEQ:
5725 if (!u) {
5726 switch (size) {
5727 case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
5728 case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
5729 case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
5730 default: abort();
5731 }
5732 } else {
5733 switch (size) {
5734 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
5735 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
5736 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
5737 default: abort();
5738 }
5739 }
5740 break;
5741 case NEON_3R_VML:
5742 switch (size) {
5743 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5744 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5745 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5746 default: abort();
5747 }
5748 tcg_temp_free_i32(tmp2);
5749 tmp2 = neon_load_reg(rd, pass);
5750 if (u) {
5751 gen_neon_rsb(size, tmp, tmp2);
5752 } else {
5753 gen_neon_add(size, tmp, tmp2);
5754 }
5755 break;
5756 case NEON_3R_VMUL:
5757 if (u) {
5758 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
5759 } else {
5760 switch (size) {
5761 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5762 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5763 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5764 default: abort();
5765 }
5766 }
5767 break;
5768 case NEON_3R_VPMAX:
5769 GEN_NEON_INTEGER_OP(pmax);
5770 break;
5771 case NEON_3R_VPMIN:
5772 GEN_NEON_INTEGER_OP(pmin);
5773 break;
5774 case NEON_3R_VQDMULH_VQRDMULH:
5775 if (!u) {
5776 switch (size) {
5777 case 1:
5778 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5779 break;
5780 case 2:
5781 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5782 break;
5783 default: abort();
5784 }
5785 } else {
5786 switch (size) {
5787 case 1:
5788 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5789 break;
5790 case 2:
5791 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5792 break;
5793 default: abort();
5794 }
5795 }
5796 break;
5797 case NEON_3R_VPADD:
5798 switch (size) {
5799 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
5800 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
5801 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
5802 default: abort();
5803 }
5804 break;
5805 case NEON_3R_FLOAT_ARITH:
5806 {
5807 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5808 switch ((u << 2) | size) {
5809 case 0:
5810 case 4:
5811 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
5812 break;
5813 case 2:
5814 gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
5815 break;
5816 case 6:
5817 gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
5818 break;
5819 default:
5820 abort();
5821 }
5822 tcg_temp_free_ptr(fpstatus);
5823 break;
5824 }
5825 case NEON_3R_FLOAT_MULTIPLY:
5826 {
5827 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5828 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
5829 if (!u) {
5830 tcg_temp_free_i32(tmp2);
5831 tmp2 = neon_load_reg(rd, pass);
5832 if (size == 0) {
5833 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
5834 } else {
5835 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
5836 }
5837 }
5838 tcg_temp_free_ptr(fpstatus);
5839 break;
5840 }
5841 case NEON_3R_FLOAT_CMP:
5842 {
5843 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5844 if (!u) {
5845 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
5846 } else {
5847 if (size == 0) {
5848 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
5849 } else {
5850 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
5851 }
5852 }
5853 tcg_temp_free_ptr(fpstatus);
5854 break;
5855 }
5856 case NEON_3R_FLOAT_ACMP:
5857 {
5858 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5859 if (size == 0) {
5860 gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
5861 } else {
5862 gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
5863 }
5864 tcg_temp_free_ptr(fpstatus);
5865 break;
5866 }
5867 case NEON_3R_FLOAT_MINMAX:
5868 {
5869 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5870 if (size == 0) {
5871 gen_helper_vfp_maxs(tmp, tmp, tmp2, fpstatus);
5872 } else {
5873 gen_helper_vfp_mins(tmp, tmp, tmp2, fpstatus);
5874 }
5875 tcg_temp_free_ptr(fpstatus);
5876 break;
5877 }
5878 case NEON_3R_FLOAT_MISC:
5879 if (u) {
5880
5881 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5882 if (size == 0) {
5883 gen_helper_vfp_maxnums(tmp, tmp, tmp2, fpstatus);
5884 } else {
5885 gen_helper_vfp_minnums(tmp, tmp, tmp2, fpstatus);
5886 }
5887 tcg_temp_free_ptr(fpstatus);
5888 } else {
5889 if (size == 0) {
5890 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
5891 } else {
5892 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
5893 }
5894 }
5895 break;
5896 case NEON_3R_VFM:
5897 {
5898
5899 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5900 TCGv_i32 tmp3 = neon_load_reg(rd, pass);
5901 if (size) {
5902
5903 gen_helper_vfp_negs(tmp, tmp);
5904 }
5905 gen_helper_vfp_muladds(tmp, tmp, tmp2, tmp3, fpstatus);
5906 tcg_temp_free_i32(tmp3);
5907 tcg_temp_free_ptr(fpstatus);
5908 break;
5909 }
5910 default:
5911 abort();
5912 }
5913 tcg_temp_free_i32(tmp2);
5914
5915
5916
5917
5918 if (pairwise && rd == rm) {
5919 neon_store_scratch(pass, tmp);
5920 } else {
5921 neon_store_reg(rd, pass, tmp);
5922 }
5923
5924 }
5925 if (pairwise && rd == rm) {
5926 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5927 tmp = neon_load_scratch(pass);
5928 neon_store_reg(rd, pass, tmp);
5929 }
5930 }
5931
5932 } else if (insn & (1 << 4)) {
5933 if ((insn & 0x00380080) != 0) {
5934
5935 op = (insn >> 8) & 0xf;
5936 if (insn & (1 << 7)) {
5937
5938 if (op > 7) {
5939 return 1;
5940 }
5941 size = 3;
5942 } else {
5943 size = 2;
5944 while ((insn & (1 << (size + 19))) == 0)
5945 size--;
5946 }
5947 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
5948
5949
5950 if (op < 8) {
5951
5952
5953 if (q && ((rd | rm) & 1)) {
5954 return 1;
5955 }
5956 if (!u && (op == 4 || op == 6)) {
5957 return 1;
5958 }
5959
5960
5961 if (op <= 4)
5962 shift = shift - (1 << (size + 3));
5963 if (size == 3) {
5964 count = q + 1;
5965 } else {
5966 count = q ? 4: 2;
5967 }
5968 switch (size) {
5969 case 0:
5970 imm = (uint8_t) shift;
5971 imm |= imm << 8;
5972 imm |= imm << 16;
5973 break;
5974 case 1:
5975 imm = (uint16_t) shift;
5976 imm |= imm << 16;
5977 break;
5978 case 2:
5979 case 3:
5980 imm = shift;
5981 break;
5982 default:
5983 abort();
5984 }
5985
5986 for (pass = 0; pass < count; pass++) {
5987 if (size == 3) {
5988 neon_load_reg64(cpu_V0, rm + pass);
5989 tcg_gen_movi_i64(cpu_V1, imm);
5990 switch (op) {
5991 case 0:
5992 case 1:
5993 if (u)
5994 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
5995 else
5996 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
5997 break;
5998 case 2:
5999 case 3:
6000 if (u)
6001 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
6002 else
6003 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
6004 break;
6005 case 4:
6006 case 5:
6007 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
6008 break;
6009 case 6:
6010 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
6011 cpu_V0, cpu_V1);
6012 break;
6013 case 7:
6014 if (u) {
6015 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
6016 cpu_V0, cpu_V1);
6017 } else {
6018 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
6019 cpu_V0, cpu_V1);
6020 }
6021 break;
6022 }
6023 if (op == 1 || op == 3) {
6024
6025 neon_load_reg64(cpu_V1, rd + pass);
6026 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
6027 } else if (op == 4 || (op == 5 && u)) {
6028
6029 neon_load_reg64(cpu_V1, rd + pass);
6030 uint64_t mask;
6031 if (shift < -63 || shift > 63) {
6032 mask = 0;
6033 } else {
6034 if (op == 4) {
6035 mask = 0xffffffffffffffffull >> -shift;
6036 } else {
6037 mask = 0xffffffffffffffffull << shift;
6038 }
6039 }
6040 tcg_gen_andi_i64(cpu_V1, cpu_V1, ~mask);
6041 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6042 }
6043 neon_store_reg64(cpu_V0, rd + pass);
6044 } else {
6045
6046 tmp = neon_load_reg(rm, pass);
6047 tmp2 = tcg_temp_new_i32();
6048 tcg_gen_movi_i32(tmp2, imm);
6049 switch (op) {
6050 case 0:
6051 case 1:
6052 GEN_NEON_INTEGER_OP(shl);
6053 break;
6054 case 2:
6055 case 3:
6056 GEN_NEON_INTEGER_OP(rshl);
6057 break;
6058 case 4:
6059 case 5:
6060 switch (size) {
6061 case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
6062 case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
6063 case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
6064 default: abort();
6065 }
6066 break;
6067 case 6:
6068 switch (size) {
6069 case 0:
6070 gen_helper_neon_qshlu_s8(tmp, cpu_env,
6071 tmp, tmp2);
6072 break;
6073 case 1:
6074 gen_helper_neon_qshlu_s16(tmp, cpu_env,
6075 tmp, tmp2);
6076 break;
6077 case 2:
6078 gen_helper_neon_qshlu_s32(tmp, cpu_env,
6079 tmp, tmp2);
6080 break;
6081 default:
6082 abort();
6083 }
6084 break;
6085 case 7:
6086 GEN_NEON_INTEGER_OP_ENV(qshl);
6087 break;
6088 }
6089 tcg_temp_free_i32(tmp2);
6090
6091 if (op == 1 || op == 3) {
6092
6093 tmp2 = neon_load_reg(rd, pass);
6094 gen_neon_add(size, tmp, tmp2);
6095 tcg_temp_free_i32(tmp2);
6096 } else if (op == 4 || (op == 5 && u)) {
6097
6098 switch (size) {
6099 case 0:
6100 if (op == 4)
6101 mask = 0xff >> -shift;
6102 else
6103 mask = (uint8_t)(0xff << shift);
6104 mask |= mask << 8;
6105 mask |= mask << 16;
6106 break;
6107 case 1:
6108 if (op == 4)
6109 mask = 0xffff >> -shift;
6110 else
6111 mask = (uint16_t)(0xffff << shift);
6112 mask |= mask << 16;
6113 break;
6114 case 2:
6115 if (shift < -31 || shift > 31) {
6116 mask = 0;
6117 } else {
6118 if (op == 4)
6119 mask = 0xffffffffu >> -shift;
6120 else
6121 mask = 0xffffffffu << shift;
6122 }
6123 break;
6124 default:
6125 abort();
6126 }
6127 tmp2 = neon_load_reg(rd, pass);
6128 tcg_gen_andi_i32(tmp, tmp, mask);
6129 tcg_gen_andi_i32(tmp2, tmp2, ~mask);
6130 tcg_gen_or_i32(tmp, tmp, tmp2);
6131 tcg_temp_free_i32(tmp2);
6132 }
6133 neon_store_reg(rd, pass, tmp);
6134 }
6135 }
6136 } else if (op < 10) {
6137
6138
6139 int input_unsigned = (op == 8) ? !u : u;
6140 if (rm & 1) {
6141 return 1;
6142 }
6143 shift = shift - (1 << (size + 3));
6144 size++;
6145 if (size == 3) {
6146 tmp64 = tcg_const_i64(shift);
6147 neon_load_reg64(cpu_V0, rm);
6148 neon_load_reg64(cpu_V1, rm + 1);
6149 for (pass = 0; pass < 2; pass++) {
6150 TCGv_i64 in;
6151 if (pass == 0) {
6152 in = cpu_V0;
6153 } else {
6154 in = cpu_V1;
6155 }
6156 if (q) {
6157 if (input_unsigned) {
6158 gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
6159 } else {
6160 gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
6161 }
6162 } else {
6163 if (input_unsigned) {
6164 gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
6165 } else {
6166 gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
6167 }
6168 }
6169 tmp = tcg_temp_new_i32();
6170 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
6171 neon_store_reg(rd, pass, tmp);
6172 }
6173 tcg_temp_free_i64(tmp64);
6174 } else {
6175 if (size == 1) {
6176 imm = (uint16_t)shift;
6177 imm |= imm << 16;
6178 } else {
6179
6180 imm = (uint32_t)shift;
6181 }
6182 tmp2 = tcg_const_i32(imm);
6183 tmp4 = neon_load_reg(rm + 1, 0);
6184 tmp5 = neon_load_reg(rm + 1, 1);
6185 for (pass = 0; pass < 2; pass++) {
6186 if (pass == 0) {
6187 tmp = neon_load_reg(rm, 0);
6188 } else {
6189 tmp = tmp4;
6190 }
6191 gen_neon_shift_narrow(size, tmp, tmp2, q,
6192 input_unsigned);
6193 if (pass == 0) {
6194 tmp3 = neon_load_reg(rm, 1);
6195 } else {
6196 tmp3 = tmp5;
6197 }
6198 gen_neon_shift_narrow(size, tmp3, tmp2, q,
6199 input_unsigned);
6200 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
6201 tcg_temp_free_i32(tmp);
6202 tcg_temp_free_i32(tmp3);
6203 tmp = tcg_temp_new_i32();
6204 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
6205 neon_store_reg(rd, pass, tmp);
6206 }
6207 tcg_temp_free_i32(tmp2);
6208 }
6209 } else if (op == 10) {
6210
6211 if (q || (rd & 1)) {
6212 return 1;
6213 }
6214 tmp = neon_load_reg(rm, 0);
6215 tmp2 = neon_load_reg(rm, 1);
6216 for (pass = 0; pass < 2; pass++) {
6217 if (pass == 1)
6218 tmp = tmp2;
6219
6220 gen_neon_widen(cpu_V0, tmp, size, u);
6221
6222 if (shift != 0) {
6223
6224
6225 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
6226
6227
6228
6229
6230
6231 if (size < 2 || !u) {
6232 uint64_t imm64;
6233 if (size == 0) {
6234 imm = (0xffu >> (8 - shift));
6235 imm |= imm << 16;
6236 } else if (size == 1) {
6237 imm = 0xffff >> (16 - shift);
6238 } else {
6239
6240 imm = 0xffffffff >> (32 - shift);
6241 }
6242 if (size < 2) {
6243 imm64 = imm | (((uint64_t)imm) << 32);
6244 } else {
6245 imm64 = imm;
6246 }
6247 tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
6248 }
6249 }
6250 neon_store_reg64(cpu_V0, rd + pass);
6251 }
6252 } else if (op >= 14) {
6253
6254 if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
6255 return 1;
6256 }
6257
6258
6259
6260 shift = 32 - shift;
6261 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6262 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
6263 if (!(op & 1)) {
6264 if (u)
6265 gen_vfp_ulto(0, shift, 1);
6266 else
6267 gen_vfp_slto(0, shift, 1);
6268 } else {
6269 if (u)
6270 gen_vfp_toul(0, shift, 1);
6271 else
6272 gen_vfp_tosl(0, shift, 1);
6273 }
6274 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
6275 }
6276 } else {
6277 return 1;
6278 }
6279 } else {
6280 int invert;
6281 if (q && (rd & 1)) {
6282 return 1;
6283 }
6284
6285 op = (insn >> 8) & 0xf;
6286
6287 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
6288 invert = (insn & (1 << 5)) != 0;
6289
6290
6291
6292
6293 switch (op) {
6294 case 0: case 1:
6295
6296 break;
6297 case 2: case 3:
6298 imm <<= 8;
6299 break;
6300 case 4: case 5:
6301 imm <<= 16;
6302 break;
6303 case 6: case 7:
6304 imm <<= 24;
6305 break;
6306 case 8: case 9:
6307 imm |= imm << 16;
6308 break;
6309 case 10: case 11:
6310 imm = (imm << 8) | (imm << 24);
6311 break;
6312 case 12:
6313 imm = (imm << 8) | 0xff;
6314 break;
6315 case 13:
6316 imm = (imm << 16) | 0xffff;
6317 break;
6318 case 14:
6319 imm |= (imm << 8) | (imm << 16) | (imm << 24);
6320 if (invert)
6321 imm = ~imm;
6322 break;
6323 case 15:
6324 if (invert) {
6325 return 1;
6326 }
6327 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
6328 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
6329 break;
6330 }
6331 if (invert)
6332 imm = ~imm;
6333
6334 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6335 if (op & 1 && op < 12) {
6336 tmp = neon_load_reg(rd, pass);
6337 if (invert) {
6338
6339
6340 tcg_gen_andi_i32(tmp, tmp, imm);
6341 } else {
6342 tcg_gen_ori_i32(tmp, tmp, imm);
6343 }
6344 } else {
6345
6346 tmp = tcg_temp_new_i32();
6347 if (op == 14 && invert) {
6348 int n;
6349 uint32_t val;
6350 val = 0;
6351 for (n = 0; n < 4; n++) {
6352 if (imm & (1 << (n + (pass & 1) * 4)))
6353 val |= 0xff << (n * 8);
6354 }
6355 tcg_gen_movi_i32(tmp, val);
6356 } else {
6357 tcg_gen_movi_i32(tmp, imm);
6358 }
6359 }
6360 neon_store_reg(rd, pass, tmp);
6361 }
6362 }
6363 } else {
6364 if (size != 3) {
6365 op = (insn >> 8) & 0xf;
6366 if ((insn & (1 << 6)) == 0) {
6367
6368 int src1_wide;
6369 int src2_wide;
6370 int prewiden;
6371
6372
6373
6374
6375
6376
6377 int undefreq;
6378
6379 static const int neon_3reg_wide[16][4] = {
6380 {1, 0, 0, 0},
6381 {1, 1, 0, 0},
6382 {1, 0, 0, 0},
6383 {1, 1, 0, 0},
6384 {0, 1, 1, 0},
6385 {0, 0, 0, 0},
6386 {0, 1, 1, 0},
6387 {0, 0, 0, 0},
6388 {0, 0, 0, 0},
6389 {0, 0, 0, 9},
6390 {0, 0, 0, 0},
6391 {0, 0, 0, 9},
6392 {0, 0, 0, 0},
6393 {0, 0, 0, 1},
6394 {0, 0, 0, 0xa},
6395 {0, 0, 0, 7},
6396 };
6397
6398 prewiden = neon_3reg_wide[op][0];
6399 src1_wide = neon_3reg_wide[op][1];
6400 src2_wide = neon_3reg_wide[op][2];
6401 undefreq = neon_3reg_wide[op][3];
6402
6403 if ((undefreq & (1 << size)) ||
6404 ((undefreq & 8) && u)) {
6405 return 1;
6406 }
6407 if ((src1_wide && (rn & 1)) ||
6408 (src2_wide && (rm & 1)) ||
6409 (!src2_wide && (rd & 1))) {
6410 return 1;
6411 }
6412
6413
6414
6415
6416 if (op == 14 && size == 2) {
6417 TCGv_i64 tcg_rn, tcg_rm, tcg_rd;
6418
6419 if (!arm_dc_feature(s, ARM_FEATURE_V8_PMULL)) {
6420 return 1;
6421 }
6422 tcg_rn = tcg_temp_new_i64();
6423 tcg_rm = tcg_temp_new_i64();
6424 tcg_rd = tcg_temp_new_i64();
6425 neon_load_reg64(tcg_rn, rn);
6426 neon_load_reg64(tcg_rm, rm);
6427 gen_helper_neon_pmull_64_lo(tcg_rd, tcg_rn, tcg_rm);
6428 neon_store_reg64(tcg_rd, rd);
6429 gen_helper_neon_pmull_64_hi(tcg_rd, tcg_rn, tcg_rm);
6430 neon_store_reg64(tcg_rd, rd + 1);
6431 tcg_temp_free_i64(tcg_rn);
6432 tcg_temp_free_i64(tcg_rm);
6433 tcg_temp_free_i64(tcg_rd);
6434 return 0;
6435 }
6436
6437
6438
6439
6440 if (rd == rm && !src2_wide) {
6441 tmp = neon_load_reg(rm, 1);
6442 neon_store_scratch(2, tmp);
6443 } else if (rd == rn && !src1_wide) {
6444 tmp = neon_load_reg(rn, 1);
6445 neon_store_scratch(2, tmp);
6446 }
6447 TCGV_UNUSED_I32(tmp3);
6448 for (pass = 0; pass < 2; pass++) {
6449 if (src1_wide) {
6450 neon_load_reg64(cpu_V0, rn + pass);
6451 TCGV_UNUSED_I32(tmp);
6452 } else {
6453 if (pass == 1 && rd == rn) {
6454 tmp = neon_load_scratch(2);
6455 } else {
6456 tmp = neon_load_reg(rn, pass);
6457 }
6458 if (prewiden) {
6459 gen_neon_widen(cpu_V0, tmp, size, u);
6460 }
6461 }
6462 if (src2_wide) {
6463 neon_load_reg64(cpu_V1, rm + pass);
6464 TCGV_UNUSED_I32(tmp2);
6465 } else {
6466 if (pass == 1 && rd == rm) {
6467 tmp2 = neon_load_scratch(2);
6468 } else {
6469 tmp2 = neon_load_reg(rm, pass);
6470 }
6471 if (prewiden) {
6472 gen_neon_widen(cpu_V1, tmp2, size, u);
6473 }
6474 }
6475 switch (op) {
6476 case 0: case 1: case 4:
6477 gen_neon_addl(size);
6478 break;
6479 case 2: case 3: case 6:
6480 gen_neon_subl(size);
6481 break;
6482 case 5: case 7:
6483 switch ((size << 1) | u) {
6484 case 0:
6485 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
6486 break;
6487 case 1:
6488 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
6489 break;
6490 case 2:
6491 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
6492 break;
6493 case 3:
6494 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
6495 break;
6496 case 4:
6497 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
6498 break;
6499 case 5:
6500 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
6501 break;
6502 default: abort();
6503 }
6504 tcg_temp_free_i32(tmp2);
6505 tcg_temp_free_i32(tmp);
6506 break;
6507 case 8: case 9: case 10: case 11: case 12: case 13:
6508
6509 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
6510 break;
6511 case 14:
6512 gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
6513 tcg_temp_free_i32(tmp2);
6514 tcg_temp_free_i32(tmp);
6515 break;
6516 default:
6517 abort();
6518 }
6519 if (op == 13) {
6520
6521 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6522 neon_store_reg64(cpu_V0, rd + pass);
6523 } else if (op == 5 || (op >= 8 && op <= 11)) {
6524
6525 neon_load_reg64(cpu_V1, rd + pass);
6526 switch (op) {
6527 case 10:
6528 gen_neon_negl(cpu_V0, size);
6529
6530 case 5: case 8:
6531 gen_neon_addl(size);
6532 break;
6533 case 9: case 11:
6534 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6535 if (op == 11) {
6536 gen_neon_negl(cpu_V0, size);
6537 }
6538 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
6539 break;
6540 default:
6541 abort();
6542 }
6543 neon_store_reg64(cpu_V0, rd + pass);
6544 } else if (op == 4 || op == 6) {
6545
6546 tmp = tcg_temp_new_i32();
6547 if (!u) {
6548 switch (size) {
6549 case 0:
6550 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
6551 break;
6552 case 1:
6553 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
6554 break;
6555 case 2:
6556 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
6557 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
6558 break;
6559 default: abort();
6560 }
6561 } else {
6562 switch (size) {
6563 case 0:
6564 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
6565 break;
6566 case 1:
6567 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
6568 break;
6569 case 2:
6570 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
6571 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
6572 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
6573 break;
6574 default: abort();
6575 }
6576 }
6577 if (pass == 0) {
6578 tmp3 = tmp;
6579 } else {
6580 neon_store_reg(rd, 0, tmp3);
6581 neon_store_reg(rd, 1, tmp);
6582 }
6583 } else {
6584
6585 neon_store_reg64(cpu_V0, rd + pass);
6586 }
6587 }
6588 } else {
6589
6590
6591
6592
6593 if (size == 0) {
6594 return 1;
6595 }
6596 switch (op) {
6597 case 1:
6598 case 5:
6599 case 9:
6600 if (size == 1) {
6601 return 1;
6602 }
6603
6604 case 0:
6605 case 4:
6606 case 8:
6607 case 12:
6608 case 13:
6609 if (u && ((rd | rn) & 1)) {
6610 return 1;
6611 }
6612 tmp = neon_get_scalar(size, rm);
6613 neon_store_scratch(0, tmp);
6614 for (pass = 0; pass < (u ? 4 : 2); pass++) {
6615 tmp = neon_load_scratch(0);
6616 tmp2 = neon_load_reg(rn, pass);
6617 if (op == 12) {
6618 if (size == 1) {
6619 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
6620 } else {
6621 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
6622 }
6623 } else if (op == 13) {
6624 if (size == 1) {
6625 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
6626 } else {
6627 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
6628 }
6629 } else if (op & 1) {
6630 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6631 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
6632 tcg_temp_free_ptr(fpstatus);
6633 } else {
6634 switch (size) {
6635 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
6636 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
6637 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
6638 default: abort();
6639 }
6640 }
6641 tcg_temp_free_i32(tmp2);
6642 if (op < 8) {
6643
6644 tmp2 = neon_load_reg(rd, pass);
6645 switch (op) {
6646 case 0:
6647 gen_neon_add(size, tmp, tmp2);
6648 break;
6649 case 1:
6650 {
6651 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6652 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
6653 tcg_temp_free_ptr(fpstatus);
6654 break;
6655 }
6656 case 4:
6657 gen_neon_rsb(size, tmp, tmp2);
6658 break;
6659 case 5:
6660 {
6661 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6662 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
6663 tcg_temp_free_ptr(fpstatus);
6664 break;
6665 }
6666 default:
6667 abort();
6668 }
6669 tcg_temp_free_i32(tmp2);
6670 }
6671 neon_store_reg(rd, pass, tmp);
6672 }
6673 break;
6674 case 3:
6675 case 7:
6676 case 11:
6677 if (u == 1) {
6678 return 1;
6679 }
6680
6681 case 2:
6682 case 6:
6683 case 10:
6684 if (rd & 1) {
6685 return 1;
6686 }
6687 tmp2 = neon_get_scalar(size, rm);
6688
6689
6690 tmp4 = tcg_temp_new_i32();
6691 tcg_gen_mov_i32(tmp4, tmp2);
6692 tmp3 = neon_load_reg(rn, 1);
6693
6694 for (pass = 0; pass < 2; pass++) {
6695 if (pass == 0) {
6696 tmp = neon_load_reg(rn, 0);
6697 } else {
6698 tmp = tmp3;
6699 tmp2 = tmp4;
6700 }
6701 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
6702 if (op != 11) {
6703 neon_load_reg64(cpu_V1, rd + pass);
6704 }
6705 switch (op) {
6706 case 6:
6707 gen_neon_negl(cpu_V0, size);
6708
6709 case 2:
6710 gen_neon_addl(size);
6711 break;
6712 case 3: case 7:
6713 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6714 if (op == 7) {
6715 gen_neon_negl(cpu_V0, size);
6716 }
6717 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
6718 break;
6719 case 10:
6720
6721 break;
6722 case 11:
6723 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6724 break;
6725 default:
6726 abort();
6727 }
6728 neon_store_reg64(cpu_V0, rd + pass);
6729 }
6730
6731
6732 break;
6733 default:
6734 return 1;
6735 }
6736 }
6737 } else {
6738 if (!u) {
6739
6740 imm = (insn >> 8) & 0xf;
6741
6742 if (imm > 7 && !q)
6743 return 1;
6744
6745 if (q && ((rd | rn | rm) & 1)) {
6746 return 1;
6747 }
6748
6749 if (imm == 0) {
6750 neon_load_reg64(cpu_V0, rn);
6751 if (q) {
6752 neon_load_reg64(cpu_V1, rn + 1);
6753 }
6754 } else if (imm == 8) {
6755 neon_load_reg64(cpu_V0, rn + 1);
6756 if (q) {
6757 neon_load_reg64(cpu_V1, rm);
6758 }
6759 } else if (q) {
6760 tmp64 = tcg_temp_new_i64();
6761 if (imm < 8) {
6762 neon_load_reg64(cpu_V0, rn);
6763 neon_load_reg64(tmp64, rn + 1);
6764 } else {
6765 neon_load_reg64(cpu_V0, rn + 1);
6766 neon_load_reg64(tmp64, rm);
6767 }
6768 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
6769 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
6770 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6771 if (imm < 8) {
6772 neon_load_reg64(cpu_V1, rm);
6773 } else {
6774 neon_load_reg64(cpu_V1, rm + 1);
6775 imm -= 8;
6776 }
6777 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
6778 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
6779 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
6780 tcg_temp_free_i64(tmp64);
6781 } else {
6782
6783 neon_load_reg64(cpu_V0, rn);
6784 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
6785 neon_load_reg64(cpu_V1, rm);
6786 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
6787 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6788 }
6789 neon_store_reg64(cpu_V0, rd);
6790 if (q) {
6791 neon_store_reg64(cpu_V1, rd + 1);
6792 }
6793 } else if ((insn & (1 << 11)) == 0) {
6794
6795 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
6796 size = (insn >> 18) & 3;
6797
6798 if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
6799 return 1;
6800 }
6801 if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
6802 q && ((rm | rd) & 1)) {
6803 return 1;
6804 }
6805 switch (op) {
6806 case NEON_2RM_VREV64:
6807 for (pass = 0; pass < (q ? 2 : 1); pass++) {
6808 tmp = neon_load_reg(rm, pass * 2);
6809 tmp2 = neon_load_reg(rm, pass * 2 + 1);
6810 switch (size) {
6811 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6812 case 1: gen_swap_half(tmp); break;
6813 case 2: break;
6814 default: abort();
6815 }
6816 neon_store_reg(rd, pass * 2 + 1, tmp);
6817 if (size == 2) {
6818 neon_store_reg(rd, pass * 2, tmp2);
6819 } else {
6820 switch (size) {
6821 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
6822 case 1: gen_swap_half(tmp2); break;
6823 default: abort();
6824 }
6825 neon_store_reg(rd, pass * 2, tmp2);
6826 }
6827 }
6828 break;
6829 case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
6830 case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
6831 for (pass = 0; pass < q + 1; pass++) {
6832 tmp = neon_load_reg(rm, pass * 2);
6833 gen_neon_widen(cpu_V0, tmp, size, op & 1);
6834 tmp = neon_load_reg(rm, pass * 2 + 1);
6835 gen_neon_widen(cpu_V1, tmp, size, op & 1);
6836 switch (size) {
6837 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
6838 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
6839 case 2: tcg_gen_add_i64(CPU_V001); break;
6840 default: abort();
6841 }
6842 if (op >= NEON_2RM_VPADAL) {
6843
6844 neon_load_reg64(cpu_V1, rd + pass);
6845 gen_neon_addl(size);
6846 }
6847 neon_store_reg64(cpu_V0, rd + pass);
6848 }
6849 break;
6850 case NEON_2RM_VTRN:
6851 if (size == 2) {
6852 int n;
6853 for (n = 0; n < (q ? 4 : 2); n += 2) {
6854 tmp = neon_load_reg(rm, n);
6855 tmp2 = neon_load_reg(rd, n + 1);
6856 neon_store_reg(rm, n, tmp2);
6857 neon_store_reg(rd, n + 1, tmp);
6858 }
6859 } else {
6860 goto elementwise;
6861 }
6862 break;
6863 case NEON_2RM_VUZP:
6864 if (gen_neon_unzip(rd, rm, size, q)) {
6865 return 1;
6866 }
6867 break;
6868 case NEON_2RM_VZIP:
6869 if (gen_neon_zip(rd, rm, size, q)) {
6870 return 1;
6871 }
6872 break;
6873 case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
6874
6875 if (rm & 1) {
6876 return 1;
6877 }
6878 TCGV_UNUSED_I32(tmp2);
6879 for (pass = 0; pass < 2; pass++) {
6880 neon_load_reg64(cpu_V0, rm + pass);
6881 tmp = tcg_temp_new_i32();
6882 gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
6883 tmp, cpu_V0);
6884 if (pass == 0) {
6885 tmp2 = tmp;
6886 } else {
6887 neon_store_reg(rd, 0, tmp2);
6888 neon_store_reg(rd, 1, tmp);
6889 }
6890 }
6891 break;
6892 case NEON_2RM_VSHLL:
6893 if (q || (rd & 1)) {
6894 return 1;
6895 }
6896 tmp = neon_load_reg(rm, 0);
6897 tmp2 = neon_load_reg(rm, 1);
6898 for (pass = 0; pass < 2; pass++) {
6899 if (pass == 1)
6900 tmp = tmp2;
6901 gen_neon_widen(cpu_V0, tmp, size, 1);
6902 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
6903 neon_store_reg64(cpu_V0, rd + pass);
6904 }
6905 break;
6906 case NEON_2RM_VCVT_F16_F32:
6907 if (!arm_dc_feature(s, ARM_FEATURE_VFP_FP16) ||
6908 q || (rm & 1)) {
6909 return 1;
6910 }
6911 tmp = tcg_temp_new_i32();
6912 tmp2 = tcg_temp_new_i32();
6913 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
6914 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
6915 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
6916 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
6917 tcg_gen_shli_i32(tmp2, tmp2, 16);
6918 tcg_gen_or_i32(tmp2, tmp2, tmp);
6919 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
6920 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
6921 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
6922 neon_store_reg(rd, 0, tmp2);
6923 tmp2 = tcg_temp_new_i32();
6924 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
6925 tcg_gen_shli_i32(tmp2, tmp2, 16);
6926 tcg_gen_or_i32(tmp2, tmp2, tmp);
6927 neon_store_reg(rd, 1, tmp2);
6928 tcg_temp_free_i32(tmp);
6929 break;
6930 case NEON_2RM_VCVT_F32_F16:
6931 if (!arm_dc_feature(s, ARM_FEATURE_VFP_FP16) ||
6932 q || (rd & 1)) {
6933 return 1;
6934 }
6935 tmp3 = tcg_temp_new_i32();
6936 tmp = neon_load_reg(rm, 0);
6937 tmp2 = neon_load_reg(rm, 1);
6938 tcg_gen_ext16u_i32(tmp3, tmp);
6939 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6940 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
6941 tcg_gen_shri_i32(tmp3, tmp, 16);
6942 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6943 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
6944 tcg_temp_free_i32(tmp);
6945 tcg_gen_ext16u_i32(tmp3, tmp2);
6946 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6947 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
6948 tcg_gen_shri_i32(tmp3, tmp2, 16);
6949 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6950 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
6951 tcg_temp_free_i32(tmp2);
6952 tcg_temp_free_i32(tmp3);
6953 break;
6954 case NEON_2RM_AESE: case NEON_2RM_AESMC:
6955 if (!arm_dc_feature(s, ARM_FEATURE_V8_AES)
6956 || ((rm | rd) & 1)) {
6957 return 1;
6958 }
6959 tmp = tcg_const_i32(rd);
6960 tmp2 = tcg_const_i32(rm);
6961
6962
6963
6964
6965 tmp3 = tcg_const_i32(extract32(insn, 6, 1));
6966
6967 if (op == NEON_2RM_AESE) {
6968 gen_helper_crypto_aese(cpu_env, tmp, tmp2, tmp3);
6969 } else {
6970 gen_helper_crypto_aesmc(cpu_env, tmp, tmp2, tmp3);
6971 }
6972 tcg_temp_free_i32(tmp);
6973 tcg_temp_free_i32(tmp2);
6974 tcg_temp_free_i32(tmp3);
6975 break;
6976 case NEON_2RM_SHA1H:
6977 if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA1)
6978 || ((rm | rd) & 1)) {
6979 return 1;
6980 }
6981 tmp = tcg_const_i32(rd);
6982 tmp2 = tcg_const_i32(rm);
6983
6984 gen_helper_crypto_sha1h(cpu_env, tmp, tmp2);
6985
6986 tcg_temp_free_i32(tmp);
6987 tcg_temp_free_i32(tmp2);
6988 break;
6989 case NEON_2RM_SHA1SU1:
6990 if ((rm | rd) & 1) {
6991 return 1;
6992 }
6993
6994 if (q) {
6995 if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA256)) {
6996 return 1;
6997 }
6998 } else if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA1)) {
6999 return 1;
7000 }
7001 tmp = tcg_const_i32(rd);
7002 tmp2 = tcg_const_i32(rm);
7003 if (q) {
7004 gen_helper_crypto_sha256su0(cpu_env, tmp, tmp2);
7005 } else {
7006 gen_helper_crypto_sha1su1(cpu_env, tmp, tmp2);
7007 }
7008 tcg_temp_free_i32(tmp);
7009 tcg_temp_free_i32(tmp2);
7010 break;
7011 default:
7012 elementwise:
7013 for (pass = 0; pass < (q ? 4 : 2); pass++) {
7014 if (neon_2rm_is_float_op(op)) {
7015 tcg_gen_ld_f32(cpu_F0s, cpu_env,
7016 neon_reg_offset(rm, pass));
7017 TCGV_UNUSED_I32(tmp);
7018 } else {
7019 tmp = neon_load_reg(rm, pass);
7020 }
7021 switch (op) {
7022 case NEON_2RM_VREV32:
7023 switch (size) {
7024 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
7025 case 1: gen_swap_half(tmp); break;
7026 default: abort();
7027 }
7028 break;
7029 case NEON_2RM_VREV16:
7030 gen_rev16(tmp);
7031 break;
7032 case NEON_2RM_VCLS:
7033 switch (size) {
7034 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
7035 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
7036 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
7037 default: abort();
7038 }
7039 break;
7040 case NEON_2RM_VCLZ:
7041 switch (size) {
7042 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
7043 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
7044 case 2: gen_helper_clz(tmp, tmp); break;
7045 default: abort();
7046 }
7047 break;
7048 case NEON_2RM_VCNT:
7049 gen_helper_neon_cnt_u8(tmp, tmp);
7050 break;
7051 case NEON_2RM_VMVN:
7052 tcg_gen_not_i32(tmp, tmp);
7053 break;
7054 case NEON_2RM_VQABS:
7055 switch (size) {
7056 case 0:
7057 gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
7058 break;
7059 case 1:
7060 gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
7061 break;
7062 case 2:
7063 gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
7064 break;
7065 default: abort();
7066 }
7067 break;
7068 case NEON_2RM_VQNEG:
7069 switch (size) {
7070 case 0:
7071 gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
7072 break;
7073 case 1:
7074 gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
7075 break;
7076 case 2:
7077 gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
7078 break;
7079 default: abort();
7080 }
7081 break;
7082 case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
7083 tmp2 = tcg_const_i32(0);
7084 switch(size) {
7085 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
7086 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
7087 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
7088 default: abort();
7089 }
7090 tcg_temp_free_i32(tmp2);
7091 if (op == NEON_2RM_VCLE0) {
7092 tcg_gen_not_i32(tmp, tmp);
7093 }
7094 break;
7095 case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
7096 tmp2 = tcg_const_i32(0);
7097 switch(size) {
7098 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
7099 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
7100 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
7101 default: abort();
7102 }
7103 tcg_temp_free_i32(tmp2);
7104 if (op == NEON_2RM_VCLT0) {
7105 tcg_gen_not_i32(tmp, tmp);
7106 }
7107 break;
7108 case NEON_2RM_VCEQ0:
7109 tmp2 = tcg_const_i32(0);
7110 switch(size) {
7111 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
7112 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
7113 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
7114 default: abort();
7115 }
7116 tcg_temp_free_i32(tmp2);
7117 break;
7118 case NEON_2RM_VABS:
7119 switch(size) {
7120 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
7121 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
7122 case 2: tcg_gen_abs_i32(tmp, tmp); break;
7123 default: abort();
7124 }
7125 break;
7126 case NEON_2RM_VNEG:
7127 tmp2 = tcg_const_i32(0);
7128 gen_neon_rsb(size, tmp, tmp2);
7129 tcg_temp_free_i32(tmp2);
7130 break;
7131 case NEON_2RM_VCGT0_F:
7132 {
7133 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7134 tmp2 = tcg_const_i32(0);
7135 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
7136 tcg_temp_free_i32(tmp2);
7137 tcg_temp_free_ptr(fpstatus);
7138 break;
7139 }
7140 case NEON_2RM_VCGE0_F:
7141 {
7142 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7143 tmp2 = tcg_const_i32(0);
7144 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
7145 tcg_temp_free_i32(tmp2);
7146 tcg_temp_free_ptr(fpstatus);
7147 break;
7148 }
7149 case NEON_2RM_VCEQ0_F:
7150 {
7151 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7152 tmp2 = tcg_const_i32(0);
7153 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
7154 tcg_temp_free_i32(tmp2);
7155 tcg_temp_free_ptr(fpstatus);
7156 break;
7157 }
7158 case NEON_2RM_VCLE0_F:
7159 {
7160 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7161 tmp2 = tcg_const_i32(0);
7162 gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
7163 tcg_temp_free_i32(tmp2);
7164 tcg_temp_free_ptr(fpstatus);
7165 break;
7166 }
7167 case NEON_2RM_VCLT0_F:
7168 {
7169 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7170 tmp2 = tcg_const_i32(0);
7171 gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
7172 tcg_temp_free_i32(tmp2);
7173 tcg_temp_free_ptr(fpstatus);
7174 break;
7175 }
7176 case NEON_2RM_VABS_F:
7177 gen_vfp_abs(0);
7178 break;
7179 case NEON_2RM_VNEG_F:
7180 gen_vfp_neg(0);
7181 break;
7182 case NEON_2RM_VSWP:
7183 tmp2 = neon_load_reg(rd, pass);
7184 neon_store_reg(rm, pass, tmp2);
7185 break;
7186 case NEON_2RM_VTRN:
7187 tmp2 = neon_load_reg(rd, pass);
7188 switch (size) {
7189 case 0: gen_neon_trn_u8(tmp, tmp2); break;
7190 case 1: gen_neon_trn_u16(tmp, tmp2); break;
7191 default: abort();
7192 }
7193 neon_store_reg(rm, pass, tmp2);
7194 break;
7195 case NEON_2RM_VRINTN:
7196 case NEON_2RM_VRINTA:
7197 case NEON_2RM_VRINTM:
7198 case NEON_2RM_VRINTP:
7199 case NEON_2RM_VRINTZ:
7200 {
7201 TCGv_i32 tcg_rmode;
7202 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7203 int rmode;
7204
7205 if (op == NEON_2RM_VRINTZ) {
7206 rmode = FPROUNDING_ZERO;
7207 } else {
7208 rmode = fp_decode_rm[((op & 0x6) >> 1) ^ 1];
7209 }
7210
7211 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
7212 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
7213 cpu_env);
7214 gen_helper_rints(cpu_F0s, cpu_F0s, fpstatus);
7215 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
7216 cpu_env);
7217 tcg_temp_free_ptr(fpstatus);
7218 tcg_temp_free_i32(tcg_rmode);
7219 break;
7220 }
7221 case NEON_2RM_VRINTX:
7222 {
7223 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7224 gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpstatus);
7225 tcg_temp_free_ptr(fpstatus);
7226 break;
7227 }
7228 case NEON_2RM_VCVTAU:
7229 case NEON_2RM_VCVTAS:
7230 case NEON_2RM_VCVTNU:
7231 case NEON_2RM_VCVTNS:
7232 case NEON_2RM_VCVTPU:
7233 case NEON_2RM_VCVTPS:
7234 case NEON_2RM_VCVTMU:
7235 case NEON_2RM_VCVTMS:
7236 {
7237 bool is_signed = !extract32(insn, 7, 1);
7238 TCGv_ptr fpst = get_fpstatus_ptr(1);
7239 TCGv_i32 tcg_rmode, tcg_shift;
7240 int rmode = fp_decode_rm[extract32(insn, 8, 2)];
7241
7242 tcg_shift = tcg_const_i32(0);
7243 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
7244 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
7245 cpu_env);
7246
7247 if (is_signed) {
7248 gen_helper_vfp_tosls(cpu_F0s, cpu_F0s,
7249 tcg_shift, fpst);
7250 } else {
7251 gen_helper_vfp_touls(cpu_F0s, cpu_F0s,
7252 tcg_shift, fpst);
7253 }
7254
7255 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
7256 cpu_env);
7257 tcg_temp_free_i32(tcg_rmode);
7258 tcg_temp_free_i32(tcg_shift);
7259 tcg_temp_free_ptr(fpst);
7260 break;
7261 }
7262 case NEON_2RM_VRECPE:
7263 {
7264 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7265 gen_helper_recpe_u32(tmp, tmp, fpstatus);
7266 tcg_temp_free_ptr(fpstatus);
7267 break;
7268 }
7269 case NEON_2RM_VRSQRTE:
7270 {
7271 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7272 gen_helper_rsqrte_u32(tmp, tmp, fpstatus);
7273 tcg_temp_free_ptr(fpstatus);
7274 break;
7275 }
7276 case NEON_2RM_VRECPE_F:
7277 {
7278 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7279 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, fpstatus);
7280 tcg_temp_free_ptr(fpstatus);
7281 break;
7282 }
7283 case NEON_2RM_VRSQRTE_F:
7284 {
7285 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7286 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, fpstatus);
7287 tcg_temp_free_ptr(fpstatus);
7288 break;
7289 }
7290 case NEON_2RM_VCVT_FS:
7291 gen_vfp_sito(0, 1);
7292 break;
7293 case NEON_2RM_VCVT_FU:
7294 gen_vfp_uito(0, 1);
7295 break;
7296 case NEON_2RM_VCVT_SF:
7297 gen_vfp_tosiz(0, 1);
7298 break;
7299 case NEON_2RM_VCVT_UF:
7300 gen_vfp_touiz(0, 1);
7301 break;
7302 default:
7303
7304
7305
7306 abort();
7307 }
7308 if (neon_2rm_is_float_op(op)) {
7309 tcg_gen_st_f32(cpu_F0s, cpu_env,
7310 neon_reg_offset(rd, pass));
7311 } else {
7312 neon_store_reg(rd, pass, tmp);
7313 }
7314 }
7315 break;
7316 }
7317 } else if ((insn & (1 << 10)) == 0) {
7318
7319 int n = ((insn >> 8) & 3) + 1;
7320 if ((rn + n) > 32) {
7321
7322
7323
7324 return 1;
7325 }
7326 n <<= 3;
7327 if (insn & (1 << 6)) {
7328 tmp = neon_load_reg(rd, 0);
7329 } else {
7330 tmp = tcg_temp_new_i32();
7331 tcg_gen_movi_i32(tmp, 0);
7332 }
7333 tmp2 = neon_load_reg(rm, 0);
7334 tmp4 = tcg_const_i32(rn);
7335 tmp5 = tcg_const_i32(n);
7336 gen_helper_neon_tbl(tmp2, cpu_env, tmp2, tmp, tmp4, tmp5);
7337 tcg_temp_free_i32(tmp);
7338 if (insn & (1 << 6)) {
7339 tmp = neon_load_reg(rd, 1);
7340 } else {
7341 tmp = tcg_temp_new_i32();
7342 tcg_gen_movi_i32(tmp, 0);
7343 }
7344 tmp3 = neon_load_reg(rm, 1);
7345 gen_helper_neon_tbl(tmp3, cpu_env, tmp3, tmp, tmp4, tmp5);
7346 tcg_temp_free_i32(tmp5);
7347 tcg_temp_free_i32(tmp4);
7348 neon_store_reg(rd, 0, tmp2);
7349 neon_store_reg(rd, 1, tmp3);
7350 tcg_temp_free_i32(tmp);
7351 } else if ((insn & 0x380) == 0) {
7352
7353 if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
7354 return 1;
7355 }
7356 if (insn & (1 << 19)) {
7357 tmp = neon_load_reg(rm, 1);
7358 } else {
7359 tmp = neon_load_reg(rm, 0);
7360 }
7361 if (insn & (1 << 16)) {
7362 gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
7363 } else if (insn & (1 << 17)) {
7364 if ((insn >> 18) & 1)
7365 gen_neon_dup_high16(tmp);
7366 else
7367 gen_neon_dup_low16(tmp);
7368 }
7369 for (pass = 0; pass < (q ? 4 : 2); pass++) {
7370 tmp2 = tcg_temp_new_i32();
7371 tcg_gen_mov_i32(tmp2, tmp);
7372 neon_store_reg(rd, pass, tmp2);
7373 }
7374 tcg_temp_free_i32(tmp);
7375 } else {
7376 return 1;
7377 }
7378 }
7379 }
7380 return 0;
7381}
7382
7383static int disas_coproc_insn(DisasContext *s, uint32_t insn)
7384{
7385 int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
7386 const ARMCPRegInfo *ri;
7387
7388 cpnum = (insn >> 8) & 0xf;
7389
7390
7391 if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cpnum < 2)) {
7392 if (extract32(s->c15_cpar, cpnum, 1) == 0) {
7393 return 1;
7394 }
7395 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
7396 return disas_iwmmxt_insn(s, insn);
7397 } else if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) {
7398 return disas_dsp_insn(s, insn);
7399 }
7400 return 1;
7401 }
7402
7403
7404 is64 = (insn & (1 << 25)) == 0;
7405 if (!is64 && ((insn & (1 << 4)) == 0)) {
7406
7407 return 1;
7408 }
7409
7410 crm = insn & 0xf;
7411 if (is64) {
7412 crn = 0;
7413 opc1 = (insn >> 4) & 0xf;
7414 opc2 = 0;
7415 rt2 = (insn >> 16) & 0xf;
7416 } else {
7417 crn = (insn >> 16) & 0xf;
7418 opc1 = (insn >> 21) & 7;
7419 opc2 = (insn >> 5) & 7;
7420 rt2 = 0;
7421 }
7422 isread = (insn >> 20) & 1;
7423 rt = (insn >> 12) & 0xf;
7424
7425 ri = get_arm_cp_reginfo(s->cp_regs,
7426 ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2));
7427 if (ri) {
7428
7429 if (!cp_access_ok(s->current_el, ri, isread)) {
7430 return 1;
7431 }
7432
7433 if (ri->accessfn ||
7434 (arm_dc_feature(s, ARM_FEATURE_XSCALE) && cpnum < 14)) {
7435
7436
7437
7438
7439
7440 TCGv_ptr tmpptr;
7441 TCGv_i32 tcg_syn, tcg_isread;
7442 uint32_t syndrome;
7443
7444
7445
7446
7447
7448
7449
7450
7451
7452 switch (cpnum) {
7453 case 14:
7454 if (is64) {
7455 syndrome = syn_cp14_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
7456 isread, false);
7457 } else {
7458 syndrome = syn_cp14_rt_trap(1, 0xe, opc1, opc2, crn, crm,
7459 rt, isread, false);
7460 }
7461 break;
7462 case 15:
7463 if (is64) {
7464 syndrome = syn_cp15_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
7465 isread, false);
7466 } else {
7467 syndrome = syn_cp15_rt_trap(1, 0xe, opc1, opc2, crn, crm,
7468 rt, isread, false);
7469 }
7470 break;
7471 default:
7472
7473
7474
7475
7476
7477 assert(!arm_dc_feature(s, ARM_FEATURE_V8));
7478 syndrome = syn_uncategorized();
7479 break;
7480 }
7481
7482 gen_set_condexec(s);
7483 gen_set_pc_im(s, s->pc - 4);
7484 tmpptr = tcg_const_ptr(ri);
7485 tcg_syn = tcg_const_i32(syndrome);
7486 tcg_isread = tcg_const_i32(isread);
7487 gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn,
7488 tcg_isread);
7489 tcg_temp_free_ptr(tmpptr);
7490 tcg_temp_free_i32(tcg_syn);
7491 tcg_temp_free_i32(tcg_isread);
7492 }
7493
7494
7495 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
7496 case ARM_CP_NOP:
7497 return 0;
7498 case ARM_CP_WFI:
7499 if (isread) {
7500 return 1;
7501 }
7502 gen_set_pc_im(s, s->pc);
7503 s->is_jmp = DISAS_WFI;
7504 return 0;
7505 default:
7506 break;
7507 }
7508
7509 if ((s->tb->cflags & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
7510 gen_io_start();
7511 }
7512
7513 if (isread) {
7514
7515 if (is64) {
7516 TCGv_i64 tmp64;
7517 TCGv_i32 tmp;
7518 if (ri->type & ARM_CP_CONST) {
7519 tmp64 = tcg_const_i64(ri->resetvalue);
7520 } else if (ri->readfn) {
7521 TCGv_ptr tmpptr;
7522 tmp64 = tcg_temp_new_i64();
7523 tmpptr = tcg_const_ptr(ri);
7524 gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr);
7525 tcg_temp_free_ptr(tmpptr);
7526 } else {
7527 tmp64 = tcg_temp_new_i64();
7528 tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
7529 }
7530 tmp = tcg_temp_new_i32();
7531 tcg_gen_extrl_i64_i32(tmp, tmp64);
7532 store_reg(s, rt, tmp);
7533 tcg_gen_shri_i64(tmp64, tmp64, 32);
7534 tmp = tcg_temp_new_i32();
7535 tcg_gen_extrl_i64_i32(tmp, tmp64);
7536 tcg_temp_free_i64(tmp64);
7537 store_reg(s, rt2, tmp);
7538 } else {
7539 TCGv_i32 tmp;
7540 if (ri->type & ARM_CP_CONST) {
7541 tmp = tcg_const_i32(ri->resetvalue);
7542 } else if (ri->readfn) {
7543 TCGv_ptr tmpptr;
7544 tmp = tcg_temp_new_i32();
7545 tmpptr = tcg_const_ptr(ri);
7546 gen_helper_get_cp_reg(tmp, cpu_env, tmpptr);
7547 tcg_temp_free_ptr(tmpptr);
7548 } else {
7549 tmp = load_cpu_offset(ri->fieldoffset);
7550 }
7551 if (rt == 15) {
7552
7553
7554
7555 gen_set_nzcv(tmp);
7556 tcg_temp_free_i32(tmp);
7557 } else {
7558 store_reg(s, rt, tmp);
7559 }
7560 }
7561 } else {
7562
7563 if (ri->type & ARM_CP_CONST) {
7564
7565 return 0;
7566 }
7567
7568 if (is64) {
7569 TCGv_i32 tmplo, tmphi;
7570 TCGv_i64 tmp64 = tcg_temp_new_i64();
7571 tmplo = load_reg(s, rt);
7572 tmphi = load_reg(s, rt2);
7573 tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
7574 tcg_temp_free_i32(tmplo);
7575 tcg_temp_free_i32(tmphi);
7576 if (ri->writefn) {
7577 TCGv_ptr tmpptr = tcg_const_ptr(ri);
7578 gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64);
7579 tcg_temp_free_ptr(tmpptr);
7580 } else {
7581 tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
7582 }
7583 tcg_temp_free_i64(tmp64);
7584 } else {
7585 if (ri->writefn) {
7586 TCGv_i32 tmp;
7587 TCGv_ptr tmpptr;
7588 tmp = load_reg(s, rt);
7589 tmpptr = tcg_const_ptr(ri);
7590 gen_helper_set_cp_reg(cpu_env, tmpptr, tmp);
7591 tcg_temp_free_ptr(tmpptr);
7592 tcg_temp_free_i32(tmp);
7593 } else {
7594 TCGv_i32 tmp = load_reg(s, rt);
7595 store_cpu_offset(tmp, ri->fieldoffset);
7596 }
7597 }
7598 }
7599
7600 if ((s->tb->cflags & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
7601
7602 gen_io_end();
7603 gen_lookup_tb(s);
7604 } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
7605
7606
7607
7608
7609 gen_lookup_tb(s);
7610 }
7611
7612 return 0;
7613 }
7614
7615
7616
7617
7618 if (is64) {
7619 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
7620 "64 bit system register cp:%d opc1: %d crm:%d "
7621 "(%s)\n",
7622 isread ? "read" : "write", cpnum, opc1, crm,
7623 s->ns ? "non-secure" : "secure");
7624 } else {
7625 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
7626 "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d "
7627 "(%s)\n",
7628 isread ? "read" : "write", cpnum, opc1, crn, crm, opc2,
7629 s->ns ? "non-secure" : "secure");
7630 }
7631
7632 return 1;
7633}
7634
7635
7636
7637static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
7638{
7639 TCGv_i32 tmp;
7640 tmp = tcg_temp_new_i32();
7641 tcg_gen_extrl_i64_i32(tmp, val);
7642 store_reg(s, rlow, tmp);
7643 tmp = tcg_temp_new_i32();
7644 tcg_gen_shri_i64(val, val, 32);
7645 tcg_gen_extrl_i64_i32(tmp, val);
7646 store_reg(s, rhigh, tmp);
7647}
7648
7649
7650static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
7651{
7652 TCGv_i64 tmp;
7653 TCGv_i32 tmp2;
7654
7655
7656 tmp = tcg_temp_new_i64();
7657 tmp2 = load_reg(s, rlow);
7658 tcg_gen_extu_i32_i64(tmp, tmp2);
7659 tcg_temp_free_i32(tmp2);
7660 tcg_gen_add_i64(val, val, tmp);
7661 tcg_temp_free_i64(tmp);
7662}
7663
7664
7665static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
7666{
7667 TCGv_i64 tmp;
7668 TCGv_i32 tmpl;
7669 TCGv_i32 tmph;
7670
7671
7672 tmpl = load_reg(s, rlow);
7673 tmph = load_reg(s, rhigh);
7674 tmp = tcg_temp_new_i64();
7675 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
7676 tcg_temp_free_i32(tmpl);
7677 tcg_temp_free_i32(tmph);
7678 tcg_gen_add_i64(val, val, tmp);
7679 tcg_temp_free_i64(tmp);
7680}
7681
7682
7683static void gen_logicq_cc(TCGv_i32 lo, TCGv_i32 hi)
7684{
7685 tcg_gen_mov_i32(cpu_NF, hi);
7686 tcg_gen_or_i32(cpu_ZF, lo, hi);
7687}
7688
7689
7690
7691
7692
7693
7694
7695
7696
7697
7698static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
7699 TCGv_i32 addr, int size)
7700{
7701 TCGv_i32 tmp = tcg_temp_new_i32();
7702
7703 s->is_ldex = true;
7704
7705 switch (size) {
7706 case 0:
7707 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
7708 break;
7709 case 1:
7710 gen_aa32_ld16ua(s, tmp, addr, get_mem_index(s));
7711 break;
7712 case 2:
7713 case 3:
7714 gen_aa32_ld32ua(s, tmp, addr, get_mem_index(s));
7715 break;
7716 default:
7717 abort();
7718 }
7719
7720 if (size == 3) {
7721 TCGv_i32 tmp2 = tcg_temp_new_i32();
7722 TCGv_i32 tmp3 = tcg_temp_new_i32();
7723
7724 tcg_gen_addi_i32(tmp2, addr, 4);
7725 gen_aa32_ld32u(s, tmp3, tmp2, get_mem_index(s));
7726 tcg_temp_free_i32(tmp2);
7727 tcg_gen_concat_i32_i64(cpu_exclusive_val, tmp, tmp3);
7728 store_reg(s, rt2, tmp3);
7729 } else {
7730 tcg_gen_extu_i32_i64(cpu_exclusive_val, tmp);
7731 }
7732
7733 store_reg(s, rt, tmp);
7734 tcg_gen_extu_i32_i64(cpu_exclusive_addr, addr);
7735}
7736
7737static void gen_clrex(DisasContext *s)
7738{
7739 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
7740}
7741
7742#ifdef CONFIG_USER_ONLY
7743static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
7744 TCGv_i32 addr, int size)
7745{
7746 tcg_gen_extu_i32_i64(cpu_exclusive_test, addr);
7747 tcg_gen_movi_i32(cpu_exclusive_info,
7748 size | (rd << 4) | (rt << 8) | (rt2 << 12));
7749 gen_exception_internal_insn(s, 4, EXCP_STREX);
7750}
7751#else
7752static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
7753 TCGv_i32 addr, int size)
7754{
7755 TCGv_i32 tmp;
7756 TCGv_i64 val64, extaddr;
7757 TCGLabel *done_label;
7758 TCGLabel *fail_label;
7759
7760
7761
7762
7763
7764
7765
7766 fail_label = gen_new_label();
7767 done_label = gen_new_label();
7768 extaddr = tcg_temp_new_i64();
7769 tcg_gen_extu_i32_i64(extaddr, addr);
7770 tcg_gen_brcond_i64(TCG_COND_NE, extaddr, cpu_exclusive_addr, fail_label);
7771 tcg_temp_free_i64(extaddr);
7772
7773 tmp = tcg_temp_new_i32();
7774 switch (size) {
7775 case 0:
7776 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
7777 break;
7778 case 1:
7779 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
7780 break;
7781 case 2:
7782 case 3:
7783 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
7784 break;
7785 default:
7786 abort();
7787 }
7788
7789 val64 = tcg_temp_new_i64();
7790 if (size == 3) {
7791 TCGv_i32 tmp2 = tcg_temp_new_i32();
7792 TCGv_i32 tmp3 = tcg_temp_new_i32();
7793 tcg_gen_addi_i32(tmp2, addr, 4);
7794 gen_aa32_ld32u(s, tmp3, tmp2, get_mem_index(s));
7795 tcg_temp_free_i32(tmp2);
7796 tcg_gen_concat_i32_i64(val64, tmp, tmp3);
7797 tcg_temp_free_i32(tmp3);
7798 } else {
7799 tcg_gen_extu_i32_i64(val64, tmp);
7800 }
7801 tcg_temp_free_i32(tmp);
7802
7803 tcg_gen_brcond_i64(TCG_COND_NE, val64, cpu_exclusive_val, fail_label);
7804 tcg_temp_free_i64(val64);
7805
7806 tmp = load_reg(s, rt);
7807 switch (size) {
7808 case 0:
7809 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
7810 break;
7811 case 1:
7812 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
7813 break;
7814 case 2:
7815 case 3:
7816 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
7817 break;
7818 default:
7819 abort();
7820 }
7821 tcg_temp_free_i32(tmp);
7822 if (size == 3) {
7823 tcg_gen_addi_i32(addr, addr, 4);
7824 tmp = load_reg(s, rt2);
7825 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
7826 tcg_temp_free_i32(tmp);
7827 }
7828 tcg_gen_movi_i32(cpu_R[rd], 0);
7829 tcg_gen_br(done_label);
7830 gen_set_label(fail_label);
7831 tcg_gen_movi_i32(cpu_R[rd], 1);
7832 gen_set_label(done_label);
7833 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
7834}
7835#endif
7836
7837
7838
7839
7840
7841
7842
7843
7844
7845
7846static void gen_srs(DisasContext *s,
7847 uint32_t mode, uint32_t amode, bool writeback)
7848{
7849 int32_t offset;
7850 TCGv_i32 addr, tmp;
7851 bool undef = false;
7852
7853
7854
7855
7856
7857
7858
7859
7860
7861
7862
7863
7864
7865 if (s->current_el == 1 && !s->ns && mode == ARM_CPU_MODE_MON) {
7866 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(), 3);
7867 return;
7868 }
7869
7870 if (s->current_el == 0 || s->current_el == 2) {
7871 undef = true;
7872 }
7873
7874 switch (mode) {
7875 case ARM_CPU_MODE_USR:
7876 case ARM_CPU_MODE_FIQ:
7877 case ARM_CPU_MODE_IRQ:
7878 case ARM_CPU_MODE_SVC:
7879 case ARM_CPU_MODE_ABT:
7880 case ARM_CPU_MODE_UND:
7881 case ARM_CPU_MODE_SYS:
7882 break;
7883 case ARM_CPU_MODE_HYP:
7884 if (s->current_el == 1 || !arm_dc_feature(s, ARM_FEATURE_EL2)) {
7885 undef = true;
7886 }
7887 break;
7888 case ARM_CPU_MODE_MON:
7889
7890
7891
7892
7893 if (s->current_el != 3) {
7894 undef = true;
7895 }
7896 break;
7897 default:
7898 undef = true;
7899 }
7900
7901 if (undef) {
7902 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
7903 default_exception_el(s));
7904 return;
7905 }
7906
7907 addr = tcg_temp_new_i32();
7908 tmp = tcg_const_i32(mode);
7909
7910 gen_set_condexec(s);
7911 gen_set_pc_im(s, s->pc - 4);
7912 gen_helper_get_r13_banked(addr, cpu_env, tmp);
7913 tcg_temp_free_i32(tmp);
7914 switch (amode) {
7915 case 0:
7916 offset = -4;
7917 break;
7918 case 1:
7919 offset = 0;
7920 break;
7921 case 2:
7922 offset = -8;
7923 break;
7924 case 3:
7925 offset = 4;
7926 break;
7927 default:
7928 abort();
7929 }
7930 tcg_gen_addi_i32(addr, addr, offset);
7931 tmp = load_reg(s, 14);
7932 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
7933 tcg_temp_free_i32(tmp);
7934 tmp = load_cpu_field(spsr);
7935 tcg_gen_addi_i32(addr, addr, 4);
7936 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
7937 tcg_temp_free_i32(tmp);
7938 if (writeback) {
7939 switch (amode) {
7940 case 0:
7941 offset = -8;
7942 break;
7943 case 1:
7944 offset = 4;
7945 break;
7946 case 2:
7947 offset = -4;
7948 break;
7949 case 3:
7950 offset = 0;
7951 break;
7952 default:
7953 abort();
7954 }
7955 tcg_gen_addi_i32(addr, addr, offset);
7956 tmp = tcg_const_i32(mode);
7957 gen_helper_set_r13_banked(cpu_env, tmp, addr);
7958 tcg_temp_free_i32(tmp);
7959 }
7960 tcg_temp_free_i32(addr);
7961 s->is_jmp = DISAS_UPDATE;
7962}
7963
7964static void disas_arm_insn(DisasContext *s, unsigned int insn)
7965{
7966 unsigned int cond, val, op1, i, shift, rm, rs, rn, rd, sh;
7967 TCGv_i32 tmp;
7968 TCGv_i32 tmp2;
7969 TCGv_i32 tmp3;
7970 TCGv_i32 addr;
7971 TCGv_i64 tmp64;
7972
7973
7974 if (arm_dc_feature(s, ARM_FEATURE_M)) {
7975 goto illegal_op;
7976 }
7977 cond = insn >> 28;
7978 if (cond == 0xf){
7979
7980
7981
7982
7983 ARCH(5);
7984
7985
7986 if (((insn >> 25) & 7) == 1) {
7987
7988 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
7989 goto illegal_op;
7990 }
7991
7992 if (disas_neon_data_insn(s, insn)) {
7993 goto illegal_op;
7994 }
7995 return;
7996 }
7997 if ((insn & 0x0f100000) == 0x04000000) {
7998
7999 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
8000 goto illegal_op;
8001 }
8002
8003 if (disas_neon_ls_insn(s, insn)) {
8004 goto illegal_op;
8005 }
8006 return;
8007 }
8008 if ((insn & 0x0f000e10) == 0x0e000a00) {
8009
8010 if (disas_vfp_insn(s, insn)) {
8011 goto illegal_op;
8012 }
8013 return;
8014 }
8015 if (((insn & 0x0f30f000) == 0x0510f000) ||
8016 ((insn & 0x0f30f010) == 0x0710f000)) {
8017 if ((insn & (1 << 22)) == 0) {
8018
8019 if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
8020 goto illegal_op;
8021 }
8022 }
8023
8024 ARCH(5TE);
8025 return;
8026 }
8027 if (((insn & 0x0f70f000) == 0x0450f000) ||
8028 ((insn & 0x0f70f010) == 0x0650f000)) {
8029 ARCH(7);
8030 return;
8031 }
8032 if (((insn & 0x0f700000) == 0x04100000) ||
8033 ((insn & 0x0f700010) == 0x06100000)) {
8034 if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
8035 goto illegal_op;
8036 }
8037 return;
8038 }
8039
8040 if ((insn & 0x0ffffdff) == 0x01010000) {
8041 ARCH(6);
8042
8043 if (((insn >> 9) & 1) != !!(s->be_data == MO_BE)) {
8044 gen_helper_setend(cpu_env);
8045 s->is_jmp = DISAS_UPDATE;
8046 }
8047 return;
8048 } else if ((insn & 0x0fffff00) == 0x057ff000) {
8049 switch ((insn >> 4) & 0xf) {
8050 case 1:
8051 ARCH(6K);
8052 gen_clrex(s);
8053 return;
8054 case 4:
8055 case 5:
8056 ARCH(7);
8057
8058 return;
8059 case 6:
8060
8061
8062
8063
8064 gen_lookup_tb(s);
8065 return;
8066 default:
8067 goto illegal_op;
8068 }
8069 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
8070
8071 ARCH(6);
8072 gen_srs(s, (insn & 0x1f), (insn >> 23) & 3, insn & (1 << 21));
8073 return;
8074 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
8075
8076 int32_t offset;
8077 if (IS_USER(s))
8078 goto illegal_op;
8079 ARCH(6);
8080 rn = (insn >> 16) & 0xf;
8081 addr = load_reg(s, rn);
8082 i = (insn >> 23) & 3;
8083 switch (i) {
8084 case 0: offset = -4; break;
8085 case 1: offset = 0; break;
8086 case 2: offset = -8; break;
8087 case 3: offset = 4; break;
8088 default: abort();
8089 }
8090 if (offset)
8091 tcg_gen_addi_i32(addr, addr, offset);
8092
8093 tmp = tcg_temp_new_i32();
8094 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
8095 tcg_gen_addi_i32(addr, addr, 4);
8096 tmp2 = tcg_temp_new_i32();
8097 gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
8098 if (insn & (1 << 21)) {
8099
8100 switch (i) {
8101 case 0: offset = -8; break;
8102 case 1: offset = 4; break;
8103 case 2: offset = -4; break;
8104 case 3: offset = 0; break;
8105 default: abort();
8106 }
8107 if (offset)
8108 tcg_gen_addi_i32(addr, addr, offset);
8109 store_reg(s, rn, addr);
8110 } else {
8111 tcg_temp_free_i32(addr);
8112 }
8113 gen_rfe(s, tmp, tmp2);
8114 return;
8115 } else if ((insn & 0x0e000000) == 0x0a000000) {
8116
8117 int32_t offset;
8118
8119 val = (uint32_t)s->pc;
8120 tmp = tcg_temp_new_i32();
8121 tcg_gen_movi_i32(tmp, val);
8122 store_reg(s, 14, tmp);
8123
8124 offset = (((int32_t)insn) << 8) >> 8;
8125
8126 val += (offset << 2) | ((insn >> 23) & 2) | 1;
8127
8128 val += 4;
8129
8130 gen_bx_im(s, val);
8131 return;
8132 } else if ((insn & 0x0e000f00) == 0x0c000100) {
8133 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
8134
8135 if (extract32(s->c15_cpar, 1, 1)) {
8136 if (!disas_iwmmxt_insn(s, insn)) {
8137 return;
8138 }
8139 }
8140 }
8141 } else if ((insn & 0x0fe00000) == 0x0c400000) {
8142
8143 ARCH(5TE);
8144 } else if ((insn & 0x0f000010) == 0x0e000010) {
8145
8146 } else if ((insn & 0x0ff10020) == 0x01000000) {
8147 uint32_t mask;
8148 uint32_t val;
8149
8150 if (IS_USER(s))
8151 return;
8152 mask = val = 0;
8153 if (insn & (1 << 19)) {
8154 if (insn & (1 << 8))
8155 mask |= CPSR_A;
8156 if (insn & (1 << 7))
8157 mask |= CPSR_I;
8158 if (insn & (1 << 6))
8159 mask |= CPSR_F;
8160 if (insn & (1 << 18))
8161 val |= mask;
8162 }
8163 if (insn & (1 << 17)) {
8164 mask |= CPSR_M;
8165 val |= (insn & 0x1f);
8166 }
8167 if (mask) {
8168 gen_set_psr_im(s, mask, 0, val);
8169 }
8170 return;
8171 }
8172 goto illegal_op;
8173 }
8174 if (cond != 0xe) {
8175
8176
8177 s->condlabel = gen_new_label();
8178 arm_gen_test_cc(cond ^ 1, s->condlabel);
8179 s->condjmp = 1;
8180 }
8181 if ((insn & 0x0f900000) == 0x03000000) {
8182 if ((insn & (1 << 21)) == 0) {
8183 ARCH(6T2);
8184 rd = (insn >> 12) & 0xf;
8185 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
8186 if ((insn & (1 << 22)) == 0) {
8187
8188 tmp = tcg_temp_new_i32();
8189 tcg_gen_movi_i32(tmp, val);
8190 } else {
8191
8192 tmp = load_reg(s, rd);
8193 tcg_gen_ext16u_i32(tmp, tmp);
8194 tcg_gen_ori_i32(tmp, tmp, val << 16);
8195 }
8196 store_reg(s, rd, tmp);
8197 } else {
8198 if (((insn >> 12) & 0xf) != 0xf)
8199 goto illegal_op;
8200 if (((insn >> 16) & 0xf) == 0) {
8201 gen_nop_hint(s, insn & 0xff);
8202 } else {
8203
8204 val = insn & 0xff;
8205 shift = ((insn >> 8) & 0xf) * 2;
8206 if (shift)
8207 val = (val >> shift) | (val << (32 - shift));
8208 i = ((insn & (1 << 22)) != 0);
8209 if (gen_set_psr_im(s, msr_mask(s, (insn >> 16) & 0xf, i),
8210 i, val)) {
8211 goto illegal_op;
8212 }
8213 }
8214 }
8215 } else if ((insn & 0x0f900000) == 0x01000000
8216 && (insn & 0x00000090) != 0x00000090) {
8217
8218 op1 = (insn >> 21) & 3;
8219 sh = (insn >> 4) & 0xf;
8220 rm = insn & 0xf;
8221 switch (sh) {
8222 case 0x0:
8223 if (insn & (1 << 9)) {
8224
8225 int sysm = extract32(insn, 16, 4) |
8226 (extract32(insn, 8, 1) << 4);
8227 int r = extract32(insn, 22, 1);
8228
8229 if (op1 & 1) {
8230
8231 gen_msr_banked(s, r, sysm, rm);
8232 } else {
8233
8234 int rd = extract32(insn, 12, 4);
8235
8236 gen_mrs_banked(s, r, sysm, rd);
8237 }
8238 break;
8239 }
8240
8241
8242 if (op1 & 1) {
8243
8244 tmp = load_reg(s, rm);
8245 i = ((op1 & 2) != 0);
8246 if (gen_set_psr(s, msr_mask(s, (insn >> 16) & 0xf, i), i, tmp))
8247 goto illegal_op;
8248 } else {
8249
8250 rd = (insn >> 12) & 0xf;
8251 if (op1 & 2) {
8252 if (IS_USER(s))
8253 goto illegal_op;
8254 tmp = load_cpu_field(spsr);
8255 } else {
8256 tmp = tcg_temp_new_i32();
8257 gen_helper_cpsr_read(tmp, cpu_env);
8258 }
8259 store_reg(s, rd, tmp);
8260 }
8261 break;
8262 case 0x1:
8263 if (op1 == 1) {
8264
8265 ARCH(4T);
8266 tmp = load_reg(s, rm);
8267 gen_bx(s, tmp);
8268 } else if (op1 == 3) {
8269
8270 ARCH(5);
8271 rd = (insn >> 12) & 0xf;
8272 tmp = load_reg(s, rm);
8273 gen_helper_clz(tmp, tmp);
8274 store_reg(s, rd, tmp);
8275 } else {
8276 goto illegal_op;
8277 }
8278 break;
8279 case 0x2:
8280 if (op1 == 1) {
8281 ARCH(5J);
8282
8283 tmp = load_reg(s, rm);
8284 gen_bx(s, tmp);
8285 } else {
8286 goto illegal_op;
8287 }
8288 break;
8289 case 0x3:
8290 if (op1 != 1)
8291 goto illegal_op;
8292
8293 ARCH(5);
8294
8295 tmp = load_reg(s, rm);
8296 tmp2 = tcg_temp_new_i32();
8297 tcg_gen_movi_i32(tmp2, s->pc);
8298 store_reg(s, 14, tmp2);
8299 gen_bx(s, tmp);
8300 break;
8301 case 0x4:
8302 {
8303
8304 uint32_t c = extract32(insn, 8, 4);
8305
8306
8307
8308
8309
8310 if (!arm_dc_feature(s, ARM_FEATURE_CRC) || op1 == 0x3 ||
8311 (c & 0xd) != 0) {
8312 goto illegal_op;
8313 }
8314
8315 rn = extract32(insn, 16, 4);
8316 rd = extract32(insn, 12, 4);
8317
8318 tmp = load_reg(s, rn);
8319 tmp2 = load_reg(s, rm);
8320 if (op1 == 0) {
8321 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
8322 } else if (op1 == 1) {
8323 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
8324 }
8325 tmp3 = tcg_const_i32(1 << op1);
8326 if (c & 0x2) {
8327 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
8328 } else {
8329 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
8330 }
8331 tcg_temp_free_i32(tmp2);
8332 tcg_temp_free_i32(tmp3);
8333 store_reg(s, rd, tmp);
8334 break;
8335 }
8336 case 0x5:
8337 ARCH(5TE);
8338 rd = (insn >> 12) & 0xf;
8339 rn = (insn >> 16) & 0xf;
8340 tmp = load_reg(s, rm);
8341 tmp2 = load_reg(s, rn);
8342 if (op1 & 2)
8343 gen_helper_double_saturate(tmp2, cpu_env, tmp2);
8344 if (op1 & 1)
8345 gen_helper_sub_saturate(tmp, cpu_env, tmp, tmp2);
8346 else
8347 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
8348 tcg_temp_free_i32(tmp2);
8349 store_reg(s, rd, tmp);
8350 break;
8351 case 7:
8352 {
8353 int imm16 = extract32(insn, 0, 4) | (extract32(insn, 8, 12) << 4);
8354 switch (op1) {
8355 case 1:
8356
8357 ARCH(5);
8358 gen_exception_insn(s, 4, EXCP_BKPT,
8359 syn_aa32_bkpt(imm16, false),
8360 default_exception_el(s));
8361 break;
8362 case 2:
8363
8364 ARCH(7);
8365 if (IS_USER(s)) {
8366 goto illegal_op;
8367 }
8368 gen_hvc(s, imm16);
8369 break;
8370 case 3:
8371
8372 ARCH(6K);
8373 if (IS_USER(s)) {
8374 goto illegal_op;
8375 }
8376 gen_smc(s);
8377 break;
8378 default:
8379 goto illegal_op;
8380 }
8381 break;
8382 }
8383 case 0x8:
8384 case 0xa:
8385 case 0xc:
8386 case 0xe:
8387 ARCH(5TE);
8388 rs = (insn >> 8) & 0xf;
8389 rn = (insn >> 12) & 0xf;
8390 rd = (insn >> 16) & 0xf;
8391 if (op1 == 1) {
8392
8393 tmp = load_reg(s, rm);
8394 tmp2 = load_reg(s, rs);
8395 if (sh & 4)
8396 tcg_gen_sari_i32(tmp2, tmp2, 16);
8397 else
8398 gen_sxth(tmp2);
8399 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8400 tcg_gen_shri_i64(tmp64, tmp64, 16);
8401 tmp = tcg_temp_new_i32();
8402 tcg_gen_extrl_i64_i32(tmp, tmp64);
8403 tcg_temp_free_i64(tmp64);
8404 if ((sh & 2) == 0) {
8405 tmp2 = load_reg(s, rn);
8406 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8407 tcg_temp_free_i32(tmp2);
8408 }
8409 store_reg(s, rd, tmp);
8410 } else {
8411
8412 tmp = load_reg(s, rm);
8413 tmp2 = load_reg(s, rs);
8414 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
8415 tcg_temp_free_i32(tmp2);
8416 if (op1 == 2) {
8417 tmp64 = tcg_temp_new_i64();
8418 tcg_gen_ext_i32_i64(tmp64, tmp);
8419 tcg_temp_free_i32(tmp);
8420 gen_addq(s, tmp64, rn, rd);
8421 gen_storeq_reg(s, rn, rd, tmp64);
8422 tcg_temp_free_i64(tmp64);
8423 } else {
8424 if (op1 == 0) {
8425 tmp2 = load_reg(s, rn);
8426 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8427 tcg_temp_free_i32(tmp2);
8428 }
8429 store_reg(s, rd, tmp);
8430 }
8431 }
8432 break;
8433 default:
8434 goto illegal_op;
8435 }
8436 } else if (((insn & 0x0e000000) == 0 &&
8437 (insn & 0x00000090) != 0x90) ||
8438 ((insn & 0x0e000000) == (1 << 25))) {
8439 int set_cc, logic_cc, shiftop;
8440
8441 op1 = (insn >> 21) & 0xf;
8442 set_cc = (insn >> 20) & 1;
8443 logic_cc = table_logic_cc[op1] & set_cc;
8444
8445
8446 if (insn & (1 << 25)) {
8447
8448 val = insn & 0xff;
8449 shift = ((insn >> 8) & 0xf) * 2;
8450 if (shift) {
8451 val = (val >> shift) | (val << (32 - shift));
8452 }
8453 tmp2 = tcg_temp_new_i32();
8454 tcg_gen_movi_i32(tmp2, val);
8455 if (logic_cc && shift) {
8456 gen_set_CF_bit31(tmp2);
8457 }
8458 } else {
8459
8460 rm = (insn) & 0xf;
8461 tmp2 = load_reg(s, rm);
8462 shiftop = (insn >> 5) & 3;
8463 if (!(insn & (1 << 4))) {
8464 shift = (insn >> 7) & 0x1f;
8465 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
8466 } else {
8467 rs = (insn >> 8) & 0xf;
8468 tmp = load_reg(s, rs);
8469 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
8470 }
8471 }
8472 if (op1 != 0x0f && op1 != 0x0d) {
8473 rn = (insn >> 16) & 0xf;
8474 tmp = load_reg(s, rn);
8475 } else {
8476 TCGV_UNUSED_I32(tmp);
8477 }
8478 rd = (insn >> 12) & 0xf;
8479 switch(op1) {
8480 case 0x00:
8481 tcg_gen_and_i32(tmp, tmp, tmp2);
8482 if (logic_cc) {
8483 gen_logic_CC(tmp);
8484 }
8485 store_reg_bx(s, rd, tmp);
8486 break;
8487 case 0x01:
8488 tcg_gen_xor_i32(tmp, tmp, tmp2);
8489 if (logic_cc) {
8490 gen_logic_CC(tmp);
8491 }
8492 store_reg_bx(s, rd, tmp);
8493 break;
8494 case 0x02:
8495 if (set_cc && rd == 15) {
8496
8497 if (IS_USER(s)) {
8498 goto illegal_op;
8499 }
8500 gen_sub_CC(tmp, tmp, tmp2);
8501 gen_exception_return(s, tmp);
8502 } else {
8503 if (set_cc) {
8504 gen_sub_CC(tmp, tmp, tmp2);
8505 } else {
8506 tcg_gen_sub_i32(tmp, tmp, tmp2);
8507 }
8508 store_reg_bx(s, rd, tmp);
8509 }
8510 break;
8511 case 0x03:
8512 if (set_cc) {
8513 gen_sub_CC(tmp, tmp2, tmp);
8514 } else {
8515 tcg_gen_sub_i32(tmp, tmp2, tmp);
8516 }
8517 store_reg_bx(s, rd, tmp);
8518 break;
8519 case 0x04:
8520 if (set_cc) {
8521 gen_add_CC(tmp, tmp, tmp2);
8522 } else {
8523 tcg_gen_add_i32(tmp, tmp, tmp2);
8524 }
8525 store_reg_bx(s, rd, tmp);
8526 break;
8527 case 0x05:
8528 if (set_cc) {
8529 gen_adc_CC(tmp, tmp, tmp2);
8530 } else {
8531 gen_add_carry(tmp, tmp, tmp2);
8532 }
8533 store_reg_bx(s, rd, tmp);
8534 break;
8535 case 0x06:
8536 if (set_cc) {
8537 gen_sbc_CC(tmp, tmp, tmp2);
8538 } else {
8539 gen_sub_carry(tmp, tmp, tmp2);
8540 }
8541 store_reg_bx(s, rd, tmp);
8542 break;
8543 case 0x07:
8544 if (set_cc) {
8545 gen_sbc_CC(tmp, tmp2, tmp);
8546 } else {
8547 gen_sub_carry(tmp, tmp2, tmp);
8548 }
8549 store_reg_bx(s, rd, tmp);
8550 break;
8551 case 0x08:
8552 if (set_cc) {
8553 tcg_gen_and_i32(tmp, tmp, tmp2);
8554 gen_logic_CC(tmp);
8555 }
8556 tcg_temp_free_i32(tmp);
8557 break;
8558 case 0x09:
8559 if (set_cc) {
8560 tcg_gen_xor_i32(tmp, tmp, tmp2);
8561 gen_logic_CC(tmp);
8562 }
8563 tcg_temp_free_i32(tmp);
8564 break;
8565 case 0x0a:
8566 if (set_cc) {
8567 gen_sub_CC(tmp, tmp, tmp2);
8568 }
8569 tcg_temp_free_i32(tmp);
8570 break;
8571 case 0x0b:
8572 if (set_cc) {
8573 gen_add_CC(tmp, tmp, tmp2);
8574 }
8575 tcg_temp_free_i32(tmp);
8576 break;
8577 case 0x0c:
8578 tcg_gen_or_i32(tmp, tmp, tmp2);
8579 if (logic_cc) {
8580 gen_logic_CC(tmp);
8581 }
8582 store_reg_bx(s, rd, tmp);
8583 break;
8584 case 0x0d:
8585 if (logic_cc && rd == 15) {
8586
8587 if (IS_USER(s)) {
8588 goto illegal_op;
8589 }
8590 gen_exception_return(s, tmp2);
8591 } else {
8592 if (logic_cc) {
8593 gen_logic_CC(tmp2);
8594 }
8595 store_reg_bx(s, rd, tmp2);
8596 }
8597 break;
8598 case 0x0e:
8599 tcg_gen_andc_i32(tmp, tmp, tmp2);
8600 if (logic_cc) {
8601 gen_logic_CC(tmp);
8602 }
8603 store_reg_bx(s, rd, tmp);
8604 break;
8605 default:
8606 case 0x0f:
8607 tcg_gen_not_i32(tmp2, tmp2);
8608 if (logic_cc) {
8609 gen_logic_CC(tmp2);
8610 }
8611 store_reg_bx(s, rd, tmp2);
8612 break;
8613 }
8614 if (op1 != 0x0f && op1 != 0x0d) {
8615 tcg_temp_free_i32(tmp2);
8616 }
8617 } else {
8618
8619 op1 = (insn >> 24) & 0xf;
8620 switch(op1) {
8621 case 0x0:
8622 case 0x1:
8623
8624 sh = (insn >> 5) & 3;
8625 if (sh == 0) {
8626 if (op1 == 0x0) {
8627 rd = (insn >> 16) & 0xf;
8628 rn = (insn >> 12) & 0xf;
8629 rs = (insn >> 8) & 0xf;
8630 rm = (insn) & 0xf;
8631 op1 = (insn >> 20) & 0xf;
8632 switch (op1) {
8633 case 0: case 1: case 2: case 3: case 6:
8634
8635 tmp = load_reg(s, rs);
8636 tmp2 = load_reg(s, rm);
8637 tcg_gen_mul_i32(tmp, tmp, tmp2);
8638 tcg_temp_free_i32(tmp2);
8639 if (insn & (1 << 22)) {
8640
8641 ARCH(6T2);
8642 tmp2 = load_reg(s, rn);
8643 tcg_gen_sub_i32(tmp, tmp2, tmp);
8644 tcg_temp_free_i32(tmp2);
8645 } else if (insn & (1 << 21)) {
8646
8647 tmp2 = load_reg(s, rn);
8648 tcg_gen_add_i32(tmp, tmp, tmp2);
8649 tcg_temp_free_i32(tmp2);
8650 }
8651 if (insn & (1 << 20))
8652 gen_logic_CC(tmp);
8653 store_reg(s, rd, tmp);
8654 break;
8655 case 4:
8656
8657 ARCH(6);
8658 tmp = load_reg(s, rs);
8659 tmp2 = load_reg(s, rm);
8660 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
8661 gen_addq_lo(s, tmp64, rn);
8662 gen_addq_lo(s, tmp64, rd);
8663 gen_storeq_reg(s, rn, rd, tmp64);
8664 tcg_temp_free_i64(tmp64);
8665 break;
8666 case 8: case 9: case 10: case 11:
8667 case 12: case 13: case 14: case 15:
8668
8669 tmp = load_reg(s, rs);
8670 tmp2 = load_reg(s, rm);
8671 if (insn & (1 << 22)) {
8672 tcg_gen_muls2_i32(tmp, tmp2, tmp, tmp2);
8673 } else {
8674 tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2);
8675 }
8676 if (insn & (1 << 21)) {
8677 TCGv_i32 al = load_reg(s, rn);
8678 TCGv_i32 ah = load_reg(s, rd);
8679 tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, al, ah);
8680 tcg_temp_free_i32(al);
8681 tcg_temp_free_i32(ah);
8682 }
8683 if (insn & (1 << 20)) {
8684 gen_logicq_cc(tmp, tmp2);
8685 }
8686 store_reg(s, rn, tmp);
8687 store_reg(s, rd, tmp2);
8688 break;
8689 default:
8690 goto illegal_op;
8691 }
8692 } else {
8693 rn = (insn >> 16) & 0xf;
8694 rd = (insn >> 12) & 0xf;
8695 if (insn & (1 << 23)) {
8696
8697 int op2 = (insn >> 8) & 3;
8698 op1 = (insn >> 21) & 0x3;
8699
8700 switch (op2) {
8701 case 0:
8702 if (op1 == 1) {
8703 goto illegal_op;
8704 }
8705 ARCH(8);
8706 break;
8707 case 1:
8708 goto illegal_op;
8709 case 2:
8710 ARCH(8);
8711 break;
8712 case 3:
8713 if (op1) {
8714 ARCH(6K);
8715 } else {
8716 ARCH(6);
8717 }
8718 break;
8719 }
8720
8721 addr = tcg_temp_local_new_i32();
8722 load_reg_var(s, addr, rn);
8723
8724
8725
8726
8727 if (op2 == 0) {
8728 if (insn & (1 << 20)) {
8729 tmp = tcg_temp_new_i32();
8730 switch (op1) {
8731 case 0:
8732 gen_aa32_ld32u(s, tmp, addr,
8733 get_mem_index(s));
8734 break;
8735 case 2:
8736 gen_aa32_ld8u(s, tmp, addr,
8737 get_mem_index(s));
8738 break;
8739 case 3:
8740 gen_aa32_ld16u(s, tmp, addr,
8741 get_mem_index(s));
8742 break;
8743 default:
8744 abort();
8745 }
8746 store_reg(s, rd, tmp);
8747 } else {
8748 rm = insn & 0xf;
8749 tmp = load_reg(s, rm);
8750 switch (op1) {
8751 case 0:
8752 gen_aa32_st32(s, tmp, addr,
8753 get_mem_index(s));
8754 break;
8755 case 2:
8756 gen_aa32_st8(s, tmp, addr,
8757 get_mem_index(s));
8758 break;
8759 case 3:
8760 gen_aa32_st16(s, tmp, addr,
8761 get_mem_index(s));
8762 break;
8763 default:
8764 abort();
8765 }
8766 tcg_temp_free_i32(tmp);
8767 }
8768 } else if (insn & (1 << 20)) {
8769 switch (op1) {
8770 case 0:
8771 gen_load_exclusive(s, rd, 15, addr, 2);
8772 break;
8773 case 1:
8774 gen_load_exclusive(s, rd, rd + 1, addr, 3);
8775 break;
8776 case 2:
8777 gen_load_exclusive(s, rd, 15, addr, 0);
8778 break;
8779 case 3:
8780 gen_load_exclusive(s, rd, 15, addr, 1);
8781 break;
8782 default:
8783 abort();
8784 }
8785 } else {
8786 rm = insn & 0xf;
8787 switch (op1) {
8788 case 0:
8789 gen_store_exclusive(s, rd, rm, 15, addr, 2);
8790 break;
8791 case 1:
8792 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
8793 break;
8794 case 2:
8795 gen_store_exclusive(s, rd, rm, 15, addr, 0);
8796 break;
8797 case 3:
8798 gen_store_exclusive(s, rd, rm, 15, addr, 1);
8799 break;
8800 default:
8801 abort();
8802 }
8803 }
8804 tcg_temp_free_i32(addr);
8805 } else {
8806
8807 rm = (insn) & 0xf;
8808
8809
8810
8811
8812 addr = load_reg(s, rn);
8813 tmp = load_reg(s, rm);
8814 tmp2 = tcg_temp_new_i32();
8815 if (insn & (1 << 22)) {
8816 gen_aa32_ld8u(s, tmp2, addr, get_mem_index(s));
8817 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
8818 } else {
8819 gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
8820 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
8821 }
8822 tcg_temp_free_i32(tmp);
8823 tcg_temp_free_i32(addr);
8824 store_reg(s, rd, tmp2);
8825 }
8826 }
8827 } else {
8828 int address_offset;
8829 bool load = insn & (1 << 20);
8830 bool doubleword = false;
8831
8832 rn = (insn >> 16) & 0xf;
8833 rd = (insn >> 12) & 0xf;
8834
8835 if (!load && (sh & 2)) {
8836
8837 ARCH(5TE);
8838 if (rd & 1) {
8839
8840 goto illegal_op;
8841 }
8842 load = (sh & 1) == 0;
8843 doubleword = true;
8844 }
8845
8846 addr = load_reg(s, rn);
8847 if (insn & (1 << 24))
8848 gen_add_datah_offset(s, insn, 0, addr);
8849 address_offset = 0;
8850
8851 if (doubleword) {
8852 if (!load) {
8853
8854 tmp = load_reg(s, rd);
8855 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
8856 tcg_temp_free_i32(tmp);
8857 tcg_gen_addi_i32(addr, addr, 4);
8858 tmp = load_reg(s, rd + 1);
8859 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
8860 tcg_temp_free_i32(tmp);
8861 } else {
8862
8863 tmp = tcg_temp_new_i32();
8864 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
8865 store_reg(s, rd, tmp);
8866 tcg_gen_addi_i32(addr, addr, 4);
8867 tmp = tcg_temp_new_i32();
8868 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
8869 rd++;
8870 }
8871 address_offset = -4;
8872 } else if (load) {
8873
8874 tmp = tcg_temp_new_i32();
8875 switch (sh) {
8876 case 1:
8877 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
8878 break;
8879 case 2:
8880 gen_aa32_ld8s(s, tmp, addr, get_mem_index(s));
8881 break;
8882 default:
8883 case 3:
8884 gen_aa32_ld16s(s, tmp, addr, get_mem_index(s));
8885 break;
8886 }
8887 } else {
8888
8889 tmp = load_reg(s, rd);
8890 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
8891 tcg_temp_free_i32(tmp);
8892 }
8893
8894
8895
8896
8897 if (!(insn & (1 << 24))) {
8898 gen_add_datah_offset(s, insn, address_offset, addr);
8899 store_reg(s, rn, addr);
8900 } else if (insn & (1 << 21)) {
8901 if (address_offset)
8902 tcg_gen_addi_i32(addr, addr, address_offset);
8903 store_reg(s, rn, addr);
8904 } else {
8905 tcg_temp_free_i32(addr);
8906 }
8907 if (load) {
8908
8909 store_reg(s, rd, tmp);
8910 }
8911 }
8912 break;
8913 case 0x4:
8914 case 0x5:
8915 goto do_ldst;
8916 case 0x6:
8917 case 0x7:
8918 if (insn & (1 << 4)) {
8919 ARCH(6);
8920
8921 rm = insn & 0xf;
8922 rn = (insn >> 16) & 0xf;
8923 rd = (insn >> 12) & 0xf;
8924 rs = (insn >> 8) & 0xf;
8925 switch ((insn >> 23) & 3) {
8926 case 0:
8927 op1 = (insn >> 20) & 7;
8928 tmp = load_reg(s, rn);
8929 tmp2 = load_reg(s, rm);
8930 sh = (insn >> 5) & 7;
8931 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
8932 goto illegal_op;
8933 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
8934 tcg_temp_free_i32(tmp2);
8935 store_reg(s, rd, tmp);
8936 break;
8937 case 1:
8938 if ((insn & 0x00700020) == 0) {
8939
8940 tmp = load_reg(s, rn);
8941 tmp2 = load_reg(s, rm);
8942 shift = (insn >> 7) & 0x1f;
8943 if (insn & (1 << 6)) {
8944
8945 if (shift == 0)
8946 shift = 31;
8947 tcg_gen_sari_i32(tmp2, tmp2, shift);
8948 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
8949 tcg_gen_ext16u_i32(tmp2, tmp2);
8950 } else {
8951
8952 if (shift)
8953 tcg_gen_shli_i32(tmp2, tmp2, shift);
8954 tcg_gen_ext16u_i32(tmp, tmp);
8955 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
8956 }
8957 tcg_gen_or_i32(tmp, tmp, tmp2);
8958 tcg_temp_free_i32(tmp2);
8959 store_reg(s, rd, tmp);
8960 } else if ((insn & 0x00200020) == 0x00200000) {
8961
8962 tmp = load_reg(s, rm);
8963 shift = (insn >> 7) & 0x1f;
8964 if (insn & (1 << 6)) {
8965 if (shift == 0)
8966 shift = 31;
8967 tcg_gen_sari_i32(tmp, tmp, shift);
8968 } else {
8969 tcg_gen_shli_i32(tmp, tmp, shift);
8970 }
8971 sh = (insn >> 16) & 0x1f;
8972 tmp2 = tcg_const_i32(sh);
8973 if (insn & (1 << 22))
8974 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
8975 else
8976 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
8977 tcg_temp_free_i32(tmp2);
8978 store_reg(s, rd, tmp);
8979 } else if ((insn & 0x00300fe0) == 0x00200f20) {
8980
8981 tmp = load_reg(s, rm);
8982 sh = (insn >> 16) & 0x1f;
8983 tmp2 = tcg_const_i32(sh);
8984 if (insn & (1 << 22))
8985 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
8986 else
8987 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
8988 tcg_temp_free_i32(tmp2);
8989 store_reg(s, rd, tmp);
8990 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
8991
8992 tmp = load_reg(s, rn);
8993 tmp2 = load_reg(s, rm);
8994 tmp3 = tcg_temp_new_i32();
8995 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
8996 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
8997 tcg_temp_free_i32(tmp3);
8998 tcg_temp_free_i32(tmp2);
8999 store_reg(s, rd, tmp);
9000 } else if ((insn & 0x000003e0) == 0x00000060) {
9001 tmp = load_reg(s, rm);
9002 shift = (insn >> 10) & 3;
9003
9004
9005 if (shift != 0)
9006 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
9007 op1 = (insn >> 20) & 7;
9008 switch (op1) {
9009 case 0: gen_sxtb16(tmp); break;
9010 case 2: gen_sxtb(tmp); break;
9011 case 3: gen_sxth(tmp); break;
9012 case 4: gen_uxtb16(tmp); break;
9013 case 6: gen_uxtb(tmp); break;
9014 case 7: gen_uxth(tmp); break;
9015 default: goto illegal_op;
9016 }
9017 if (rn != 15) {
9018 tmp2 = load_reg(s, rn);
9019 if ((op1 & 3) == 0) {
9020 gen_add16(tmp, tmp2);
9021 } else {
9022 tcg_gen_add_i32(tmp, tmp, tmp2);
9023 tcg_temp_free_i32(tmp2);
9024 }
9025 }
9026 store_reg(s, rd, tmp);
9027 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
9028
9029 tmp = load_reg(s, rm);
9030 if (insn & (1 << 22)) {
9031 if (insn & (1 << 7)) {
9032 gen_revsh(tmp);
9033 } else {
9034 ARCH(6T2);
9035 gen_helper_rbit(tmp, tmp);
9036 }
9037 } else {
9038 if (insn & (1 << 7))
9039 gen_rev16(tmp);
9040 else
9041 tcg_gen_bswap32_i32(tmp, tmp);
9042 }
9043 store_reg(s, rd, tmp);
9044 } else {
9045 goto illegal_op;
9046 }
9047 break;
9048 case 2:
9049 switch ((insn >> 20) & 0x7) {
9050 case 5:
9051 if (((insn >> 6) ^ (insn >> 7)) & 1) {
9052
9053 goto illegal_op;
9054 }
9055
9056
9057 tmp = load_reg(s, rm);
9058 tmp2 = load_reg(s, rs);
9059 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9060
9061 if (rd != 15) {
9062 tmp = load_reg(s, rd);
9063 if (insn & (1 << 6)) {
9064 tmp64 = gen_subq_msw(tmp64, tmp);
9065 } else {
9066 tmp64 = gen_addq_msw(tmp64, tmp);
9067 }
9068 }
9069 if (insn & (1 << 5)) {
9070 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
9071 }
9072 tcg_gen_shri_i64(tmp64, tmp64, 32);
9073 tmp = tcg_temp_new_i32();
9074 tcg_gen_extrl_i64_i32(tmp, tmp64);
9075 tcg_temp_free_i64(tmp64);
9076 store_reg(s, rn, tmp);
9077 break;
9078 case 0:
9079 case 4:
9080
9081 if (insn & (1 << 7)) {
9082 goto illegal_op;
9083 }
9084 tmp = load_reg(s, rm);
9085 tmp2 = load_reg(s, rs);
9086 if (insn & (1 << 5))
9087 gen_swap_half(tmp2);
9088 gen_smul_dual(tmp, tmp2);
9089 if (insn & (1 << 22)) {
9090
9091 TCGv_i64 tmp64_2;
9092
9093 tmp64 = tcg_temp_new_i64();
9094 tmp64_2 = tcg_temp_new_i64();
9095 tcg_gen_ext_i32_i64(tmp64, tmp);
9096 tcg_gen_ext_i32_i64(tmp64_2, tmp2);
9097 tcg_temp_free_i32(tmp);
9098 tcg_temp_free_i32(tmp2);
9099 if (insn & (1 << 6)) {
9100 tcg_gen_sub_i64(tmp64, tmp64, tmp64_2);
9101 } else {
9102 tcg_gen_add_i64(tmp64, tmp64, tmp64_2);
9103 }
9104 tcg_temp_free_i64(tmp64_2);
9105 gen_addq(s, tmp64, rd, rn);
9106 gen_storeq_reg(s, rd, rn, tmp64);
9107 tcg_temp_free_i64(tmp64);
9108 } else {
9109
9110 if (insn & (1 << 6)) {
9111
9112 tcg_gen_sub_i32(tmp, tmp, tmp2);
9113 } else {
9114
9115
9116
9117
9118
9119 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9120 }
9121 tcg_temp_free_i32(tmp2);
9122 if (rd != 15)
9123 {
9124 tmp2 = load_reg(s, rd);
9125 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9126 tcg_temp_free_i32(tmp2);
9127 }
9128 store_reg(s, rn, tmp);
9129 }
9130 break;
9131 case 1:
9132 case 3:
9133
9134 if (!arm_dc_feature(s, ARM_FEATURE_ARM_DIV)) {
9135 goto illegal_op;
9136 }
9137 if (((insn >> 5) & 7) || (rd != 15)) {
9138 goto illegal_op;
9139 }
9140 tmp = load_reg(s, rm);
9141 tmp2 = load_reg(s, rs);
9142 if (insn & (1 << 21)) {
9143 gen_helper_udiv(tmp, tmp, tmp2);
9144 } else {
9145 gen_helper_sdiv(tmp, tmp, tmp2);
9146 }
9147 tcg_temp_free_i32(tmp2);
9148 store_reg(s, rn, tmp);
9149 break;
9150 default:
9151 goto illegal_op;
9152 }
9153 break;
9154 case 3:
9155 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
9156 switch (op1) {
9157 case 0:
9158 ARCH(6);
9159 tmp = load_reg(s, rm);
9160 tmp2 = load_reg(s, rs);
9161 gen_helper_usad8(tmp, tmp, tmp2);
9162 tcg_temp_free_i32(tmp2);
9163 if (rd != 15) {
9164 tmp2 = load_reg(s, rd);
9165 tcg_gen_add_i32(tmp, tmp, tmp2);
9166 tcg_temp_free_i32(tmp2);
9167 }
9168 store_reg(s, rn, tmp);
9169 break;
9170 case 0x20: case 0x24: case 0x28: case 0x2c:
9171
9172 ARCH(6T2);
9173 shift = (insn >> 7) & 0x1f;
9174 i = (insn >> 16) & 0x1f;
9175 if (i < shift) {
9176
9177 goto illegal_op;
9178 }
9179 i = i + 1 - shift;
9180 if (rm == 15) {
9181 tmp = tcg_temp_new_i32();
9182 tcg_gen_movi_i32(tmp, 0);
9183 } else {
9184 tmp = load_reg(s, rm);
9185 }
9186 if (i != 32) {
9187 tmp2 = load_reg(s, rd);
9188 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, i);
9189 tcg_temp_free_i32(tmp2);
9190 }
9191 store_reg(s, rd, tmp);
9192 break;
9193 case 0x12: case 0x16: case 0x1a: case 0x1e:
9194 case 0x32: case 0x36: case 0x3a: case 0x3e:
9195 ARCH(6T2);
9196 tmp = load_reg(s, rm);
9197 shift = (insn >> 7) & 0x1f;
9198 i = ((insn >> 16) & 0x1f) + 1;
9199 if (shift + i > 32)
9200 goto illegal_op;
9201 if (i < 32) {
9202 if (op1 & 0x20) {
9203 gen_ubfx(tmp, shift, (1u << i) - 1);
9204 } else {
9205 gen_sbfx(tmp, shift, i);
9206 }
9207 }
9208 store_reg(s, rd, tmp);
9209 break;
9210 default:
9211 goto illegal_op;
9212 }
9213 break;
9214 }
9215 break;
9216 }
9217 do_ldst:
9218
9219
9220
9221
9222 sh = (0xf << 20) | (0xf << 4);
9223 if (op1 == 0x7 && ((insn & sh) == sh))
9224 {
9225 goto illegal_op;
9226 }
9227
9228 rn = (insn >> 16) & 0xf;
9229 rd = (insn >> 12) & 0xf;
9230 tmp2 = load_reg(s, rn);
9231 if ((insn & 0x01200000) == 0x00200000) {
9232
9233 i = get_a32_user_mem_index(s);
9234 } else {
9235 i = get_mem_index(s);
9236 }
9237 if (insn & (1 << 24))
9238 gen_add_data_offset(s, insn, tmp2);
9239 if (insn & (1 << 20)) {
9240
9241 tmp = tcg_temp_new_i32();
9242 if (insn & (1 << 22)) {
9243 gen_aa32_ld8u(s, tmp, tmp2, i);
9244 } else {
9245 gen_aa32_ld32u(s, tmp, tmp2, i);
9246 }
9247 } else {
9248
9249 tmp = load_reg(s, rd);
9250 if (insn & (1 << 22)) {
9251 gen_aa32_st8(s, tmp, tmp2, i);
9252 } else {
9253 gen_aa32_st32(s, tmp, tmp2, i);
9254 }
9255 tcg_temp_free_i32(tmp);
9256 }
9257 if (!(insn & (1 << 24))) {
9258 gen_add_data_offset(s, insn, tmp2);
9259 store_reg(s, rn, tmp2);
9260 } else if (insn & (1 << 21)) {
9261 store_reg(s, rn, tmp2);
9262 } else {
9263 tcg_temp_free_i32(tmp2);
9264 }
9265 if (insn & (1 << 20)) {
9266
9267 store_reg_from_load(s, rd, tmp);
9268 }
9269 break;
9270 case 0x08:
9271 case 0x09:
9272 {
9273 int j, n, loaded_base;
9274 bool exc_return = false;
9275 bool is_load = extract32(insn, 20, 1);
9276 bool user = false;
9277 TCGv_i32 loaded_var;
9278
9279
9280 if (insn & (1 << 22)) {
9281
9282 if (IS_USER(s))
9283 goto illegal_op;
9284
9285 if (is_load && extract32(insn, 15, 1)) {
9286 exc_return = true;
9287 } else {
9288 user = true;
9289 }
9290 }
9291 rn = (insn >> 16) & 0xf;
9292 addr = load_reg(s, rn);
9293
9294
9295 loaded_base = 0;
9296 TCGV_UNUSED_I32(loaded_var);
9297 n = 0;
9298 for(i=0;i<16;i++) {
9299 if (insn & (1 << i))
9300 n++;
9301 }
9302
9303 if (insn & (1 << 23)) {
9304 if (insn & (1 << 24)) {
9305
9306 tcg_gen_addi_i32(addr, addr, 4);
9307 } else {
9308
9309 }
9310 } else {
9311 if (insn & (1 << 24)) {
9312
9313 tcg_gen_addi_i32(addr, addr, -(n * 4));
9314 } else {
9315
9316 if (n != 1)
9317 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
9318 }
9319 }
9320 j = 0;
9321 for(i=0;i<16;i++) {
9322 if (insn & (1 << i)) {
9323 if (is_load) {
9324
9325 tmp = tcg_temp_new_i32();
9326 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
9327 if (user) {
9328 tmp2 = tcg_const_i32(i);
9329 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
9330 tcg_temp_free_i32(tmp2);
9331 tcg_temp_free_i32(tmp);
9332 } else if (i == rn) {
9333 loaded_var = tmp;
9334 loaded_base = 1;
9335 } else {
9336 store_reg_from_load(s, i, tmp);
9337 }
9338 } else {
9339
9340 if (i == 15) {
9341
9342 val = (long)s->pc + 4;
9343 tmp = tcg_temp_new_i32();
9344 tcg_gen_movi_i32(tmp, val);
9345 } else if (user) {
9346 tmp = tcg_temp_new_i32();
9347 tmp2 = tcg_const_i32(i);
9348 gen_helper_get_user_reg(tmp, cpu_env, tmp2);
9349 tcg_temp_free_i32(tmp2);
9350 } else {
9351 tmp = load_reg(s, i);
9352 }
9353 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
9354 tcg_temp_free_i32(tmp);
9355 }
9356 j++;
9357
9358 if (j != n)
9359 tcg_gen_addi_i32(addr, addr, 4);
9360 }
9361 }
9362 if (insn & (1 << 21)) {
9363
9364 if (insn & (1 << 23)) {
9365 if (insn & (1 << 24)) {
9366
9367 } else {
9368
9369 tcg_gen_addi_i32(addr, addr, 4);
9370 }
9371 } else {
9372 if (insn & (1 << 24)) {
9373
9374 if (n != 1)
9375 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
9376 } else {
9377
9378 tcg_gen_addi_i32(addr, addr, -(n * 4));
9379 }
9380 }
9381 store_reg(s, rn, addr);
9382 } else {
9383 tcg_temp_free_i32(addr);
9384 }
9385 if (loaded_base) {
9386 store_reg(s, rn, loaded_var);
9387 }
9388 if (exc_return) {
9389
9390 tmp = load_cpu_field(spsr);
9391 gen_helper_cpsr_write_eret(cpu_env, tmp);
9392 tcg_temp_free_i32(tmp);
9393 s->is_jmp = DISAS_JUMP;
9394 }
9395 }
9396 break;
9397 case 0xa:
9398 case 0xb:
9399 {
9400 int32_t offset;
9401
9402
9403 val = (int32_t)s->pc;
9404 if (insn & (1 << 24)) {
9405 tmp = tcg_temp_new_i32();
9406 tcg_gen_movi_i32(tmp, val);
9407 store_reg(s, 14, tmp);
9408 }
9409 offset = sextract32(insn << 2, 0, 26);
9410 val += offset + 4;
9411 gen_jmp(s, val);
9412 }
9413 break;
9414 case 0xc:
9415 case 0xd:
9416 case 0xe:
9417 if (((insn >> 8) & 0xe) == 10) {
9418
9419 if (disas_vfp_insn(s, insn)) {
9420 goto illegal_op;
9421 }
9422 } else if (disas_coproc_insn(s, insn)) {
9423
9424 goto illegal_op;
9425 }
9426 break;
9427 case 0xf:
9428
9429 gen_set_pc_im(s, s->pc);
9430 s->svc_imm = extract32(insn, 0, 24);
9431 s->is_jmp = DISAS_SWI;
9432 break;
9433 default:
9434 illegal_op:
9435 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
9436 default_exception_el(s));
9437 break;
9438 }
9439 }
9440}
9441
9442
9443static int
9444thumb2_logic_op(int op)
9445{
9446 return (op < 8);
9447}
9448
9449
9450
9451
9452
9453
9454
9455static int
9456gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out,
9457 TCGv_i32 t0, TCGv_i32 t1)
9458{
9459 int logic_cc;
9460
9461 logic_cc = 0;
9462 switch (op) {
9463 case 0:
9464 tcg_gen_and_i32(t0, t0, t1);
9465 logic_cc = conds;
9466 break;
9467 case 1:
9468 tcg_gen_andc_i32(t0, t0, t1);
9469 logic_cc = conds;
9470 break;
9471 case 2:
9472 tcg_gen_or_i32(t0, t0, t1);
9473 logic_cc = conds;
9474 break;
9475 case 3:
9476 tcg_gen_orc_i32(t0, t0, t1);
9477 logic_cc = conds;
9478 break;
9479 case 4:
9480 tcg_gen_xor_i32(t0, t0, t1);
9481 logic_cc = conds;
9482 break;
9483 case 8:
9484 if (conds)
9485 gen_add_CC(t0, t0, t1);
9486 else
9487 tcg_gen_add_i32(t0, t0, t1);
9488 break;
9489 case 10:
9490 if (conds)
9491 gen_adc_CC(t0, t0, t1);
9492 else
9493 gen_adc(t0, t1);
9494 break;
9495 case 11:
9496 if (conds) {
9497 gen_sbc_CC(t0, t0, t1);
9498 } else {
9499 gen_sub_carry(t0, t0, t1);
9500 }
9501 break;
9502 case 13:
9503 if (conds)
9504 gen_sub_CC(t0, t0, t1);
9505 else
9506 tcg_gen_sub_i32(t0, t0, t1);
9507 break;
9508 case 14:
9509 if (conds)
9510 gen_sub_CC(t0, t1, t0);
9511 else
9512 tcg_gen_sub_i32(t0, t1, t0);
9513 break;
9514 default:
9515 return 1;
9516 }
9517 if (logic_cc) {
9518 gen_logic_CC(t0);
9519 if (shifter_out)
9520 gen_set_CF_bit31(t1);
9521 }
9522 return 0;
9523}
9524
9525
9526
9527static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw1)
9528{
9529 uint32_t insn, imm, shift, offset;
9530 uint32_t rd, rn, rm, rs;
9531 TCGv_i32 tmp;
9532 TCGv_i32 tmp2;
9533 TCGv_i32 tmp3;
9534 TCGv_i32 addr;
9535 TCGv_i64 tmp64;
9536 int op;
9537 int shiftop;
9538 int conds;
9539 int logic_cc;
9540
9541 if (!(arm_dc_feature(s, ARM_FEATURE_THUMB2)
9542 || arm_dc_feature(s, ARM_FEATURE_M))) {
9543
9544
9545 insn = insn_hw1;
9546 if ((insn & (1 << 12)) == 0) {
9547 ARCH(5);
9548
9549 offset = ((insn & 0x7ff) << 1);
9550 tmp = load_reg(s, 14);
9551 tcg_gen_addi_i32(tmp, tmp, offset);
9552 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
9553
9554 tmp2 = tcg_temp_new_i32();
9555 tcg_gen_movi_i32(tmp2, s->pc | 1);
9556 store_reg(s, 14, tmp2);
9557 gen_bx(s, tmp);
9558 return 0;
9559 }
9560 if (insn & (1 << 11)) {
9561
9562 offset = ((insn & 0x7ff) << 1) | 1;
9563 tmp = load_reg(s, 14);
9564 tcg_gen_addi_i32(tmp, tmp, offset);
9565
9566 tmp2 = tcg_temp_new_i32();
9567 tcg_gen_movi_i32(tmp2, s->pc | 1);
9568 store_reg(s, 14, tmp2);
9569 gen_bx(s, tmp);
9570 return 0;
9571 }
9572 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
9573
9574
9575
9576 offset = ((int32_t)insn << 21) >> 9;
9577 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
9578 return 0;
9579 }
9580
9581 }
9582
9583 insn = arm_lduw_code(env, s->pc, s->sctlr_b);
9584 s->pc += 2;
9585 insn |= (uint32_t)insn_hw1 << 16;
9586
9587 if ((insn & 0xf800e800) != 0xf000e800) {
9588 ARCH(6T2);
9589 }
9590
9591 rn = (insn >> 16) & 0xf;
9592 rs = (insn >> 12) & 0xf;
9593 rd = (insn >> 8) & 0xf;
9594 rm = insn & 0xf;
9595 switch ((insn >> 25) & 0xf) {
9596 case 0: case 1: case 2: case 3:
9597
9598 abort();
9599 case 4:
9600 if (insn & (1 << 22)) {
9601
9602 if (insn & 0x01200000) {
9603
9604 if (rn == 15) {
9605 addr = tcg_temp_new_i32();
9606 tcg_gen_movi_i32(addr, s->pc & ~3);
9607 } else {
9608 addr = load_reg(s, rn);
9609 }
9610 offset = (insn & 0xff) * 4;
9611 if ((insn & (1 << 23)) == 0)
9612 offset = -offset;
9613 if (insn & (1 << 24)) {
9614 tcg_gen_addi_i32(addr, addr, offset);
9615 offset = 0;
9616 }
9617 if (insn & (1 << 20)) {
9618
9619 tmp = tcg_temp_new_i32();
9620 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
9621 store_reg(s, rs, tmp);
9622 tcg_gen_addi_i32(addr, addr, 4);
9623 tmp = tcg_temp_new_i32();
9624 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
9625 store_reg(s, rd, tmp);
9626 } else {
9627
9628 tmp = load_reg(s, rs);
9629 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
9630 tcg_temp_free_i32(tmp);
9631 tcg_gen_addi_i32(addr, addr, 4);
9632 tmp = load_reg(s, rd);
9633 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
9634 tcg_temp_free_i32(tmp);
9635 }
9636 if (insn & (1 << 21)) {
9637
9638 if (rn == 15)
9639 goto illegal_op;
9640 tcg_gen_addi_i32(addr, addr, offset - 4);
9641 store_reg(s, rn, addr);
9642 } else {
9643 tcg_temp_free_i32(addr);
9644 }
9645 } else if ((insn & (1 << 23)) == 0) {
9646
9647 addr = tcg_temp_local_new_i32();
9648 load_reg_var(s, addr, rn);
9649 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
9650 if (insn & (1 << 20)) {
9651 gen_load_exclusive(s, rs, 15, addr, 2);
9652 } else {
9653 gen_store_exclusive(s, rd, rs, 15, addr, 2);
9654 }
9655 tcg_temp_free_i32(addr);
9656 } else if ((insn & (7 << 5)) == 0) {
9657
9658 if (rn == 15) {
9659 addr = tcg_temp_new_i32();
9660 tcg_gen_movi_i32(addr, s->pc);
9661 } else {
9662 addr = load_reg(s, rn);
9663 }
9664 tmp = load_reg(s, rm);
9665 tcg_gen_add_i32(addr, addr, tmp);
9666 if (insn & (1 << 4)) {
9667
9668 tcg_gen_add_i32(addr, addr, tmp);
9669 tcg_temp_free_i32(tmp);
9670 tmp = tcg_temp_new_i32();
9671 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
9672 } else {
9673 tcg_temp_free_i32(tmp);
9674 tmp = tcg_temp_new_i32();
9675 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
9676 }
9677 tcg_temp_free_i32(addr);
9678 tcg_gen_shli_i32(tmp, tmp, 1);
9679 tcg_gen_addi_i32(tmp, tmp, s->pc);
9680 store_reg(s, 15, tmp);
9681 } else {
9682 int op2 = (insn >> 6) & 0x3;
9683 op = (insn >> 4) & 0x3;
9684 switch (op2) {
9685 case 0:
9686 goto illegal_op;
9687 case 1:
9688
9689 if (op == 2) {
9690 goto illegal_op;
9691 }
9692 ARCH(7);
9693 break;
9694 case 2:
9695
9696 if (op == 3) {
9697 goto illegal_op;
9698 }
9699
9700 case 3:
9701
9702 ARCH(8);
9703 break;
9704 }
9705 addr = tcg_temp_local_new_i32();
9706 load_reg_var(s, addr, rn);
9707 if (!(op2 & 1)) {
9708 if (insn & (1 << 20)) {
9709 tmp = tcg_temp_new_i32();
9710 switch (op) {
9711 case 0:
9712 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
9713 break;
9714 case 1:
9715 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
9716 break;
9717 case 2:
9718 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
9719 break;
9720 default:
9721 abort();
9722 }
9723 store_reg(s, rs, tmp);
9724 } else {
9725 tmp = load_reg(s, rs);
9726 switch (op) {
9727 case 0:
9728 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
9729 break;
9730 case 1:
9731 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
9732 break;
9733 case 2:
9734 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
9735 break;
9736 default:
9737 abort();
9738 }
9739 tcg_temp_free_i32(tmp);
9740 }
9741 } else if (insn & (1 << 20)) {
9742 gen_load_exclusive(s, rs, rd, addr, op);
9743 } else {
9744 gen_store_exclusive(s, rm, rs, rd, addr, op);
9745 }
9746 tcg_temp_free_i32(addr);
9747 }
9748 } else {
9749
9750 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
9751
9752 if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
9753 goto illegal_op;
9754 }
9755 if (insn & (1 << 20)) {
9756
9757 addr = load_reg(s, rn);
9758 if ((insn & (1 << 24)) == 0)
9759 tcg_gen_addi_i32(addr, addr, -8);
9760
9761 tmp = tcg_temp_new_i32();
9762 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
9763 tcg_gen_addi_i32(addr, addr, 4);
9764 tmp2 = tcg_temp_new_i32();
9765 gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
9766 if (insn & (1 << 21)) {
9767
9768 if (insn & (1 << 24)) {
9769 tcg_gen_addi_i32(addr, addr, 4);
9770 } else {
9771 tcg_gen_addi_i32(addr, addr, -4);
9772 }
9773 store_reg(s, rn, addr);
9774 } else {
9775 tcg_temp_free_i32(addr);
9776 }
9777 gen_rfe(s, tmp, tmp2);
9778 } else {
9779
9780 gen_srs(s, (insn & 0x1f), (insn & (1 << 24)) ? 1 : 2,
9781 insn & (1 << 21));
9782 }
9783 } else {
9784 int i, loaded_base = 0;
9785 TCGv_i32 loaded_var;
9786
9787 addr = load_reg(s, rn);
9788 offset = 0;
9789 for (i = 0; i < 16; i++) {
9790 if (insn & (1 << i))
9791 offset += 4;
9792 }
9793 if (insn & (1 << 24)) {
9794 tcg_gen_addi_i32(addr, addr, -offset);
9795 }
9796
9797 TCGV_UNUSED_I32(loaded_var);
9798 for (i = 0; i < 16; i++) {
9799 if ((insn & (1 << i)) == 0)
9800 continue;
9801 if (insn & (1 << 20)) {
9802
9803 tmp = tcg_temp_new_i32();
9804 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
9805 if (i == 15) {
9806 gen_bx(s, tmp);
9807 } else if (i == rn) {
9808 loaded_var = tmp;
9809 loaded_base = 1;
9810 } else {
9811 store_reg(s, i, tmp);
9812 }
9813 } else {
9814
9815 tmp = load_reg(s, i);
9816 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
9817 tcg_temp_free_i32(tmp);
9818 }
9819 tcg_gen_addi_i32(addr, addr, 4);
9820 }
9821 if (loaded_base) {
9822 store_reg(s, rn, loaded_var);
9823 }
9824 if (insn & (1 << 21)) {
9825
9826 if (insn & (1 << 24)) {
9827 tcg_gen_addi_i32(addr, addr, -offset);
9828 }
9829
9830 if (insn & (1 << rn))
9831 goto illegal_op;
9832 store_reg(s, rn, addr);
9833 } else {
9834 tcg_temp_free_i32(addr);
9835 }
9836 }
9837 }
9838 break;
9839 case 5:
9840
9841 op = (insn >> 21) & 0xf;
9842 if (op == 6) {
9843 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9844 goto illegal_op;
9845 }
9846
9847 tmp = load_reg(s, rn);
9848 tmp2 = load_reg(s, rm);
9849 shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
9850 if (insn & (1 << 5)) {
9851
9852 if (shift == 0)
9853 shift = 31;
9854 tcg_gen_sari_i32(tmp2, tmp2, shift);
9855 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
9856 tcg_gen_ext16u_i32(tmp2, tmp2);
9857 } else {
9858
9859 if (shift)
9860 tcg_gen_shli_i32(tmp2, tmp2, shift);
9861 tcg_gen_ext16u_i32(tmp, tmp);
9862 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
9863 }
9864 tcg_gen_or_i32(tmp, tmp, tmp2);
9865 tcg_temp_free_i32(tmp2);
9866 store_reg(s, rd, tmp);
9867 } else {
9868
9869 if (rn == 15) {
9870 tmp = tcg_temp_new_i32();
9871 tcg_gen_movi_i32(tmp, 0);
9872 } else {
9873 tmp = load_reg(s, rn);
9874 }
9875 tmp2 = load_reg(s, rm);
9876
9877 shiftop = (insn >> 4) & 3;
9878 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
9879 conds = (insn & (1 << 20)) != 0;
9880 logic_cc = (conds && thumb2_logic_op(op));
9881 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
9882 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
9883 goto illegal_op;
9884 tcg_temp_free_i32(tmp2);
9885 if (rd != 15) {
9886 store_reg(s, rd, tmp);
9887 } else {
9888 tcg_temp_free_i32(tmp);
9889 }
9890 }
9891 break;
9892 case 13:
9893 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
9894 if (op < 4 && (insn & 0xf000) != 0xf000)
9895 goto illegal_op;
9896 switch (op) {
9897 case 0:
9898 tmp = load_reg(s, rn);
9899 tmp2 = load_reg(s, rm);
9900 if ((insn & 0x70) != 0)
9901 goto illegal_op;
9902 op = (insn >> 21) & 3;
9903 logic_cc = (insn & (1 << 20)) != 0;
9904 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
9905 if (logic_cc)
9906 gen_logic_CC(tmp);
9907 store_reg_bx(s, rd, tmp);
9908 break;
9909 case 1:
9910 op = (insn >> 20) & 7;
9911 switch (op) {
9912 case 0:
9913 case 1:
9914 case 4:
9915 case 5:
9916 break;
9917 case 2:
9918 case 3:
9919 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9920 goto illegal_op;
9921 }
9922 break;
9923 default:
9924 goto illegal_op;
9925 }
9926 if (rn != 15) {
9927 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9928 goto illegal_op;
9929 }
9930 }
9931 tmp = load_reg(s, rm);
9932 shift = (insn >> 4) & 3;
9933
9934
9935 if (shift != 0)
9936 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
9937 op = (insn >> 20) & 7;
9938 switch (op) {
9939 case 0: gen_sxth(tmp); break;
9940 case 1: gen_uxth(tmp); break;
9941 case 2: gen_sxtb16(tmp); break;
9942 case 3: gen_uxtb16(tmp); break;
9943 case 4: gen_sxtb(tmp); break;
9944 case 5: gen_uxtb(tmp); break;
9945 default:
9946 g_assert_not_reached();
9947 }
9948 if (rn != 15) {
9949 tmp2 = load_reg(s, rn);
9950 if ((op >> 1) == 1) {
9951 gen_add16(tmp, tmp2);
9952 } else {
9953 tcg_gen_add_i32(tmp, tmp, tmp2);
9954 tcg_temp_free_i32(tmp2);
9955 }
9956 }
9957 store_reg(s, rd, tmp);
9958 break;
9959 case 2:
9960 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9961 goto illegal_op;
9962 }
9963 op = (insn >> 20) & 7;
9964 shift = (insn >> 4) & 7;
9965 if ((op & 3) == 3 || (shift & 3) == 3)
9966 goto illegal_op;
9967 tmp = load_reg(s, rn);
9968 tmp2 = load_reg(s, rm);
9969 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
9970 tcg_temp_free_i32(tmp2);
9971 store_reg(s, rd, tmp);
9972 break;
9973 case 3:
9974 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
9975 if (op < 4) {
9976
9977 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9978 goto illegal_op;
9979 }
9980 tmp = load_reg(s, rn);
9981 tmp2 = load_reg(s, rm);
9982 if (op & 1)
9983 gen_helper_double_saturate(tmp, cpu_env, tmp);
9984 if (op & 2)
9985 gen_helper_sub_saturate(tmp, cpu_env, tmp2, tmp);
9986 else
9987 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
9988 tcg_temp_free_i32(tmp2);
9989 } else {
9990 switch (op) {
9991 case 0x0a:
9992 case 0x08:
9993 case 0x09:
9994 case 0x0b:
9995 case 0x18:
9996 break;
9997 case 0x10:
9998 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9999 goto illegal_op;
10000 }
10001 break;
10002 case 0x20:
10003 case 0x21:
10004 case 0x22:
10005 case 0x28:
10006 case 0x29:
10007 case 0x2a:
10008 if (!arm_dc_feature(s, ARM_FEATURE_CRC)) {
10009 goto illegal_op;
10010 }
10011 break;
10012 default:
10013 goto illegal_op;
10014 }
10015 tmp = load_reg(s, rn);
10016 switch (op) {
10017 case 0x0a:
10018 gen_helper_rbit(tmp, tmp);
10019 break;
10020 case 0x08:
10021 tcg_gen_bswap32_i32(tmp, tmp);
10022 break;
10023 case 0x09:
10024 gen_rev16(tmp);
10025 break;
10026 case 0x0b:
10027 gen_revsh(tmp);
10028 break;
10029 case 0x10:
10030 tmp2 = load_reg(s, rm);
10031 tmp3 = tcg_temp_new_i32();
10032 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
10033 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
10034 tcg_temp_free_i32(tmp3);
10035 tcg_temp_free_i32(tmp2);
10036 break;
10037 case 0x18:
10038 gen_helper_clz(tmp, tmp);
10039 break;
10040 case 0x20:
10041 case 0x21:
10042 case 0x22:
10043 case 0x28:
10044 case 0x29:
10045 case 0x2a:
10046 {
10047
10048 uint32_t sz = op & 0x3;
10049 uint32_t c = op & 0x8;
10050
10051 tmp2 = load_reg(s, rm);
10052 if (sz == 0) {
10053 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
10054 } else if (sz == 1) {
10055 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
10056 }
10057 tmp3 = tcg_const_i32(1 << sz);
10058 if (c) {
10059 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
10060 } else {
10061 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
10062 }
10063 tcg_temp_free_i32(tmp2);
10064 tcg_temp_free_i32(tmp3);
10065 break;
10066 }
10067 default:
10068 g_assert_not_reached();
10069 }
10070 }
10071 store_reg(s, rd, tmp);
10072 break;
10073 case 4: case 5:
10074 switch ((insn >> 20) & 7) {
10075 case 0:
10076 case 7:
10077 break;
10078 case 1:
10079 case 2:
10080 case 3:
10081 case 4:
10082 case 5: case 6:
10083 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10084 goto illegal_op;
10085 }
10086 break;
10087 }
10088 op = (insn >> 4) & 0xf;
10089 tmp = load_reg(s, rn);
10090 tmp2 = load_reg(s, rm);
10091 switch ((insn >> 20) & 7) {
10092 case 0:
10093 tcg_gen_mul_i32(tmp, tmp, tmp2);
10094 tcg_temp_free_i32(tmp2);
10095 if (rs != 15) {
10096 tmp2 = load_reg(s, rs);
10097 if (op)
10098 tcg_gen_sub_i32(tmp, tmp2, tmp);
10099 else
10100 tcg_gen_add_i32(tmp, tmp, tmp2);
10101 tcg_temp_free_i32(tmp2);
10102 }
10103 break;
10104 case 1:
10105 gen_mulxy(tmp, tmp2, op & 2, op & 1);
10106 tcg_temp_free_i32(tmp2);
10107 if (rs != 15) {
10108 tmp2 = load_reg(s, rs);
10109 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
10110 tcg_temp_free_i32(tmp2);
10111 }
10112 break;
10113 case 2:
10114 case 4:
10115 if (op)
10116 gen_swap_half(tmp2);
10117 gen_smul_dual(tmp, tmp2);
10118 if (insn & (1 << 22)) {
10119
10120 tcg_gen_sub_i32(tmp, tmp, tmp2);
10121 } else {
10122
10123
10124
10125
10126 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
10127 }
10128 tcg_temp_free_i32(tmp2);
10129 if (rs != 15)
10130 {
10131 tmp2 = load_reg(s, rs);
10132 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
10133 tcg_temp_free_i32(tmp2);
10134 }
10135 break;
10136 case 3:
10137 if (op)
10138 tcg_gen_sari_i32(tmp2, tmp2, 16);
10139 else
10140 gen_sxth(tmp2);
10141 tmp64 = gen_muls_i64_i32(tmp, tmp2);
10142 tcg_gen_shri_i64(tmp64, tmp64, 16);
10143 tmp = tcg_temp_new_i32();
10144 tcg_gen_extrl_i64_i32(tmp, tmp64);
10145 tcg_temp_free_i64(tmp64);
10146 if (rs != 15)
10147 {
10148 tmp2 = load_reg(s, rs);
10149 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
10150 tcg_temp_free_i32(tmp2);
10151 }
10152 break;
10153 case 5: case 6:
10154 tmp64 = gen_muls_i64_i32(tmp, tmp2);
10155 if (rs != 15) {
10156 tmp = load_reg(s, rs);
10157 if (insn & (1 << 20)) {
10158 tmp64 = gen_addq_msw(tmp64, tmp);
10159 } else {
10160 tmp64 = gen_subq_msw(tmp64, tmp);
10161 }
10162 }
10163 if (insn & (1 << 4)) {
10164 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
10165 }
10166 tcg_gen_shri_i64(tmp64, tmp64, 32);
10167 tmp = tcg_temp_new_i32();
10168 tcg_gen_extrl_i64_i32(tmp, tmp64);
10169 tcg_temp_free_i64(tmp64);
10170 break;
10171 case 7:
10172 gen_helper_usad8(tmp, tmp, tmp2);
10173 tcg_temp_free_i32(tmp2);
10174 if (rs != 15) {
10175 tmp2 = load_reg(s, rs);
10176 tcg_gen_add_i32(tmp, tmp, tmp2);
10177 tcg_temp_free_i32(tmp2);
10178 }
10179 break;
10180 }
10181 store_reg(s, rd, tmp);
10182 break;
10183 case 6: case 7:
10184 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
10185 tmp = load_reg(s, rn);
10186 tmp2 = load_reg(s, rm);
10187 if ((op & 0x50) == 0x10) {
10188
10189 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DIV)) {
10190 goto illegal_op;
10191 }
10192 if (op & 0x20)
10193 gen_helper_udiv(tmp, tmp, tmp2);
10194 else
10195 gen_helper_sdiv(tmp, tmp, tmp2);
10196 tcg_temp_free_i32(tmp2);
10197 store_reg(s, rd, tmp);
10198 } else if ((op & 0xe) == 0xc) {
10199
10200 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10201 tcg_temp_free_i32(tmp);
10202 tcg_temp_free_i32(tmp2);
10203 goto illegal_op;
10204 }
10205 if (op & 1)
10206 gen_swap_half(tmp2);
10207 gen_smul_dual(tmp, tmp2);
10208 if (op & 0x10) {
10209 tcg_gen_sub_i32(tmp, tmp, tmp2);
10210 } else {
10211 tcg_gen_add_i32(tmp, tmp, tmp2);
10212 }
10213 tcg_temp_free_i32(tmp2);
10214
10215 tmp64 = tcg_temp_new_i64();
10216 tcg_gen_ext_i32_i64(tmp64, tmp);
10217 tcg_temp_free_i32(tmp);
10218 gen_addq(s, tmp64, rs, rd);
10219 gen_storeq_reg(s, rs, rd, tmp64);
10220 tcg_temp_free_i64(tmp64);
10221 } else {
10222 if (op & 0x20) {
10223
10224 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
10225 } else {
10226 if (op & 8) {
10227
10228 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10229 tcg_temp_free_i32(tmp2);
10230 tcg_temp_free_i32(tmp);
10231 goto illegal_op;
10232 }
10233 gen_mulxy(tmp, tmp2, op & 2, op & 1);
10234 tcg_temp_free_i32(tmp2);
10235 tmp64 = tcg_temp_new_i64();
10236 tcg_gen_ext_i32_i64(tmp64, tmp);
10237 tcg_temp_free_i32(tmp);
10238 } else {
10239
10240 tmp64 = gen_muls_i64_i32(tmp, tmp2);
10241 }
10242 }
10243 if (op & 4) {
10244
10245 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10246 tcg_temp_free_i64(tmp64);
10247 goto illegal_op;
10248 }
10249 gen_addq_lo(s, tmp64, rs);
10250 gen_addq_lo(s, tmp64, rd);
10251 } else if (op & 0x40) {
10252
10253 gen_addq(s, tmp64, rs, rd);
10254 }
10255 gen_storeq_reg(s, rs, rd, tmp64);
10256 tcg_temp_free_i64(tmp64);
10257 }
10258 break;
10259 }
10260 break;
10261 case 6: case 7: case 14: case 15:
10262
10263 if (((insn >> 24) & 3) == 3) {
10264
10265 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
10266 if (disas_neon_data_insn(s, insn)) {
10267 goto illegal_op;
10268 }
10269 } else if (((insn >> 8) & 0xe) == 10) {
10270 if (disas_vfp_insn(s, insn)) {
10271 goto illegal_op;
10272 }
10273 } else {
10274 if (insn & (1 << 28))
10275 goto illegal_op;
10276 if (disas_coproc_insn(s, insn)) {
10277 goto illegal_op;
10278 }
10279 }
10280 break;
10281 case 8: case 9: case 10: case 11:
10282 if (insn & (1 << 15)) {
10283
10284 if (insn & 0x5000) {
10285
10286
10287 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
10288
10289 offset |= (insn & 0x7ff) << 1;
10290
10291
10292
10293 offset ^= ((~insn) & (1 << 13)) << 10;
10294 offset ^= ((~insn) & (1 << 11)) << 11;
10295
10296 if (insn & (1 << 14)) {
10297
10298 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
10299 }
10300
10301 offset += s->pc;
10302 if (insn & (1 << 12)) {
10303
10304 gen_jmp(s, offset);
10305 } else {
10306
10307 offset &= ~(uint32_t)2;
10308
10309 gen_bx_im(s, offset);
10310 }
10311 } else if (((insn >> 23) & 7) == 7) {
10312
10313 if (insn & (1 << 13))
10314 goto illegal_op;
10315
10316 if (insn & (1 << 26)) {
10317 if (!(insn & (1 << 20))) {
10318
10319 int imm16 = extract32(insn, 16, 4) << 12
10320 | extract32(insn, 0, 12);
10321 ARCH(7);
10322 if (IS_USER(s)) {
10323 goto illegal_op;
10324 }
10325 gen_hvc(s, imm16);
10326 } else {
10327
10328 ARCH(6K);
10329 if (IS_USER(s)) {
10330 goto illegal_op;
10331 }
10332 gen_smc(s);
10333 }
10334 } else {
10335 op = (insn >> 20) & 7;
10336 switch (op) {
10337 case 0:
10338 if (arm_dc_feature(s, ARM_FEATURE_M)) {
10339 tmp = load_reg(s, rn);
10340 addr = tcg_const_i32(insn & 0xff);
10341 gen_helper_v7m_msr(cpu_env, addr, tmp);
10342 tcg_temp_free_i32(addr);
10343 tcg_temp_free_i32(tmp);
10344 gen_lookup_tb(s);
10345 break;
10346 }
10347
10348 case 1:
10349 if (arm_dc_feature(s, ARM_FEATURE_M)) {
10350 goto illegal_op;
10351 }
10352
10353 if (extract32(insn, 5, 1)) {
10354
10355 int sysm = extract32(insn, 8, 4) |
10356 (extract32(insn, 4, 1) << 4);
10357 int r = op & 1;
10358
10359 gen_msr_banked(s, r, sysm, rm);
10360 break;
10361 }
10362
10363
10364 tmp = load_reg(s, rn);
10365 if (gen_set_psr(s,
10366 msr_mask(s, (insn >> 8) & 0xf, op == 1),
10367 op == 1, tmp))
10368 goto illegal_op;
10369 break;
10370 case 2:
10371 if (((insn >> 8) & 7) == 0) {
10372 gen_nop_hint(s, insn & 0xff);
10373 }
10374
10375 if (IS_USER(s))
10376 break;
10377 offset = 0;
10378 imm = 0;
10379 if (insn & (1 << 10)) {
10380 if (insn & (1 << 7))
10381 offset |= CPSR_A;
10382 if (insn & (1 << 6))
10383 offset |= CPSR_I;
10384 if (insn & (1 << 5))
10385 offset |= CPSR_F;
10386 if (insn & (1 << 9))
10387 imm = CPSR_A | CPSR_I | CPSR_F;
10388 }
10389 if (insn & (1 << 8)) {
10390 offset |= 0x1f;
10391 imm |= (insn & 0x1f);
10392 }
10393 if (offset) {
10394 gen_set_psr_im(s, offset, 0, imm);
10395 }
10396 break;
10397 case 3:
10398 ARCH(7);
10399 op = (insn >> 4) & 0xf;
10400 switch (op) {
10401 case 2:
10402 gen_clrex(s);
10403 break;
10404 case 4:
10405 case 5:
10406
10407 break;
10408 case 6:
10409
10410
10411
10412
10413
10414 gen_lookup_tb(s);
10415 break;
10416 default:
10417 goto illegal_op;
10418 }
10419 break;
10420 case 4:
10421
10422 tmp = load_reg(s, rn);
10423 gen_bx(s, tmp);
10424 break;
10425 case 5:
10426 if (IS_USER(s)) {
10427 goto illegal_op;
10428 }
10429 if (rn != 14 || rd != 15) {
10430 goto illegal_op;
10431 }
10432 tmp = load_reg(s, rn);
10433 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
10434 gen_exception_return(s, tmp);
10435 break;
10436 case 6:
10437 if (extract32(insn, 5, 1)) {
10438
10439 int sysm = extract32(insn, 16, 4) |
10440 (extract32(insn, 4, 1) << 4);
10441
10442 gen_mrs_banked(s, 0, sysm, rd);
10443 break;
10444 }
10445
10446
10447 tmp = tcg_temp_new_i32();
10448 if (arm_dc_feature(s, ARM_FEATURE_M)) {
10449 addr = tcg_const_i32(insn & 0xff);
10450 gen_helper_v7m_mrs(tmp, cpu_env, addr);
10451 tcg_temp_free_i32(addr);
10452 } else {
10453 gen_helper_cpsr_read(tmp, cpu_env);
10454 }
10455 store_reg(s, rd, tmp);
10456 break;
10457 case 7:
10458 if (extract32(insn, 5, 1)) {
10459
10460 int sysm = extract32(insn, 16, 4) |
10461 (extract32(insn, 4, 1) << 4);
10462
10463 gen_mrs_banked(s, 1, sysm, rd);
10464 break;
10465 }
10466
10467
10468
10469 if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
10470 goto illegal_op;
10471 }
10472 tmp = load_cpu_field(spsr);
10473 store_reg(s, rd, tmp);
10474 break;
10475 }
10476 }
10477 } else {
10478
10479 op = (insn >> 22) & 0xf;
10480
10481 s->condlabel = gen_new_label();
10482 arm_gen_test_cc(op ^ 1, s->condlabel);
10483 s->condjmp = 1;
10484
10485
10486 offset = (insn & 0x7ff) << 1;
10487
10488 offset |= (insn & 0x003f0000) >> 4;
10489
10490 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
10491
10492 offset |= (insn & (1 << 13)) << 5;
10493
10494 offset |= (insn & (1 << 11)) << 8;
10495
10496
10497 gen_jmp(s, s->pc + offset);
10498 }
10499 } else {
10500
10501 if (insn & (1 << 25)) {
10502 if (insn & (1 << 24)) {
10503 if (insn & (1 << 20))
10504 goto illegal_op;
10505
10506 op = (insn >> 21) & 7;
10507 imm = insn & 0x1f;
10508 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
10509 if (rn == 15) {
10510 tmp = tcg_temp_new_i32();
10511 tcg_gen_movi_i32(tmp, 0);
10512 } else {
10513 tmp = load_reg(s, rn);
10514 }
10515 switch (op) {
10516 case 2:
10517 imm++;
10518 if (shift + imm > 32)
10519 goto illegal_op;
10520 if (imm < 32)
10521 gen_sbfx(tmp, shift, imm);
10522 break;
10523 case 6:
10524 imm++;
10525 if (shift + imm > 32)
10526 goto illegal_op;
10527 if (imm < 32)
10528 gen_ubfx(tmp, shift, (1u << imm) - 1);
10529 break;
10530 case 3:
10531 if (imm < shift)
10532 goto illegal_op;
10533 imm = imm + 1 - shift;
10534 if (imm != 32) {
10535 tmp2 = load_reg(s, rd);
10536 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, imm);
10537 tcg_temp_free_i32(tmp2);
10538 }
10539 break;
10540 case 7:
10541 goto illegal_op;
10542 default:
10543 if (shift) {
10544 if (op & 1)
10545 tcg_gen_sari_i32(tmp, tmp, shift);
10546 else
10547 tcg_gen_shli_i32(tmp, tmp, shift);
10548 }
10549 tmp2 = tcg_const_i32(imm);
10550 if (op & 4) {
10551
10552 if ((op & 1) && shift == 0) {
10553 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10554 tcg_temp_free_i32(tmp);
10555 tcg_temp_free_i32(tmp2);
10556 goto illegal_op;
10557 }
10558 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
10559 } else {
10560 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
10561 }
10562 } else {
10563
10564 if ((op & 1) && shift == 0) {
10565 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10566 tcg_temp_free_i32(tmp);
10567 tcg_temp_free_i32(tmp2);
10568 goto illegal_op;
10569 }
10570 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
10571 } else {
10572 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
10573 }
10574 }
10575 tcg_temp_free_i32(tmp2);
10576 break;
10577 }
10578 store_reg(s, rd, tmp);
10579 } else {
10580 imm = ((insn & 0x04000000) >> 15)
10581 | ((insn & 0x7000) >> 4) | (insn & 0xff);
10582 if (insn & (1 << 22)) {
10583
10584 imm |= (insn >> 4) & 0xf000;
10585 if (insn & (1 << 23)) {
10586
10587 tmp = load_reg(s, rd);
10588 tcg_gen_ext16u_i32(tmp, tmp);
10589 tcg_gen_ori_i32(tmp, tmp, imm << 16);
10590 } else {
10591
10592 tmp = tcg_temp_new_i32();
10593 tcg_gen_movi_i32(tmp, imm);
10594 }
10595 } else {
10596
10597 if (rn == 15) {
10598 offset = s->pc & ~(uint32_t)3;
10599 if (insn & (1 << 23))
10600 offset -= imm;
10601 else
10602 offset += imm;
10603 tmp = tcg_temp_new_i32();
10604 tcg_gen_movi_i32(tmp, offset);
10605 } else {
10606 tmp = load_reg(s, rn);
10607 if (insn & (1 << 23))
10608 tcg_gen_subi_i32(tmp, tmp, imm);
10609 else
10610 tcg_gen_addi_i32(tmp, tmp, imm);
10611 }
10612 }
10613 store_reg(s, rd, tmp);
10614 }
10615 } else {
10616 int shifter_out = 0;
10617
10618 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
10619 imm = (insn & 0xff);
10620 switch (shift) {
10621 case 0:
10622
10623 break;
10624 case 1:
10625 imm |= imm << 16;
10626 break;
10627 case 2:
10628 imm |= imm << 16;
10629 imm <<= 8;
10630 break;
10631 case 3:
10632 imm |= imm << 16;
10633 imm |= imm << 8;
10634 break;
10635 default:
10636 shift = (shift << 1) | (imm >> 7);
10637 imm |= 0x80;
10638 imm = imm << (32 - shift);
10639 shifter_out = 1;
10640 break;
10641 }
10642 tmp2 = tcg_temp_new_i32();
10643 tcg_gen_movi_i32(tmp2, imm);
10644 rn = (insn >> 16) & 0xf;
10645 if (rn == 15) {
10646 tmp = tcg_temp_new_i32();
10647 tcg_gen_movi_i32(tmp, 0);
10648 } else {
10649 tmp = load_reg(s, rn);
10650 }
10651 op = (insn >> 21) & 0xf;
10652 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
10653 shifter_out, tmp, tmp2))
10654 goto illegal_op;
10655 tcg_temp_free_i32(tmp2);
10656 rd = (insn >> 8) & 0xf;
10657 if (rd != 15) {
10658 store_reg(s, rd, tmp);
10659 } else {
10660 tcg_temp_free_i32(tmp);
10661 }
10662 }
10663 }
10664 break;
10665 case 12:
10666 {
10667 int postinc = 0;
10668 int writeback = 0;
10669 int memidx;
10670 if ((insn & 0x01100000) == 0x01000000) {
10671 if (disas_neon_ls_insn(s, insn)) {
10672 goto illegal_op;
10673 }
10674 break;
10675 }
10676 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
10677 if (rs == 15) {
10678 if (!(insn & (1 << 20))) {
10679 goto illegal_op;
10680 }
10681 if (op != 2) {
10682
10683
10684
10685
10686
10687
10688
10689
10690
10691
10692
10693 int op1 = (insn >> 23) & 3;
10694 int op2 = (insn >> 6) & 0x3f;
10695 if (op & 2) {
10696 goto illegal_op;
10697 }
10698 if (rn == 15) {
10699
10700
10701
10702 return 0;
10703 }
10704 if (op1 & 1) {
10705 return 0;
10706 }
10707 if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
10708 return 0;
10709 }
10710
10711 return 1;
10712 }
10713 }
10714 memidx = get_mem_index(s);
10715 if (rn == 15) {
10716 addr = tcg_temp_new_i32();
10717
10718
10719 imm = s->pc & 0xfffffffc;
10720 if (insn & (1 << 23))
10721 imm += insn & 0xfff;
10722 else
10723 imm -= insn & 0xfff;
10724 tcg_gen_movi_i32(addr, imm);
10725 } else {
10726 addr = load_reg(s, rn);
10727 if (insn & (1 << 23)) {
10728
10729 imm = insn & 0xfff;
10730 tcg_gen_addi_i32(addr, addr, imm);
10731 } else {
10732 imm = insn & 0xff;
10733 switch ((insn >> 8) & 0xf) {
10734 case 0x0:
10735 shift = (insn >> 4) & 0xf;
10736 if (shift > 3) {
10737 tcg_temp_free_i32(addr);
10738 goto illegal_op;
10739 }
10740 tmp = load_reg(s, rm);
10741 if (shift)
10742 tcg_gen_shli_i32(tmp, tmp, shift);
10743 tcg_gen_add_i32(addr, addr, tmp);
10744 tcg_temp_free_i32(tmp);
10745 break;
10746 case 0xc:
10747 tcg_gen_addi_i32(addr, addr, -imm);
10748 break;
10749 case 0xe:
10750 tcg_gen_addi_i32(addr, addr, imm);
10751 memidx = get_a32_user_mem_index(s);
10752 break;
10753 case 0x9:
10754 imm = -imm;
10755
10756 case 0xb:
10757 postinc = 1;
10758 writeback = 1;
10759 break;
10760 case 0xd:
10761 imm = -imm;
10762
10763 case 0xf:
10764 tcg_gen_addi_i32(addr, addr, imm);
10765 writeback = 1;
10766 break;
10767 default:
10768 tcg_temp_free_i32(addr);
10769 goto illegal_op;
10770 }
10771 }
10772 }
10773 if (insn & (1 << 20)) {
10774
10775 tmp = tcg_temp_new_i32();
10776 switch (op) {
10777 case 0:
10778 gen_aa32_ld8u(s, tmp, addr, memidx);
10779 break;
10780 case 4:
10781 gen_aa32_ld8s(s, tmp, addr, memidx);
10782 break;
10783 case 1:
10784 gen_aa32_ld16u(s, tmp, addr, memidx);
10785 break;
10786 case 5:
10787 gen_aa32_ld16s(s, tmp, addr, memidx);
10788 break;
10789 case 2:
10790 gen_aa32_ld32u(s, tmp, addr, memidx);
10791 break;
10792 default:
10793 tcg_temp_free_i32(tmp);
10794 tcg_temp_free_i32(addr);
10795 goto illegal_op;
10796 }
10797 if (rs == 15) {
10798 gen_bx(s, tmp);
10799 } else {
10800 store_reg(s, rs, tmp);
10801 }
10802 } else {
10803
10804 tmp = load_reg(s, rs);
10805 switch (op) {
10806 case 0:
10807 gen_aa32_st8(s, tmp, addr, memidx);
10808 break;
10809 case 1:
10810 gen_aa32_st16(s, tmp, addr, memidx);
10811 break;
10812 case 2:
10813 gen_aa32_st32(s, tmp, addr, memidx);
10814 break;
10815 default:
10816 tcg_temp_free_i32(tmp);
10817 tcg_temp_free_i32(addr);
10818 goto illegal_op;
10819 }
10820 tcg_temp_free_i32(tmp);
10821 }
10822 if (postinc)
10823 tcg_gen_addi_i32(addr, addr, imm);
10824 if (writeback) {
10825 store_reg(s, rn, addr);
10826 } else {
10827 tcg_temp_free_i32(addr);
10828 }
10829 }
10830 break;
10831 default:
10832 goto illegal_op;
10833 }
10834 return 0;
10835illegal_op:
10836 return 1;
10837}
10838
10839static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
10840{
10841 uint32_t val, insn, op, rm, rn, rd, shift, cond;
10842 int32_t offset;
10843 int i;
10844 TCGv_i32 tmp;
10845 TCGv_i32 tmp2;
10846 TCGv_i32 addr;
10847
10848 if (s->condexec_mask) {
10849 cond = s->condexec_cond;
10850 if (cond != 0x0e) {
10851 s->condlabel = gen_new_label();
10852 arm_gen_test_cc(cond ^ 1, s->condlabel);
10853 s->condjmp = 1;
10854 }
10855 }
10856
10857 insn = arm_lduw_code(env, s->pc, s->sctlr_b);
10858 s->pc += 2;
10859
10860 switch (insn >> 12) {
10861 case 0: case 1:
10862
10863 rd = insn & 7;
10864 op = (insn >> 11) & 3;
10865 if (op == 3) {
10866
10867 rn = (insn >> 3) & 7;
10868 tmp = load_reg(s, rn);
10869 if (insn & (1 << 10)) {
10870
10871 tmp2 = tcg_temp_new_i32();
10872 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
10873 } else {
10874
10875 rm = (insn >> 6) & 7;
10876 tmp2 = load_reg(s, rm);
10877 }
10878 if (insn & (1 << 9)) {
10879 if (s->condexec_mask)
10880 tcg_gen_sub_i32(tmp, tmp, tmp2);
10881 else
10882 gen_sub_CC(tmp, tmp, tmp2);
10883 } else {
10884 if (s->condexec_mask)
10885 tcg_gen_add_i32(tmp, tmp, tmp2);
10886 else
10887 gen_add_CC(tmp, tmp, tmp2);
10888 }
10889 tcg_temp_free_i32(tmp2);
10890 store_reg(s, rd, tmp);
10891 } else {
10892
10893 rm = (insn >> 3) & 7;
10894 shift = (insn >> 6) & 0x1f;
10895 tmp = load_reg(s, rm);
10896 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
10897 if (!s->condexec_mask)
10898 gen_logic_CC(tmp);
10899 store_reg(s, rd, tmp);
10900 }
10901 break;
10902 case 2: case 3:
10903
10904 op = (insn >> 11) & 3;
10905 rd = (insn >> 8) & 0x7;
10906 if (op == 0) {
10907 tmp = tcg_temp_new_i32();
10908 tcg_gen_movi_i32(tmp, insn & 0xff);
10909 if (!s->condexec_mask)
10910 gen_logic_CC(tmp);
10911 store_reg(s, rd, tmp);
10912 } else {
10913 tmp = load_reg(s, rd);
10914 tmp2 = tcg_temp_new_i32();
10915 tcg_gen_movi_i32(tmp2, insn & 0xff);
10916 switch (op) {
10917 case 1:
10918 gen_sub_CC(tmp, tmp, tmp2);
10919 tcg_temp_free_i32(tmp);
10920 tcg_temp_free_i32(tmp2);
10921 break;
10922 case 2:
10923 if (s->condexec_mask)
10924 tcg_gen_add_i32(tmp, tmp, tmp2);
10925 else
10926 gen_add_CC(tmp, tmp, tmp2);
10927 tcg_temp_free_i32(tmp2);
10928 store_reg(s, rd, tmp);
10929 break;
10930 case 3:
10931 if (s->condexec_mask)
10932 tcg_gen_sub_i32(tmp, tmp, tmp2);
10933 else
10934 gen_sub_CC(tmp, tmp, tmp2);
10935 tcg_temp_free_i32(tmp2);
10936 store_reg(s, rd, tmp);
10937 break;
10938 }
10939 }
10940 break;
10941 case 4:
10942 if (insn & (1 << 11)) {
10943 rd = (insn >> 8) & 7;
10944
10945 val = s->pc + 2 + ((insn & 0xff) * 4);
10946 val &= ~(uint32_t)2;
10947 addr = tcg_temp_new_i32();
10948 tcg_gen_movi_i32(addr, val);
10949 tmp = tcg_temp_new_i32();
10950 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
10951 tcg_temp_free_i32(addr);
10952 store_reg(s, rd, tmp);
10953 break;
10954 }
10955 if (insn & (1 << 10)) {
10956
10957 rd = (insn & 7) | ((insn >> 4) & 8);
10958 rm = (insn >> 3) & 0xf;
10959 op = (insn >> 8) & 3;
10960 switch (op) {
10961 case 0:
10962 tmp = load_reg(s, rd);
10963 tmp2 = load_reg(s, rm);
10964 tcg_gen_add_i32(tmp, tmp, tmp2);
10965 tcg_temp_free_i32(tmp2);
10966 store_reg(s, rd, tmp);
10967 break;
10968 case 1:
10969 tmp = load_reg(s, rd);
10970 tmp2 = load_reg(s, rm);
10971 gen_sub_CC(tmp, tmp, tmp2);
10972 tcg_temp_free_i32(tmp2);
10973 tcg_temp_free_i32(tmp);
10974 break;
10975 case 2:
10976 tmp = load_reg(s, rm);
10977 store_reg(s, rd, tmp);
10978 break;
10979 case 3:
10980 tmp = load_reg(s, rm);
10981 if (insn & (1 << 7)) {
10982 ARCH(5);
10983 val = (uint32_t)s->pc | 1;
10984 tmp2 = tcg_temp_new_i32();
10985 tcg_gen_movi_i32(tmp2, val);
10986 store_reg(s, 14, tmp2);
10987 }
10988
10989 gen_bx(s, tmp);
10990 break;
10991 }
10992 break;
10993 }
10994
10995
10996 rd = insn & 7;
10997 rm = (insn >> 3) & 7;
10998 op = (insn >> 6) & 0xf;
10999 if (op == 2 || op == 3 || op == 4 || op == 7) {
11000
11001 val = rm;
11002 rm = rd;
11003 rd = val;
11004 val = 1;
11005 } else {
11006 val = 0;
11007 }
11008
11009 if (op == 9) {
11010 tmp = tcg_temp_new_i32();
11011 tcg_gen_movi_i32(tmp, 0);
11012 } else if (op != 0xf) {
11013 tmp = load_reg(s, rd);
11014 } else {
11015 TCGV_UNUSED_I32(tmp);
11016 }
11017
11018 tmp2 = load_reg(s, rm);
11019 switch (op) {
11020 case 0x0:
11021 tcg_gen_and_i32(tmp, tmp, tmp2);
11022 if (!s->condexec_mask)
11023 gen_logic_CC(tmp);
11024 break;
11025 case 0x1:
11026 tcg_gen_xor_i32(tmp, tmp, tmp2);
11027 if (!s->condexec_mask)
11028 gen_logic_CC(tmp);
11029 break;
11030 case 0x2:
11031 if (s->condexec_mask) {
11032 gen_shl(tmp2, tmp2, tmp);
11033 } else {
11034 gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);
11035 gen_logic_CC(tmp2);
11036 }
11037 break;
11038 case 0x3:
11039 if (s->condexec_mask) {
11040 gen_shr(tmp2, tmp2, tmp);
11041 } else {
11042 gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);
11043 gen_logic_CC(tmp2);
11044 }
11045 break;
11046 case 0x4:
11047 if (s->condexec_mask) {
11048 gen_sar(tmp2, tmp2, tmp);
11049 } else {
11050 gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);
11051 gen_logic_CC(tmp2);
11052 }
11053 break;
11054 case 0x5:
11055 if (s->condexec_mask) {
11056 gen_adc(tmp, tmp2);
11057 } else {
11058 gen_adc_CC(tmp, tmp, tmp2);
11059 }
11060 break;
11061 case 0x6:
11062 if (s->condexec_mask) {
11063 gen_sub_carry(tmp, tmp, tmp2);
11064 } else {
11065 gen_sbc_CC(tmp, tmp, tmp2);
11066 }
11067 break;
11068 case 0x7:
11069 if (s->condexec_mask) {
11070 tcg_gen_andi_i32(tmp, tmp, 0x1f);
11071 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
11072 } else {
11073 gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp);
11074 gen_logic_CC(tmp2);
11075 }
11076 break;
11077 case 0x8:
11078 tcg_gen_and_i32(tmp, tmp, tmp2);
11079 gen_logic_CC(tmp);
11080 rd = 16;
11081 break;
11082 case 0x9:
11083 if (s->condexec_mask)
11084 tcg_gen_neg_i32(tmp, tmp2);
11085 else
11086 gen_sub_CC(tmp, tmp, tmp2);
11087 break;
11088 case 0xa:
11089 gen_sub_CC(tmp, tmp, tmp2);
11090 rd = 16;
11091 break;
11092 case 0xb:
11093 gen_add_CC(tmp, tmp, tmp2);
11094 rd = 16;
11095 break;
11096 case 0xc:
11097 tcg_gen_or_i32(tmp, tmp, tmp2);
11098 if (!s->condexec_mask)
11099 gen_logic_CC(tmp);
11100 break;
11101 case 0xd:
11102 tcg_gen_mul_i32(tmp, tmp, tmp2);
11103 if (!s->condexec_mask)
11104 gen_logic_CC(tmp);
11105 break;
11106 case 0xe:
11107 tcg_gen_andc_i32(tmp, tmp, tmp2);
11108 if (!s->condexec_mask)
11109 gen_logic_CC(tmp);
11110 break;
11111 case 0xf:
11112 tcg_gen_not_i32(tmp2, tmp2);
11113 if (!s->condexec_mask)
11114 gen_logic_CC(tmp2);
11115 val = 1;
11116 rm = rd;
11117 break;
11118 }
11119 if (rd != 16) {
11120 if (val) {
11121 store_reg(s, rm, tmp2);
11122 if (op != 0xf)
11123 tcg_temp_free_i32(tmp);
11124 } else {
11125 store_reg(s, rd, tmp);
11126 tcg_temp_free_i32(tmp2);
11127 }
11128 } else {
11129 tcg_temp_free_i32(tmp);
11130 tcg_temp_free_i32(tmp2);
11131 }
11132 break;
11133
11134 case 5:
11135
11136 rd = insn & 7;
11137 rn = (insn >> 3) & 7;
11138 rm = (insn >> 6) & 7;
11139 op = (insn >> 9) & 7;
11140 addr = load_reg(s, rn);
11141 tmp = load_reg(s, rm);
11142 tcg_gen_add_i32(addr, addr, tmp);
11143 tcg_temp_free_i32(tmp);
11144
11145 if (op < 3) {
11146 tmp = load_reg(s, rd);
11147 } else {
11148 tmp = tcg_temp_new_i32();
11149 }
11150
11151 switch (op) {
11152 case 0:
11153 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
11154 break;
11155 case 1:
11156 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
11157 break;
11158 case 2:
11159 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
11160 break;
11161 case 3:
11162 gen_aa32_ld8s(s, tmp, addr, get_mem_index(s));
11163 break;
11164 case 4:
11165 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
11166 break;
11167 case 5:
11168 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
11169 break;
11170 case 6:
11171 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
11172 break;
11173 case 7:
11174 gen_aa32_ld16s(s, tmp, addr, get_mem_index(s));
11175 break;
11176 }
11177 if (op >= 3) {
11178 store_reg(s, rd, tmp);
11179 } else {
11180 tcg_temp_free_i32(tmp);
11181 }
11182 tcg_temp_free_i32(addr);
11183 break;
11184
11185 case 6:
11186
11187 rd = insn & 7;
11188 rn = (insn >> 3) & 7;
11189 addr = load_reg(s, rn);
11190 val = (insn >> 4) & 0x7c;
11191 tcg_gen_addi_i32(addr, addr, val);
11192
11193 if (insn & (1 << 11)) {
11194
11195 tmp = tcg_temp_new_i32();
11196 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
11197 store_reg(s, rd, tmp);
11198 } else {
11199
11200 tmp = load_reg(s, rd);
11201 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
11202 tcg_temp_free_i32(tmp);
11203 }
11204 tcg_temp_free_i32(addr);
11205 break;
11206
11207 case 7:
11208
11209 rd = insn & 7;
11210 rn = (insn >> 3) & 7;
11211 addr = load_reg(s, rn);
11212 val = (insn >> 6) & 0x1f;
11213 tcg_gen_addi_i32(addr, addr, val);
11214
11215 if (insn & (1 << 11)) {
11216
11217 tmp = tcg_temp_new_i32();
11218 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
11219 store_reg(s, rd, tmp);
11220 } else {
11221
11222 tmp = load_reg(s, rd);
11223 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
11224 tcg_temp_free_i32(tmp);
11225 }
11226 tcg_temp_free_i32(addr);
11227 break;
11228
11229 case 8:
11230
11231 rd = insn & 7;
11232 rn = (insn >> 3) & 7;
11233 addr = load_reg(s, rn);
11234 val = (insn >> 5) & 0x3e;
11235 tcg_gen_addi_i32(addr, addr, val);
11236
11237 if (insn & (1 << 11)) {
11238
11239 tmp = tcg_temp_new_i32();
11240 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
11241 store_reg(s, rd, tmp);
11242 } else {
11243
11244 tmp = load_reg(s, rd);
11245 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
11246 tcg_temp_free_i32(tmp);
11247 }
11248 tcg_temp_free_i32(addr);
11249 break;
11250
11251 case 9:
11252
11253 rd = (insn >> 8) & 7;
11254 addr = load_reg(s, 13);
11255 val = (insn & 0xff) * 4;
11256 tcg_gen_addi_i32(addr, addr, val);
11257
11258 if (insn & (1 << 11)) {
11259
11260 tmp = tcg_temp_new_i32();
11261 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
11262 store_reg(s, rd, tmp);
11263 } else {
11264
11265 tmp = load_reg(s, rd);
11266 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
11267 tcg_temp_free_i32(tmp);
11268 }
11269 tcg_temp_free_i32(addr);
11270 break;
11271
11272 case 10:
11273
11274 rd = (insn >> 8) & 7;
11275 if (insn & (1 << 11)) {
11276
11277 tmp = load_reg(s, 13);
11278 } else {
11279
11280 tmp = tcg_temp_new_i32();
11281 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
11282 }
11283 val = (insn & 0xff) * 4;
11284 tcg_gen_addi_i32(tmp, tmp, val);
11285 store_reg(s, rd, tmp);
11286 break;
11287
11288 case 11:
11289
11290 op = (insn >> 8) & 0xf;
11291 switch (op) {
11292 case 0:
11293
11294 tmp = load_reg(s, 13);
11295 val = (insn & 0x7f) * 4;
11296 if (insn & (1 << 7))
11297 val = -(int32_t)val;
11298 tcg_gen_addi_i32(tmp, tmp, val);
11299 store_reg(s, 13, tmp);
11300 break;
11301
11302 case 2:
11303 ARCH(6);
11304 rd = insn & 7;
11305 rm = (insn >> 3) & 7;
11306 tmp = load_reg(s, rm);
11307 switch ((insn >> 6) & 3) {
11308 case 0: gen_sxth(tmp); break;
11309 case 1: gen_sxtb(tmp); break;
11310 case 2: gen_uxth(tmp); break;
11311 case 3: gen_uxtb(tmp); break;
11312 }
11313 store_reg(s, rd, tmp);
11314 break;
11315 case 4: case 5: case 0xc: case 0xd:
11316
11317 addr = load_reg(s, 13);
11318 if (insn & (1 << 8))
11319 offset = 4;
11320 else
11321 offset = 0;
11322 for (i = 0; i < 8; i++) {
11323 if (insn & (1 << i))
11324 offset += 4;
11325 }
11326 if ((insn & (1 << 11)) == 0) {
11327 tcg_gen_addi_i32(addr, addr, -offset);
11328 }
11329 for (i = 0; i < 8; i++) {
11330 if (insn & (1 << i)) {
11331 if (insn & (1 << 11)) {
11332
11333 tmp = tcg_temp_new_i32();
11334 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
11335 store_reg(s, i, tmp);
11336 } else {
11337
11338 tmp = load_reg(s, i);
11339 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
11340 tcg_temp_free_i32(tmp);
11341 }
11342
11343 tcg_gen_addi_i32(addr, addr, 4);
11344 }
11345 }
11346 TCGV_UNUSED_I32(tmp);
11347 if (insn & (1 << 8)) {
11348 if (insn & (1 << 11)) {
11349
11350 tmp = tcg_temp_new_i32();
11351 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
11352
11353
11354 } else {
11355
11356 tmp = load_reg(s, 14);
11357 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
11358 tcg_temp_free_i32(tmp);
11359 }
11360 tcg_gen_addi_i32(addr, addr, 4);
11361 }
11362 if ((insn & (1 << 11)) == 0) {
11363 tcg_gen_addi_i32(addr, addr, -offset);
11364 }
11365
11366 store_reg(s, 13, addr);
11367
11368 if ((insn & 0x0900) == 0x0900) {
11369 store_reg_from_load(s, 15, tmp);
11370 }
11371 break;
11372
11373 case 1: case 3: case 9: case 11:
11374 rm = insn & 7;
11375 tmp = load_reg(s, rm);
11376 s->condlabel = gen_new_label();
11377 s->condjmp = 1;
11378 if (insn & (1 << 11))
11379 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
11380 else
11381 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
11382 tcg_temp_free_i32(tmp);
11383 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
11384 val = (uint32_t)s->pc + 2;
11385 val += offset;
11386 gen_jmp(s, val);
11387 break;
11388
11389 case 15:
11390 if ((insn & 0xf) == 0) {
11391 gen_nop_hint(s, (insn >> 4) & 0xf);
11392 break;
11393 }
11394
11395 s->condexec_cond = (insn >> 4) & 0xe;
11396 s->condexec_mask = insn & 0x1f;
11397
11398 break;
11399
11400 case 0xe:
11401 {
11402 int imm8 = extract32(insn, 0, 8);
11403 ARCH(5);
11404 gen_exception_insn(s, 2, EXCP_BKPT, syn_aa32_bkpt(imm8, true),
11405 default_exception_el(s));
11406 break;
11407 }
11408
11409 case 0xa:
11410 ARCH(6);
11411 rn = (insn >> 3) & 0x7;
11412 rd = insn & 0x7;
11413 tmp = load_reg(s, rn);
11414 switch ((insn >> 6) & 3) {
11415 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
11416 case 1: gen_rev16(tmp); break;
11417 case 3: gen_revsh(tmp); break;
11418 default: goto illegal_op;
11419 }
11420 store_reg(s, rd, tmp);
11421 break;
11422
11423 case 6:
11424 switch ((insn >> 5) & 7) {
11425 case 2:
11426
11427 ARCH(6);
11428 if (((insn >> 3) & 1) != !!(s->be_data == MO_BE)) {
11429 gen_helper_setend(cpu_env);
11430 s->is_jmp = DISAS_UPDATE;
11431 }
11432 break;
11433 case 3:
11434
11435 ARCH(6);
11436 if (IS_USER(s)) {
11437 break;
11438 }
11439 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11440 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
11441
11442 if (insn & 1) {
11443 addr = tcg_const_i32(19);
11444 gen_helper_v7m_msr(cpu_env, addr, tmp);
11445 tcg_temp_free_i32(addr);
11446 }
11447
11448 if (insn & 2) {
11449 addr = tcg_const_i32(16);
11450 gen_helper_v7m_msr(cpu_env, addr, tmp);
11451 tcg_temp_free_i32(addr);
11452 }
11453 tcg_temp_free_i32(tmp);
11454 gen_lookup_tb(s);
11455 } else {
11456 if (insn & (1 << 4)) {
11457 shift = CPSR_A | CPSR_I | CPSR_F;
11458 } else {
11459 shift = 0;
11460 }
11461 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
11462 }
11463 break;
11464 default:
11465 goto undef;
11466 }
11467 break;
11468
11469 default:
11470 goto undef;
11471 }
11472 break;
11473
11474 case 12:
11475 {
11476
11477 TCGv_i32 loaded_var;
11478 TCGV_UNUSED_I32(loaded_var);
11479 rn = (insn >> 8) & 0x7;
11480 addr = load_reg(s, rn);
11481 for (i = 0; i < 8; i++) {
11482 if (insn & (1 << i)) {
11483 if (insn & (1 << 11)) {
11484
11485 tmp = tcg_temp_new_i32();
11486 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
11487 if (i == rn) {
11488 loaded_var = tmp;
11489 } else {
11490 store_reg(s, i, tmp);
11491 }
11492 } else {
11493
11494 tmp = load_reg(s, i);
11495 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
11496 tcg_temp_free_i32(tmp);
11497 }
11498
11499 tcg_gen_addi_i32(addr, addr, 4);
11500 }
11501 }
11502 if ((insn & (1 << rn)) == 0) {
11503
11504 store_reg(s, rn, addr);
11505 } else {
11506
11507 if (insn & (1 << 11)) {
11508 store_reg(s, rn, loaded_var);
11509 }
11510 tcg_temp_free_i32(addr);
11511 }
11512 break;
11513 }
11514 case 13:
11515
11516 cond = (insn >> 8) & 0xf;
11517 if (cond == 0xe)
11518 goto undef;
11519
11520 if (cond == 0xf) {
11521
11522 gen_set_pc_im(s, s->pc);
11523 s->svc_imm = extract32(insn, 0, 8);
11524 s->is_jmp = DISAS_SWI;
11525 break;
11526 }
11527
11528 s->condlabel = gen_new_label();
11529 arm_gen_test_cc(cond ^ 1, s->condlabel);
11530 s->condjmp = 1;
11531
11532
11533 val = (uint32_t)s->pc + 2;
11534 offset = ((int32_t)insn << 24) >> 24;
11535 val += offset << 1;
11536 gen_jmp(s, val);
11537 break;
11538
11539 case 14:
11540 if (insn & (1 << 11)) {
11541 if (disas_thumb2_insn(env, s, insn))
11542 goto undef32;
11543 break;
11544 }
11545
11546 val = (uint32_t)s->pc;
11547 offset = ((int32_t)insn << 21) >> 21;
11548 val += (offset << 1) + 2;
11549 gen_jmp(s, val);
11550 break;
11551
11552 case 15:
11553 if (disas_thumb2_insn(env, s, insn))
11554 goto undef32;
11555 break;
11556 }
11557 return;
11558undef32:
11559 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
11560 default_exception_el(s));
11561 return;
11562illegal_op:
11563undef:
11564 gen_exception_insn(s, 2, EXCP_UDEF, syn_uncategorized(),
11565 default_exception_el(s));
11566}
11567
11568static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
11569{
11570
11571
11572
11573 uint16_t insn;
11574
11575 if ((s->pc & 3) == 0) {
11576
11577 return false;
11578 }
11579
11580
11581 insn = arm_lduw_code(env, s->pc, s->sctlr_b);
11582
11583 if ((insn >> 11) >= 0x1d) {
11584
11585
11586
11587
11588
11589
11590
11591 return true;
11592 }
11593
11594 return false;
11595}
11596
11597
11598void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
11599{
11600 ARMCPU *cpu = arm_env_get_cpu(env);
11601 CPUState *cs = CPU(cpu);
11602 DisasContext dc1, *dc = &dc1;
11603 target_ulong pc_start;
11604 target_ulong next_page_start;
11605 int num_insns;
11606 int max_insns;
11607 bool end_of_page;
11608
11609
11610
11611
11612
11613
11614 if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
11615 gen_intermediate_code_a64(cpu, tb);
11616 return;
11617 }
11618
11619 pc_start = tb->pc;
11620
11621 dc->tb = tb;
11622
11623 dc->is_jmp = DISAS_NEXT;
11624 dc->pc = pc_start;
11625 dc->singlestep_enabled = cs->singlestep_enabled;
11626 dc->condjmp = 0;
11627
11628 dc->aarch64 = 0;
11629
11630
11631
11632 dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
11633 !arm_el_is_aa64(env, 3);
11634 dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
11635 dc->sctlr_b = ARM_TBFLAG_SCTLR_B(tb->flags);
11636 dc->be_data = ARM_TBFLAG_BE_DATA(tb->flags) ? MO_BE : MO_LE;
11637 dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
11638 dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
11639 dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);
11640 dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
11641#if !defined(CONFIG_USER_ONLY)
11642 dc->user = (dc->current_el == 0);
11643#endif
11644 dc->ns = ARM_TBFLAG_NS(tb->flags);
11645 dc->fp_excp_el = ARM_TBFLAG_FPEXC_EL(tb->flags);
11646 dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
11647 dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
11648 dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
11649 dc->c15_cpar = ARM_TBFLAG_XSCALE_CPAR(tb->flags);
11650 dc->cp_regs = cpu->cp_regs;
11651 dc->features = env->features;
11652
11653
11654
11655
11656
11657
11658
11659
11660
11661
11662
11663
11664
11665
11666
11667
11668 dc->ss_active = ARM_TBFLAG_SS_ACTIVE(tb->flags);
11669 dc->pstate_ss = ARM_TBFLAG_PSTATE_SS(tb->flags);
11670 dc->is_ldex = false;
11671 dc->ss_same_el = false;
11672
11673 cpu_F0s = tcg_temp_new_i32();
11674 cpu_F1s = tcg_temp_new_i32();
11675 cpu_F0d = tcg_temp_new_i64();
11676 cpu_F1d = tcg_temp_new_i64();
11677 cpu_V0 = cpu_F0d;
11678 cpu_V1 = cpu_F1d;
11679
11680 cpu_M0 = tcg_temp_new_i64();
11681 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
11682 num_insns = 0;
11683 max_insns = tb->cflags & CF_COUNT_MASK;
11684 if (max_insns == 0) {
11685 max_insns = CF_COUNT_MASK;
11686 }
11687 if (max_insns > TCG_MAX_INSNS) {
11688 max_insns = TCG_MAX_INSNS;
11689 }
11690
11691 gen_tb_start(tb);
11692
11693 tcg_clear_temp_count();
11694
11695
11696
11697
11698
11699
11700
11701
11702
11703
11704
11705
11706
11707
11708
11709
11710
11711
11712
11713
11714
11715
11716
11717
11718
11719
11720
11721
11722
11723
11724
11725
11726
11727 if (dc->condexec_mask || dc->condexec_cond)
11728 {
11729 TCGv_i32 tmp = tcg_temp_new_i32();
11730 tcg_gen_movi_i32(tmp, 0);
11731 store_cpu_field(tmp, condexec_bits);
11732 }
11733 do {
11734 tcg_gen_insn_start(dc->pc,
11735 (dc->condexec_cond << 4) | (dc->condexec_mask >> 1),
11736 0);
11737 num_insns++;
11738
11739#ifdef CONFIG_USER_ONLY
11740
11741 if (dc->pc >= 0xffff0000) {
11742
11743
11744 gen_exception_internal(EXCP_KERNEL_TRAP);
11745 dc->is_jmp = DISAS_EXC;
11746 break;
11747 }
11748#else
11749 if (dc->pc >= 0xfffffff0 && arm_dc_feature(dc, ARM_FEATURE_M)) {
11750
11751
11752 gen_exception_internal(EXCP_EXCEPTION_EXIT);
11753 dc->is_jmp = DISAS_EXC;
11754 break;
11755 }
11756#endif
11757
11758 if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
11759 CPUBreakpoint *bp;
11760 QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
11761 if (bp->pc == dc->pc) {
11762 if (bp->flags & BP_CPU) {
11763 gen_set_condexec(dc);
11764 gen_set_pc_im(dc, dc->pc);
11765 gen_helper_check_breakpoints(cpu_env);
11766
11767 dc->is_jmp = DISAS_UPDATE;
11768 } else {
11769 gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
11770
11771
11772
11773
11774
11775
11776
11777 dc->pc += 2;
11778 goto done_generating;
11779 }
11780 break;
11781 }
11782 }
11783 }
11784
11785 if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
11786 gen_io_start();
11787 }
11788
11789 if (dc->ss_active && !dc->pstate_ss) {
11790
11791
11792
11793
11794
11795
11796
11797
11798
11799
11800 assert(num_insns == 1);
11801 gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
11802 default_exception_el(dc));
11803 goto done_generating;
11804 }
11805
11806 if (dc->thumb) {
11807 disas_thumb_insn(env, dc);
11808 if (dc->condexec_mask) {
11809 dc->condexec_cond = (dc->condexec_cond & 0xe)
11810 | ((dc->condexec_mask >> 4) & 1);
11811 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
11812 if (dc->condexec_mask == 0) {
11813 dc->condexec_cond = 0;
11814 }
11815 }
11816 } else {
11817 unsigned int insn = arm_ldl_code(env, dc->pc, dc->sctlr_b);
11818 dc->pc += 4;
11819 disas_arm_insn(dc, insn);
11820 }
11821
11822 if (dc->condjmp && !dc->is_jmp) {
11823 gen_set_label(dc->condlabel);
11824 dc->condjmp = 0;
11825 }
11826
11827 if (tcg_check_temp_count()) {
11828 fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
11829 dc->pc);
11830 }
11831
11832
11833
11834
11835
11836
11837
11838
11839
11840
11841
11842
11843
11844
11845
11846 end_of_page = (dc->pc >= next_page_start) ||
11847 ((dc->pc >= next_page_start - 3) && insn_crosses_page(env, dc));
11848
11849 } while (!dc->is_jmp && !tcg_op_buf_full() &&
11850 !cs->singlestep_enabled &&
11851 !singlestep &&
11852 !dc->ss_active &&
11853 !end_of_page &&
11854 num_insns < max_insns);
11855
11856 if (tb->cflags & CF_LAST_IO) {
11857 if (dc->condjmp) {
11858
11859
11860 cpu_abort(cs, "IO on conditional branch instruction");
11861 }
11862 gen_io_end();
11863 }
11864
11865
11866
11867
11868 if (unlikely(cs->singlestep_enabled || dc->ss_active)) {
11869
11870 gen_set_condexec(dc);
11871 switch (dc->is_jmp) {
11872 case DISAS_SWI:
11873 gen_ss_advance(dc);
11874 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
11875 default_exception_el(dc));
11876 break;
11877 case DISAS_HVC:
11878 gen_ss_advance(dc);
11879 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
11880 break;
11881 case DISAS_SMC:
11882 gen_ss_advance(dc);
11883 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
11884 break;
11885 case DISAS_NEXT:
11886 case DISAS_UPDATE:
11887 gen_set_pc_im(dc, dc->pc);
11888
11889 default:
11890 if (dc->ss_active) {
11891 gen_step_complete_exception(dc);
11892 } else {
11893
11894
11895 gen_exception_internal(EXCP_DEBUG);
11896 }
11897 }
11898 if (dc->condjmp) {
11899
11900 gen_set_label(dc->condlabel);
11901 gen_set_condexec(dc);
11902 gen_set_pc_im(dc, dc->pc);
11903 if (dc->ss_active) {
11904 gen_step_complete_exception(dc);
11905 } else {
11906 gen_exception_internal(EXCP_DEBUG);
11907 }
11908 }
11909 } else {
11910
11911
11912
11913
11914
11915
11916
11917
11918 gen_set_condexec(dc);
11919 switch(dc->is_jmp) {
11920 case DISAS_NEXT:
11921 gen_goto_tb(dc, 1, dc->pc);
11922 break;
11923 case DISAS_UPDATE:
11924 gen_set_pc_im(dc, dc->pc);
11925
11926 case DISAS_JUMP:
11927 default:
11928
11929 tcg_gen_exit_tb(0);
11930 break;
11931 case DISAS_TB_JUMP:
11932
11933 break;
11934 case DISAS_WFI:
11935 gen_helper_wfi(cpu_env);
11936
11937
11938
11939 tcg_gen_exit_tb(0);
11940 break;
11941 case DISAS_WFE:
11942 gen_helper_wfe(cpu_env);
11943 break;
11944 case DISAS_YIELD:
11945 gen_helper_yield(cpu_env);
11946 break;
11947 case DISAS_SWI:
11948 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
11949 default_exception_el(dc));
11950 break;
11951 case DISAS_HVC:
11952 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
11953 break;
11954 case DISAS_SMC:
11955 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
11956 break;
11957 }
11958 if (dc->condjmp) {
11959 gen_set_label(dc->condlabel);
11960 gen_set_condexec(dc);
11961 gen_goto_tb(dc, 1, dc->pc);
11962 dc->condjmp = 0;
11963 }
11964 }
11965
11966done_generating:
11967 gen_tb_end(tb, num_insns);
11968
11969#ifdef DEBUG_DISAS
11970 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) &&
11971 qemu_log_in_addr_range(pc_start)) {
11972 qemu_log("----------------\n");
11973 qemu_log("IN: %s\n", lookup_symbol(pc_start));
11974 log_target_disas(cs, pc_start, dc->pc - pc_start,
11975 dc->thumb | (dc->sctlr_b << 1));
11976 qemu_log("\n");
11977 }
11978#endif
11979 tb->size = dc->pc - pc_start;
11980 tb->icount = num_insns;
11981}
11982
11983static const char *cpu_mode_names[16] = {
11984 "usr", "fiq", "irq", "svc", "???", "???", "mon", "abt",
11985 "???", "???", "hyp", "und", "???", "???", "???", "sys"
11986};
11987
11988void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
11989 int flags)
11990{
11991 ARMCPU *cpu = ARM_CPU(cs);
11992 CPUARMState *env = &cpu->env;
11993 int i;
11994 uint32_t psr;
11995 const char *ns_status;
11996
11997 if (is_a64(env)) {
11998 aarch64_cpu_dump_state(cs, f, cpu_fprintf, flags);
11999 return;
12000 }
12001
12002 for(i=0;i<16;i++) {
12003 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
12004 if ((i % 4) == 3)
12005 cpu_fprintf(f, "\n");
12006 else
12007 cpu_fprintf(f, " ");
12008 }
12009 psr = cpsr_read(env);
12010
12011 if (arm_feature(env, ARM_FEATURE_EL3) &&
12012 (psr & CPSR_M) != ARM_CPU_MODE_MON) {
12013 ns_status = env->cp15.scr_el3 & SCR_NS ? "NS " : "S ";
12014 } else {
12015 ns_status = "";
12016 }
12017
12018 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%s%d\n",
12019 psr,
12020 psr & (1 << 31) ? 'N' : '-',
12021 psr & (1 << 30) ? 'Z' : '-',
12022 psr & (1 << 29) ? 'C' : '-',
12023 psr & (1 << 28) ? 'V' : '-',
12024 psr & CPSR_T ? 'T' : 'A',
12025 ns_status,
12026 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
12027
12028 if (flags & CPU_DUMP_FPU) {
12029 int numvfpregs = 0;
12030 if (arm_feature(env, ARM_FEATURE_VFP)) {
12031 numvfpregs += 16;
12032 }
12033 if (arm_feature(env, ARM_FEATURE_VFP3)) {
12034 numvfpregs += 16;
12035 }
12036 for (i = 0; i < numvfpregs; i++) {
12037 uint64_t v = float64_val(env->vfp.regs[i]);
12038 cpu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n",
12039 i * 2, (uint32_t)v,
12040 i * 2 + 1, (uint32_t)(v >> 32),
12041 i, v);
12042 }
12043 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
12044 }
12045}
12046
12047void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb,
12048 target_ulong *data)
12049{
12050 if (is_a64(env)) {
12051 env->pc = data[0];
12052 env->condexec_bits = 0;
12053 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
12054 } else {
12055 env->regs[15] = data[0];
12056 env->condexec_bits = data[1];
12057 }
12058}
12059