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