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