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