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