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