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