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