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