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