hw/sd/pl181: Replace fprintf(stderr, "*\n") with error_report()
[qemu/ar7.git] / target / arm / translate.c
blob556588d92fe3fb0e1f49e5c03b5a176fb0dbb004
1 /*
2 * ARM translation
4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2005-2007 CodeSourcery
6 * Copyright (c) 2007 OpenedHand, Ltd.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #include "qemu/osdep.h"
23 #include "cpu.h"
24 #include "internals.h"
25 #include "disas/disas.h"
26 #include "exec/exec-all.h"
27 #include "tcg/tcg-op.h"
28 #include "tcg/tcg-op-gvec.h"
29 #include "qemu/log.h"
30 #include "qemu/bitops.h"
31 #include "arm_ldst.h"
32 #include "hw/semihosting/semihost.h"
34 #include "exec/helper-proto.h"
35 #include "exec/helper-gen.h"
37 #include "trace-tcg.h"
38 #include "exec/log.h"
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 /* currently all emulated v5 cores are also v5TE, so don't bother */
44 #define ENABLE_ARCH_5TE arm_dc_feature(s, ARM_FEATURE_V5)
45 #define ENABLE_ARCH_5J dc_isar_feature(aa32_jazelle, s)
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)
52 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
54 #include "translate.h"
56 #if defined(CONFIG_USER_ONLY)
57 #define IS_USER(s) 1
58 #else
59 #define IS_USER(s) (s->user)
60 #endif
62 /* We reuse the same 64-bit temporaries for efficiency. */
63 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
64 static TCGv_i32 cpu_R[16];
65 TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
66 TCGv_i64 cpu_exclusive_addr;
67 TCGv_i64 cpu_exclusive_val;
69 #include "exec/gen-icount.h"
71 static const char * const regnames[] =
72 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
73 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
75 /* Function prototypes for gen_ functions calling Neon helpers. */
76 typedef void NeonGenThreeOpEnvFn(TCGv_i32, TCGv_env, TCGv_i32,
77 TCGv_i32, TCGv_i32);
78 /* Function prototypes for gen_ functions for fix point conversions */
79 typedef void VFPGenFixPointFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
81 /* initialize TCG globals. */
82 void arm_translate_init(void)
84 int i;
86 for (i = 0; i < 16; i++) {
87 cpu_R[i] = tcg_global_mem_new_i32(cpu_env,
88 offsetof(CPUARMState, regs[i]),
89 regnames[i]);
91 cpu_CF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, CF), "CF");
92 cpu_NF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, NF), "NF");
93 cpu_VF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, VF), "VF");
94 cpu_ZF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, ZF), "ZF");
96 cpu_exclusive_addr = tcg_global_mem_new_i64(cpu_env,
97 offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
98 cpu_exclusive_val = tcg_global_mem_new_i64(cpu_env,
99 offsetof(CPUARMState, exclusive_val), "exclusive_val");
101 a64_translate_init();
104 /* Flags for the disas_set_da_iss info argument:
105 * lower bits hold the Rt register number, higher bits are flags.
107 typedef enum ISSInfo {
108 ISSNone = 0,
109 ISSRegMask = 0x1f,
110 ISSInvalid = (1 << 5),
111 ISSIsAcqRel = (1 << 6),
112 ISSIsWrite = (1 << 7),
113 ISSIs16Bit = (1 << 8),
114 } ISSInfo;
116 /* Save the syndrome information for a Data Abort */
117 static void disas_set_da_iss(DisasContext *s, MemOp memop, ISSInfo issinfo)
119 uint32_t syn;
120 int sas = memop & MO_SIZE;
121 bool sse = memop & MO_SIGN;
122 bool is_acqrel = issinfo & ISSIsAcqRel;
123 bool is_write = issinfo & ISSIsWrite;
124 bool is_16bit = issinfo & ISSIs16Bit;
125 int srt = issinfo & ISSRegMask;
127 if (issinfo & ISSInvalid) {
128 /* Some callsites want to conditionally provide ISS info,
129 * eg "only if this was not a writeback"
131 return;
134 if (srt == 15) {
135 /* For AArch32, insns where the src/dest is R15 never generate
136 * ISS information. Catching that here saves checking at all
137 * the call sites.
139 return;
142 syn = syn_data_abort_with_iss(0, sas, sse, srt, 0, is_acqrel,
143 0, 0, 0, is_write, 0, is_16bit);
144 disas_set_insn_syndrome(s, syn);
147 static inline int get_a32_user_mem_index(DisasContext *s)
149 /* Return the core mmu_idx to use for A32/T32 "unprivileged load/store"
150 * insns:
151 * if PL2, UNPREDICTABLE (we choose to implement as if PL0)
152 * otherwise, access as if at PL0.
154 switch (s->mmu_idx) {
155 case ARMMMUIdx_E2: /* this one is UNPREDICTABLE */
156 case ARMMMUIdx_E10_0:
157 case ARMMMUIdx_E10_1:
158 case ARMMMUIdx_E10_1_PAN:
159 return arm_to_core_mmu_idx(ARMMMUIdx_E10_0);
160 case ARMMMUIdx_SE3:
161 case ARMMMUIdx_SE10_0:
162 case ARMMMUIdx_SE10_1:
163 case ARMMMUIdx_SE10_1_PAN:
164 return arm_to_core_mmu_idx(ARMMMUIdx_SE10_0);
165 case ARMMMUIdx_MUser:
166 case ARMMMUIdx_MPriv:
167 return arm_to_core_mmu_idx(ARMMMUIdx_MUser);
168 case ARMMMUIdx_MUserNegPri:
169 case ARMMMUIdx_MPrivNegPri:
170 return arm_to_core_mmu_idx(ARMMMUIdx_MUserNegPri);
171 case ARMMMUIdx_MSUser:
172 case ARMMMUIdx_MSPriv:
173 return arm_to_core_mmu_idx(ARMMMUIdx_MSUser);
174 case ARMMMUIdx_MSUserNegPri:
175 case ARMMMUIdx_MSPrivNegPri:
176 return arm_to_core_mmu_idx(ARMMMUIdx_MSUserNegPri);
177 default:
178 g_assert_not_reached();
182 static inline TCGv_i32 load_cpu_offset(int offset)
184 TCGv_i32 tmp = tcg_temp_new_i32();
185 tcg_gen_ld_i32(tmp, cpu_env, offset);
186 return tmp;
189 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
191 static inline void store_cpu_offset(TCGv_i32 var, int offset)
193 tcg_gen_st_i32(var, cpu_env, offset);
194 tcg_temp_free_i32(var);
197 #define store_cpu_field(var, name) \
198 store_cpu_offset(var, offsetof(CPUARMState, name))
200 /* The architectural value of PC. */
201 static uint32_t read_pc(DisasContext *s)
203 return s->pc_curr + (s->thumb ? 4 : 8);
206 /* Set a variable to the value of a CPU register. */
207 static void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
209 if (reg == 15) {
210 tcg_gen_movi_i32(var, read_pc(s));
211 } else {
212 tcg_gen_mov_i32(var, cpu_R[reg]);
216 /* Create a new temporary and set it to the value of a CPU register. */
217 static inline TCGv_i32 load_reg(DisasContext *s, int reg)
219 TCGv_i32 tmp = tcg_temp_new_i32();
220 load_reg_var(s, tmp, reg);
221 return tmp;
225 * Create a new temp, REG + OFS, except PC is ALIGN(PC, 4).
226 * This is used for load/store for which use of PC implies (literal),
227 * or ADD that implies ADR.
229 static TCGv_i32 add_reg_for_lit(DisasContext *s, int reg, int ofs)
231 TCGv_i32 tmp = tcg_temp_new_i32();
233 if (reg == 15) {
234 tcg_gen_movi_i32(tmp, (read_pc(s) & ~3) + ofs);
235 } else {
236 tcg_gen_addi_i32(tmp, cpu_R[reg], ofs);
238 return tmp;
241 /* Set a CPU register. The source must be a temporary and will be
242 marked as dead. */
243 static void store_reg(DisasContext *s, int reg, TCGv_i32 var)
245 if (reg == 15) {
246 /* In Thumb mode, we must ignore bit 0.
247 * In ARM mode, for ARMv4 and ARMv5, it is UNPREDICTABLE if bits [1:0]
248 * are not 0b00, but for ARMv6 and above, we must ignore bits [1:0].
249 * We choose to ignore [1:0] in ARM mode for all architecture versions.
251 tcg_gen_andi_i32(var, var, s->thumb ? ~1 : ~3);
252 s->base.is_jmp = DISAS_JUMP;
254 tcg_gen_mov_i32(cpu_R[reg], var);
255 tcg_temp_free_i32(var);
259 * Variant of store_reg which applies v8M stack-limit checks before updating
260 * SP. If the check fails this will result in an exception being taken.
261 * We disable the stack checks for CONFIG_USER_ONLY because we have
262 * no idea what the stack limits should be in that case.
263 * If stack checking is not being done this just acts like store_reg().
265 static void store_sp_checked(DisasContext *s, TCGv_i32 var)
267 #ifndef CONFIG_USER_ONLY
268 if (s->v8m_stackcheck) {
269 gen_helper_v8m_stackcheck(cpu_env, var);
271 #endif
272 store_reg(s, 13, var);
275 /* Value extensions. */
276 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
277 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
278 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
279 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
281 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
282 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
285 static inline void gen_set_cpsr(TCGv_i32 var, uint32_t mask)
287 TCGv_i32 tmp_mask = tcg_const_i32(mask);
288 gen_helper_cpsr_write(cpu_env, var, tmp_mask);
289 tcg_temp_free_i32(tmp_mask);
291 /* Set NZCV flags from the high 4 bits of var. */
292 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
294 static void gen_exception_internal(int excp)
296 TCGv_i32 tcg_excp = tcg_const_i32(excp);
298 assert(excp_is_internal(excp));
299 gen_helper_exception_internal(cpu_env, tcg_excp);
300 tcg_temp_free_i32(tcg_excp);
303 static void gen_step_complete_exception(DisasContext *s)
305 /* We just completed step of an insn. Move from Active-not-pending
306 * to Active-pending, and then also take the swstep exception.
307 * This corresponds to making the (IMPDEF) choice to prioritize
308 * swstep exceptions over asynchronous exceptions taken to an exception
309 * level where debug is disabled. This choice has the advantage that
310 * we do not need to maintain internal state corresponding to the
311 * ISV/EX syndrome bits between completion of the step and generation
312 * of the exception, and our syndrome information is always correct.
314 gen_ss_advance(s);
315 gen_swstep_exception(s, 1, s->is_ldex);
316 s->base.is_jmp = DISAS_NORETURN;
319 static void gen_singlestep_exception(DisasContext *s)
321 /* Generate the right kind of exception for singlestep, which is
322 * either the architectural singlestep or EXCP_DEBUG for QEMU's
323 * gdb singlestepping.
325 if (s->ss_active) {
326 gen_step_complete_exception(s);
327 } else {
328 gen_exception_internal(EXCP_DEBUG);
332 static inline bool is_singlestepping(DisasContext *s)
334 /* Return true if we are singlestepping either because of
335 * architectural singlestep or QEMU gdbstub singlestep. This does
336 * not include the command line '-singlestep' mode which is rather
337 * misnamed as it only means "one instruction per TB" and doesn't
338 * affect the code we generate.
340 return s->base.singlestep_enabled || s->ss_active;
343 static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
345 TCGv_i32 tmp1 = tcg_temp_new_i32();
346 TCGv_i32 tmp2 = tcg_temp_new_i32();
347 tcg_gen_ext16s_i32(tmp1, a);
348 tcg_gen_ext16s_i32(tmp2, b);
349 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
350 tcg_temp_free_i32(tmp2);
351 tcg_gen_sari_i32(a, a, 16);
352 tcg_gen_sari_i32(b, b, 16);
353 tcg_gen_mul_i32(b, b, a);
354 tcg_gen_mov_i32(a, tmp1);
355 tcg_temp_free_i32(tmp1);
358 /* Byteswap each halfword. */
359 static void gen_rev16(TCGv_i32 dest, TCGv_i32 var)
361 TCGv_i32 tmp = tcg_temp_new_i32();
362 TCGv_i32 mask = tcg_const_i32(0x00ff00ff);
363 tcg_gen_shri_i32(tmp, var, 8);
364 tcg_gen_and_i32(tmp, tmp, mask);
365 tcg_gen_and_i32(var, var, mask);
366 tcg_gen_shli_i32(var, var, 8);
367 tcg_gen_or_i32(dest, var, tmp);
368 tcg_temp_free_i32(mask);
369 tcg_temp_free_i32(tmp);
372 /* Byteswap low halfword and sign extend. */
373 static void gen_revsh(TCGv_i32 dest, TCGv_i32 var)
375 tcg_gen_ext16u_i32(var, var);
376 tcg_gen_bswap16_i32(var, var);
377 tcg_gen_ext16s_i32(dest, var);
380 /* Swap low and high halfwords. */
381 static void gen_swap_half(TCGv_i32 dest, TCGv_i32 var)
383 tcg_gen_rotri_i32(dest, var, 16);
386 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
387 tmp = (t0 ^ t1) & 0x8000;
388 t0 &= ~0x8000;
389 t1 &= ~0x8000;
390 t0 = (t0 + t1) ^ tmp;
393 static void gen_add16(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
395 TCGv_i32 tmp = tcg_temp_new_i32();
396 tcg_gen_xor_i32(tmp, t0, t1);
397 tcg_gen_andi_i32(tmp, tmp, 0x8000);
398 tcg_gen_andi_i32(t0, t0, ~0x8000);
399 tcg_gen_andi_i32(t1, t1, ~0x8000);
400 tcg_gen_add_i32(t0, t0, t1);
401 tcg_gen_xor_i32(dest, t0, tmp);
402 tcg_temp_free_i32(tmp);
405 /* Set N and Z flags from var. */
406 static inline void gen_logic_CC(TCGv_i32 var)
408 tcg_gen_mov_i32(cpu_NF, var);
409 tcg_gen_mov_i32(cpu_ZF, var);
412 /* dest = T0 + T1 + CF. */
413 static void gen_add_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
415 tcg_gen_add_i32(dest, t0, t1);
416 tcg_gen_add_i32(dest, dest, cpu_CF);
419 /* dest = T0 - T1 + CF - 1. */
420 static void gen_sub_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
422 tcg_gen_sub_i32(dest, t0, t1);
423 tcg_gen_add_i32(dest, dest, cpu_CF);
424 tcg_gen_subi_i32(dest, dest, 1);
427 /* dest = T0 + T1. Compute C, N, V and Z flags */
428 static void gen_add_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
430 TCGv_i32 tmp = tcg_temp_new_i32();
431 tcg_gen_movi_i32(tmp, 0);
432 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, t1, tmp);
433 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
434 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
435 tcg_gen_xor_i32(tmp, t0, t1);
436 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
437 tcg_temp_free_i32(tmp);
438 tcg_gen_mov_i32(dest, cpu_NF);
441 /* dest = T0 + T1 + CF. Compute C, N, V and Z flags */
442 static void gen_adc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
444 TCGv_i32 tmp = tcg_temp_new_i32();
445 if (TCG_TARGET_HAS_add2_i32) {
446 tcg_gen_movi_i32(tmp, 0);
447 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, cpu_CF, tmp);
448 tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1, tmp);
449 } else {
450 TCGv_i64 q0 = tcg_temp_new_i64();
451 TCGv_i64 q1 = tcg_temp_new_i64();
452 tcg_gen_extu_i32_i64(q0, t0);
453 tcg_gen_extu_i32_i64(q1, t1);
454 tcg_gen_add_i64(q0, q0, q1);
455 tcg_gen_extu_i32_i64(q1, cpu_CF);
456 tcg_gen_add_i64(q0, q0, q1);
457 tcg_gen_extr_i64_i32(cpu_NF, cpu_CF, q0);
458 tcg_temp_free_i64(q0);
459 tcg_temp_free_i64(q1);
461 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
462 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
463 tcg_gen_xor_i32(tmp, t0, t1);
464 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
465 tcg_temp_free_i32(tmp);
466 tcg_gen_mov_i32(dest, cpu_NF);
469 /* dest = T0 - T1. Compute C, N, V and Z flags */
470 static void gen_sub_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
472 TCGv_i32 tmp;
473 tcg_gen_sub_i32(cpu_NF, t0, t1);
474 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
475 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0, t1);
476 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
477 tmp = tcg_temp_new_i32();
478 tcg_gen_xor_i32(tmp, t0, t1);
479 tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
480 tcg_temp_free_i32(tmp);
481 tcg_gen_mov_i32(dest, cpu_NF);
484 /* dest = T0 + ~T1 + CF. Compute C, N, V and Z flags */
485 static void gen_sbc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
487 TCGv_i32 tmp = tcg_temp_new_i32();
488 tcg_gen_not_i32(tmp, t1);
489 gen_adc_CC(dest, t0, tmp);
490 tcg_temp_free_i32(tmp);
493 #define GEN_SHIFT(name) \
494 static void gen_##name(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) \
496 TCGv_i32 tmp1, tmp2, tmp3; \
497 tmp1 = tcg_temp_new_i32(); \
498 tcg_gen_andi_i32(tmp1, t1, 0xff); \
499 tmp2 = tcg_const_i32(0); \
500 tmp3 = tcg_const_i32(0x1f); \
501 tcg_gen_movcond_i32(TCG_COND_GTU, tmp2, tmp1, tmp3, tmp2, t0); \
502 tcg_temp_free_i32(tmp3); \
503 tcg_gen_andi_i32(tmp1, tmp1, 0x1f); \
504 tcg_gen_##name##_i32(dest, tmp2, tmp1); \
505 tcg_temp_free_i32(tmp2); \
506 tcg_temp_free_i32(tmp1); \
508 GEN_SHIFT(shl)
509 GEN_SHIFT(shr)
510 #undef GEN_SHIFT
512 static void gen_sar(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
514 TCGv_i32 tmp1, tmp2;
515 tmp1 = tcg_temp_new_i32();
516 tcg_gen_andi_i32(tmp1, t1, 0xff);
517 tmp2 = tcg_const_i32(0x1f);
518 tcg_gen_movcond_i32(TCG_COND_GTU, tmp1, tmp1, tmp2, tmp2, tmp1);
519 tcg_temp_free_i32(tmp2);
520 tcg_gen_sar_i32(dest, t0, tmp1);
521 tcg_temp_free_i32(tmp1);
524 static void shifter_out_im(TCGv_i32 var, int shift)
526 tcg_gen_extract_i32(cpu_CF, var, shift, 1);
529 /* Shift by immediate. Includes special handling for shift == 0. */
530 static inline void gen_arm_shift_im(TCGv_i32 var, int shiftop,
531 int shift, int flags)
533 switch (shiftop) {
534 case 0: /* LSL */
535 if (shift != 0) {
536 if (flags)
537 shifter_out_im(var, 32 - shift);
538 tcg_gen_shli_i32(var, var, shift);
540 break;
541 case 1: /* LSR */
542 if (shift == 0) {
543 if (flags) {
544 tcg_gen_shri_i32(cpu_CF, var, 31);
546 tcg_gen_movi_i32(var, 0);
547 } else {
548 if (flags)
549 shifter_out_im(var, shift - 1);
550 tcg_gen_shri_i32(var, var, shift);
552 break;
553 case 2: /* ASR */
554 if (shift == 0)
555 shift = 32;
556 if (flags)
557 shifter_out_im(var, shift - 1);
558 if (shift == 32)
559 shift = 31;
560 tcg_gen_sari_i32(var, var, shift);
561 break;
562 case 3: /* ROR/RRX */
563 if (shift != 0) {
564 if (flags)
565 shifter_out_im(var, shift - 1);
566 tcg_gen_rotri_i32(var, var, shift); break;
567 } else {
568 TCGv_i32 tmp = tcg_temp_new_i32();
569 tcg_gen_shli_i32(tmp, cpu_CF, 31);
570 if (flags)
571 shifter_out_im(var, 0);
572 tcg_gen_shri_i32(var, var, 1);
573 tcg_gen_or_i32(var, var, tmp);
574 tcg_temp_free_i32(tmp);
579 static inline void gen_arm_shift_reg(TCGv_i32 var, int shiftop,
580 TCGv_i32 shift, int flags)
582 if (flags) {
583 switch (shiftop) {
584 case 0: gen_helper_shl_cc(var, cpu_env, var, shift); break;
585 case 1: gen_helper_shr_cc(var, cpu_env, var, shift); break;
586 case 2: gen_helper_sar_cc(var, cpu_env, var, shift); break;
587 case 3: gen_helper_ror_cc(var, cpu_env, var, shift); break;
589 } else {
590 switch (shiftop) {
591 case 0:
592 gen_shl(var, var, shift);
593 break;
594 case 1:
595 gen_shr(var, var, shift);
596 break;
597 case 2:
598 gen_sar(var, var, shift);
599 break;
600 case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
601 tcg_gen_rotr_i32(var, var, shift); break;
604 tcg_temp_free_i32(shift);
608 * Generate a conditional based on ARM condition code cc.
609 * This is common between ARM and Aarch64 targets.
611 void arm_test_cc(DisasCompare *cmp, int cc)
613 TCGv_i32 value;
614 TCGCond cond;
615 bool global = true;
617 switch (cc) {
618 case 0: /* eq: Z */
619 case 1: /* ne: !Z */
620 cond = TCG_COND_EQ;
621 value = cpu_ZF;
622 break;
624 case 2: /* cs: C */
625 case 3: /* cc: !C */
626 cond = TCG_COND_NE;
627 value = cpu_CF;
628 break;
630 case 4: /* mi: N */
631 case 5: /* pl: !N */
632 cond = TCG_COND_LT;
633 value = cpu_NF;
634 break;
636 case 6: /* vs: V */
637 case 7: /* vc: !V */
638 cond = TCG_COND_LT;
639 value = cpu_VF;
640 break;
642 case 8: /* hi: C && !Z */
643 case 9: /* ls: !C || Z -> !(C && !Z) */
644 cond = TCG_COND_NE;
645 value = tcg_temp_new_i32();
646 global = false;
647 /* CF is 1 for C, so -CF is an all-bits-set mask for C;
648 ZF is non-zero for !Z; so AND the two subexpressions. */
649 tcg_gen_neg_i32(value, cpu_CF);
650 tcg_gen_and_i32(value, value, cpu_ZF);
651 break;
653 case 10: /* ge: N == V -> N ^ V == 0 */
654 case 11: /* lt: N != V -> N ^ V != 0 */
655 /* Since we're only interested in the sign bit, == 0 is >= 0. */
656 cond = TCG_COND_GE;
657 value = tcg_temp_new_i32();
658 global = false;
659 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
660 break;
662 case 12: /* gt: !Z && N == V */
663 case 13: /* le: Z || N != V */
664 cond = TCG_COND_NE;
665 value = tcg_temp_new_i32();
666 global = false;
667 /* (N == V) is equal to the sign bit of ~(NF ^ VF). Propagate
668 * the sign bit then AND with ZF to yield the result. */
669 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
670 tcg_gen_sari_i32(value, value, 31);
671 tcg_gen_andc_i32(value, cpu_ZF, value);
672 break;
674 case 14: /* always */
675 case 15: /* always */
676 /* Use the ALWAYS condition, which will fold early.
677 * It doesn't matter what we use for the value. */
678 cond = TCG_COND_ALWAYS;
679 value = cpu_ZF;
680 goto no_invert;
682 default:
683 fprintf(stderr, "Bad condition code 0x%x\n", cc);
684 abort();
687 if (cc & 1) {
688 cond = tcg_invert_cond(cond);
691 no_invert:
692 cmp->cond = cond;
693 cmp->value = value;
694 cmp->value_global = global;
697 void arm_free_cc(DisasCompare *cmp)
699 if (!cmp->value_global) {
700 tcg_temp_free_i32(cmp->value);
704 void arm_jump_cc(DisasCompare *cmp, TCGLabel *label)
706 tcg_gen_brcondi_i32(cmp->cond, cmp->value, 0, label);
709 void arm_gen_test_cc(int cc, TCGLabel *label)
711 DisasCompare cmp;
712 arm_test_cc(&cmp, cc);
713 arm_jump_cc(&cmp, label);
714 arm_free_cc(&cmp);
717 static inline void gen_set_condexec(DisasContext *s)
719 if (s->condexec_mask) {
720 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
721 TCGv_i32 tmp = tcg_temp_new_i32();
722 tcg_gen_movi_i32(tmp, val);
723 store_cpu_field(tmp, condexec_bits);
727 static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
729 tcg_gen_movi_i32(cpu_R[15], val);
732 /* Set PC and Thumb state from var. var is marked as dead. */
733 static inline void gen_bx(DisasContext *s, TCGv_i32 var)
735 s->base.is_jmp = DISAS_JUMP;
736 tcg_gen_andi_i32(cpu_R[15], var, ~1);
737 tcg_gen_andi_i32(var, var, 1);
738 store_cpu_field(var, thumb);
742 * Set PC and Thumb state from var. var is marked as dead.
743 * For M-profile CPUs, include logic to detect exception-return
744 * branches and handle them. This is needed for Thumb POP/LDM to PC, LDR to PC,
745 * and BX reg, and no others, and happens only for code in Handler mode.
746 * The Security Extension also requires us to check for the FNC_RETURN
747 * which signals a function return from non-secure state; this can happen
748 * in both Handler and Thread mode.
749 * To avoid having to do multiple comparisons in inline generated code,
750 * we make the check we do here loose, so it will match for EXC_RETURN
751 * in Thread mode. For system emulation do_v7m_exception_exit() checks
752 * for these spurious cases and returns without doing anything (giving
753 * the same behaviour as for a branch to a non-magic address).
755 * In linux-user mode it is unclear what the right behaviour for an
756 * attempted FNC_RETURN should be, because in real hardware this will go
757 * directly to Secure code (ie not the Linux kernel) which will then treat
758 * the error in any way it chooses. For QEMU we opt to make the FNC_RETURN
759 * attempt behave the way it would on a CPU without the security extension,
760 * which is to say "like a normal branch". That means we can simply treat
761 * all branches as normal with no magic address behaviour.
763 static inline void gen_bx_excret(DisasContext *s, TCGv_i32 var)
765 /* Generate the same code here as for a simple bx, but flag via
766 * s->base.is_jmp that we need to do the rest of the work later.
768 gen_bx(s, var);
769 #ifndef CONFIG_USER_ONLY
770 if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY) ||
771 (s->v7m_handler_mode && arm_dc_feature(s, ARM_FEATURE_M))) {
772 s->base.is_jmp = DISAS_BX_EXCRET;
774 #endif
777 static inline void gen_bx_excret_final_code(DisasContext *s)
779 /* Generate the code to finish possible exception return and end the TB */
780 TCGLabel *excret_label = gen_new_label();
781 uint32_t min_magic;
783 if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY)) {
784 /* Covers FNC_RETURN and EXC_RETURN magic */
785 min_magic = FNC_RETURN_MIN_MAGIC;
786 } else {
787 /* EXC_RETURN magic only */
788 min_magic = EXC_RETURN_MIN_MAGIC;
791 /* Is the new PC value in the magic range indicating exception return? */
792 tcg_gen_brcondi_i32(TCG_COND_GEU, cpu_R[15], min_magic, excret_label);
793 /* No: end the TB as we would for a DISAS_JMP */
794 if (is_singlestepping(s)) {
795 gen_singlestep_exception(s);
796 } else {
797 tcg_gen_exit_tb(NULL, 0);
799 gen_set_label(excret_label);
800 /* Yes: this is an exception return.
801 * At this point in runtime env->regs[15] and env->thumb will hold
802 * the exception-return magic number, which do_v7m_exception_exit()
803 * will read. Nothing else will be able to see those values because
804 * the cpu-exec main loop guarantees that we will always go straight
805 * from raising the exception to the exception-handling code.
807 * gen_ss_advance(s) does nothing on M profile currently but
808 * calling it is conceptually the right thing as we have executed
809 * this instruction (compare SWI, HVC, SMC handling).
811 gen_ss_advance(s);
812 gen_exception_internal(EXCP_EXCEPTION_EXIT);
815 static inline void gen_bxns(DisasContext *s, int rm)
817 TCGv_i32 var = load_reg(s, rm);
819 /* The bxns helper may raise an EXCEPTION_EXIT exception, so in theory
820 * we need to sync state before calling it, but:
821 * - we don't need to do gen_set_pc_im() because the bxns helper will
822 * always set the PC itself
823 * - we don't need to do gen_set_condexec() because BXNS is UNPREDICTABLE
824 * unless it's outside an IT block or the last insn in an IT block,
825 * so we know that condexec == 0 (already set at the top of the TB)
826 * is correct in the non-UNPREDICTABLE cases, and we can choose
827 * "zeroes the IT bits" as our UNPREDICTABLE behaviour otherwise.
829 gen_helper_v7m_bxns(cpu_env, var);
830 tcg_temp_free_i32(var);
831 s->base.is_jmp = DISAS_EXIT;
834 static inline void gen_blxns(DisasContext *s, int rm)
836 TCGv_i32 var = load_reg(s, rm);
838 /* We don't need to sync condexec state, for the same reason as bxns.
839 * We do however need to set the PC, because the blxns helper reads it.
840 * The blxns helper may throw an exception.
842 gen_set_pc_im(s, s->base.pc_next);
843 gen_helper_v7m_blxns(cpu_env, var);
844 tcg_temp_free_i32(var);
845 s->base.is_jmp = DISAS_EXIT;
848 /* Variant of store_reg which uses branch&exchange logic when storing
849 to r15 in ARM architecture v7 and above. The source must be a temporary
850 and will be marked as dead. */
851 static inline void store_reg_bx(DisasContext *s, int reg, TCGv_i32 var)
853 if (reg == 15 && ENABLE_ARCH_7) {
854 gen_bx(s, var);
855 } else {
856 store_reg(s, reg, var);
860 /* Variant of store_reg which uses branch&exchange logic when storing
861 * to r15 in ARM architecture v5T and above. This is used for storing
862 * the results of a LDR/LDM/POP into r15, and corresponds to the cases
863 * in the ARM ARM which use the LoadWritePC() pseudocode function. */
864 static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
866 if (reg == 15 && ENABLE_ARCH_5) {
867 gen_bx_excret(s, var);
868 } else {
869 store_reg(s, reg, var);
873 #ifdef CONFIG_USER_ONLY
874 #define IS_USER_ONLY 1
875 #else
876 #define IS_USER_ONLY 0
877 #endif
879 /* Abstractions of "generate code to do a guest load/store for
880 * AArch32", where a vaddr is always 32 bits (and is zero
881 * extended if we're a 64 bit core) and data is also
882 * 32 bits unless specifically doing a 64 bit access.
883 * These functions work like tcg_gen_qemu_{ld,st}* except
884 * that the address argument is TCGv_i32 rather than TCGv.
887 static inline TCGv gen_aa32_addr(DisasContext *s, TCGv_i32 a32, MemOp op)
889 TCGv addr = tcg_temp_new();
890 tcg_gen_extu_i32_tl(addr, a32);
892 /* Not needed for user-mode BE32, where we use MO_BE instead. */
893 if (!IS_USER_ONLY && s->sctlr_b && (op & MO_SIZE) < MO_32) {
894 tcg_gen_xori_tl(addr, addr, 4 - (1 << (op & MO_SIZE)));
896 return addr;
899 static void gen_aa32_ld_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
900 int index, MemOp opc)
902 TCGv addr;
904 if (arm_dc_feature(s, ARM_FEATURE_M) &&
905 !arm_dc_feature(s, ARM_FEATURE_M_MAIN)) {
906 opc |= MO_ALIGN;
909 addr = gen_aa32_addr(s, a32, opc);
910 tcg_gen_qemu_ld_i32(val, addr, index, opc);
911 tcg_temp_free(addr);
914 static void gen_aa32_st_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
915 int index, MemOp opc)
917 TCGv addr;
919 if (arm_dc_feature(s, ARM_FEATURE_M) &&
920 !arm_dc_feature(s, ARM_FEATURE_M_MAIN)) {
921 opc |= MO_ALIGN;
924 addr = gen_aa32_addr(s, a32, opc);
925 tcg_gen_qemu_st_i32(val, addr, index, opc);
926 tcg_temp_free(addr);
929 #define DO_GEN_LD(SUFF, OPC) \
930 static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \
931 TCGv_i32 a32, int index) \
933 gen_aa32_ld_i32(s, val, a32, index, OPC | s->be_data); \
936 #define DO_GEN_ST(SUFF, OPC) \
937 static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, \
938 TCGv_i32 a32, int index) \
940 gen_aa32_st_i32(s, val, a32, index, OPC | s->be_data); \
943 static inline void gen_aa32_frob64(DisasContext *s, TCGv_i64 val)
945 /* Not needed for user-mode BE32, where we use MO_BE instead. */
946 if (!IS_USER_ONLY && s->sctlr_b) {
947 tcg_gen_rotri_i64(val, val, 32);
951 static void gen_aa32_ld_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
952 int index, MemOp opc)
954 TCGv addr = gen_aa32_addr(s, a32, opc);
955 tcg_gen_qemu_ld_i64(val, addr, index, opc);
956 gen_aa32_frob64(s, val);
957 tcg_temp_free(addr);
960 static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
961 TCGv_i32 a32, int index)
963 gen_aa32_ld_i64(s, val, a32, index, MO_Q | s->be_data);
966 static void gen_aa32_st_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
967 int index, MemOp opc)
969 TCGv addr = gen_aa32_addr(s, a32, opc);
971 /* Not needed for user-mode BE32, where we use MO_BE instead. */
972 if (!IS_USER_ONLY && s->sctlr_b) {
973 TCGv_i64 tmp = tcg_temp_new_i64();
974 tcg_gen_rotri_i64(tmp, val, 32);
975 tcg_gen_qemu_st_i64(tmp, addr, index, opc);
976 tcg_temp_free_i64(tmp);
977 } else {
978 tcg_gen_qemu_st_i64(val, addr, index, opc);
980 tcg_temp_free(addr);
983 static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
984 TCGv_i32 a32, int index)
986 gen_aa32_st_i64(s, val, a32, index, MO_Q | s->be_data);
989 DO_GEN_LD(8u, MO_UB)
990 DO_GEN_LD(16u, MO_UW)
991 DO_GEN_LD(32u, MO_UL)
992 DO_GEN_ST(8, MO_UB)
993 DO_GEN_ST(16, MO_UW)
994 DO_GEN_ST(32, MO_UL)
996 static inline void gen_hvc(DisasContext *s, int imm16)
998 /* The pre HVC helper handles cases when HVC gets trapped
999 * as an undefined insn by runtime configuration (ie before
1000 * the insn really executes).
1002 gen_set_pc_im(s, s->pc_curr);
1003 gen_helper_pre_hvc(cpu_env);
1004 /* Otherwise we will treat this as a real exception which
1005 * happens after execution of the insn. (The distinction matters
1006 * for the PC value reported to the exception handler and also
1007 * for single stepping.)
1009 s->svc_imm = imm16;
1010 gen_set_pc_im(s, s->base.pc_next);
1011 s->base.is_jmp = DISAS_HVC;
1014 static inline void gen_smc(DisasContext *s)
1016 /* As with HVC, we may take an exception either before or after
1017 * the insn executes.
1019 TCGv_i32 tmp;
1021 gen_set_pc_im(s, s->pc_curr);
1022 tmp = tcg_const_i32(syn_aa32_smc());
1023 gen_helper_pre_smc(cpu_env, tmp);
1024 tcg_temp_free_i32(tmp);
1025 gen_set_pc_im(s, s->base.pc_next);
1026 s->base.is_jmp = DISAS_SMC;
1029 static void gen_exception_internal_insn(DisasContext *s, uint32_t pc, int excp)
1031 gen_set_condexec(s);
1032 gen_set_pc_im(s, pc);
1033 gen_exception_internal(excp);
1034 s->base.is_jmp = DISAS_NORETURN;
1037 static void gen_exception_insn(DisasContext *s, uint32_t pc, int excp,
1038 int syn, uint32_t target_el)
1040 gen_set_condexec(s);
1041 gen_set_pc_im(s, pc);
1042 gen_exception(excp, syn, target_el);
1043 s->base.is_jmp = DISAS_NORETURN;
1046 static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn)
1048 TCGv_i32 tcg_syn;
1050 gen_set_condexec(s);
1051 gen_set_pc_im(s, s->pc_curr);
1052 tcg_syn = tcg_const_i32(syn);
1053 gen_helper_exception_bkpt_insn(cpu_env, tcg_syn);
1054 tcg_temp_free_i32(tcg_syn);
1055 s->base.is_jmp = DISAS_NORETURN;
1058 static void unallocated_encoding(DisasContext *s)
1060 /* Unallocated and reserved encodings are uncategorized */
1061 gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(),
1062 default_exception_el(s));
1065 /* Force a TB lookup after an instruction that changes the CPU state. */
1066 static inline void gen_lookup_tb(DisasContext *s)
1068 tcg_gen_movi_i32(cpu_R[15], s->base.pc_next);
1069 s->base.is_jmp = DISAS_EXIT;
1072 static inline void gen_hlt(DisasContext *s, int imm)
1074 /* HLT. This has two purposes.
1075 * Architecturally, it is an external halting debug instruction.
1076 * Since QEMU doesn't implement external debug, we treat this as
1077 * it is required for halting debug disabled: it will UNDEF.
1078 * Secondly, "HLT 0x3C" is a T32 semihosting trap instruction,
1079 * and "HLT 0xF000" is an A32 semihosting syscall. These traps
1080 * must trigger semihosting even for ARMv7 and earlier, where
1081 * HLT was an undefined encoding.
1082 * In system mode, we don't allow userspace access to
1083 * semihosting, to provide some semblance of security
1084 * (and for consistency with our 32-bit semihosting).
1086 if (semihosting_enabled() &&
1087 #ifndef CONFIG_USER_ONLY
1088 s->current_el != 0 &&
1089 #endif
1090 (imm == (s->thumb ? 0x3c : 0xf000))) {
1091 gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
1092 return;
1095 unallocated_encoding(s);
1098 static TCGv_ptr get_fpstatus_ptr(int neon)
1100 TCGv_ptr statusptr = tcg_temp_new_ptr();
1101 int offset;
1102 if (neon) {
1103 offset = offsetof(CPUARMState, vfp.standard_fp_status);
1104 } else {
1105 offset = offsetof(CPUARMState, vfp.fp_status);
1107 tcg_gen_addi_ptr(statusptr, cpu_env, offset);
1108 return statusptr;
1111 static inline long vfp_reg_offset(bool dp, unsigned reg)
1113 if (dp) {
1114 return offsetof(CPUARMState, vfp.zregs[reg >> 1].d[reg & 1]);
1115 } else {
1116 long ofs = offsetof(CPUARMState, vfp.zregs[reg >> 2].d[(reg >> 1) & 1]);
1117 if (reg & 1) {
1118 ofs += offsetof(CPU_DoubleU, l.upper);
1119 } else {
1120 ofs += offsetof(CPU_DoubleU, l.lower);
1122 return ofs;
1126 /* Return the offset of a 32-bit piece of a NEON register.
1127 zero is the least significant end of the register. */
1128 static inline long
1129 neon_reg_offset (int reg, int n)
1131 int sreg;
1132 sreg = reg * 2 + n;
1133 return vfp_reg_offset(0, sreg);
1136 static TCGv_i32 neon_load_reg(int reg, int pass)
1138 TCGv_i32 tmp = tcg_temp_new_i32();
1139 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1140 return tmp;
1143 static void neon_store_reg(int reg, int pass, TCGv_i32 var)
1145 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1146 tcg_temp_free_i32(var);
1149 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1151 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1154 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1156 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1159 static inline void neon_load_reg32(TCGv_i32 var, int reg)
1161 tcg_gen_ld_i32(var, cpu_env, vfp_reg_offset(false, reg));
1164 static inline void neon_store_reg32(TCGv_i32 var, int reg)
1166 tcg_gen_st_i32(var, cpu_env, vfp_reg_offset(false, reg));
1169 static TCGv_ptr vfp_reg_ptr(bool dp, int reg)
1171 TCGv_ptr ret = tcg_temp_new_ptr();
1172 tcg_gen_addi_ptr(ret, cpu_env, vfp_reg_offset(dp, reg));
1173 return ret;
1176 #define ARM_CP_RW_BIT (1 << 20)
1178 /* Include the VFP and Neon decoders */
1179 #include "translate-vfp.c.inc"
1180 #include "translate-neon.c.inc"
1182 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1184 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1187 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1189 tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1192 static inline TCGv_i32 iwmmxt_load_creg(int reg)
1194 TCGv_i32 var = tcg_temp_new_i32();
1195 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1196 return var;
1199 static inline void iwmmxt_store_creg(int reg, TCGv_i32 var)
1201 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1202 tcg_temp_free_i32(var);
1205 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1207 iwmmxt_store_reg(cpu_M0, rn);
1210 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1212 iwmmxt_load_reg(cpu_M0, rn);
1215 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1217 iwmmxt_load_reg(cpu_V1, rn);
1218 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1221 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1223 iwmmxt_load_reg(cpu_V1, rn);
1224 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1227 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1229 iwmmxt_load_reg(cpu_V1, rn);
1230 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1233 #define IWMMXT_OP(name) \
1234 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1236 iwmmxt_load_reg(cpu_V1, rn); \
1237 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1240 #define IWMMXT_OP_ENV(name) \
1241 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1243 iwmmxt_load_reg(cpu_V1, rn); \
1244 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1247 #define IWMMXT_OP_ENV_SIZE(name) \
1248 IWMMXT_OP_ENV(name##b) \
1249 IWMMXT_OP_ENV(name##w) \
1250 IWMMXT_OP_ENV(name##l)
1252 #define IWMMXT_OP_ENV1(name) \
1253 static inline void gen_op_iwmmxt_##name##_M0(void) \
1255 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1258 IWMMXT_OP(maddsq)
1259 IWMMXT_OP(madduq)
1260 IWMMXT_OP(sadb)
1261 IWMMXT_OP(sadw)
1262 IWMMXT_OP(mulslw)
1263 IWMMXT_OP(mulshw)
1264 IWMMXT_OP(mululw)
1265 IWMMXT_OP(muluhw)
1266 IWMMXT_OP(macsw)
1267 IWMMXT_OP(macuw)
1269 IWMMXT_OP_ENV_SIZE(unpackl)
1270 IWMMXT_OP_ENV_SIZE(unpackh)
1272 IWMMXT_OP_ENV1(unpacklub)
1273 IWMMXT_OP_ENV1(unpackluw)
1274 IWMMXT_OP_ENV1(unpacklul)
1275 IWMMXT_OP_ENV1(unpackhub)
1276 IWMMXT_OP_ENV1(unpackhuw)
1277 IWMMXT_OP_ENV1(unpackhul)
1278 IWMMXT_OP_ENV1(unpacklsb)
1279 IWMMXT_OP_ENV1(unpacklsw)
1280 IWMMXT_OP_ENV1(unpacklsl)
1281 IWMMXT_OP_ENV1(unpackhsb)
1282 IWMMXT_OP_ENV1(unpackhsw)
1283 IWMMXT_OP_ENV1(unpackhsl)
1285 IWMMXT_OP_ENV_SIZE(cmpeq)
1286 IWMMXT_OP_ENV_SIZE(cmpgtu)
1287 IWMMXT_OP_ENV_SIZE(cmpgts)
1289 IWMMXT_OP_ENV_SIZE(mins)
1290 IWMMXT_OP_ENV_SIZE(minu)
1291 IWMMXT_OP_ENV_SIZE(maxs)
1292 IWMMXT_OP_ENV_SIZE(maxu)
1294 IWMMXT_OP_ENV_SIZE(subn)
1295 IWMMXT_OP_ENV_SIZE(addn)
1296 IWMMXT_OP_ENV_SIZE(subu)
1297 IWMMXT_OP_ENV_SIZE(addu)
1298 IWMMXT_OP_ENV_SIZE(subs)
1299 IWMMXT_OP_ENV_SIZE(adds)
1301 IWMMXT_OP_ENV(avgb0)
1302 IWMMXT_OP_ENV(avgb1)
1303 IWMMXT_OP_ENV(avgw0)
1304 IWMMXT_OP_ENV(avgw1)
1306 IWMMXT_OP_ENV(packuw)
1307 IWMMXT_OP_ENV(packul)
1308 IWMMXT_OP_ENV(packuq)
1309 IWMMXT_OP_ENV(packsw)
1310 IWMMXT_OP_ENV(packsl)
1311 IWMMXT_OP_ENV(packsq)
1313 static void gen_op_iwmmxt_set_mup(void)
1315 TCGv_i32 tmp;
1316 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1317 tcg_gen_ori_i32(tmp, tmp, 2);
1318 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1321 static void gen_op_iwmmxt_set_cup(void)
1323 TCGv_i32 tmp;
1324 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1325 tcg_gen_ori_i32(tmp, tmp, 1);
1326 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1329 static void gen_op_iwmmxt_setpsr_nz(void)
1331 TCGv_i32 tmp = tcg_temp_new_i32();
1332 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1333 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1336 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1338 iwmmxt_load_reg(cpu_V1, rn);
1339 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1340 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1343 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn,
1344 TCGv_i32 dest)
1346 int rd;
1347 uint32_t offset;
1348 TCGv_i32 tmp;
1350 rd = (insn >> 16) & 0xf;
1351 tmp = load_reg(s, rd);
1353 offset = (insn & 0xff) << ((insn >> 7) & 2);
1354 if (insn & (1 << 24)) {
1355 /* Pre indexed */
1356 if (insn & (1 << 23))
1357 tcg_gen_addi_i32(tmp, tmp, offset);
1358 else
1359 tcg_gen_addi_i32(tmp, tmp, -offset);
1360 tcg_gen_mov_i32(dest, tmp);
1361 if (insn & (1 << 21))
1362 store_reg(s, rd, tmp);
1363 else
1364 tcg_temp_free_i32(tmp);
1365 } else if (insn & (1 << 21)) {
1366 /* Post indexed */
1367 tcg_gen_mov_i32(dest, tmp);
1368 if (insn & (1 << 23))
1369 tcg_gen_addi_i32(tmp, tmp, offset);
1370 else
1371 tcg_gen_addi_i32(tmp, tmp, -offset);
1372 store_reg(s, rd, tmp);
1373 } else if (!(insn & (1 << 23)))
1374 return 1;
1375 return 0;
1378 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv_i32 dest)
1380 int rd = (insn >> 0) & 0xf;
1381 TCGv_i32 tmp;
1383 if (insn & (1 << 8)) {
1384 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1385 return 1;
1386 } else {
1387 tmp = iwmmxt_load_creg(rd);
1389 } else {
1390 tmp = tcg_temp_new_i32();
1391 iwmmxt_load_reg(cpu_V0, rd);
1392 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
1394 tcg_gen_andi_i32(tmp, tmp, mask);
1395 tcg_gen_mov_i32(dest, tmp);
1396 tcg_temp_free_i32(tmp);
1397 return 0;
1400 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
1401 (ie. an undefined instruction). */
1402 static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
1404 int rd, wrd;
1405 int rdhi, rdlo, rd0, rd1, i;
1406 TCGv_i32 addr;
1407 TCGv_i32 tmp, tmp2, tmp3;
1409 if ((insn & 0x0e000e00) == 0x0c000000) {
1410 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1411 wrd = insn & 0xf;
1412 rdlo = (insn >> 12) & 0xf;
1413 rdhi = (insn >> 16) & 0xf;
1414 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1415 iwmmxt_load_reg(cpu_V0, wrd);
1416 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
1417 tcg_gen_extrh_i64_i32(cpu_R[rdhi], cpu_V0);
1418 } else { /* TMCRR */
1419 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1420 iwmmxt_store_reg(cpu_V0, wrd);
1421 gen_op_iwmmxt_set_mup();
1423 return 0;
1426 wrd = (insn >> 12) & 0xf;
1427 addr = tcg_temp_new_i32();
1428 if (gen_iwmmxt_address(s, insn, addr)) {
1429 tcg_temp_free_i32(addr);
1430 return 1;
1432 if (insn & ARM_CP_RW_BIT) {
1433 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1434 tmp = tcg_temp_new_i32();
1435 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
1436 iwmmxt_store_creg(wrd, tmp);
1437 } else {
1438 i = 1;
1439 if (insn & (1 << 8)) {
1440 if (insn & (1 << 22)) { /* WLDRD */
1441 gen_aa32_ld64(s, cpu_M0, addr, get_mem_index(s));
1442 i = 0;
1443 } else { /* WLDRW wRd */
1444 tmp = tcg_temp_new_i32();
1445 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
1447 } else {
1448 tmp = tcg_temp_new_i32();
1449 if (insn & (1 << 22)) { /* WLDRH */
1450 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
1451 } else { /* WLDRB */
1452 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
1455 if (i) {
1456 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1457 tcg_temp_free_i32(tmp);
1459 gen_op_iwmmxt_movq_wRn_M0(wrd);
1461 } else {
1462 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1463 tmp = iwmmxt_load_creg(wrd);
1464 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
1465 } else {
1466 gen_op_iwmmxt_movq_M0_wRn(wrd);
1467 tmp = tcg_temp_new_i32();
1468 if (insn & (1 << 8)) {
1469 if (insn & (1 << 22)) { /* WSTRD */
1470 gen_aa32_st64(s, cpu_M0, addr, get_mem_index(s));
1471 } else { /* WSTRW wRd */
1472 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1473 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
1475 } else {
1476 if (insn & (1 << 22)) { /* WSTRH */
1477 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1478 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
1479 } else { /* WSTRB */
1480 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1481 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
1485 tcg_temp_free_i32(tmp);
1487 tcg_temp_free_i32(addr);
1488 return 0;
1491 if ((insn & 0x0f000000) != 0x0e000000)
1492 return 1;
1494 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1495 case 0x000: /* WOR */
1496 wrd = (insn >> 12) & 0xf;
1497 rd0 = (insn >> 0) & 0xf;
1498 rd1 = (insn >> 16) & 0xf;
1499 gen_op_iwmmxt_movq_M0_wRn(rd0);
1500 gen_op_iwmmxt_orq_M0_wRn(rd1);
1501 gen_op_iwmmxt_setpsr_nz();
1502 gen_op_iwmmxt_movq_wRn_M0(wrd);
1503 gen_op_iwmmxt_set_mup();
1504 gen_op_iwmmxt_set_cup();
1505 break;
1506 case 0x011: /* TMCR */
1507 if (insn & 0xf)
1508 return 1;
1509 rd = (insn >> 12) & 0xf;
1510 wrd = (insn >> 16) & 0xf;
1511 switch (wrd) {
1512 case ARM_IWMMXT_wCID:
1513 case ARM_IWMMXT_wCASF:
1514 break;
1515 case ARM_IWMMXT_wCon:
1516 gen_op_iwmmxt_set_cup();
1517 /* Fall through. */
1518 case ARM_IWMMXT_wCSSF:
1519 tmp = iwmmxt_load_creg(wrd);
1520 tmp2 = load_reg(s, rd);
1521 tcg_gen_andc_i32(tmp, tmp, tmp2);
1522 tcg_temp_free_i32(tmp2);
1523 iwmmxt_store_creg(wrd, tmp);
1524 break;
1525 case ARM_IWMMXT_wCGR0:
1526 case ARM_IWMMXT_wCGR1:
1527 case ARM_IWMMXT_wCGR2:
1528 case ARM_IWMMXT_wCGR3:
1529 gen_op_iwmmxt_set_cup();
1530 tmp = load_reg(s, rd);
1531 iwmmxt_store_creg(wrd, tmp);
1532 break;
1533 default:
1534 return 1;
1536 break;
1537 case 0x100: /* WXOR */
1538 wrd = (insn >> 12) & 0xf;
1539 rd0 = (insn >> 0) & 0xf;
1540 rd1 = (insn >> 16) & 0xf;
1541 gen_op_iwmmxt_movq_M0_wRn(rd0);
1542 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1543 gen_op_iwmmxt_setpsr_nz();
1544 gen_op_iwmmxt_movq_wRn_M0(wrd);
1545 gen_op_iwmmxt_set_mup();
1546 gen_op_iwmmxt_set_cup();
1547 break;
1548 case 0x111: /* TMRC */
1549 if (insn & 0xf)
1550 return 1;
1551 rd = (insn >> 12) & 0xf;
1552 wrd = (insn >> 16) & 0xf;
1553 tmp = iwmmxt_load_creg(wrd);
1554 store_reg(s, rd, tmp);
1555 break;
1556 case 0x300: /* WANDN */
1557 wrd = (insn >> 12) & 0xf;
1558 rd0 = (insn >> 0) & 0xf;
1559 rd1 = (insn >> 16) & 0xf;
1560 gen_op_iwmmxt_movq_M0_wRn(rd0);
1561 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1562 gen_op_iwmmxt_andq_M0_wRn(rd1);
1563 gen_op_iwmmxt_setpsr_nz();
1564 gen_op_iwmmxt_movq_wRn_M0(wrd);
1565 gen_op_iwmmxt_set_mup();
1566 gen_op_iwmmxt_set_cup();
1567 break;
1568 case 0x200: /* WAND */
1569 wrd = (insn >> 12) & 0xf;
1570 rd0 = (insn >> 0) & 0xf;
1571 rd1 = (insn >> 16) & 0xf;
1572 gen_op_iwmmxt_movq_M0_wRn(rd0);
1573 gen_op_iwmmxt_andq_M0_wRn(rd1);
1574 gen_op_iwmmxt_setpsr_nz();
1575 gen_op_iwmmxt_movq_wRn_M0(wrd);
1576 gen_op_iwmmxt_set_mup();
1577 gen_op_iwmmxt_set_cup();
1578 break;
1579 case 0x810: case 0xa10: /* WMADD */
1580 wrd = (insn >> 12) & 0xf;
1581 rd0 = (insn >> 0) & 0xf;
1582 rd1 = (insn >> 16) & 0xf;
1583 gen_op_iwmmxt_movq_M0_wRn(rd0);
1584 if (insn & (1 << 21))
1585 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1586 else
1587 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1588 gen_op_iwmmxt_movq_wRn_M0(wrd);
1589 gen_op_iwmmxt_set_mup();
1590 break;
1591 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1592 wrd = (insn >> 12) & 0xf;
1593 rd0 = (insn >> 16) & 0xf;
1594 rd1 = (insn >> 0) & 0xf;
1595 gen_op_iwmmxt_movq_M0_wRn(rd0);
1596 switch ((insn >> 22) & 3) {
1597 case 0:
1598 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1599 break;
1600 case 1:
1601 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1602 break;
1603 case 2:
1604 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1605 break;
1606 case 3:
1607 return 1;
1609 gen_op_iwmmxt_movq_wRn_M0(wrd);
1610 gen_op_iwmmxt_set_mup();
1611 gen_op_iwmmxt_set_cup();
1612 break;
1613 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1614 wrd = (insn >> 12) & 0xf;
1615 rd0 = (insn >> 16) & 0xf;
1616 rd1 = (insn >> 0) & 0xf;
1617 gen_op_iwmmxt_movq_M0_wRn(rd0);
1618 switch ((insn >> 22) & 3) {
1619 case 0:
1620 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1621 break;
1622 case 1:
1623 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1624 break;
1625 case 2:
1626 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1627 break;
1628 case 3:
1629 return 1;
1631 gen_op_iwmmxt_movq_wRn_M0(wrd);
1632 gen_op_iwmmxt_set_mup();
1633 gen_op_iwmmxt_set_cup();
1634 break;
1635 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1636 wrd = (insn >> 12) & 0xf;
1637 rd0 = (insn >> 16) & 0xf;
1638 rd1 = (insn >> 0) & 0xf;
1639 gen_op_iwmmxt_movq_M0_wRn(rd0);
1640 if (insn & (1 << 22))
1641 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1642 else
1643 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1644 if (!(insn & (1 << 20)))
1645 gen_op_iwmmxt_addl_M0_wRn(wrd);
1646 gen_op_iwmmxt_movq_wRn_M0(wrd);
1647 gen_op_iwmmxt_set_mup();
1648 break;
1649 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1650 wrd = (insn >> 12) & 0xf;
1651 rd0 = (insn >> 16) & 0xf;
1652 rd1 = (insn >> 0) & 0xf;
1653 gen_op_iwmmxt_movq_M0_wRn(rd0);
1654 if (insn & (1 << 21)) {
1655 if (insn & (1 << 20))
1656 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1657 else
1658 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1659 } else {
1660 if (insn & (1 << 20))
1661 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1662 else
1663 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1665 gen_op_iwmmxt_movq_wRn_M0(wrd);
1666 gen_op_iwmmxt_set_mup();
1667 break;
1668 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1669 wrd = (insn >> 12) & 0xf;
1670 rd0 = (insn >> 16) & 0xf;
1671 rd1 = (insn >> 0) & 0xf;
1672 gen_op_iwmmxt_movq_M0_wRn(rd0);
1673 if (insn & (1 << 21))
1674 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1675 else
1676 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1677 if (!(insn & (1 << 20))) {
1678 iwmmxt_load_reg(cpu_V1, wrd);
1679 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1681 gen_op_iwmmxt_movq_wRn_M0(wrd);
1682 gen_op_iwmmxt_set_mup();
1683 break;
1684 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1685 wrd = (insn >> 12) & 0xf;
1686 rd0 = (insn >> 16) & 0xf;
1687 rd1 = (insn >> 0) & 0xf;
1688 gen_op_iwmmxt_movq_M0_wRn(rd0);
1689 switch ((insn >> 22) & 3) {
1690 case 0:
1691 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1692 break;
1693 case 1:
1694 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1695 break;
1696 case 2:
1697 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1698 break;
1699 case 3:
1700 return 1;
1702 gen_op_iwmmxt_movq_wRn_M0(wrd);
1703 gen_op_iwmmxt_set_mup();
1704 gen_op_iwmmxt_set_cup();
1705 break;
1706 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1707 wrd = (insn >> 12) & 0xf;
1708 rd0 = (insn >> 16) & 0xf;
1709 rd1 = (insn >> 0) & 0xf;
1710 gen_op_iwmmxt_movq_M0_wRn(rd0);
1711 if (insn & (1 << 22)) {
1712 if (insn & (1 << 20))
1713 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1714 else
1715 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1716 } else {
1717 if (insn & (1 << 20))
1718 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1719 else
1720 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1722 gen_op_iwmmxt_movq_wRn_M0(wrd);
1723 gen_op_iwmmxt_set_mup();
1724 gen_op_iwmmxt_set_cup();
1725 break;
1726 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1727 wrd = (insn >> 12) & 0xf;
1728 rd0 = (insn >> 16) & 0xf;
1729 rd1 = (insn >> 0) & 0xf;
1730 gen_op_iwmmxt_movq_M0_wRn(rd0);
1731 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1732 tcg_gen_andi_i32(tmp, tmp, 7);
1733 iwmmxt_load_reg(cpu_V1, rd1);
1734 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
1735 tcg_temp_free_i32(tmp);
1736 gen_op_iwmmxt_movq_wRn_M0(wrd);
1737 gen_op_iwmmxt_set_mup();
1738 break;
1739 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1740 if (((insn >> 6) & 3) == 3)
1741 return 1;
1742 rd = (insn >> 12) & 0xf;
1743 wrd = (insn >> 16) & 0xf;
1744 tmp = load_reg(s, rd);
1745 gen_op_iwmmxt_movq_M0_wRn(wrd);
1746 switch ((insn >> 6) & 3) {
1747 case 0:
1748 tmp2 = tcg_const_i32(0xff);
1749 tmp3 = tcg_const_i32((insn & 7) << 3);
1750 break;
1751 case 1:
1752 tmp2 = tcg_const_i32(0xffff);
1753 tmp3 = tcg_const_i32((insn & 3) << 4);
1754 break;
1755 case 2:
1756 tmp2 = tcg_const_i32(0xffffffff);
1757 tmp3 = tcg_const_i32((insn & 1) << 5);
1758 break;
1759 default:
1760 tmp2 = NULL;
1761 tmp3 = NULL;
1763 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
1764 tcg_temp_free_i32(tmp3);
1765 tcg_temp_free_i32(tmp2);
1766 tcg_temp_free_i32(tmp);
1767 gen_op_iwmmxt_movq_wRn_M0(wrd);
1768 gen_op_iwmmxt_set_mup();
1769 break;
1770 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1771 rd = (insn >> 12) & 0xf;
1772 wrd = (insn >> 16) & 0xf;
1773 if (rd == 15 || ((insn >> 22) & 3) == 3)
1774 return 1;
1775 gen_op_iwmmxt_movq_M0_wRn(wrd);
1776 tmp = tcg_temp_new_i32();
1777 switch ((insn >> 22) & 3) {
1778 case 0:
1779 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
1780 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1781 if (insn & 8) {
1782 tcg_gen_ext8s_i32(tmp, tmp);
1783 } else {
1784 tcg_gen_andi_i32(tmp, tmp, 0xff);
1786 break;
1787 case 1:
1788 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
1789 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1790 if (insn & 8) {
1791 tcg_gen_ext16s_i32(tmp, tmp);
1792 } else {
1793 tcg_gen_andi_i32(tmp, tmp, 0xffff);
1795 break;
1796 case 2:
1797 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
1798 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1799 break;
1801 store_reg(s, rd, tmp);
1802 break;
1803 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1804 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1805 return 1;
1806 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1807 switch ((insn >> 22) & 3) {
1808 case 0:
1809 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
1810 break;
1811 case 1:
1812 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
1813 break;
1814 case 2:
1815 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
1816 break;
1818 tcg_gen_shli_i32(tmp, tmp, 28);
1819 gen_set_nzcv(tmp);
1820 tcg_temp_free_i32(tmp);
1821 break;
1822 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1823 if (((insn >> 6) & 3) == 3)
1824 return 1;
1825 rd = (insn >> 12) & 0xf;
1826 wrd = (insn >> 16) & 0xf;
1827 tmp = load_reg(s, rd);
1828 switch ((insn >> 6) & 3) {
1829 case 0:
1830 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
1831 break;
1832 case 1:
1833 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
1834 break;
1835 case 2:
1836 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
1837 break;
1839 tcg_temp_free_i32(tmp);
1840 gen_op_iwmmxt_movq_wRn_M0(wrd);
1841 gen_op_iwmmxt_set_mup();
1842 break;
1843 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1844 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1845 return 1;
1846 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1847 tmp2 = tcg_temp_new_i32();
1848 tcg_gen_mov_i32(tmp2, tmp);
1849 switch ((insn >> 22) & 3) {
1850 case 0:
1851 for (i = 0; i < 7; i ++) {
1852 tcg_gen_shli_i32(tmp2, tmp2, 4);
1853 tcg_gen_and_i32(tmp, tmp, tmp2);
1855 break;
1856 case 1:
1857 for (i = 0; i < 3; i ++) {
1858 tcg_gen_shli_i32(tmp2, tmp2, 8);
1859 tcg_gen_and_i32(tmp, tmp, tmp2);
1861 break;
1862 case 2:
1863 tcg_gen_shli_i32(tmp2, tmp2, 16);
1864 tcg_gen_and_i32(tmp, tmp, tmp2);
1865 break;
1867 gen_set_nzcv(tmp);
1868 tcg_temp_free_i32(tmp2);
1869 tcg_temp_free_i32(tmp);
1870 break;
1871 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1872 wrd = (insn >> 12) & 0xf;
1873 rd0 = (insn >> 16) & 0xf;
1874 gen_op_iwmmxt_movq_M0_wRn(rd0);
1875 switch ((insn >> 22) & 3) {
1876 case 0:
1877 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1878 break;
1879 case 1:
1880 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1881 break;
1882 case 2:
1883 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1884 break;
1885 case 3:
1886 return 1;
1888 gen_op_iwmmxt_movq_wRn_M0(wrd);
1889 gen_op_iwmmxt_set_mup();
1890 break;
1891 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1892 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1893 return 1;
1894 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1895 tmp2 = tcg_temp_new_i32();
1896 tcg_gen_mov_i32(tmp2, tmp);
1897 switch ((insn >> 22) & 3) {
1898 case 0:
1899 for (i = 0; i < 7; i ++) {
1900 tcg_gen_shli_i32(tmp2, tmp2, 4);
1901 tcg_gen_or_i32(tmp, tmp, tmp2);
1903 break;
1904 case 1:
1905 for (i = 0; i < 3; i ++) {
1906 tcg_gen_shli_i32(tmp2, tmp2, 8);
1907 tcg_gen_or_i32(tmp, tmp, tmp2);
1909 break;
1910 case 2:
1911 tcg_gen_shli_i32(tmp2, tmp2, 16);
1912 tcg_gen_or_i32(tmp, tmp, tmp2);
1913 break;
1915 gen_set_nzcv(tmp);
1916 tcg_temp_free_i32(tmp2);
1917 tcg_temp_free_i32(tmp);
1918 break;
1919 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1920 rd = (insn >> 12) & 0xf;
1921 rd0 = (insn >> 16) & 0xf;
1922 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
1923 return 1;
1924 gen_op_iwmmxt_movq_M0_wRn(rd0);
1925 tmp = tcg_temp_new_i32();
1926 switch ((insn >> 22) & 3) {
1927 case 0:
1928 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
1929 break;
1930 case 1:
1931 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
1932 break;
1933 case 2:
1934 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
1935 break;
1937 store_reg(s, rd, tmp);
1938 break;
1939 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1940 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1941 wrd = (insn >> 12) & 0xf;
1942 rd0 = (insn >> 16) & 0xf;
1943 rd1 = (insn >> 0) & 0xf;
1944 gen_op_iwmmxt_movq_M0_wRn(rd0);
1945 switch ((insn >> 22) & 3) {
1946 case 0:
1947 if (insn & (1 << 21))
1948 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
1949 else
1950 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
1951 break;
1952 case 1:
1953 if (insn & (1 << 21))
1954 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
1955 else
1956 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
1957 break;
1958 case 2:
1959 if (insn & (1 << 21))
1960 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
1961 else
1962 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
1963 break;
1964 case 3:
1965 return 1;
1967 gen_op_iwmmxt_movq_wRn_M0(wrd);
1968 gen_op_iwmmxt_set_mup();
1969 gen_op_iwmmxt_set_cup();
1970 break;
1971 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
1972 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1973 wrd = (insn >> 12) & 0xf;
1974 rd0 = (insn >> 16) & 0xf;
1975 gen_op_iwmmxt_movq_M0_wRn(rd0);
1976 switch ((insn >> 22) & 3) {
1977 case 0:
1978 if (insn & (1 << 21))
1979 gen_op_iwmmxt_unpacklsb_M0();
1980 else
1981 gen_op_iwmmxt_unpacklub_M0();
1982 break;
1983 case 1:
1984 if (insn & (1 << 21))
1985 gen_op_iwmmxt_unpacklsw_M0();
1986 else
1987 gen_op_iwmmxt_unpackluw_M0();
1988 break;
1989 case 2:
1990 if (insn & (1 << 21))
1991 gen_op_iwmmxt_unpacklsl_M0();
1992 else
1993 gen_op_iwmmxt_unpacklul_M0();
1994 break;
1995 case 3:
1996 return 1;
1998 gen_op_iwmmxt_movq_wRn_M0(wrd);
1999 gen_op_iwmmxt_set_mup();
2000 gen_op_iwmmxt_set_cup();
2001 break;
2002 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2003 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2004 wrd = (insn >> 12) & 0xf;
2005 rd0 = (insn >> 16) & 0xf;
2006 gen_op_iwmmxt_movq_M0_wRn(rd0);
2007 switch ((insn >> 22) & 3) {
2008 case 0:
2009 if (insn & (1 << 21))
2010 gen_op_iwmmxt_unpackhsb_M0();
2011 else
2012 gen_op_iwmmxt_unpackhub_M0();
2013 break;
2014 case 1:
2015 if (insn & (1 << 21))
2016 gen_op_iwmmxt_unpackhsw_M0();
2017 else
2018 gen_op_iwmmxt_unpackhuw_M0();
2019 break;
2020 case 2:
2021 if (insn & (1 << 21))
2022 gen_op_iwmmxt_unpackhsl_M0();
2023 else
2024 gen_op_iwmmxt_unpackhul_M0();
2025 break;
2026 case 3:
2027 return 1;
2029 gen_op_iwmmxt_movq_wRn_M0(wrd);
2030 gen_op_iwmmxt_set_mup();
2031 gen_op_iwmmxt_set_cup();
2032 break;
2033 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2034 case 0x214: case 0x614: case 0xa14: case 0xe14:
2035 if (((insn >> 22) & 3) == 0)
2036 return 1;
2037 wrd = (insn >> 12) & 0xf;
2038 rd0 = (insn >> 16) & 0xf;
2039 gen_op_iwmmxt_movq_M0_wRn(rd0);
2040 tmp = tcg_temp_new_i32();
2041 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2042 tcg_temp_free_i32(tmp);
2043 return 1;
2045 switch ((insn >> 22) & 3) {
2046 case 1:
2047 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
2048 break;
2049 case 2:
2050 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
2051 break;
2052 case 3:
2053 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
2054 break;
2056 tcg_temp_free_i32(tmp);
2057 gen_op_iwmmxt_movq_wRn_M0(wrd);
2058 gen_op_iwmmxt_set_mup();
2059 gen_op_iwmmxt_set_cup();
2060 break;
2061 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2062 case 0x014: case 0x414: case 0x814: case 0xc14:
2063 if (((insn >> 22) & 3) == 0)
2064 return 1;
2065 wrd = (insn >> 12) & 0xf;
2066 rd0 = (insn >> 16) & 0xf;
2067 gen_op_iwmmxt_movq_M0_wRn(rd0);
2068 tmp = tcg_temp_new_i32();
2069 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2070 tcg_temp_free_i32(tmp);
2071 return 1;
2073 switch ((insn >> 22) & 3) {
2074 case 1:
2075 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
2076 break;
2077 case 2:
2078 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
2079 break;
2080 case 3:
2081 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
2082 break;
2084 tcg_temp_free_i32(tmp);
2085 gen_op_iwmmxt_movq_wRn_M0(wrd);
2086 gen_op_iwmmxt_set_mup();
2087 gen_op_iwmmxt_set_cup();
2088 break;
2089 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2090 case 0x114: case 0x514: case 0x914: case 0xd14:
2091 if (((insn >> 22) & 3) == 0)
2092 return 1;
2093 wrd = (insn >> 12) & 0xf;
2094 rd0 = (insn >> 16) & 0xf;
2095 gen_op_iwmmxt_movq_M0_wRn(rd0);
2096 tmp = tcg_temp_new_i32();
2097 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2098 tcg_temp_free_i32(tmp);
2099 return 1;
2101 switch ((insn >> 22) & 3) {
2102 case 1:
2103 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2104 break;
2105 case 2:
2106 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2107 break;
2108 case 3:
2109 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2110 break;
2112 tcg_temp_free_i32(tmp);
2113 gen_op_iwmmxt_movq_wRn_M0(wrd);
2114 gen_op_iwmmxt_set_mup();
2115 gen_op_iwmmxt_set_cup();
2116 break;
2117 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2118 case 0x314: case 0x714: case 0xb14: case 0xf14:
2119 if (((insn >> 22) & 3) == 0)
2120 return 1;
2121 wrd = (insn >> 12) & 0xf;
2122 rd0 = (insn >> 16) & 0xf;
2123 gen_op_iwmmxt_movq_M0_wRn(rd0);
2124 tmp = tcg_temp_new_i32();
2125 switch ((insn >> 22) & 3) {
2126 case 1:
2127 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2128 tcg_temp_free_i32(tmp);
2129 return 1;
2131 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2132 break;
2133 case 2:
2134 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2135 tcg_temp_free_i32(tmp);
2136 return 1;
2138 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2139 break;
2140 case 3:
2141 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2142 tcg_temp_free_i32(tmp);
2143 return 1;
2145 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2146 break;
2148 tcg_temp_free_i32(tmp);
2149 gen_op_iwmmxt_movq_wRn_M0(wrd);
2150 gen_op_iwmmxt_set_mup();
2151 gen_op_iwmmxt_set_cup();
2152 break;
2153 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2154 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2155 wrd = (insn >> 12) & 0xf;
2156 rd0 = (insn >> 16) & 0xf;
2157 rd1 = (insn >> 0) & 0xf;
2158 gen_op_iwmmxt_movq_M0_wRn(rd0);
2159 switch ((insn >> 22) & 3) {
2160 case 0:
2161 if (insn & (1 << 21))
2162 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2163 else
2164 gen_op_iwmmxt_minub_M0_wRn(rd1);
2165 break;
2166 case 1:
2167 if (insn & (1 << 21))
2168 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2169 else
2170 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2171 break;
2172 case 2:
2173 if (insn & (1 << 21))
2174 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2175 else
2176 gen_op_iwmmxt_minul_M0_wRn(rd1);
2177 break;
2178 case 3:
2179 return 1;
2181 gen_op_iwmmxt_movq_wRn_M0(wrd);
2182 gen_op_iwmmxt_set_mup();
2183 break;
2184 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2185 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2186 wrd = (insn >> 12) & 0xf;
2187 rd0 = (insn >> 16) & 0xf;
2188 rd1 = (insn >> 0) & 0xf;
2189 gen_op_iwmmxt_movq_M0_wRn(rd0);
2190 switch ((insn >> 22) & 3) {
2191 case 0:
2192 if (insn & (1 << 21))
2193 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2194 else
2195 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2196 break;
2197 case 1:
2198 if (insn & (1 << 21))
2199 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2200 else
2201 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2202 break;
2203 case 2:
2204 if (insn & (1 << 21))
2205 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2206 else
2207 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2208 break;
2209 case 3:
2210 return 1;
2212 gen_op_iwmmxt_movq_wRn_M0(wrd);
2213 gen_op_iwmmxt_set_mup();
2214 break;
2215 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2216 case 0x402: case 0x502: case 0x602: case 0x702:
2217 wrd = (insn >> 12) & 0xf;
2218 rd0 = (insn >> 16) & 0xf;
2219 rd1 = (insn >> 0) & 0xf;
2220 gen_op_iwmmxt_movq_M0_wRn(rd0);
2221 tmp = tcg_const_i32((insn >> 20) & 3);
2222 iwmmxt_load_reg(cpu_V1, rd1);
2223 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2224 tcg_temp_free_i32(tmp);
2225 gen_op_iwmmxt_movq_wRn_M0(wrd);
2226 gen_op_iwmmxt_set_mup();
2227 break;
2228 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2229 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2230 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2231 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2232 wrd = (insn >> 12) & 0xf;
2233 rd0 = (insn >> 16) & 0xf;
2234 rd1 = (insn >> 0) & 0xf;
2235 gen_op_iwmmxt_movq_M0_wRn(rd0);
2236 switch ((insn >> 20) & 0xf) {
2237 case 0x0:
2238 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2239 break;
2240 case 0x1:
2241 gen_op_iwmmxt_subub_M0_wRn(rd1);
2242 break;
2243 case 0x3:
2244 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2245 break;
2246 case 0x4:
2247 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2248 break;
2249 case 0x5:
2250 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2251 break;
2252 case 0x7:
2253 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2254 break;
2255 case 0x8:
2256 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2257 break;
2258 case 0x9:
2259 gen_op_iwmmxt_subul_M0_wRn(rd1);
2260 break;
2261 case 0xb:
2262 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2263 break;
2264 default:
2265 return 1;
2267 gen_op_iwmmxt_movq_wRn_M0(wrd);
2268 gen_op_iwmmxt_set_mup();
2269 gen_op_iwmmxt_set_cup();
2270 break;
2271 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2272 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2273 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2274 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2275 wrd = (insn >> 12) & 0xf;
2276 rd0 = (insn >> 16) & 0xf;
2277 gen_op_iwmmxt_movq_M0_wRn(rd0);
2278 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2279 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2280 tcg_temp_free_i32(tmp);
2281 gen_op_iwmmxt_movq_wRn_M0(wrd);
2282 gen_op_iwmmxt_set_mup();
2283 gen_op_iwmmxt_set_cup();
2284 break;
2285 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2286 case 0x418: case 0x518: case 0x618: case 0x718:
2287 case 0x818: case 0x918: case 0xa18: case 0xb18:
2288 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2289 wrd = (insn >> 12) & 0xf;
2290 rd0 = (insn >> 16) & 0xf;
2291 rd1 = (insn >> 0) & 0xf;
2292 gen_op_iwmmxt_movq_M0_wRn(rd0);
2293 switch ((insn >> 20) & 0xf) {
2294 case 0x0:
2295 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2296 break;
2297 case 0x1:
2298 gen_op_iwmmxt_addub_M0_wRn(rd1);
2299 break;
2300 case 0x3:
2301 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2302 break;
2303 case 0x4:
2304 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2305 break;
2306 case 0x5:
2307 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2308 break;
2309 case 0x7:
2310 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2311 break;
2312 case 0x8:
2313 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2314 break;
2315 case 0x9:
2316 gen_op_iwmmxt_addul_M0_wRn(rd1);
2317 break;
2318 case 0xb:
2319 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2320 break;
2321 default:
2322 return 1;
2324 gen_op_iwmmxt_movq_wRn_M0(wrd);
2325 gen_op_iwmmxt_set_mup();
2326 gen_op_iwmmxt_set_cup();
2327 break;
2328 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2329 case 0x408: case 0x508: case 0x608: case 0x708:
2330 case 0x808: case 0x908: case 0xa08: case 0xb08:
2331 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2332 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2333 return 1;
2334 wrd = (insn >> 12) & 0xf;
2335 rd0 = (insn >> 16) & 0xf;
2336 rd1 = (insn >> 0) & 0xf;
2337 gen_op_iwmmxt_movq_M0_wRn(rd0);
2338 switch ((insn >> 22) & 3) {
2339 case 1:
2340 if (insn & (1 << 21))
2341 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2342 else
2343 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2344 break;
2345 case 2:
2346 if (insn & (1 << 21))
2347 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2348 else
2349 gen_op_iwmmxt_packul_M0_wRn(rd1);
2350 break;
2351 case 3:
2352 if (insn & (1 << 21))
2353 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2354 else
2355 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2356 break;
2358 gen_op_iwmmxt_movq_wRn_M0(wrd);
2359 gen_op_iwmmxt_set_mup();
2360 gen_op_iwmmxt_set_cup();
2361 break;
2362 case 0x201: case 0x203: case 0x205: case 0x207:
2363 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2364 case 0x211: case 0x213: case 0x215: case 0x217:
2365 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2366 wrd = (insn >> 5) & 0xf;
2367 rd0 = (insn >> 12) & 0xf;
2368 rd1 = (insn >> 0) & 0xf;
2369 if (rd0 == 0xf || rd1 == 0xf)
2370 return 1;
2371 gen_op_iwmmxt_movq_M0_wRn(wrd);
2372 tmp = load_reg(s, rd0);
2373 tmp2 = load_reg(s, rd1);
2374 switch ((insn >> 16) & 0xf) {
2375 case 0x0: /* TMIA */
2376 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2377 break;
2378 case 0x8: /* TMIAPH */
2379 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2380 break;
2381 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2382 if (insn & (1 << 16))
2383 tcg_gen_shri_i32(tmp, tmp, 16);
2384 if (insn & (1 << 17))
2385 tcg_gen_shri_i32(tmp2, tmp2, 16);
2386 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2387 break;
2388 default:
2389 tcg_temp_free_i32(tmp2);
2390 tcg_temp_free_i32(tmp);
2391 return 1;
2393 tcg_temp_free_i32(tmp2);
2394 tcg_temp_free_i32(tmp);
2395 gen_op_iwmmxt_movq_wRn_M0(wrd);
2396 gen_op_iwmmxt_set_mup();
2397 break;
2398 default:
2399 return 1;
2402 return 0;
2405 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
2406 (ie. an undefined instruction). */
2407 static int disas_dsp_insn(DisasContext *s, uint32_t insn)
2409 int acc, rd0, rd1, rdhi, rdlo;
2410 TCGv_i32 tmp, tmp2;
2412 if ((insn & 0x0ff00f10) == 0x0e200010) {
2413 /* Multiply with Internal Accumulate Format */
2414 rd0 = (insn >> 12) & 0xf;
2415 rd1 = insn & 0xf;
2416 acc = (insn >> 5) & 7;
2418 if (acc != 0)
2419 return 1;
2421 tmp = load_reg(s, rd0);
2422 tmp2 = load_reg(s, rd1);
2423 switch ((insn >> 16) & 0xf) {
2424 case 0x0: /* MIA */
2425 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2426 break;
2427 case 0x8: /* MIAPH */
2428 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2429 break;
2430 case 0xc: /* MIABB */
2431 case 0xd: /* MIABT */
2432 case 0xe: /* MIATB */
2433 case 0xf: /* MIATT */
2434 if (insn & (1 << 16))
2435 tcg_gen_shri_i32(tmp, tmp, 16);
2436 if (insn & (1 << 17))
2437 tcg_gen_shri_i32(tmp2, tmp2, 16);
2438 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2439 break;
2440 default:
2441 return 1;
2443 tcg_temp_free_i32(tmp2);
2444 tcg_temp_free_i32(tmp);
2446 gen_op_iwmmxt_movq_wRn_M0(acc);
2447 return 0;
2450 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2451 /* Internal Accumulator Access Format */
2452 rdhi = (insn >> 16) & 0xf;
2453 rdlo = (insn >> 12) & 0xf;
2454 acc = insn & 7;
2456 if (acc != 0)
2457 return 1;
2459 if (insn & ARM_CP_RW_BIT) { /* MRA */
2460 iwmmxt_load_reg(cpu_V0, acc);
2461 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
2462 tcg_gen_extrh_i64_i32(cpu_R[rdhi], cpu_V0);
2463 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
2464 } else { /* MAR */
2465 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2466 iwmmxt_store_reg(cpu_V0, acc);
2468 return 0;
2471 return 1;
2474 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2475 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2476 if (dc_isar_feature(aa32_simd_r32, s)) { \
2477 reg = (((insn) >> (bigbit)) & 0x0f) \
2478 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2479 } else { \
2480 if (insn & (1 << (smallbit))) \
2481 return 1; \
2482 reg = ((insn) >> (bigbit)) & 0x0f; \
2483 }} while (0)
2485 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2486 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2487 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2489 static inline bool use_goto_tb(DisasContext *s, target_ulong dest)
2491 #ifndef CONFIG_USER_ONLY
2492 return (s->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
2493 ((s->base.pc_next - 1) & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
2494 #else
2495 return true;
2496 #endif
2499 static void gen_goto_ptr(void)
2501 tcg_gen_lookup_and_goto_ptr();
2504 /* This will end the TB but doesn't guarantee we'll return to
2505 * cpu_loop_exec. Any live exit_requests will be processed as we
2506 * enter the next TB.
2508 static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
2510 if (use_goto_tb(s, dest)) {
2511 tcg_gen_goto_tb(n);
2512 gen_set_pc_im(s, dest);
2513 tcg_gen_exit_tb(s->base.tb, n);
2514 } else {
2515 gen_set_pc_im(s, dest);
2516 gen_goto_ptr();
2518 s->base.is_jmp = DISAS_NORETURN;
2521 static inline void gen_jmp (DisasContext *s, uint32_t dest)
2523 if (unlikely(is_singlestepping(s))) {
2524 /* An indirect jump so that we still trigger the debug exception. */
2525 gen_set_pc_im(s, dest);
2526 s->base.is_jmp = DISAS_JUMP;
2527 } else {
2528 gen_goto_tb(s, 0, dest);
2532 static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
2534 if (x)
2535 tcg_gen_sari_i32(t0, t0, 16);
2536 else
2537 gen_sxth(t0);
2538 if (y)
2539 tcg_gen_sari_i32(t1, t1, 16);
2540 else
2541 gen_sxth(t1);
2542 tcg_gen_mul_i32(t0, t0, t1);
2545 /* Return the mask of PSR bits set by a MSR instruction. */
2546 static uint32_t msr_mask(DisasContext *s, int flags, int spsr)
2548 uint32_t mask = 0;
2550 if (flags & (1 << 0)) {
2551 mask |= 0xff;
2553 if (flags & (1 << 1)) {
2554 mask |= 0xff00;
2556 if (flags & (1 << 2)) {
2557 mask |= 0xff0000;
2559 if (flags & (1 << 3)) {
2560 mask |= 0xff000000;
2563 /* Mask out undefined and reserved bits. */
2564 mask &= aarch32_cpsr_valid_mask(s->features, s->isar);
2566 /* Mask out execution state. */
2567 if (!spsr) {
2568 mask &= ~CPSR_EXEC;
2571 /* Mask out privileged bits. */
2572 if (IS_USER(s)) {
2573 mask &= CPSR_USER;
2575 return mask;
2578 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
2579 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv_i32 t0)
2581 TCGv_i32 tmp;
2582 if (spsr) {
2583 /* ??? This is also undefined in system mode. */
2584 if (IS_USER(s))
2585 return 1;
2587 tmp = load_cpu_field(spsr);
2588 tcg_gen_andi_i32(tmp, tmp, ~mask);
2589 tcg_gen_andi_i32(t0, t0, mask);
2590 tcg_gen_or_i32(tmp, tmp, t0);
2591 store_cpu_field(tmp, spsr);
2592 } else {
2593 gen_set_cpsr(t0, mask);
2595 tcg_temp_free_i32(t0);
2596 gen_lookup_tb(s);
2597 return 0;
2600 /* Returns nonzero if access to the PSR is not permitted. */
2601 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
2603 TCGv_i32 tmp;
2604 tmp = tcg_temp_new_i32();
2605 tcg_gen_movi_i32(tmp, val);
2606 return gen_set_psr(s, mask, spsr, tmp);
2609 static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
2610 int *tgtmode, int *regno)
2612 /* Decode the r and sysm fields of MSR/MRS banked accesses into
2613 * the target mode and register number, and identify the various
2614 * unpredictable cases.
2615 * MSR (banked) and MRS (banked) are CONSTRAINED UNPREDICTABLE if:
2616 * + executed in user mode
2617 * + using R15 as the src/dest register
2618 * + accessing an unimplemented register
2619 * + accessing a register that's inaccessible at current PL/security state*
2620 * + accessing a register that you could access with a different insn
2621 * We choose to UNDEF in all these cases.
2622 * Since we don't know which of the various AArch32 modes we are in
2623 * we have to defer some checks to runtime.
2624 * Accesses to Monitor mode registers from Secure EL1 (which implies
2625 * that EL3 is AArch64) must trap to EL3.
2627 * If the access checks fail this function will emit code to take
2628 * an exception and return false. Otherwise it will return true,
2629 * and set *tgtmode and *regno appropriately.
2631 int exc_target = default_exception_el(s);
2633 /* These instructions are present only in ARMv8, or in ARMv7 with the
2634 * Virtualization Extensions.
2636 if (!arm_dc_feature(s, ARM_FEATURE_V8) &&
2637 !arm_dc_feature(s, ARM_FEATURE_EL2)) {
2638 goto undef;
2641 if (IS_USER(s) || rn == 15) {
2642 goto undef;
2645 /* The table in the v8 ARM ARM section F5.2.3 describes the encoding
2646 * of registers into (r, sysm).
2648 if (r) {
2649 /* SPSRs for other modes */
2650 switch (sysm) {
2651 case 0xe: /* SPSR_fiq */
2652 *tgtmode = ARM_CPU_MODE_FIQ;
2653 break;
2654 case 0x10: /* SPSR_irq */
2655 *tgtmode = ARM_CPU_MODE_IRQ;
2656 break;
2657 case 0x12: /* SPSR_svc */
2658 *tgtmode = ARM_CPU_MODE_SVC;
2659 break;
2660 case 0x14: /* SPSR_abt */
2661 *tgtmode = ARM_CPU_MODE_ABT;
2662 break;
2663 case 0x16: /* SPSR_und */
2664 *tgtmode = ARM_CPU_MODE_UND;
2665 break;
2666 case 0x1c: /* SPSR_mon */
2667 *tgtmode = ARM_CPU_MODE_MON;
2668 break;
2669 case 0x1e: /* SPSR_hyp */
2670 *tgtmode = ARM_CPU_MODE_HYP;
2671 break;
2672 default: /* unallocated */
2673 goto undef;
2675 /* We arbitrarily assign SPSR a register number of 16. */
2676 *regno = 16;
2677 } else {
2678 /* general purpose registers for other modes */
2679 switch (sysm) {
2680 case 0x0 ... 0x6: /* 0b00xxx : r8_usr ... r14_usr */
2681 *tgtmode = ARM_CPU_MODE_USR;
2682 *regno = sysm + 8;
2683 break;
2684 case 0x8 ... 0xe: /* 0b01xxx : r8_fiq ... r14_fiq */
2685 *tgtmode = ARM_CPU_MODE_FIQ;
2686 *regno = sysm;
2687 break;
2688 case 0x10 ... 0x11: /* 0b1000x : r14_irq, r13_irq */
2689 *tgtmode = ARM_CPU_MODE_IRQ;
2690 *regno = sysm & 1 ? 13 : 14;
2691 break;
2692 case 0x12 ... 0x13: /* 0b1001x : r14_svc, r13_svc */
2693 *tgtmode = ARM_CPU_MODE_SVC;
2694 *regno = sysm & 1 ? 13 : 14;
2695 break;
2696 case 0x14 ... 0x15: /* 0b1010x : r14_abt, r13_abt */
2697 *tgtmode = ARM_CPU_MODE_ABT;
2698 *regno = sysm & 1 ? 13 : 14;
2699 break;
2700 case 0x16 ... 0x17: /* 0b1011x : r14_und, r13_und */
2701 *tgtmode = ARM_CPU_MODE_UND;
2702 *regno = sysm & 1 ? 13 : 14;
2703 break;
2704 case 0x1c ... 0x1d: /* 0b1110x : r14_mon, r13_mon */
2705 *tgtmode = ARM_CPU_MODE_MON;
2706 *regno = sysm & 1 ? 13 : 14;
2707 break;
2708 case 0x1e ... 0x1f: /* 0b1111x : elr_hyp, r13_hyp */
2709 *tgtmode = ARM_CPU_MODE_HYP;
2710 /* Arbitrarily pick 17 for ELR_Hyp (which is not a banked LR!) */
2711 *regno = sysm & 1 ? 13 : 17;
2712 break;
2713 default: /* unallocated */
2714 goto undef;
2718 /* Catch the 'accessing inaccessible register' cases we can detect
2719 * at translate time.
2721 switch (*tgtmode) {
2722 case ARM_CPU_MODE_MON:
2723 if (!arm_dc_feature(s, ARM_FEATURE_EL3) || s->ns) {
2724 goto undef;
2726 if (s->current_el == 1) {
2727 /* If we're in Secure EL1 (which implies that EL3 is AArch64)
2728 * then accesses to Mon registers trap to EL3
2730 exc_target = 3;
2731 goto undef;
2733 break;
2734 case ARM_CPU_MODE_HYP:
2736 * SPSR_hyp and r13_hyp can only be accessed from Monitor mode
2737 * (and so we can forbid accesses from EL2 or below). elr_hyp
2738 * can be accessed also from Hyp mode, so forbid accesses from
2739 * EL0 or EL1.
2741 if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_el < 2 ||
2742 (s->current_el < 3 && *regno != 17)) {
2743 goto undef;
2745 break;
2746 default:
2747 break;
2750 return true;
2752 undef:
2753 /* If we get here then some access check did not pass */
2754 gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
2755 syn_uncategorized(), exc_target);
2756 return false;
2759 static void gen_msr_banked(DisasContext *s, int r, int sysm, int rn)
2761 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
2762 int tgtmode = 0, regno = 0;
2764 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
2765 return;
2768 /* Sync state because msr_banked() can raise exceptions */
2769 gen_set_condexec(s);
2770 gen_set_pc_im(s, s->pc_curr);
2771 tcg_reg = load_reg(s, rn);
2772 tcg_tgtmode = tcg_const_i32(tgtmode);
2773 tcg_regno = tcg_const_i32(regno);
2774 gen_helper_msr_banked(cpu_env, tcg_reg, tcg_tgtmode, tcg_regno);
2775 tcg_temp_free_i32(tcg_tgtmode);
2776 tcg_temp_free_i32(tcg_regno);
2777 tcg_temp_free_i32(tcg_reg);
2778 s->base.is_jmp = DISAS_UPDATE_EXIT;
2781 static void gen_mrs_banked(DisasContext *s, int r, int sysm, int rn)
2783 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
2784 int tgtmode = 0, regno = 0;
2786 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
2787 return;
2790 /* Sync state because mrs_banked() can raise exceptions */
2791 gen_set_condexec(s);
2792 gen_set_pc_im(s, s->pc_curr);
2793 tcg_reg = tcg_temp_new_i32();
2794 tcg_tgtmode = tcg_const_i32(tgtmode);
2795 tcg_regno = tcg_const_i32(regno);
2796 gen_helper_mrs_banked(tcg_reg, cpu_env, tcg_tgtmode, tcg_regno);
2797 tcg_temp_free_i32(tcg_tgtmode);
2798 tcg_temp_free_i32(tcg_regno);
2799 store_reg(s, rn, tcg_reg);
2800 s->base.is_jmp = DISAS_UPDATE_EXIT;
2803 /* Store value to PC as for an exception return (ie don't
2804 * mask bits). The subsequent call to gen_helper_cpsr_write_eret()
2805 * will do the masking based on the new value of the Thumb bit.
2807 static void store_pc_exc_ret(DisasContext *s, TCGv_i32 pc)
2809 tcg_gen_mov_i32(cpu_R[15], pc);
2810 tcg_temp_free_i32(pc);
2813 /* Generate a v6 exception return. Marks both values as dead. */
2814 static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
2816 store_pc_exc_ret(s, pc);
2817 /* The cpsr_write_eret helper will mask the low bits of PC
2818 * appropriately depending on the new Thumb bit, so it must
2819 * be called after storing the new PC.
2821 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
2822 gen_io_start();
2824 gen_helper_cpsr_write_eret(cpu_env, cpsr);
2825 tcg_temp_free_i32(cpsr);
2826 /* Must exit loop to check un-masked IRQs */
2827 s->base.is_jmp = DISAS_EXIT;
2830 /* Generate an old-style exception return. Marks pc as dead. */
2831 static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
2833 gen_rfe(s, pc, load_cpu_field(spsr));
2836 static void gen_gvec_fn3_qc(uint32_t rd_ofs, uint32_t rn_ofs, uint32_t rm_ofs,
2837 uint32_t opr_sz, uint32_t max_sz,
2838 gen_helper_gvec_3_ptr *fn)
2840 TCGv_ptr qc_ptr = tcg_temp_new_ptr();
2842 tcg_gen_addi_ptr(qc_ptr, cpu_env, offsetof(CPUARMState, vfp.qc));
2843 tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, qc_ptr,
2844 opr_sz, max_sz, 0, fn);
2845 tcg_temp_free_ptr(qc_ptr);
2848 void gen_gvec_sqrdmlah_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
2849 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
2851 static gen_helper_gvec_3_ptr * const fns[2] = {
2852 gen_helper_gvec_qrdmlah_s16, gen_helper_gvec_qrdmlah_s32
2854 tcg_debug_assert(vece >= 1 && vece <= 2);
2855 gen_gvec_fn3_qc(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, fns[vece - 1]);
2858 void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
2859 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
2861 static gen_helper_gvec_3_ptr * const fns[2] = {
2862 gen_helper_gvec_qrdmlsh_s16, gen_helper_gvec_qrdmlsh_s32
2864 tcg_debug_assert(vece >= 1 && vece <= 2);
2865 gen_gvec_fn3_qc(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, fns[vece - 1]);
2868 #define GEN_CMP0(NAME, COND) \
2869 static void gen_##NAME##0_i32(TCGv_i32 d, TCGv_i32 a) \
2871 tcg_gen_setcondi_i32(COND, d, a, 0); \
2872 tcg_gen_neg_i32(d, d); \
2874 static void gen_##NAME##0_i64(TCGv_i64 d, TCGv_i64 a) \
2876 tcg_gen_setcondi_i64(COND, d, a, 0); \
2877 tcg_gen_neg_i64(d, d); \
2879 static void gen_##NAME##0_vec(unsigned vece, TCGv_vec d, TCGv_vec a) \
2881 TCGv_vec zero = tcg_const_zeros_vec_matching(d); \
2882 tcg_gen_cmp_vec(COND, vece, d, a, zero); \
2883 tcg_temp_free_vec(zero); \
2885 void gen_gvec_##NAME##0(unsigned vece, uint32_t d, uint32_t m, \
2886 uint32_t opr_sz, uint32_t max_sz) \
2888 const GVecGen2 op[4] = { \
2889 { .fno = gen_helper_gvec_##NAME##0_b, \
2890 .fniv = gen_##NAME##0_vec, \
2891 .opt_opc = vecop_list_cmp, \
2892 .vece = MO_8 }, \
2893 { .fno = gen_helper_gvec_##NAME##0_h, \
2894 .fniv = gen_##NAME##0_vec, \
2895 .opt_opc = vecop_list_cmp, \
2896 .vece = MO_16 }, \
2897 { .fni4 = gen_##NAME##0_i32, \
2898 .fniv = gen_##NAME##0_vec, \
2899 .opt_opc = vecop_list_cmp, \
2900 .vece = MO_32 }, \
2901 { .fni8 = gen_##NAME##0_i64, \
2902 .fniv = gen_##NAME##0_vec, \
2903 .opt_opc = vecop_list_cmp, \
2904 .prefer_i64 = TCG_TARGET_REG_BITS == 64, \
2905 .vece = MO_64 }, \
2906 }; \
2907 tcg_gen_gvec_2(d, m, opr_sz, max_sz, &op[vece]); \
2910 static const TCGOpcode vecop_list_cmp[] = {
2911 INDEX_op_cmp_vec, 0
2914 GEN_CMP0(ceq, TCG_COND_EQ)
2915 GEN_CMP0(cle, TCG_COND_LE)
2916 GEN_CMP0(cge, TCG_COND_GE)
2917 GEN_CMP0(clt, TCG_COND_LT)
2918 GEN_CMP0(cgt, TCG_COND_GT)
2920 #undef GEN_CMP0
2922 static void gen_ssra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
2924 tcg_gen_vec_sar8i_i64(a, a, shift);
2925 tcg_gen_vec_add8_i64(d, d, a);
2928 static void gen_ssra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
2930 tcg_gen_vec_sar16i_i64(a, a, shift);
2931 tcg_gen_vec_add16_i64(d, d, a);
2934 static void gen_ssra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
2936 tcg_gen_sari_i32(a, a, shift);
2937 tcg_gen_add_i32(d, d, a);
2940 static void gen_ssra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
2942 tcg_gen_sari_i64(a, a, shift);
2943 tcg_gen_add_i64(d, d, a);
2946 static void gen_ssra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
2948 tcg_gen_sari_vec(vece, a, a, sh);
2949 tcg_gen_add_vec(vece, d, d, a);
2952 void gen_gvec_ssra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
2953 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
2955 static const TCGOpcode vecop_list[] = {
2956 INDEX_op_sari_vec, INDEX_op_add_vec, 0
2958 static const GVecGen2i ops[4] = {
2959 { .fni8 = gen_ssra8_i64,
2960 .fniv = gen_ssra_vec,
2961 .fno = gen_helper_gvec_ssra_b,
2962 .load_dest = true,
2963 .opt_opc = vecop_list,
2964 .vece = MO_8 },
2965 { .fni8 = gen_ssra16_i64,
2966 .fniv = gen_ssra_vec,
2967 .fno = gen_helper_gvec_ssra_h,
2968 .load_dest = true,
2969 .opt_opc = vecop_list,
2970 .vece = MO_16 },
2971 { .fni4 = gen_ssra32_i32,
2972 .fniv = gen_ssra_vec,
2973 .fno = gen_helper_gvec_ssra_s,
2974 .load_dest = true,
2975 .opt_opc = vecop_list,
2976 .vece = MO_32 },
2977 { .fni8 = gen_ssra64_i64,
2978 .fniv = gen_ssra_vec,
2979 .fno = gen_helper_gvec_ssra_b,
2980 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
2981 .opt_opc = vecop_list,
2982 .load_dest = true,
2983 .vece = MO_64 },
2986 /* tszimm encoding produces immediates in the range [1..esize]. */
2987 tcg_debug_assert(shift > 0);
2988 tcg_debug_assert(shift <= (8 << vece));
2991 * Shifts larger than the element size are architecturally valid.
2992 * Signed results in all sign bits.
2994 shift = MIN(shift, (8 << vece) - 1);
2995 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
2998 static void gen_usra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3000 tcg_gen_vec_shr8i_i64(a, a, shift);
3001 tcg_gen_vec_add8_i64(d, d, a);
3004 static void gen_usra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3006 tcg_gen_vec_shr16i_i64(a, a, shift);
3007 tcg_gen_vec_add16_i64(d, d, a);
3010 static void gen_usra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
3012 tcg_gen_shri_i32(a, a, shift);
3013 tcg_gen_add_i32(d, d, a);
3016 static void gen_usra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3018 tcg_gen_shri_i64(a, a, shift);
3019 tcg_gen_add_i64(d, d, a);
3022 static void gen_usra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3024 tcg_gen_shri_vec(vece, a, a, sh);
3025 tcg_gen_add_vec(vece, d, d, a);
3028 void gen_gvec_usra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3029 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3031 static const TCGOpcode vecop_list[] = {
3032 INDEX_op_shri_vec, INDEX_op_add_vec, 0
3034 static const GVecGen2i ops[4] = {
3035 { .fni8 = gen_usra8_i64,
3036 .fniv = gen_usra_vec,
3037 .fno = gen_helper_gvec_usra_b,
3038 .load_dest = true,
3039 .opt_opc = vecop_list,
3040 .vece = MO_8, },
3041 { .fni8 = gen_usra16_i64,
3042 .fniv = gen_usra_vec,
3043 .fno = gen_helper_gvec_usra_h,
3044 .load_dest = true,
3045 .opt_opc = vecop_list,
3046 .vece = MO_16, },
3047 { .fni4 = gen_usra32_i32,
3048 .fniv = gen_usra_vec,
3049 .fno = gen_helper_gvec_usra_s,
3050 .load_dest = true,
3051 .opt_opc = vecop_list,
3052 .vece = MO_32, },
3053 { .fni8 = gen_usra64_i64,
3054 .fniv = gen_usra_vec,
3055 .fno = gen_helper_gvec_usra_d,
3056 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3057 .load_dest = true,
3058 .opt_opc = vecop_list,
3059 .vece = MO_64, },
3062 /* tszimm encoding produces immediates in the range [1..esize]. */
3063 tcg_debug_assert(shift > 0);
3064 tcg_debug_assert(shift <= (8 << vece));
3067 * Shifts larger than the element size are architecturally valid.
3068 * Unsigned results in all zeros as input to accumulate: nop.
3070 if (shift < (8 << vece)) {
3071 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3072 } else {
3073 /* Nop, but we do need to clear the tail. */
3074 tcg_gen_gvec_mov(vece, rd_ofs, rd_ofs, opr_sz, max_sz);
3079 * Shift one less than the requested amount, and the low bit is
3080 * the rounding bit. For the 8 and 16-bit operations, because we
3081 * mask the low bit, we can perform a normal integer shift instead
3082 * of a vector shift.
3084 static void gen_srshr8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3086 TCGv_i64 t = tcg_temp_new_i64();
3088 tcg_gen_shri_i64(t, a, sh - 1);
3089 tcg_gen_andi_i64(t, t, dup_const(MO_8, 1));
3090 tcg_gen_vec_sar8i_i64(d, a, sh);
3091 tcg_gen_vec_add8_i64(d, d, t);
3092 tcg_temp_free_i64(t);
3095 static void gen_srshr16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3097 TCGv_i64 t = tcg_temp_new_i64();
3099 tcg_gen_shri_i64(t, a, sh - 1);
3100 tcg_gen_andi_i64(t, t, dup_const(MO_16, 1));
3101 tcg_gen_vec_sar16i_i64(d, a, sh);
3102 tcg_gen_vec_add16_i64(d, d, t);
3103 tcg_temp_free_i64(t);
3106 static void gen_srshr32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
3108 TCGv_i32 t = tcg_temp_new_i32();
3110 tcg_gen_extract_i32(t, a, sh - 1, 1);
3111 tcg_gen_sari_i32(d, a, sh);
3112 tcg_gen_add_i32(d, d, t);
3113 tcg_temp_free_i32(t);
3116 static void gen_srshr64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3118 TCGv_i64 t = tcg_temp_new_i64();
3120 tcg_gen_extract_i64(t, a, sh - 1, 1);
3121 tcg_gen_sari_i64(d, a, sh);
3122 tcg_gen_add_i64(d, d, t);
3123 tcg_temp_free_i64(t);
3126 static void gen_srshr_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3128 TCGv_vec t = tcg_temp_new_vec_matching(d);
3129 TCGv_vec ones = tcg_temp_new_vec_matching(d);
3131 tcg_gen_shri_vec(vece, t, a, sh - 1);
3132 tcg_gen_dupi_vec(vece, ones, 1);
3133 tcg_gen_and_vec(vece, t, t, ones);
3134 tcg_gen_sari_vec(vece, d, a, sh);
3135 tcg_gen_add_vec(vece, d, d, t);
3137 tcg_temp_free_vec(t);
3138 tcg_temp_free_vec(ones);
3141 void gen_gvec_srshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3142 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3144 static const TCGOpcode vecop_list[] = {
3145 INDEX_op_shri_vec, INDEX_op_sari_vec, INDEX_op_add_vec, 0
3147 static const GVecGen2i ops[4] = {
3148 { .fni8 = gen_srshr8_i64,
3149 .fniv = gen_srshr_vec,
3150 .fno = gen_helper_gvec_srshr_b,
3151 .opt_opc = vecop_list,
3152 .vece = MO_8 },
3153 { .fni8 = gen_srshr16_i64,
3154 .fniv = gen_srshr_vec,
3155 .fno = gen_helper_gvec_srshr_h,
3156 .opt_opc = vecop_list,
3157 .vece = MO_16 },
3158 { .fni4 = gen_srshr32_i32,
3159 .fniv = gen_srshr_vec,
3160 .fno = gen_helper_gvec_srshr_s,
3161 .opt_opc = vecop_list,
3162 .vece = MO_32 },
3163 { .fni8 = gen_srshr64_i64,
3164 .fniv = gen_srshr_vec,
3165 .fno = gen_helper_gvec_srshr_d,
3166 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3167 .opt_opc = vecop_list,
3168 .vece = MO_64 },
3171 /* tszimm encoding produces immediates in the range [1..esize] */
3172 tcg_debug_assert(shift > 0);
3173 tcg_debug_assert(shift <= (8 << vece));
3175 if (shift == (8 << vece)) {
3177 * Shifts larger than the element size are architecturally valid.
3178 * Signed results in all sign bits. With rounding, this produces
3179 * (-1 + 1) >> 1 == 0, or (0 + 1) >> 1 == 0.
3180 * I.e. always zero.
3182 tcg_gen_gvec_dup_imm(vece, rd_ofs, opr_sz, max_sz, 0);
3183 } else {
3184 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3188 static void gen_srsra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3190 TCGv_i64 t = tcg_temp_new_i64();
3192 gen_srshr8_i64(t, a, sh);
3193 tcg_gen_vec_add8_i64(d, d, t);
3194 tcg_temp_free_i64(t);
3197 static void gen_srsra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3199 TCGv_i64 t = tcg_temp_new_i64();
3201 gen_srshr16_i64(t, a, sh);
3202 tcg_gen_vec_add16_i64(d, d, t);
3203 tcg_temp_free_i64(t);
3206 static void gen_srsra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
3208 TCGv_i32 t = tcg_temp_new_i32();
3210 gen_srshr32_i32(t, a, sh);
3211 tcg_gen_add_i32(d, d, t);
3212 tcg_temp_free_i32(t);
3215 static void gen_srsra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3217 TCGv_i64 t = tcg_temp_new_i64();
3219 gen_srshr64_i64(t, a, sh);
3220 tcg_gen_add_i64(d, d, t);
3221 tcg_temp_free_i64(t);
3224 static void gen_srsra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3226 TCGv_vec t = tcg_temp_new_vec_matching(d);
3228 gen_srshr_vec(vece, t, a, sh);
3229 tcg_gen_add_vec(vece, d, d, t);
3230 tcg_temp_free_vec(t);
3233 void gen_gvec_srsra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3234 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3236 static const TCGOpcode vecop_list[] = {
3237 INDEX_op_shri_vec, INDEX_op_sari_vec, INDEX_op_add_vec, 0
3239 static const GVecGen2i ops[4] = {
3240 { .fni8 = gen_srsra8_i64,
3241 .fniv = gen_srsra_vec,
3242 .fno = gen_helper_gvec_srsra_b,
3243 .opt_opc = vecop_list,
3244 .load_dest = true,
3245 .vece = MO_8 },
3246 { .fni8 = gen_srsra16_i64,
3247 .fniv = gen_srsra_vec,
3248 .fno = gen_helper_gvec_srsra_h,
3249 .opt_opc = vecop_list,
3250 .load_dest = true,
3251 .vece = MO_16 },
3252 { .fni4 = gen_srsra32_i32,
3253 .fniv = gen_srsra_vec,
3254 .fno = gen_helper_gvec_srsra_s,
3255 .opt_opc = vecop_list,
3256 .load_dest = true,
3257 .vece = MO_32 },
3258 { .fni8 = gen_srsra64_i64,
3259 .fniv = gen_srsra_vec,
3260 .fno = gen_helper_gvec_srsra_d,
3261 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3262 .opt_opc = vecop_list,
3263 .load_dest = true,
3264 .vece = MO_64 },
3267 /* tszimm encoding produces immediates in the range [1..esize] */
3268 tcg_debug_assert(shift > 0);
3269 tcg_debug_assert(shift <= (8 << vece));
3272 * Shifts larger than the element size are architecturally valid.
3273 * Signed results in all sign bits. With rounding, this produces
3274 * (-1 + 1) >> 1 == 0, or (0 + 1) >> 1 == 0.
3275 * I.e. always zero. With accumulation, this leaves D unchanged.
3277 if (shift == (8 << vece)) {
3278 /* Nop, but we do need to clear the tail. */
3279 tcg_gen_gvec_mov(vece, rd_ofs, rd_ofs, opr_sz, max_sz);
3280 } else {
3281 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3285 static void gen_urshr8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3287 TCGv_i64 t = tcg_temp_new_i64();
3289 tcg_gen_shri_i64(t, a, sh - 1);
3290 tcg_gen_andi_i64(t, t, dup_const(MO_8, 1));
3291 tcg_gen_vec_shr8i_i64(d, a, sh);
3292 tcg_gen_vec_add8_i64(d, d, t);
3293 tcg_temp_free_i64(t);
3296 static void gen_urshr16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3298 TCGv_i64 t = tcg_temp_new_i64();
3300 tcg_gen_shri_i64(t, a, sh - 1);
3301 tcg_gen_andi_i64(t, t, dup_const(MO_16, 1));
3302 tcg_gen_vec_shr16i_i64(d, a, sh);
3303 tcg_gen_vec_add16_i64(d, d, t);
3304 tcg_temp_free_i64(t);
3307 static void gen_urshr32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
3309 TCGv_i32 t = tcg_temp_new_i32();
3311 tcg_gen_extract_i32(t, a, sh - 1, 1);
3312 tcg_gen_shri_i32(d, a, sh);
3313 tcg_gen_add_i32(d, d, t);
3314 tcg_temp_free_i32(t);
3317 static void gen_urshr64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3319 TCGv_i64 t = tcg_temp_new_i64();
3321 tcg_gen_extract_i64(t, a, sh - 1, 1);
3322 tcg_gen_shri_i64(d, a, sh);
3323 tcg_gen_add_i64(d, d, t);
3324 tcg_temp_free_i64(t);
3327 static void gen_urshr_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t shift)
3329 TCGv_vec t = tcg_temp_new_vec_matching(d);
3330 TCGv_vec ones = tcg_temp_new_vec_matching(d);
3332 tcg_gen_shri_vec(vece, t, a, shift - 1);
3333 tcg_gen_dupi_vec(vece, ones, 1);
3334 tcg_gen_and_vec(vece, t, t, ones);
3335 tcg_gen_shri_vec(vece, d, a, shift);
3336 tcg_gen_add_vec(vece, d, d, t);
3338 tcg_temp_free_vec(t);
3339 tcg_temp_free_vec(ones);
3342 void gen_gvec_urshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3343 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3345 static const TCGOpcode vecop_list[] = {
3346 INDEX_op_shri_vec, INDEX_op_add_vec, 0
3348 static const GVecGen2i ops[4] = {
3349 { .fni8 = gen_urshr8_i64,
3350 .fniv = gen_urshr_vec,
3351 .fno = gen_helper_gvec_urshr_b,
3352 .opt_opc = vecop_list,
3353 .vece = MO_8 },
3354 { .fni8 = gen_urshr16_i64,
3355 .fniv = gen_urshr_vec,
3356 .fno = gen_helper_gvec_urshr_h,
3357 .opt_opc = vecop_list,
3358 .vece = MO_16 },
3359 { .fni4 = gen_urshr32_i32,
3360 .fniv = gen_urshr_vec,
3361 .fno = gen_helper_gvec_urshr_s,
3362 .opt_opc = vecop_list,
3363 .vece = MO_32 },
3364 { .fni8 = gen_urshr64_i64,
3365 .fniv = gen_urshr_vec,
3366 .fno = gen_helper_gvec_urshr_d,
3367 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3368 .opt_opc = vecop_list,
3369 .vece = MO_64 },
3372 /* tszimm encoding produces immediates in the range [1..esize] */
3373 tcg_debug_assert(shift > 0);
3374 tcg_debug_assert(shift <= (8 << vece));
3376 if (shift == (8 << vece)) {
3378 * Shifts larger than the element size are architecturally valid.
3379 * Unsigned results in zero. With rounding, this produces a
3380 * copy of the most significant bit.
3382 tcg_gen_gvec_shri(vece, rd_ofs, rm_ofs, shift - 1, opr_sz, max_sz);
3383 } else {
3384 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3388 static void gen_ursra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3390 TCGv_i64 t = tcg_temp_new_i64();
3392 if (sh == 8) {
3393 tcg_gen_vec_shr8i_i64(t, a, 7);
3394 } else {
3395 gen_urshr8_i64(t, a, sh);
3397 tcg_gen_vec_add8_i64(d, d, t);
3398 tcg_temp_free_i64(t);
3401 static void gen_ursra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3403 TCGv_i64 t = tcg_temp_new_i64();
3405 if (sh == 16) {
3406 tcg_gen_vec_shr16i_i64(t, a, 15);
3407 } else {
3408 gen_urshr16_i64(t, a, sh);
3410 tcg_gen_vec_add16_i64(d, d, t);
3411 tcg_temp_free_i64(t);
3414 static void gen_ursra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
3416 TCGv_i32 t = tcg_temp_new_i32();
3418 if (sh == 32) {
3419 tcg_gen_shri_i32(t, a, 31);
3420 } else {
3421 gen_urshr32_i32(t, a, sh);
3423 tcg_gen_add_i32(d, d, t);
3424 tcg_temp_free_i32(t);
3427 static void gen_ursra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3429 TCGv_i64 t = tcg_temp_new_i64();
3431 if (sh == 64) {
3432 tcg_gen_shri_i64(t, a, 63);
3433 } else {
3434 gen_urshr64_i64(t, a, sh);
3436 tcg_gen_add_i64(d, d, t);
3437 tcg_temp_free_i64(t);
3440 static void gen_ursra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3442 TCGv_vec t = tcg_temp_new_vec_matching(d);
3444 if (sh == (8 << vece)) {
3445 tcg_gen_shri_vec(vece, t, a, sh - 1);
3446 } else {
3447 gen_urshr_vec(vece, t, a, sh);
3449 tcg_gen_add_vec(vece, d, d, t);
3450 tcg_temp_free_vec(t);
3453 void gen_gvec_ursra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3454 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3456 static const TCGOpcode vecop_list[] = {
3457 INDEX_op_shri_vec, INDEX_op_add_vec, 0
3459 static const GVecGen2i ops[4] = {
3460 { .fni8 = gen_ursra8_i64,
3461 .fniv = gen_ursra_vec,
3462 .fno = gen_helper_gvec_ursra_b,
3463 .opt_opc = vecop_list,
3464 .load_dest = true,
3465 .vece = MO_8 },
3466 { .fni8 = gen_ursra16_i64,
3467 .fniv = gen_ursra_vec,
3468 .fno = gen_helper_gvec_ursra_h,
3469 .opt_opc = vecop_list,
3470 .load_dest = true,
3471 .vece = MO_16 },
3472 { .fni4 = gen_ursra32_i32,
3473 .fniv = gen_ursra_vec,
3474 .fno = gen_helper_gvec_ursra_s,
3475 .opt_opc = vecop_list,
3476 .load_dest = true,
3477 .vece = MO_32 },
3478 { .fni8 = gen_ursra64_i64,
3479 .fniv = gen_ursra_vec,
3480 .fno = gen_helper_gvec_ursra_d,
3481 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3482 .opt_opc = vecop_list,
3483 .load_dest = true,
3484 .vece = MO_64 },
3487 /* tszimm encoding produces immediates in the range [1..esize] */
3488 tcg_debug_assert(shift > 0);
3489 tcg_debug_assert(shift <= (8 << vece));
3491 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3494 static void gen_shr8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3496 uint64_t mask = dup_const(MO_8, 0xff >> shift);
3497 TCGv_i64 t = tcg_temp_new_i64();
3499 tcg_gen_shri_i64(t, a, shift);
3500 tcg_gen_andi_i64(t, t, mask);
3501 tcg_gen_andi_i64(d, d, ~mask);
3502 tcg_gen_or_i64(d, d, t);
3503 tcg_temp_free_i64(t);
3506 static void gen_shr16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3508 uint64_t mask = dup_const(MO_16, 0xffff >> shift);
3509 TCGv_i64 t = tcg_temp_new_i64();
3511 tcg_gen_shri_i64(t, a, shift);
3512 tcg_gen_andi_i64(t, t, mask);
3513 tcg_gen_andi_i64(d, d, ~mask);
3514 tcg_gen_or_i64(d, d, t);
3515 tcg_temp_free_i64(t);
3518 static void gen_shr32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
3520 tcg_gen_shri_i32(a, a, shift);
3521 tcg_gen_deposit_i32(d, d, a, 0, 32 - shift);
3524 static void gen_shr64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3526 tcg_gen_shri_i64(a, a, shift);
3527 tcg_gen_deposit_i64(d, d, a, 0, 64 - shift);
3530 static void gen_shr_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3532 TCGv_vec t = tcg_temp_new_vec_matching(d);
3533 TCGv_vec m = tcg_temp_new_vec_matching(d);
3535 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK((8 << vece) - sh, sh));
3536 tcg_gen_shri_vec(vece, t, a, sh);
3537 tcg_gen_and_vec(vece, d, d, m);
3538 tcg_gen_or_vec(vece, d, d, t);
3540 tcg_temp_free_vec(t);
3541 tcg_temp_free_vec(m);
3544 void gen_gvec_sri(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3545 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3547 static const TCGOpcode vecop_list[] = { INDEX_op_shri_vec, 0 };
3548 const GVecGen2i ops[4] = {
3549 { .fni8 = gen_shr8_ins_i64,
3550 .fniv = gen_shr_ins_vec,
3551 .fno = gen_helper_gvec_sri_b,
3552 .load_dest = true,
3553 .opt_opc = vecop_list,
3554 .vece = MO_8 },
3555 { .fni8 = gen_shr16_ins_i64,
3556 .fniv = gen_shr_ins_vec,
3557 .fno = gen_helper_gvec_sri_h,
3558 .load_dest = true,
3559 .opt_opc = vecop_list,
3560 .vece = MO_16 },
3561 { .fni4 = gen_shr32_ins_i32,
3562 .fniv = gen_shr_ins_vec,
3563 .fno = gen_helper_gvec_sri_s,
3564 .load_dest = true,
3565 .opt_opc = vecop_list,
3566 .vece = MO_32 },
3567 { .fni8 = gen_shr64_ins_i64,
3568 .fniv = gen_shr_ins_vec,
3569 .fno = gen_helper_gvec_sri_d,
3570 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3571 .load_dest = true,
3572 .opt_opc = vecop_list,
3573 .vece = MO_64 },
3576 /* tszimm encoding produces immediates in the range [1..esize]. */
3577 tcg_debug_assert(shift > 0);
3578 tcg_debug_assert(shift <= (8 << vece));
3580 /* Shift of esize leaves destination unchanged. */
3581 if (shift < (8 << vece)) {
3582 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3583 } else {
3584 /* Nop, but we do need to clear the tail. */
3585 tcg_gen_gvec_mov(vece, rd_ofs, rd_ofs, opr_sz, max_sz);
3589 static void gen_shl8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3591 uint64_t mask = dup_const(MO_8, 0xff << shift);
3592 TCGv_i64 t = tcg_temp_new_i64();
3594 tcg_gen_shli_i64(t, a, shift);
3595 tcg_gen_andi_i64(t, t, mask);
3596 tcg_gen_andi_i64(d, d, ~mask);
3597 tcg_gen_or_i64(d, d, t);
3598 tcg_temp_free_i64(t);
3601 static void gen_shl16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3603 uint64_t mask = dup_const(MO_16, 0xffff << shift);
3604 TCGv_i64 t = tcg_temp_new_i64();
3606 tcg_gen_shli_i64(t, a, shift);
3607 tcg_gen_andi_i64(t, t, mask);
3608 tcg_gen_andi_i64(d, d, ~mask);
3609 tcg_gen_or_i64(d, d, t);
3610 tcg_temp_free_i64(t);
3613 static void gen_shl32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
3615 tcg_gen_deposit_i32(d, d, a, shift, 32 - shift);
3618 static void gen_shl64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3620 tcg_gen_deposit_i64(d, d, a, shift, 64 - shift);
3623 static void gen_shl_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3625 TCGv_vec t = tcg_temp_new_vec_matching(d);
3626 TCGv_vec m = tcg_temp_new_vec_matching(d);
3628 tcg_gen_shli_vec(vece, t, a, sh);
3629 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK(0, sh));
3630 tcg_gen_and_vec(vece, d, d, m);
3631 tcg_gen_or_vec(vece, d, d, t);
3633 tcg_temp_free_vec(t);
3634 tcg_temp_free_vec(m);
3637 void gen_gvec_sli(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3638 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3640 static const TCGOpcode vecop_list[] = { INDEX_op_shli_vec, 0 };
3641 const GVecGen2i ops[4] = {
3642 { .fni8 = gen_shl8_ins_i64,
3643 .fniv = gen_shl_ins_vec,
3644 .fno = gen_helper_gvec_sli_b,
3645 .load_dest = true,
3646 .opt_opc = vecop_list,
3647 .vece = MO_8 },
3648 { .fni8 = gen_shl16_ins_i64,
3649 .fniv = gen_shl_ins_vec,
3650 .fno = gen_helper_gvec_sli_h,
3651 .load_dest = true,
3652 .opt_opc = vecop_list,
3653 .vece = MO_16 },
3654 { .fni4 = gen_shl32_ins_i32,
3655 .fniv = gen_shl_ins_vec,
3656 .fno = gen_helper_gvec_sli_s,
3657 .load_dest = true,
3658 .opt_opc = vecop_list,
3659 .vece = MO_32 },
3660 { .fni8 = gen_shl64_ins_i64,
3661 .fniv = gen_shl_ins_vec,
3662 .fno = gen_helper_gvec_sli_d,
3663 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3664 .load_dest = true,
3665 .opt_opc = vecop_list,
3666 .vece = MO_64 },
3669 /* tszimm encoding produces immediates in the range [0..esize-1]. */
3670 tcg_debug_assert(shift >= 0);
3671 tcg_debug_assert(shift < (8 << vece));
3673 if (shift == 0) {
3674 tcg_gen_gvec_mov(vece, rd_ofs, rm_ofs, opr_sz, max_sz);
3675 } else {
3676 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3680 static void gen_mla8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3682 gen_helper_neon_mul_u8(a, a, b);
3683 gen_helper_neon_add_u8(d, d, a);
3686 static void gen_mls8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3688 gen_helper_neon_mul_u8(a, a, b);
3689 gen_helper_neon_sub_u8(d, d, a);
3692 static void gen_mla16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3694 gen_helper_neon_mul_u16(a, a, b);
3695 gen_helper_neon_add_u16(d, d, a);
3698 static void gen_mls16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3700 gen_helper_neon_mul_u16(a, a, b);
3701 gen_helper_neon_sub_u16(d, d, a);
3704 static void gen_mla32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3706 tcg_gen_mul_i32(a, a, b);
3707 tcg_gen_add_i32(d, d, a);
3710 static void gen_mls32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3712 tcg_gen_mul_i32(a, a, b);
3713 tcg_gen_sub_i32(d, d, a);
3716 static void gen_mla64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
3718 tcg_gen_mul_i64(a, a, b);
3719 tcg_gen_add_i64(d, d, a);
3722 static void gen_mls64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
3724 tcg_gen_mul_i64(a, a, b);
3725 tcg_gen_sub_i64(d, d, a);
3728 static void gen_mla_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
3730 tcg_gen_mul_vec(vece, a, a, b);
3731 tcg_gen_add_vec(vece, d, d, a);
3734 static void gen_mls_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
3736 tcg_gen_mul_vec(vece, a, a, b);
3737 tcg_gen_sub_vec(vece, d, d, a);
3740 /* Note that while NEON does not support VMLA and VMLS as 64-bit ops,
3741 * these tables are shared with AArch64 which does support them.
3743 void gen_gvec_mla(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
3744 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
3746 static const TCGOpcode vecop_list[] = {
3747 INDEX_op_mul_vec, INDEX_op_add_vec, 0
3749 static const GVecGen3 ops[4] = {
3750 { .fni4 = gen_mla8_i32,
3751 .fniv = gen_mla_vec,
3752 .load_dest = true,
3753 .opt_opc = vecop_list,
3754 .vece = MO_8 },
3755 { .fni4 = gen_mla16_i32,
3756 .fniv = gen_mla_vec,
3757 .load_dest = true,
3758 .opt_opc = vecop_list,
3759 .vece = MO_16 },
3760 { .fni4 = gen_mla32_i32,
3761 .fniv = gen_mla_vec,
3762 .load_dest = true,
3763 .opt_opc = vecop_list,
3764 .vece = MO_32 },
3765 { .fni8 = gen_mla64_i64,
3766 .fniv = gen_mla_vec,
3767 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3768 .load_dest = true,
3769 .opt_opc = vecop_list,
3770 .vece = MO_64 },
3772 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
3775 void gen_gvec_mls(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
3776 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
3778 static const TCGOpcode vecop_list[] = {
3779 INDEX_op_mul_vec, INDEX_op_sub_vec, 0
3781 static const GVecGen3 ops[4] = {
3782 { .fni4 = gen_mls8_i32,
3783 .fniv = gen_mls_vec,
3784 .load_dest = true,
3785 .opt_opc = vecop_list,
3786 .vece = MO_8 },
3787 { .fni4 = gen_mls16_i32,
3788 .fniv = gen_mls_vec,
3789 .load_dest = true,
3790 .opt_opc = vecop_list,
3791 .vece = MO_16 },
3792 { .fni4 = gen_mls32_i32,
3793 .fniv = gen_mls_vec,
3794 .load_dest = true,
3795 .opt_opc = vecop_list,
3796 .vece = MO_32 },
3797 { .fni8 = gen_mls64_i64,
3798 .fniv = gen_mls_vec,
3799 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3800 .load_dest = true,
3801 .opt_opc = vecop_list,
3802 .vece = MO_64 },
3804 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
3807 /* CMTST : test is "if (X & Y != 0)". */
3808 static void gen_cmtst_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3810 tcg_gen_and_i32(d, a, b);
3811 tcg_gen_setcondi_i32(TCG_COND_NE, d, d, 0);
3812 tcg_gen_neg_i32(d, d);
3815 void gen_cmtst_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
3817 tcg_gen_and_i64(d, a, b);
3818 tcg_gen_setcondi_i64(TCG_COND_NE, d, d, 0);
3819 tcg_gen_neg_i64(d, d);
3822 static void gen_cmtst_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
3824 tcg_gen_and_vec(vece, d, a, b);
3825 tcg_gen_dupi_vec(vece, a, 0);
3826 tcg_gen_cmp_vec(TCG_COND_NE, vece, d, d, a);
3829 void gen_gvec_cmtst(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
3830 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
3832 static const TCGOpcode vecop_list[] = { INDEX_op_cmp_vec, 0 };
3833 static const GVecGen3 ops[4] = {
3834 { .fni4 = gen_helper_neon_tst_u8,
3835 .fniv = gen_cmtst_vec,
3836 .opt_opc = vecop_list,
3837 .vece = MO_8 },
3838 { .fni4 = gen_helper_neon_tst_u16,
3839 .fniv = gen_cmtst_vec,
3840 .opt_opc = vecop_list,
3841 .vece = MO_16 },
3842 { .fni4 = gen_cmtst_i32,
3843 .fniv = gen_cmtst_vec,
3844 .opt_opc = vecop_list,
3845 .vece = MO_32 },
3846 { .fni8 = gen_cmtst_i64,
3847 .fniv = gen_cmtst_vec,
3848 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3849 .opt_opc = vecop_list,
3850 .vece = MO_64 },
3852 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
3855 void gen_ushl_i32(TCGv_i32 dst, TCGv_i32 src, TCGv_i32 shift)
3857 TCGv_i32 lval = tcg_temp_new_i32();
3858 TCGv_i32 rval = tcg_temp_new_i32();
3859 TCGv_i32 lsh = tcg_temp_new_i32();
3860 TCGv_i32 rsh = tcg_temp_new_i32();
3861 TCGv_i32 zero = tcg_const_i32(0);
3862 TCGv_i32 max = tcg_const_i32(32);
3865 * Rely on the TCG guarantee that out of range shifts produce
3866 * unspecified results, not undefined behaviour (i.e. no trap).
3867 * Discard out-of-range results after the fact.
3869 tcg_gen_ext8s_i32(lsh, shift);
3870 tcg_gen_neg_i32(rsh, lsh);
3871 tcg_gen_shl_i32(lval, src, lsh);
3872 tcg_gen_shr_i32(rval, src, rsh);
3873 tcg_gen_movcond_i32(TCG_COND_LTU, dst, lsh, max, lval, zero);
3874 tcg_gen_movcond_i32(TCG_COND_LTU, dst, rsh, max, rval, dst);
3876 tcg_temp_free_i32(lval);
3877 tcg_temp_free_i32(rval);
3878 tcg_temp_free_i32(lsh);
3879 tcg_temp_free_i32(rsh);
3880 tcg_temp_free_i32(zero);
3881 tcg_temp_free_i32(max);
3884 void gen_ushl_i64(TCGv_i64 dst, TCGv_i64 src, TCGv_i64 shift)
3886 TCGv_i64 lval = tcg_temp_new_i64();
3887 TCGv_i64 rval = tcg_temp_new_i64();
3888 TCGv_i64 lsh = tcg_temp_new_i64();
3889 TCGv_i64 rsh = tcg_temp_new_i64();
3890 TCGv_i64 zero = tcg_const_i64(0);
3891 TCGv_i64 max = tcg_const_i64(64);
3894 * Rely on the TCG guarantee that out of range shifts produce
3895 * unspecified results, not undefined behaviour (i.e. no trap).
3896 * Discard out-of-range results after the fact.
3898 tcg_gen_ext8s_i64(lsh, shift);
3899 tcg_gen_neg_i64(rsh, lsh);
3900 tcg_gen_shl_i64(lval, src, lsh);
3901 tcg_gen_shr_i64(rval, src, rsh);
3902 tcg_gen_movcond_i64(TCG_COND_LTU, dst, lsh, max, lval, zero);
3903 tcg_gen_movcond_i64(TCG_COND_LTU, dst, rsh, max, rval, dst);
3905 tcg_temp_free_i64(lval);
3906 tcg_temp_free_i64(rval);
3907 tcg_temp_free_i64(lsh);
3908 tcg_temp_free_i64(rsh);
3909 tcg_temp_free_i64(zero);
3910 tcg_temp_free_i64(max);
3913 static void gen_ushl_vec(unsigned vece, TCGv_vec dst,
3914 TCGv_vec src, TCGv_vec shift)
3916 TCGv_vec lval = tcg_temp_new_vec_matching(dst);
3917 TCGv_vec rval = tcg_temp_new_vec_matching(dst);
3918 TCGv_vec lsh = tcg_temp_new_vec_matching(dst);
3919 TCGv_vec rsh = tcg_temp_new_vec_matching(dst);
3920 TCGv_vec msk, max;
3922 tcg_gen_neg_vec(vece, rsh, shift);
3923 if (vece == MO_8) {
3924 tcg_gen_mov_vec(lsh, shift);
3925 } else {
3926 msk = tcg_temp_new_vec_matching(dst);
3927 tcg_gen_dupi_vec(vece, msk, 0xff);
3928 tcg_gen_and_vec(vece, lsh, shift, msk);
3929 tcg_gen_and_vec(vece, rsh, rsh, msk);
3930 tcg_temp_free_vec(msk);
3934 * Rely on the TCG guarantee that out of range shifts produce
3935 * unspecified results, not undefined behaviour (i.e. no trap).
3936 * Discard out-of-range results after the fact.
3938 tcg_gen_shlv_vec(vece, lval, src, lsh);
3939 tcg_gen_shrv_vec(vece, rval, src, rsh);
3941 max = tcg_temp_new_vec_matching(dst);
3942 tcg_gen_dupi_vec(vece, max, 8 << vece);
3945 * The choice of LT (signed) and GEU (unsigned) are biased toward
3946 * the instructions of the x86_64 host. For MO_8, the whole byte
3947 * is significant so we must use an unsigned compare; otherwise we
3948 * have already masked to a byte and so a signed compare works.
3949 * Other tcg hosts have a full set of comparisons and do not care.
3951 if (vece == MO_8) {
3952 tcg_gen_cmp_vec(TCG_COND_GEU, vece, lsh, lsh, max);
3953 tcg_gen_cmp_vec(TCG_COND_GEU, vece, rsh, rsh, max);
3954 tcg_gen_andc_vec(vece, lval, lval, lsh);
3955 tcg_gen_andc_vec(vece, rval, rval, rsh);
3956 } else {
3957 tcg_gen_cmp_vec(TCG_COND_LT, vece, lsh, lsh, max);
3958 tcg_gen_cmp_vec(TCG_COND_LT, vece, rsh, rsh, max);
3959 tcg_gen_and_vec(vece, lval, lval, lsh);
3960 tcg_gen_and_vec(vece, rval, rval, rsh);
3962 tcg_gen_or_vec(vece, dst, lval, rval);
3964 tcg_temp_free_vec(max);
3965 tcg_temp_free_vec(lval);
3966 tcg_temp_free_vec(rval);
3967 tcg_temp_free_vec(lsh);
3968 tcg_temp_free_vec(rsh);
3971 void gen_gvec_ushl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
3972 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
3974 static const TCGOpcode vecop_list[] = {
3975 INDEX_op_neg_vec, INDEX_op_shlv_vec,
3976 INDEX_op_shrv_vec, INDEX_op_cmp_vec, 0
3978 static const GVecGen3 ops[4] = {
3979 { .fniv = gen_ushl_vec,
3980 .fno = gen_helper_gvec_ushl_b,
3981 .opt_opc = vecop_list,
3982 .vece = MO_8 },
3983 { .fniv = gen_ushl_vec,
3984 .fno = gen_helper_gvec_ushl_h,
3985 .opt_opc = vecop_list,
3986 .vece = MO_16 },
3987 { .fni4 = gen_ushl_i32,
3988 .fniv = gen_ushl_vec,
3989 .opt_opc = vecop_list,
3990 .vece = MO_32 },
3991 { .fni8 = gen_ushl_i64,
3992 .fniv = gen_ushl_vec,
3993 .opt_opc = vecop_list,
3994 .vece = MO_64 },
3996 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
3999 void gen_sshl_i32(TCGv_i32 dst, TCGv_i32 src, TCGv_i32 shift)
4001 TCGv_i32 lval = tcg_temp_new_i32();
4002 TCGv_i32 rval = tcg_temp_new_i32();
4003 TCGv_i32 lsh = tcg_temp_new_i32();
4004 TCGv_i32 rsh = tcg_temp_new_i32();
4005 TCGv_i32 zero = tcg_const_i32(0);
4006 TCGv_i32 max = tcg_const_i32(31);
4009 * Rely on the TCG guarantee that out of range shifts produce
4010 * unspecified results, not undefined behaviour (i.e. no trap).
4011 * Discard out-of-range results after the fact.
4013 tcg_gen_ext8s_i32(lsh, shift);
4014 tcg_gen_neg_i32(rsh, lsh);
4015 tcg_gen_shl_i32(lval, src, lsh);
4016 tcg_gen_umin_i32(rsh, rsh, max);
4017 tcg_gen_sar_i32(rval, src, rsh);
4018 tcg_gen_movcond_i32(TCG_COND_LEU, lval, lsh, max, lval, zero);
4019 tcg_gen_movcond_i32(TCG_COND_LT, dst, lsh, zero, rval, lval);
4021 tcg_temp_free_i32(lval);
4022 tcg_temp_free_i32(rval);
4023 tcg_temp_free_i32(lsh);
4024 tcg_temp_free_i32(rsh);
4025 tcg_temp_free_i32(zero);
4026 tcg_temp_free_i32(max);
4029 void gen_sshl_i64(TCGv_i64 dst, TCGv_i64 src, TCGv_i64 shift)
4031 TCGv_i64 lval = tcg_temp_new_i64();
4032 TCGv_i64 rval = tcg_temp_new_i64();
4033 TCGv_i64 lsh = tcg_temp_new_i64();
4034 TCGv_i64 rsh = tcg_temp_new_i64();
4035 TCGv_i64 zero = tcg_const_i64(0);
4036 TCGv_i64 max = tcg_const_i64(63);
4039 * Rely on the TCG guarantee that out of range shifts produce
4040 * unspecified results, not undefined behaviour (i.e. no trap).
4041 * Discard out-of-range results after the fact.
4043 tcg_gen_ext8s_i64(lsh, shift);
4044 tcg_gen_neg_i64(rsh, lsh);
4045 tcg_gen_shl_i64(lval, src, lsh);
4046 tcg_gen_umin_i64(rsh, rsh, max);
4047 tcg_gen_sar_i64(rval, src, rsh);
4048 tcg_gen_movcond_i64(TCG_COND_LEU, lval, lsh, max, lval, zero);
4049 tcg_gen_movcond_i64(TCG_COND_LT, dst, lsh, zero, rval, lval);
4051 tcg_temp_free_i64(lval);
4052 tcg_temp_free_i64(rval);
4053 tcg_temp_free_i64(lsh);
4054 tcg_temp_free_i64(rsh);
4055 tcg_temp_free_i64(zero);
4056 tcg_temp_free_i64(max);
4059 static void gen_sshl_vec(unsigned vece, TCGv_vec dst,
4060 TCGv_vec src, TCGv_vec shift)
4062 TCGv_vec lval = tcg_temp_new_vec_matching(dst);
4063 TCGv_vec rval = tcg_temp_new_vec_matching(dst);
4064 TCGv_vec lsh = tcg_temp_new_vec_matching(dst);
4065 TCGv_vec rsh = tcg_temp_new_vec_matching(dst);
4066 TCGv_vec tmp = tcg_temp_new_vec_matching(dst);
4069 * Rely on the TCG guarantee that out of range shifts produce
4070 * unspecified results, not undefined behaviour (i.e. no trap).
4071 * Discard out-of-range results after the fact.
4073 tcg_gen_neg_vec(vece, rsh, shift);
4074 if (vece == MO_8) {
4075 tcg_gen_mov_vec(lsh, shift);
4076 } else {
4077 tcg_gen_dupi_vec(vece, tmp, 0xff);
4078 tcg_gen_and_vec(vece, lsh, shift, tmp);
4079 tcg_gen_and_vec(vece, rsh, rsh, tmp);
4082 /* Bound rsh so out of bound right shift gets -1. */
4083 tcg_gen_dupi_vec(vece, tmp, (8 << vece) - 1);
4084 tcg_gen_umin_vec(vece, rsh, rsh, tmp);
4085 tcg_gen_cmp_vec(TCG_COND_GT, vece, tmp, lsh, tmp);
4087 tcg_gen_shlv_vec(vece, lval, src, lsh);
4088 tcg_gen_sarv_vec(vece, rval, src, rsh);
4090 /* Select in-bound left shift. */
4091 tcg_gen_andc_vec(vece, lval, lval, tmp);
4093 /* Select between left and right shift. */
4094 if (vece == MO_8) {
4095 tcg_gen_dupi_vec(vece, tmp, 0);
4096 tcg_gen_cmpsel_vec(TCG_COND_LT, vece, dst, lsh, tmp, rval, lval);
4097 } else {
4098 tcg_gen_dupi_vec(vece, tmp, 0x80);
4099 tcg_gen_cmpsel_vec(TCG_COND_LT, vece, dst, lsh, tmp, lval, rval);
4102 tcg_temp_free_vec(lval);
4103 tcg_temp_free_vec(rval);
4104 tcg_temp_free_vec(lsh);
4105 tcg_temp_free_vec(rsh);
4106 tcg_temp_free_vec(tmp);
4109 void gen_gvec_sshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4110 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4112 static const TCGOpcode vecop_list[] = {
4113 INDEX_op_neg_vec, INDEX_op_umin_vec, INDEX_op_shlv_vec,
4114 INDEX_op_sarv_vec, INDEX_op_cmp_vec, INDEX_op_cmpsel_vec, 0
4116 static const GVecGen3 ops[4] = {
4117 { .fniv = gen_sshl_vec,
4118 .fno = gen_helper_gvec_sshl_b,
4119 .opt_opc = vecop_list,
4120 .vece = MO_8 },
4121 { .fniv = gen_sshl_vec,
4122 .fno = gen_helper_gvec_sshl_h,
4123 .opt_opc = vecop_list,
4124 .vece = MO_16 },
4125 { .fni4 = gen_sshl_i32,
4126 .fniv = gen_sshl_vec,
4127 .opt_opc = vecop_list,
4128 .vece = MO_32 },
4129 { .fni8 = gen_sshl_i64,
4130 .fniv = gen_sshl_vec,
4131 .opt_opc = vecop_list,
4132 .vece = MO_64 },
4134 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4137 static void gen_uqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4138 TCGv_vec a, TCGv_vec b)
4140 TCGv_vec x = tcg_temp_new_vec_matching(t);
4141 tcg_gen_add_vec(vece, x, a, b);
4142 tcg_gen_usadd_vec(vece, t, a, b);
4143 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4144 tcg_gen_or_vec(vece, sat, sat, x);
4145 tcg_temp_free_vec(x);
4148 void gen_gvec_uqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4149 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4151 static const TCGOpcode vecop_list[] = {
4152 INDEX_op_usadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
4154 static const GVecGen4 ops[4] = {
4155 { .fniv = gen_uqadd_vec,
4156 .fno = gen_helper_gvec_uqadd_b,
4157 .write_aofs = true,
4158 .opt_opc = vecop_list,
4159 .vece = MO_8 },
4160 { .fniv = gen_uqadd_vec,
4161 .fno = gen_helper_gvec_uqadd_h,
4162 .write_aofs = true,
4163 .opt_opc = vecop_list,
4164 .vece = MO_16 },
4165 { .fniv = gen_uqadd_vec,
4166 .fno = gen_helper_gvec_uqadd_s,
4167 .write_aofs = true,
4168 .opt_opc = vecop_list,
4169 .vece = MO_32 },
4170 { .fniv = gen_uqadd_vec,
4171 .fno = gen_helper_gvec_uqadd_d,
4172 .write_aofs = true,
4173 .opt_opc = vecop_list,
4174 .vece = MO_64 },
4176 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
4177 rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4180 static void gen_sqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4181 TCGv_vec a, TCGv_vec b)
4183 TCGv_vec x = tcg_temp_new_vec_matching(t);
4184 tcg_gen_add_vec(vece, x, a, b);
4185 tcg_gen_ssadd_vec(vece, t, a, b);
4186 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4187 tcg_gen_or_vec(vece, sat, sat, x);
4188 tcg_temp_free_vec(x);
4191 void gen_gvec_sqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4192 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4194 static const TCGOpcode vecop_list[] = {
4195 INDEX_op_ssadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
4197 static const GVecGen4 ops[4] = {
4198 { .fniv = gen_sqadd_vec,
4199 .fno = gen_helper_gvec_sqadd_b,
4200 .opt_opc = vecop_list,
4201 .write_aofs = true,
4202 .vece = MO_8 },
4203 { .fniv = gen_sqadd_vec,
4204 .fno = gen_helper_gvec_sqadd_h,
4205 .opt_opc = vecop_list,
4206 .write_aofs = true,
4207 .vece = MO_16 },
4208 { .fniv = gen_sqadd_vec,
4209 .fno = gen_helper_gvec_sqadd_s,
4210 .opt_opc = vecop_list,
4211 .write_aofs = true,
4212 .vece = MO_32 },
4213 { .fniv = gen_sqadd_vec,
4214 .fno = gen_helper_gvec_sqadd_d,
4215 .opt_opc = vecop_list,
4216 .write_aofs = true,
4217 .vece = MO_64 },
4219 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
4220 rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4223 static void gen_uqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4224 TCGv_vec a, TCGv_vec b)
4226 TCGv_vec x = tcg_temp_new_vec_matching(t);
4227 tcg_gen_sub_vec(vece, x, a, b);
4228 tcg_gen_ussub_vec(vece, t, a, b);
4229 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4230 tcg_gen_or_vec(vece, sat, sat, x);
4231 tcg_temp_free_vec(x);
4234 void gen_gvec_uqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4235 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4237 static const TCGOpcode vecop_list[] = {
4238 INDEX_op_ussub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
4240 static const GVecGen4 ops[4] = {
4241 { .fniv = gen_uqsub_vec,
4242 .fno = gen_helper_gvec_uqsub_b,
4243 .opt_opc = vecop_list,
4244 .write_aofs = true,
4245 .vece = MO_8 },
4246 { .fniv = gen_uqsub_vec,
4247 .fno = gen_helper_gvec_uqsub_h,
4248 .opt_opc = vecop_list,
4249 .write_aofs = true,
4250 .vece = MO_16 },
4251 { .fniv = gen_uqsub_vec,
4252 .fno = gen_helper_gvec_uqsub_s,
4253 .opt_opc = vecop_list,
4254 .write_aofs = true,
4255 .vece = MO_32 },
4256 { .fniv = gen_uqsub_vec,
4257 .fno = gen_helper_gvec_uqsub_d,
4258 .opt_opc = vecop_list,
4259 .write_aofs = true,
4260 .vece = MO_64 },
4262 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
4263 rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4266 static void gen_sqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4267 TCGv_vec a, TCGv_vec b)
4269 TCGv_vec x = tcg_temp_new_vec_matching(t);
4270 tcg_gen_sub_vec(vece, x, a, b);
4271 tcg_gen_sssub_vec(vece, t, a, b);
4272 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4273 tcg_gen_or_vec(vece, sat, sat, x);
4274 tcg_temp_free_vec(x);
4277 void gen_gvec_sqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4278 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4280 static const TCGOpcode vecop_list[] = {
4281 INDEX_op_sssub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
4283 static const GVecGen4 ops[4] = {
4284 { .fniv = gen_sqsub_vec,
4285 .fno = gen_helper_gvec_sqsub_b,
4286 .opt_opc = vecop_list,
4287 .write_aofs = true,
4288 .vece = MO_8 },
4289 { .fniv = gen_sqsub_vec,
4290 .fno = gen_helper_gvec_sqsub_h,
4291 .opt_opc = vecop_list,
4292 .write_aofs = true,
4293 .vece = MO_16 },
4294 { .fniv = gen_sqsub_vec,
4295 .fno = gen_helper_gvec_sqsub_s,
4296 .opt_opc = vecop_list,
4297 .write_aofs = true,
4298 .vece = MO_32 },
4299 { .fniv = gen_sqsub_vec,
4300 .fno = gen_helper_gvec_sqsub_d,
4301 .opt_opc = vecop_list,
4302 .write_aofs = true,
4303 .vece = MO_64 },
4305 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
4306 rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4309 static void gen_sabd_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4311 TCGv_i32 t = tcg_temp_new_i32();
4313 tcg_gen_sub_i32(t, a, b);
4314 tcg_gen_sub_i32(d, b, a);
4315 tcg_gen_movcond_i32(TCG_COND_LT, d, a, b, d, t);
4316 tcg_temp_free_i32(t);
4319 static void gen_sabd_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4321 TCGv_i64 t = tcg_temp_new_i64();
4323 tcg_gen_sub_i64(t, a, b);
4324 tcg_gen_sub_i64(d, b, a);
4325 tcg_gen_movcond_i64(TCG_COND_LT, d, a, b, d, t);
4326 tcg_temp_free_i64(t);
4329 static void gen_sabd_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4331 TCGv_vec t = tcg_temp_new_vec_matching(d);
4333 tcg_gen_smin_vec(vece, t, a, b);
4334 tcg_gen_smax_vec(vece, d, a, b);
4335 tcg_gen_sub_vec(vece, d, d, t);
4336 tcg_temp_free_vec(t);
4339 void gen_gvec_sabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4340 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4342 static const TCGOpcode vecop_list[] = {
4343 INDEX_op_sub_vec, INDEX_op_smin_vec, INDEX_op_smax_vec, 0
4345 static const GVecGen3 ops[4] = {
4346 { .fniv = gen_sabd_vec,
4347 .fno = gen_helper_gvec_sabd_b,
4348 .opt_opc = vecop_list,
4349 .vece = MO_8 },
4350 { .fniv = gen_sabd_vec,
4351 .fno = gen_helper_gvec_sabd_h,
4352 .opt_opc = vecop_list,
4353 .vece = MO_16 },
4354 { .fni4 = gen_sabd_i32,
4355 .fniv = gen_sabd_vec,
4356 .fno = gen_helper_gvec_sabd_s,
4357 .opt_opc = vecop_list,
4358 .vece = MO_32 },
4359 { .fni8 = gen_sabd_i64,
4360 .fniv = gen_sabd_vec,
4361 .fno = gen_helper_gvec_sabd_d,
4362 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4363 .opt_opc = vecop_list,
4364 .vece = MO_64 },
4366 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4369 static void gen_uabd_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4371 TCGv_i32 t = tcg_temp_new_i32();
4373 tcg_gen_sub_i32(t, a, b);
4374 tcg_gen_sub_i32(d, b, a);
4375 tcg_gen_movcond_i32(TCG_COND_LTU, d, a, b, d, t);
4376 tcg_temp_free_i32(t);
4379 static void gen_uabd_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4381 TCGv_i64 t = tcg_temp_new_i64();
4383 tcg_gen_sub_i64(t, a, b);
4384 tcg_gen_sub_i64(d, b, a);
4385 tcg_gen_movcond_i64(TCG_COND_LTU, d, a, b, d, t);
4386 tcg_temp_free_i64(t);
4389 static void gen_uabd_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4391 TCGv_vec t = tcg_temp_new_vec_matching(d);
4393 tcg_gen_umin_vec(vece, t, a, b);
4394 tcg_gen_umax_vec(vece, d, a, b);
4395 tcg_gen_sub_vec(vece, d, d, t);
4396 tcg_temp_free_vec(t);
4399 void gen_gvec_uabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4400 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4402 static const TCGOpcode vecop_list[] = {
4403 INDEX_op_sub_vec, INDEX_op_umin_vec, INDEX_op_umax_vec, 0
4405 static const GVecGen3 ops[4] = {
4406 { .fniv = gen_uabd_vec,
4407 .fno = gen_helper_gvec_uabd_b,
4408 .opt_opc = vecop_list,
4409 .vece = MO_8 },
4410 { .fniv = gen_uabd_vec,
4411 .fno = gen_helper_gvec_uabd_h,
4412 .opt_opc = vecop_list,
4413 .vece = MO_16 },
4414 { .fni4 = gen_uabd_i32,
4415 .fniv = gen_uabd_vec,
4416 .fno = gen_helper_gvec_uabd_s,
4417 .opt_opc = vecop_list,
4418 .vece = MO_32 },
4419 { .fni8 = gen_uabd_i64,
4420 .fniv = gen_uabd_vec,
4421 .fno = gen_helper_gvec_uabd_d,
4422 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4423 .opt_opc = vecop_list,
4424 .vece = MO_64 },
4426 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4429 static void gen_saba_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4431 TCGv_i32 t = tcg_temp_new_i32();
4432 gen_sabd_i32(t, a, b);
4433 tcg_gen_add_i32(d, d, t);
4434 tcg_temp_free_i32(t);
4437 static void gen_saba_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4439 TCGv_i64 t = tcg_temp_new_i64();
4440 gen_sabd_i64(t, a, b);
4441 tcg_gen_add_i64(d, d, t);
4442 tcg_temp_free_i64(t);
4445 static void gen_saba_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4447 TCGv_vec t = tcg_temp_new_vec_matching(d);
4448 gen_sabd_vec(vece, t, a, b);
4449 tcg_gen_add_vec(vece, d, d, t);
4450 tcg_temp_free_vec(t);
4453 void gen_gvec_saba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4454 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4456 static const TCGOpcode vecop_list[] = {
4457 INDEX_op_sub_vec, INDEX_op_add_vec,
4458 INDEX_op_smin_vec, INDEX_op_smax_vec, 0
4460 static const GVecGen3 ops[4] = {
4461 { .fniv = gen_saba_vec,
4462 .fno = gen_helper_gvec_saba_b,
4463 .opt_opc = vecop_list,
4464 .load_dest = true,
4465 .vece = MO_8 },
4466 { .fniv = gen_saba_vec,
4467 .fno = gen_helper_gvec_saba_h,
4468 .opt_opc = vecop_list,
4469 .load_dest = true,
4470 .vece = MO_16 },
4471 { .fni4 = gen_saba_i32,
4472 .fniv = gen_saba_vec,
4473 .fno = gen_helper_gvec_saba_s,
4474 .opt_opc = vecop_list,
4475 .load_dest = true,
4476 .vece = MO_32 },
4477 { .fni8 = gen_saba_i64,
4478 .fniv = gen_saba_vec,
4479 .fno = gen_helper_gvec_saba_d,
4480 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4481 .opt_opc = vecop_list,
4482 .load_dest = true,
4483 .vece = MO_64 },
4485 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4488 static void gen_uaba_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4490 TCGv_i32 t = tcg_temp_new_i32();
4491 gen_uabd_i32(t, a, b);
4492 tcg_gen_add_i32(d, d, t);
4493 tcg_temp_free_i32(t);
4496 static void gen_uaba_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4498 TCGv_i64 t = tcg_temp_new_i64();
4499 gen_uabd_i64(t, a, b);
4500 tcg_gen_add_i64(d, d, t);
4501 tcg_temp_free_i64(t);
4504 static void gen_uaba_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4506 TCGv_vec t = tcg_temp_new_vec_matching(d);
4507 gen_uabd_vec(vece, t, a, b);
4508 tcg_gen_add_vec(vece, d, d, t);
4509 tcg_temp_free_vec(t);
4512 void gen_gvec_uaba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4513 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4515 static const TCGOpcode vecop_list[] = {
4516 INDEX_op_sub_vec, INDEX_op_add_vec,
4517 INDEX_op_umin_vec, INDEX_op_umax_vec, 0
4519 static const GVecGen3 ops[4] = {
4520 { .fniv = gen_uaba_vec,
4521 .fno = gen_helper_gvec_uaba_b,
4522 .opt_opc = vecop_list,
4523 .load_dest = true,
4524 .vece = MO_8 },
4525 { .fniv = gen_uaba_vec,
4526 .fno = gen_helper_gvec_uaba_h,
4527 .opt_opc = vecop_list,
4528 .load_dest = true,
4529 .vece = MO_16 },
4530 { .fni4 = gen_uaba_i32,
4531 .fniv = gen_uaba_vec,
4532 .fno = gen_helper_gvec_uaba_s,
4533 .opt_opc = vecop_list,
4534 .load_dest = true,
4535 .vece = MO_32 },
4536 { .fni8 = gen_uaba_i64,
4537 .fniv = gen_uaba_vec,
4538 .fno = gen_helper_gvec_uaba_d,
4539 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4540 .opt_opc = vecop_list,
4541 .load_dest = true,
4542 .vece = MO_64 },
4544 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4547 static int disas_coproc_insn(DisasContext *s, uint32_t insn)
4549 int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
4550 const ARMCPRegInfo *ri;
4552 cpnum = (insn >> 8) & 0xf;
4554 /* First check for coprocessor space used for XScale/iwMMXt insns */
4555 if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cpnum < 2)) {
4556 if (extract32(s->c15_cpar, cpnum, 1) == 0) {
4557 return 1;
4559 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
4560 return disas_iwmmxt_insn(s, insn);
4561 } else if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) {
4562 return disas_dsp_insn(s, insn);
4564 return 1;
4567 /* Otherwise treat as a generic register access */
4568 is64 = (insn & (1 << 25)) == 0;
4569 if (!is64 && ((insn & (1 << 4)) == 0)) {
4570 /* cdp */
4571 return 1;
4574 crm = insn & 0xf;
4575 if (is64) {
4576 crn = 0;
4577 opc1 = (insn >> 4) & 0xf;
4578 opc2 = 0;
4579 rt2 = (insn >> 16) & 0xf;
4580 } else {
4581 crn = (insn >> 16) & 0xf;
4582 opc1 = (insn >> 21) & 7;
4583 opc2 = (insn >> 5) & 7;
4584 rt2 = 0;
4586 isread = (insn >> 20) & 1;
4587 rt = (insn >> 12) & 0xf;
4589 ri = get_arm_cp_reginfo(s->cp_regs,
4590 ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2));
4591 if (ri) {
4592 bool need_exit_tb;
4594 /* Check access permissions */
4595 if (!cp_access_ok(s->current_el, ri, isread)) {
4596 return 1;
4599 if (s->hstr_active || ri->accessfn ||
4600 (arm_dc_feature(s, ARM_FEATURE_XSCALE) && cpnum < 14)) {
4601 /* Emit code to perform further access permissions checks at
4602 * runtime; this may result in an exception.
4603 * Note that on XScale all cp0..c13 registers do an access check
4604 * call in order to handle c15_cpar.
4606 TCGv_ptr tmpptr;
4607 TCGv_i32 tcg_syn, tcg_isread;
4608 uint32_t syndrome;
4610 /* Note that since we are an implementation which takes an
4611 * exception on a trapped conditional instruction only if the
4612 * instruction passes its condition code check, we can take
4613 * advantage of the clause in the ARM ARM that allows us to set
4614 * the COND field in the instruction to 0xE in all cases.
4615 * We could fish the actual condition out of the insn (ARM)
4616 * or the condexec bits (Thumb) but it isn't necessary.
4618 switch (cpnum) {
4619 case 14:
4620 if (is64) {
4621 syndrome = syn_cp14_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
4622 isread, false);
4623 } else {
4624 syndrome = syn_cp14_rt_trap(1, 0xe, opc1, opc2, crn, crm,
4625 rt, isread, false);
4627 break;
4628 case 15:
4629 if (is64) {
4630 syndrome = syn_cp15_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
4631 isread, false);
4632 } else {
4633 syndrome = syn_cp15_rt_trap(1, 0xe, opc1, opc2, crn, crm,
4634 rt, isread, false);
4636 break;
4637 default:
4638 /* ARMv8 defines that only coprocessors 14 and 15 exist,
4639 * so this can only happen if this is an ARMv7 or earlier CPU,
4640 * in which case the syndrome information won't actually be
4641 * guest visible.
4643 assert(!arm_dc_feature(s, ARM_FEATURE_V8));
4644 syndrome = syn_uncategorized();
4645 break;
4648 gen_set_condexec(s);
4649 gen_set_pc_im(s, s->pc_curr);
4650 tmpptr = tcg_const_ptr(ri);
4651 tcg_syn = tcg_const_i32(syndrome);
4652 tcg_isread = tcg_const_i32(isread);
4653 gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn,
4654 tcg_isread);
4655 tcg_temp_free_ptr(tmpptr);
4656 tcg_temp_free_i32(tcg_syn);
4657 tcg_temp_free_i32(tcg_isread);
4658 } else if (ri->type & ARM_CP_RAISES_EXC) {
4660 * The readfn or writefn might raise an exception;
4661 * synchronize the CPU state in case it does.
4663 gen_set_condexec(s);
4664 gen_set_pc_im(s, s->pc_curr);
4667 /* Handle special cases first */
4668 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
4669 case ARM_CP_NOP:
4670 return 0;
4671 case ARM_CP_WFI:
4672 if (isread) {
4673 return 1;
4675 gen_set_pc_im(s, s->base.pc_next);
4676 s->base.is_jmp = DISAS_WFI;
4677 return 0;
4678 default:
4679 break;
4682 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
4683 gen_io_start();
4686 if (isread) {
4687 /* Read */
4688 if (is64) {
4689 TCGv_i64 tmp64;
4690 TCGv_i32 tmp;
4691 if (ri->type & ARM_CP_CONST) {
4692 tmp64 = tcg_const_i64(ri->resetvalue);
4693 } else if (ri->readfn) {
4694 TCGv_ptr tmpptr;
4695 tmp64 = tcg_temp_new_i64();
4696 tmpptr = tcg_const_ptr(ri);
4697 gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr);
4698 tcg_temp_free_ptr(tmpptr);
4699 } else {
4700 tmp64 = tcg_temp_new_i64();
4701 tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
4703 tmp = tcg_temp_new_i32();
4704 tcg_gen_extrl_i64_i32(tmp, tmp64);
4705 store_reg(s, rt, tmp);
4706 tmp = tcg_temp_new_i32();
4707 tcg_gen_extrh_i64_i32(tmp, tmp64);
4708 tcg_temp_free_i64(tmp64);
4709 store_reg(s, rt2, tmp);
4710 } else {
4711 TCGv_i32 tmp;
4712 if (ri->type & ARM_CP_CONST) {
4713 tmp = tcg_const_i32(ri->resetvalue);
4714 } else if (ri->readfn) {
4715 TCGv_ptr tmpptr;
4716 tmp = tcg_temp_new_i32();
4717 tmpptr = tcg_const_ptr(ri);
4718 gen_helper_get_cp_reg(tmp, cpu_env, tmpptr);
4719 tcg_temp_free_ptr(tmpptr);
4720 } else {
4721 tmp = load_cpu_offset(ri->fieldoffset);
4723 if (rt == 15) {
4724 /* Destination register of r15 for 32 bit loads sets
4725 * the condition codes from the high 4 bits of the value
4727 gen_set_nzcv(tmp);
4728 tcg_temp_free_i32(tmp);
4729 } else {
4730 store_reg(s, rt, tmp);
4733 } else {
4734 /* Write */
4735 if (ri->type & ARM_CP_CONST) {
4736 /* If not forbidden by access permissions, treat as WI */
4737 return 0;
4740 if (is64) {
4741 TCGv_i32 tmplo, tmphi;
4742 TCGv_i64 tmp64 = tcg_temp_new_i64();
4743 tmplo = load_reg(s, rt);
4744 tmphi = load_reg(s, rt2);
4745 tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
4746 tcg_temp_free_i32(tmplo);
4747 tcg_temp_free_i32(tmphi);
4748 if (ri->writefn) {
4749 TCGv_ptr tmpptr = tcg_const_ptr(ri);
4750 gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64);
4751 tcg_temp_free_ptr(tmpptr);
4752 } else {
4753 tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
4755 tcg_temp_free_i64(tmp64);
4756 } else {
4757 if (ri->writefn) {
4758 TCGv_i32 tmp;
4759 TCGv_ptr tmpptr;
4760 tmp = load_reg(s, rt);
4761 tmpptr = tcg_const_ptr(ri);
4762 gen_helper_set_cp_reg(cpu_env, tmpptr, tmp);
4763 tcg_temp_free_ptr(tmpptr);
4764 tcg_temp_free_i32(tmp);
4765 } else {
4766 TCGv_i32 tmp = load_reg(s, rt);
4767 store_cpu_offset(tmp, ri->fieldoffset);
4772 /* I/O operations must end the TB here (whether read or write) */
4773 need_exit_tb = ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) &&
4774 (ri->type & ARM_CP_IO));
4776 if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
4778 * A write to any coprocessor register that ends a TB
4779 * must rebuild the hflags for the next TB.
4781 TCGv_i32 tcg_el = tcg_const_i32(s->current_el);
4782 if (arm_dc_feature(s, ARM_FEATURE_M)) {
4783 gen_helper_rebuild_hflags_m32(cpu_env, tcg_el);
4784 } else {
4785 if (ri->type & ARM_CP_NEWEL) {
4786 gen_helper_rebuild_hflags_a32_newel(cpu_env);
4787 } else {
4788 gen_helper_rebuild_hflags_a32(cpu_env, tcg_el);
4791 tcg_temp_free_i32(tcg_el);
4793 * We default to ending the TB on a coprocessor register write,
4794 * but allow this to be suppressed by the register definition
4795 * (usually only necessary to work around guest bugs).
4797 need_exit_tb = true;
4799 if (need_exit_tb) {
4800 gen_lookup_tb(s);
4803 return 0;
4806 /* Unknown register; this might be a guest error or a QEMU
4807 * unimplemented feature.
4809 if (is64) {
4810 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
4811 "64 bit system register cp:%d opc1: %d crm:%d "
4812 "(%s)\n",
4813 isread ? "read" : "write", cpnum, opc1, crm,
4814 s->ns ? "non-secure" : "secure");
4815 } else {
4816 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
4817 "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d "
4818 "(%s)\n",
4819 isread ? "read" : "write", cpnum, opc1, crn, crm, opc2,
4820 s->ns ? "non-secure" : "secure");
4823 return 1;
4827 /* Store a 64-bit value to a register pair. Clobbers val. */
4828 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
4830 TCGv_i32 tmp;
4831 tmp = tcg_temp_new_i32();
4832 tcg_gen_extrl_i64_i32(tmp, val);
4833 store_reg(s, rlow, tmp);
4834 tmp = tcg_temp_new_i32();
4835 tcg_gen_extrh_i64_i32(tmp, val);
4836 store_reg(s, rhigh, tmp);
4839 /* load and add a 64-bit value from a register pair. */
4840 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
4842 TCGv_i64 tmp;
4843 TCGv_i32 tmpl;
4844 TCGv_i32 tmph;
4846 /* Load 64-bit value rd:rn. */
4847 tmpl = load_reg(s, rlow);
4848 tmph = load_reg(s, rhigh);
4849 tmp = tcg_temp_new_i64();
4850 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
4851 tcg_temp_free_i32(tmpl);
4852 tcg_temp_free_i32(tmph);
4853 tcg_gen_add_i64(val, val, tmp);
4854 tcg_temp_free_i64(tmp);
4857 /* Set N and Z flags from hi|lo. */
4858 static void gen_logicq_cc(TCGv_i32 lo, TCGv_i32 hi)
4860 tcg_gen_mov_i32(cpu_NF, hi);
4861 tcg_gen_or_i32(cpu_ZF, lo, hi);
4864 /* Load/Store exclusive instructions are implemented by remembering
4865 the value/address loaded, and seeing if these are the same
4866 when the store is performed. This should be sufficient to implement
4867 the architecturally mandated semantics, and avoids having to monitor
4868 regular stores. The compare vs the remembered value is done during
4869 the cmpxchg operation, but we must compare the addresses manually. */
4870 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
4871 TCGv_i32 addr, int size)
4873 TCGv_i32 tmp = tcg_temp_new_i32();
4874 MemOp opc = size | MO_ALIGN | s->be_data;
4876 s->is_ldex = true;
4878 if (size == 3) {
4879 TCGv_i32 tmp2 = tcg_temp_new_i32();
4880 TCGv_i64 t64 = tcg_temp_new_i64();
4882 /* For AArch32, architecturally the 32-bit word at the lowest
4883 * address is always Rt and the one at addr+4 is Rt2, even if
4884 * the CPU is big-endian. That means we don't want to do a
4885 * gen_aa32_ld_i64(), which invokes gen_aa32_frob64() as if
4886 * for an architecturally 64-bit access, but instead do a
4887 * 64-bit access using MO_BE if appropriate and then split
4888 * the two halves.
4889 * This only makes a difference for BE32 user-mode, where
4890 * frob64() must not flip the two halves of the 64-bit data
4891 * but this code must treat BE32 user-mode like BE32 system.
4893 TCGv taddr = gen_aa32_addr(s, addr, opc);
4895 tcg_gen_qemu_ld_i64(t64, taddr, get_mem_index(s), opc);
4896 tcg_temp_free(taddr);
4897 tcg_gen_mov_i64(cpu_exclusive_val, t64);
4898 if (s->be_data == MO_BE) {
4899 tcg_gen_extr_i64_i32(tmp2, tmp, t64);
4900 } else {
4901 tcg_gen_extr_i64_i32(tmp, tmp2, t64);
4903 tcg_temp_free_i64(t64);
4905 store_reg(s, rt2, tmp2);
4906 } else {
4907 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), opc);
4908 tcg_gen_extu_i32_i64(cpu_exclusive_val, tmp);
4911 store_reg(s, rt, tmp);
4912 tcg_gen_extu_i32_i64(cpu_exclusive_addr, addr);
4915 static void gen_clrex(DisasContext *s)
4917 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
4920 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
4921 TCGv_i32 addr, int size)
4923 TCGv_i32 t0, t1, t2;
4924 TCGv_i64 extaddr;
4925 TCGv taddr;
4926 TCGLabel *done_label;
4927 TCGLabel *fail_label;
4928 MemOp opc = size | MO_ALIGN | s->be_data;
4930 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
4931 [addr] = {Rt};
4932 {Rd} = 0;
4933 } else {
4934 {Rd} = 1;
4935 } */
4936 fail_label = gen_new_label();
4937 done_label = gen_new_label();
4938 extaddr = tcg_temp_new_i64();
4939 tcg_gen_extu_i32_i64(extaddr, addr);
4940 tcg_gen_brcond_i64(TCG_COND_NE, extaddr, cpu_exclusive_addr, fail_label);
4941 tcg_temp_free_i64(extaddr);
4943 taddr = gen_aa32_addr(s, addr, opc);
4944 t0 = tcg_temp_new_i32();
4945 t1 = load_reg(s, rt);
4946 if (size == 3) {
4947 TCGv_i64 o64 = tcg_temp_new_i64();
4948 TCGv_i64 n64 = tcg_temp_new_i64();
4950 t2 = load_reg(s, rt2);
4951 /* For AArch32, architecturally the 32-bit word at the lowest
4952 * address is always Rt and the one at addr+4 is Rt2, even if
4953 * the CPU is big-endian. Since we're going to treat this as a
4954 * single 64-bit BE store, we need to put the two halves in the
4955 * opposite order for BE to LE, so that they end up in the right
4956 * places.
4957 * We don't want gen_aa32_frob64() because that does the wrong
4958 * thing for BE32 usermode.
4960 if (s->be_data == MO_BE) {
4961 tcg_gen_concat_i32_i64(n64, t2, t1);
4962 } else {
4963 tcg_gen_concat_i32_i64(n64, t1, t2);
4965 tcg_temp_free_i32(t2);
4967 tcg_gen_atomic_cmpxchg_i64(o64, taddr, cpu_exclusive_val, n64,
4968 get_mem_index(s), opc);
4969 tcg_temp_free_i64(n64);
4971 tcg_gen_setcond_i64(TCG_COND_NE, o64, o64, cpu_exclusive_val);
4972 tcg_gen_extrl_i64_i32(t0, o64);
4974 tcg_temp_free_i64(o64);
4975 } else {
4976 t2 = tcg_temp_new_i32();
4977 tcg_gen_extrl_i64_i32(t2, cpu_exclusive_val);
4978 tcg_gen_atomic_cmpxchg_i32(t0, taddr, t2, t1, get_mem_index(s), opc);
4979 tcg_gen_setcond_i32(TCG_COND_NE, t0, t0, t2);
4980 tcg_temp_free_i32(t2);
4982 tcg_temp_free_i32(t1);
4983 tcg_temp_free(taddr);
4984 tcg_gen_mov_i32(cpu_R[rd], t0);
4985 tcg_temp_free_i32(t0);
4986 tcg_gen_br(done_label);
4988 gen_set_label(fail_label);
4989 tcg_gen_movi_i32(cpu_R[rd], 1);
4990 gen_set_label(done_label);
4991 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
4994 /* gen_srs:
4995 * @env: CPUARMState
4996 * @s: DisasContext
4997 * @mode: mode field from insn (which stack to store to)
4998 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
4999 * @writeback: true if writeback bit set
5001 * Generate code for the SRS (Store Return State) insn.
5003 static void gen_srs(DisasContext *s,
5004 uint32_t mode, uint32_t amode, bool writeback)
5006 int32_t offset;
5007 TCGv_i32 addr, tmp;
5008 bool undef = false;
5010 /* SRS is:
5011 * - trapped to EL3 if EL3 is AArch64 and we are at Secure EL1
5012 * and specified mode is monitor mode
5013 * - UNDEFINED in Hyp mode
5014 * - UNPREDICTABLE in User or System mode
5015 * - UNPREDICTABLE if the specified mode is:
5016 * -- not implemented
5017 * -- not a valid mode number
5018 * -- a mode that's at a higher exception level
5019 * -- Monitor, if we are Non-secure
5020 * For the UNPREDICTABLE cases we choose to UNDEF.
5022 if (s->current_el == 1 && !s->ns && mode == ARM_CPU_MODE_MON) {
5023 gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(), 3);
5024 return;
5027 if (s->current_el == 0 || s->current_el == 2) {
5028 undef = true;
5031 switch (mode) {
5032 case ARM_CPU_MODE_USR:
5033 case ARM_CPU_MODE_FIQ:
5034 case ARM_CPU_MODE_IRQ:
5035 case ARM_CPU_MODE_SVC:
5036 case ARM_CPU_MODE_ABT:
5037 case ARM_CPU_MODE_UND:
5038 case ARM_CPU_MODE_SYS:
5039 break;
5040 case ARM_CPU_MODE_HYP:
5041 if (s->current_el == 1 || !arm_dc_feature(s, ARM_FEATURE_EL2)) {
5042 undef = true;
5044 break;
5045 case ARM_CPU_MODE_MON:
5046 /* No need to check specifically for "are we non-secure" because
5047 * we've already made EL0 UNDEF and handled the trap for S-EL1;
5048 * so if this isn't EL3 then we must be non-secure.
5050 if (s->current_el != 3) {
5051 undef = true;
5053 break;
5054 default:
5055 undef = true;
5058 if (undef) {
5059 unallocated_encoding(s);
5060 return;
5063 addr = tcg_temp_new_i32();
5064 tmp = tcg_const_i32(mode);
5065 /* get_r13_banked() will raise an exception if called from System mode */
5066 gen_set_condexec(s);
5067 gen_set_pc_im(s, s->pc_curr);
5068 gen_helper_get_r13_banked(addr, cpu_env, tmp);
5069 tcg_temp_free_i32(tmp);
5070 switch (amode) {
5071 case 0: /* DA */
5072 offset = -4;
5073 break;
5074 case 1: /* IA */
5075 offset = 0;
5076 break;
5077 case 2: /* DB */
5078 offset = -8;
5079 break;
5080 case 3: /* IB */
5081 offset = 4;
5082 break;
5083 default:
5084 abort();
5086 tcg_gen_addi_i32(addr, addr, offset);
5087 tmp = load_reg(s, 14);
5088 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5089 tcg_temp_free_i32(tmp);
5090 tmp = load_cpu_field(spsr);
5091 tcg_gen_addi_i32(addr, addr, 4);
5092 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5093 tcg_temp_free_i32(tmp);
5094 if (writeback) {
5095 switch (amode) {
5096 case 0:
5097 offset = -8;
5098 break;
5099 case 1:
5100 offset = 4;
5101 break;
5102 case 2:
5103 offset = -4;
5104 break;
5105 case 3:
5106 offset = 0;
5107 break;
5108 default:
5109 abort();
5111 tcg_gen_addi_i32(addr, addr, offset);
5112 tmp = tcg_const_i32(mode);
5113 gen_helper_set_r13_banked(cpu_env, tmp, addr);
5114 tcg_temp_free_i32(tmp);
5116 tcg_temp_free_i32(addr);
5117 s->base.is_jmp = DISAS_UPDATE_EXIT;
5120 /* Generate a label used for skipping this instruction */
5121 static void arm_gen_condlabel(DisasContext *s)
5123 if (!s->condjmp) {
5124 s->condlabel = gen_new_label();
5125 s->condjmp = 1;
5129 /* Skip this instruction if the ARM condition is false */
5130 static void arm_skip_unless(DisasContext *s, uint32_t cond)
5132 arm_gen_condlabel(s);
5133 arm_gen_test_cc(cond ^ 1, s->condlabel);
5138 * Constant expanders for the decoders.
5141 static int negate(DisasContext *s, int x)
5143 return -x;
5146 static int plus_2(DisasContext *s, int x)
5148 return x + 2;
5151 static int times_2(DisasContext *s, int x)
5153 return x * 2;
5156 static int times_4(DisasContext *s, int x)
5158 return x * 4;
5161 /* Return only the rotation part of T32ExpandImm. */
5162 static int t32_expandimm_rot(DisasContext *s, int x)
5164 return x & 0xc00 ? extract32(x, 7, 5) : 0;
5167 /* Return the unrotated immediate from T32ExpandImm. */
5168 static int t32_expandimm_imm(DisasContext *s, int x)
5170 int imm = extract32(x, 0, 8);
5172 switch (extract32(x, 8, 4)) {
5173 case 0: /* XY */
5174 /* Nothing to do. */
5175 break;
5176 case 1: /* 00XY00XY */
5177 imm *= 0x00010001;
5178 break;
5179 case 2: /* XY00XY00 */
5180 imm *= 0x01000100;
5181 break;
5182 case 3: /* XYXYXYXY */
5183 imm *= 0x01010101;
5184 break;
5185 default:
5186 /* Rotated constant. */
5187 imm |= 0x80;
5188 break;
5190 return imm;
5193 static int t32_branch24(DisasContext *s, int x)
5195 /* Convert J1:J2 at x[22:21] to I2:I1, which involves I=J^~S. */
5196 x ^= !(x < 0) * (3 << 21);
5197 /* Append the final zero. */
5198 return x << 1;
5201 static int t16_setflags(DisasContext *s)
5203 return s->condexec_mask == 0;
5206 static int t16_push_list(DisasContext *s, int x)
5208 return (x & 0xff) | (x & 0x100) << (14 - 8);
5211 static int t16_pop_list(DisasContext *s, int x)
5213 return (x & 0xff) | (x & 0x100) << (15 - 8);
5217 * Include the generated decoders.
5220 #include "decode-a32.c.inc"
5221 #include "decode-a32-uncond.c.inc"
5222 #include "decode-t32.c.inc"
5223 #include "decode-t16.c.inc"
5225 /* Helpers to swap operands for reverse-subtract. */
5226 static void gen_rsb(TCGv_i32 dst, TCGv_i32 a, TCGv_i32 b)
5228 tcg_gen_sub_i32(dst, b, a);
5231 static void gen_rsb_CC(TCGv_i32 dst, TCGv_i32 a, TCGv_i32 b)
5233 gen_sub_CC(dst, b, a);
5236 static void gen_rsc(TCGv_i32 dest, TCGv_i32 a, TCGv_i32 b)
5238 gen_sub_carry(dest, b, a);
5241 static void gen_rsc_CC(TCGv_i32 dest, TCGv_i32 a, TCGv_i32 b)
5243 gen_sbc_CC(dest, b, a);
5247 * Helpers for the data processing routines.
5249 * After the computation store the results back.
5250 * This may be suppressed altogether (STREG_NONE), require a runtime
5251 * check against the stack limits (STREG_SP_CHECK), or generate an
5252 * exception return. Oh, or store into a register.
5254 * Always return true, indicating success for a trans_* function.
5256 typedef enum {
5257 STREG_NONE,
5258 STREG_NORMAL,
5259 STREG_SP_CHECK,
5260 STREG_EXC_RET,
5261 } StoreRegKind;
5263 static bool store_reg_kind(DisasContext *s, int rd,
5264 TCGv_i32 val, StoreRegKind kind)
5266 switch (kind) {
5267 case STREG_NONE:
5268 tcg_temp_free_i32(val);
5269 return true;
5270 case STREG_NORMAL:
5271 /* See ALUWritePC: Interworking only from a32 mode. */
5272 if (s->thumb) {
5273 store_reg(s, rd, val);
5274 } else {
5275 store_reg_bx(s, rd, val);
5277 return true;
5278 case STREG_SP_CHECK:
5279 store_sp_checked(s, val);
5280 return true;
5281 case STREG_EXC_RET:
5282 gen_exception_return(s, val);
5283 return true;
5285 g_assert_not_reached();
5289 * Data Processing (register)
5291 * Operate, with set flags, one register source,
5292 * one immediate shifted register source, and a destination.
5294 static bool op_s_rrr_shi(DisasContext *s, arg_s_rrr_shi *a,
5295 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32),
5296 int logic_cc, StoreRegKind kind)
5298 TCGv_i32 tmp1, tmp2;
5300 tmp2 = load_reg(s, a->rm);
5301 gen_arm_shift_im(tmp2, a->shty, a->shim, logic_cc);
5302 tmp1 = load_reg(s, a->rn);
5304 gen(tmp1, tmp1, tmp2);
5305 tcg_temp_free_i32(tmp2);
5307 if (logic_cc) {
5308 gen_logic_CC(tmp1);
5310 return store_reg_kind(s, a->rd, tmp1, kind);
5313 static bool op_s_rxr_shi(DisasContext *s, arg_s_rrr_shi *a,
5314 void (*gen)(TCGv_i32, TCGv_i32),
5315 int logic_cc, StoreRegKind kind)
5317 TCGv_i32 tmp;
5319 tmp = load_reg(s, a->rm);
5320 gen_arm_shift_im(tmp, a->shty, a->shim, logic_cc);
5322 gen(tmp, tmp);
5323 if (logic_cc) {
5324 gen_logic_CC(tmp);
5326 return store_reg_kind(s, a->rd, tmp, kind);
5330 * Data-processing (register-shifted register)
5332 * Operate, with set flags, one register source,
5333 * one register shifted register source, and a destination.
5335 static bool op_s_rrr_shr(DisasContext *s, arg_s_rrr_shr *a,
5336 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32),
5337 int logic_cc, StoreRegKind kind)
5339 TCGv_i32 tmp1, tmp2;
5341 tmp1 = load_reg(s, a->rs);
5342 tmp2 = load_reg(s, a->rm);
5343 gen_arm_shift_reg(tmp2, a->shty, tmp1, logic_cc);
5344 tmp1 = load_reg(s, a->rn);
5346 gen(tmp1, tmp1, tmp2);
5347 tcg_temp_free_i32(tmp2);
5349 if (logic_cc) {
5350 gen_logic_CC(tmp1);
5352 return store_reg_kind(s, a->rd, tmp1, kind);
5355 static bool op_s_rxr_shr(DisasContext *s, arg_s_rrr_shr *a,
5356 void (*gen)(TCGv_i32, TCGv_i32),
5357 int logic_cc, StoreRegKind kind)
5359 TCGv_i32 tmp1, tmp2;
5361 tmp1 = load_reg(s, a->rs);
5362 tmp2 = load_reg(s, a->rm);
5363 gen_arm_shift_reg(tmp2, a->shty, tmp1, logic_cc);
5365 gen(tmp2, tmp2);
5366 if (logic_cc) {
5367 gen_logic_CC(tmp2);
5369 return store_reg_kind(s, a->rd, tmp2, kind);
5373 * Data-processing (immediate)
5375 * Operate, with set flags, one register source,
5376 * one rotated immediate, and a destination.
5378 * Note that logic_cc && a->rot setting CF based on the msb of the
5379 * immediate is the reason why we must pass in the unrotated form
5380 * of the immediate.
5382 static bool op_s_rri_rot(DisasContext *s, arg_s_rri_rot *a,
5383 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32),
5384 int logic_cc, StoreRegKind kind)
5386 TCGv_i32 tmp1, tmp2;
5387 uint32_t imm;
5389 imm = ror32(a->imm, a->rot);
5390 if (logic_cc && a->rot) {
5391 tcg_gen_movi_i32(cpu_CF, imm >> 31);
5393 tmp2 = tcg_const_i32(imm);
5394 tmp1 = load_reg(s, a->rn);
5396 gen(tmp1, tmp1, tmp2);
5397 tcg_temp_free_i32(tmp2);
5399 if (logic_cc) {
5400 gen_logic_CC(tmp1);
5402 return store_reg_kind(s, a->rd, tmp1, kind);
5405 static bool op_s_rxi_rot(DisasContext *s, arg_s_rri_rot *a,
5406 void (*gen)(TCGv_i32, TCGv_i32),
5407 int logic_cc, StoreRegKind kind)
5409 TCGv_i32 tmp;
5410 uint32_t imm;
5412 imm = ror32(a->imm, a->rot);
5413 if (logic_cc && a->rot) {
5414 tcg_gen_movi_i32(cpu_CF, imm >> 31);
5416 tmp = tcg_const_i32(imm);
5418 gen(tmp, tmp);
5419 if (logic_cc) {
5420 gen_logic_CC(tmp);
5422 return store_reg_kind(s, a->rd, tmp, kind);
5425 #define DO_ANY3(NAME, OP, L, K) \
5426 static bool trans_##NAME##_rrri(DisasContext *s, arg_s_rrr_shi *a) \
5427 { StoreRegKind k = (K); return op_s_rrr_shi(s, a, OP, L, k); } \
5428 static bool trans_##NAME##_rrrr(DisasContext *s, arg_s_rrr_shr *a) \
5429 { StoreRegKind k = (K); return op_s_rrr_shr(s, a, OP, L, k); } \
5430 static bool trans_##NAME##_rri(DisasContext *s, arg_s_rri_rot *a) \
5431 { StoreRegKind k = (K); return op_s_rri_rot(s, a, OP, L, k); }
5433 #define DO_ANY2(NAME, OP, L, K) \
5434 static bool trans_##NAME##_rxri(DisasContext *s, arg_s_rrr_shi *a) \
5435 { StoreRegKind k = (K); return op_s_rxr_shi(s, a, OP, L, k); } \
5436 static bool trans_##NAME##_rxrr(DisasContext *s, arg_s_rrr_shr *a) \
5437 { StoreRegKind k = (K); return op_s_rxr_shr(s, a, OP, L, k); } \
5438 static bool trans_##NAME##_rxi(DisasContext *s, arg_s_rri_rot *a) \
5439 { StoreRegKind k = (K); return op_s_rxi_rot(s, a, OP, L, k); }
5441 #define DO_CMP2(NAME, OP, L) \
5442 static bool trans_##NAME##_xrri(DisasContext *s, arg_s_rrr_shi *a) \
5443 { return op_s_rrr_shi(s, a, OP, L, STREG_NONE); } \
5444 static bool trans_##NAME##_xrrr(DisasContext *s, arg_s_rrr_shr *a) \
5445 { return op_s_rrr_shr(s, a, OP, L, STREG_NONE); } \
5446 static bool trans_##NAME##_xri(DisasContext *s, arg_s_rri_rot *a) \
5447 { return op_s_rri_rot(s, a, OP, L, STREG_NONE); }
5449 DO_ANY3(AND, tcg_gen_and_i32, a->s, STREG_NORMAL)
5450 DO_ANY3(EOR, tcg_gen_xor_i32, a->s, STREG_NORMAL)
5451 DO_ANY3(ORR, tcg_gen_or_i32, a->s, STREG_NORMAL)
5452 DO_ANY3(BIC, tcg_gen_andc_i32, a->s, STREG_NORMAL)
5454 DO_ANY3(RSB, a->s ? gen_rsb_CC : gen_rsb, false, STREG_NORMAL)
5455 DO_ANY3(ADC, a->s ? gen_adc_CC : gen_add_carry, false, STREG_NORMAL)
5456 DO_ANY3(SBC, a->s ? gen_sbc_CC : gen_sub_carry, false, STREG_NORMAL)
5457 DO_ANY3(RSC, a->s ? gen_rsc_CC : gen_rsc, false, STREG_NORMAL)
5459 DO_CMP2(TST, tcg_gen_and_i32, true)
5460 DO_CMP2(TEQ, tcg_gen_xor_i32, true)
5461 DO_CMP2(CMN, gen_add_CC, false)
5462 DO_CMP2(CMP, gen_sub_CC, false)
5464 DO_ANY3(ADD, a->s ? gen_add_CC : tcg_gen_add_i32, false,
5465 a->rd == 13 && a->rn == 13 ? STREG_SP_CHECK : STREG_NORMAL)
5468 * Note for the computation of StoreRegKind we return out of the
5469 * middle of the functions that are expanded by DO_ANY3, and that
5470 * we modify a->s via that parameter before it is used by OP.
5472 DO_ANY3(SUB, a->s ? gen_sub_CC : tcg_gen_sub_i32, false,
5474 StoreRegKind ret = STREG_NORMAL;
5475 if (a->rd == 15 && a->s) {
5477 * See ALUExceptionReturn:
5478 * In User mode, UNPREDICTABLE; we choose UNDEF.
5479 * In Hyp mode, UNDEFINED.
5481 if (IS_USER(s) || s->current_el == 2) {
5482 unallocated_encoding(s);
5483 return true;
5485 /* There is no writeback of nzcv to PSTATE. */
5486 a->s = 0;
5487 ret = STREG_EXC_RET;
5488 } else if (a->rd == 13 && a->rn == 13) {
5489 ret = STREG_SP_CHECK;
5491 ret;
5494 DO_ANY2(MOV, tcg_gen_mov_i32, a->s,
5496 StoreRegKind ret = STREG_NORMAL;
5497 if (a->rd == 15 && a->s) {
5499 * See ALUExceptionReturn:
5500 * In User mode, UNPREDICTABLE; we choose UNDEF.
5501 * In Hyp mode, UNDEFINED.
5503 if (IS_USER(s) || s->current_el == 2) {
5504 unallocated_encoding(s);
5505 return true;
5507 /* There is no writeback of nzcv to PSTATE. */
5508 a->s = 0;
5509 ret = STREG_EXC_RET;
5510 } else if (a->rd == 13) {
5511 ret = STREG_SP_CHECK;
5513 ret;
5516 DO_ANY2(MVN, tcg_gen_not_i32, a->s, STREG_NORMAL)
5519 * ORN is only available with T32, so there is no register-shifted-register
5520 * form of the insn. Using the DO_ANY3 macro would create an unused function.
5522 static bool trans_ORN_rrri(DisasContext *s, arg_s_rrr_shi *a)
5524 return op_s_rrr_shi(s, a, tcg_gen_orc_i32, a->s, STREG_NORMAL);
5527 static bool trans_ORN_rri(DisasContext *s, arg_s_rri_rot *a)
5529 return op_s_rri_rot(s, a, tcg_gen_orc_i32, a->s, STREG_NORMAL);
5532 #undef DO_ANY3
5533 #undef DO_ANY2
5534 #undef DO_CMP2
5536 static bool trans_ADR(DisasContext *s, arg_ri *a)
5538 store_reg_bx(s, a->rd, add_reg_for_lit(s, 15, a->imm));
5539 return true;
5542 static bool trans_MOVW(DisasContext *s, arg_MOVW *a)
5544 TCGv_i32 tmp;
5546 if (!ENABLE_ARCH_6T2) {
5547 return false;
5550 tmp = tcg_const_i32(a->imm);
5551 store_reg(s, a->rd, tmp);
5552 return true;
5555 static bool trans_MOVT(DisasContext *s, arg_MOVW *a)
5557 TCGv_i32 tmp;
5559 if (!ENABLE_ARCH_6T2) {
5560 return false;
5563 tmp = load_reg(s, a->rd);
5564 tcg_gen_ext16u_i32(tmp, tmp);
5565 tcg_gen_ori_i32(tmp, tmp, a->imm << 16);
5566 store_reg(s, a->rd, tmp);
5567 return true;
5571 * Multiply and multiply accumulate
5574 static bool op_mla(DisasContext *s, arg_s_rrrr *a, bool add)
5576 TCGv_i32 t1, t2;
5578 t1 = load_reg(s, a->rn);
5579 t2 = load_reg(s, a->rm);
5580 tcg_gen_mul_i32(t1, t1, t2);
5581 tcg_temp_free_i32(t2);
5582 if (add) {
5583 t2 = load_reg(s, a->ra);
5584 tcg_gen_add_i32(t1, t1, t2);
5585 tcg_temp_free_i32(t2);
5587 if (a->s) {
5588 gen_logic_CC(t1);
5590 store_reg(s, a->rd, t1);
5591 return true;
5594 static bool trans_MUL(DisasContext *s, arg_MUL *a)
5596 return op_mla(s, a, false);
5599 static bool trans_MLA(DisasContext *s, arg_MLA *a)
5601 return op_mla(s, a, true);
5604 static bool trans_MLS(DisasContext *s, arg_MLS *a)
5606 TCGv_i32 t1, t2;
5608 if (!ENABLE_ARCH_6T2) {
5609 return false;
5611 t1 = load_reg(s, a->rn);
5612 t2 = load_reg(s, a->rm);
5613 tcg_gen_mul_i32(t1, t1, t2);
5614 tcg_temp_free_i32(t2);
5615 t2 = load_reg(s, a->ra);
5616 tcg_gen_sub_i32(t1, t2, t1);
5617 tcg_temp_free_i32(t2);
5618 store_reg(s, a->rd, t1);
5619 return true;
5622 static bool op_mlal(DisasContext *s, arg_s_rrrr *a, bool uns, bool add)
5624 TCGv_i32 t0, t1, t2, t3;
5626 t0 = load_reg(s, a->rm);
5627 t1 = load_reg(s, a->rn);
5628 if (uns) {
5629 tcg_gen_mulu2_i32(t0, t1, t0, t1);
5630 } else {
5631 tcg_gen_muls2_i32(t0, t1, t0, t1);
5633 if (add) {
5634 t2 = load_reg(s, a->ra);
5635 t3 = load_reg(s, a->rd);
5636 tcg_gen_add2_i32(t0, t1, t0, t1, t2, t3);
5637 tcg_temp_free_i32(t2);
5638 tcg_temp_free_i32(t3);
5640 if (a->s) {
5641 gen_logicq_cc(t0, t1);
5643 store_reg(s, a->ra, t0);
5644 store_reg(s, a->rd, t1);
5645 return true;
5648 static bool trans_UMULL(DisasContext *s, arg_UMULL *a)
5650 return op_mlal(s, a, true, false);
5653 static bool trans_SMULL(DisasContext *s, arg_SMULL *a)
5655 return op_mlal(s, a, false, false);
5658 static bool trans_UMLAL(DisasContext *s, arg_UMLAL *a)
5660 return op_mlal(s, a, true, true);
5663 static bool trans_SMLAL(DisasContext *s, arg_SMLAL *a)
5665 return op_mlal(s, a, false, true);
5668 static bool trans_UMAAL(DisasContext *s, arg_UMAAL *a)
5670 TCGv_i32 t0, t1, t2, zero;
5672 if (s->thumb
5673 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
5674 : !ENABLE_ARCH_6) {
5675 return false;
5678 t0 = load_reg(s, a->rm);
5679 t1 = load_reg(s, a->rn);
5680 tcg_gen_mulu2_i32(t0, t1, t0, t1);
5681 zero = tcg_const_i32(0);
5682 t2 = load_reg(s, a->ra);
5683 tcg_gen_add2_i32(t0, t1, t0, t1, t2, zero);
5684 tcg_temp_free_i32(t2);
5685 t2 = load_reg(s, a->rd);
5686 tcg_gen_add2_i32(t0, t1, t0, t1, t2, zero);
5687 tcg_temp_free_i32(t2);
5688 tcg_temp_free_i32(zero);
5689 store_reg(s, a->ra, t0);
5690 store_reg(s, a->rd, t1);
5691 return true;
5695 * Saturating addition and subtraction
5698 static bool op_qaddsub(DisasContext *s, arg_rrr *a, bool add, bool doub)
5700 TCGv_i32 t0, t1;
5702 if (s->thumb
5703 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
5704 : !ENABLE_ARCH_5TE) {
5705 return false;
5708 t0 = load_reg(s, a->rm);
5709 t1 = load_reg(s, a->rn);
5710 if (doub) {
5711 gen_helper_add_saturate(t1, cpu_env, t1, t1);
5713 if (add) {
5714 gen_helper_add_saturate(t0, cpu_env, t0, t1);
5715 } else {
5716 gen_helper_sub_saturate(t0, cpu_env, t0, t1);
5718 tcg_temp_free_i32(t1);
5719 store_reg(s, a->rd, t0);
5720 return true;
5723 #define DO_QADDSUB(NAME, ADD, DOUB) \
5724 static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
5726 return op_qaddsub(s, a, ADD, DOUB); \
5729 DO_QADDSUB(QADD, true, false)
5730 DO_QADDSUB(QSUB, false, false)
5731 DO_QADDSUB(QDADD, true, true)
5732 DO_QADDSUB(QDSUB, false, true)
5734 #undef DO_QADDSUB
5737 * Halfword multiply and multiply accumulate
5740 static bool op_smlaxxx(DisasContext *s, arg_rrrr *a,
5741 int add_long, bool nt, bool mt)
5743 TCGv_i32 t0, t1, tl, th;
5745 if (s->thumb
5746 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
5747 : !ENABLE_ARCH_5TE) {
5748 return false;
5751 t0 = load_reg(s, a->rn);
5752 t1 = load_reg(s, a->rm);
5753 gen_mulxy(t0, t1, nt, mt);
5754 tcg_temp_free_i32(t1);
5756 switch (add_long) {
5757 case 0:
5758 store_reg(s, a->rd, t0);
5759 break;
5760 case 1:
5761 t1 = load_reg(s, a->ra);
5762 gen_helper_add_setq(t0, cpu_env, t0, t1);
5763 tcg_temp_free_i32(t1);
5764 store_reg(s, a->rd, t0);
5765 break;
5766 case 2:
5767 tl = load_reg(s, a->ra);
5768 th = load_reg(s, a->rd);
5769 /* Sign-extend the 32-bit product to 64 bits. */
5770 t1 = tcg_temp_new_i32();
5771 tcg_gen_sari_i32(t1, t0, 31);
5772 tcg_gen_add2_i32(tl, th, tl, th, t0, t1);
5773 tcg_temp_free_i32(t0);
5774 tcg_temp_free_i32(t1);
5775 store_reg(s, a->ra, tl);
5776 store_reg(s, a->rd, th);
5777 break;
5778 default:
5779 g_assert_not_reached();
5781 return true;
5784 #define DO_SMLAX(NAME, add, nt, mt) \
5785 static bool trans_##NAME(DisasContext *s, arg_rrrr *a) \
5787 return op_smlaxxx(s, a, add, nt, mt); \
5790 DO_SMLAX(SMULBB, 0, 0, 0)
5791 DO_SMLAX(SMULBT, 0, 0, 1)
5792 DO_SMLAX(SMULTB, 0, 1, 0)
5793 DO_SMLAX(SMULTT, 0, 1, 1)
5795 DO_SMLAX(SMLABB, 1, 0, 0)
5796 DO_SMLAX(SMLABT, 1, 0, 1)
5797 DO_SMLAX(SMLATB, 1, 1, 0)
5798 DO_SMLAX(SMLATT, 1, 1, 1)
5800 DO_SMLAX(SMLALBB, 2, 0, 0)
5801 DO_SMLAX(SMLALBT, 2, 0, 1)
5802 DO_SMLAX(SMLALTB, 2, 1, 0)
5803 DO_SMLAX(SMLALTT, 2, 1, 1)
5805 #undef DO_SMLAX
5807 static bool op_smlawx(DisasContext *s, arg_rrrr *a, bool add, bool mt)
5809 TCGv_i32 t0, t1;
5811 if (!ENABLE_ARCH_5TE) {
5812 return false;
5815 t0 = load_reg(s, a->rn);
5816 t1 = load_reg(s, a->rm);
5818 * Since the nominal result is product<47:16>, shift the 16-bit
5819 * input up by 16 bits, so that the result is at product<63:32>.
5821 if (mt) {
5822 tcg_gen_andi_i32(t1, t1, 0xffff0000);
5823 } else {
5824 tcg_gen_shli_i32(t1, t1, 16);
5826 tcg_gen_muls2_i32(t0, t1, t0, t1);
5827 tcg_temp_free_i32(t0);
5828 if (add) {
5829 t0 = load_reg(s, a->ra);
5830 gen_helper_add_setq(t1, cpu_env, t1, t0);
5831 tcg_temp_free_i32(t0);
5833 store_reg(s, a->rd, t1);
5834 return true;
5837 #define DO_SMLAWX(NAME, add, mt) \
5838 static bool trans_##NAME(DisasContext *s, arg_rrrr *a) \
5840 return op_smlawx(s, a, add, mt); \
5843 DO_SMLAWX(SMULWB, 0, 0)
5844 DO_SMLAWX(SMULWT, 0, 1)
5845 DO_SMLAWX(SMLAWB, 1, 0)
5846 DO_SMLAWX(SMLAWT, 1, 1)
5848 #undef DO_SMLAWX
5851 * MSR (immediate) and hints
5854 static bool trans_YIELD(DisasContext *s, arg_YIELD *a)
5857 * When running single-threaded TCG code, use the helper to ensure that
5858 * the next round-robin scheduled vCPU gets a crack. When running in
5859 * MTTCG we don't generate jumps to the helper as it won't affect the
5860 * scheduling of other vCPUs.
5862 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
5863 gen_set_pc_im(s, s->base.pc_next);
5864 s->base.is_jmp = DISAS_YIELD;
5866 return true;
5869 static bool trans_WFE(DisasContext *s, arg_WFE *a)
5872 * When running single-threaded TCG code, use the helper to ensure that
5873 * the next round-robin scheduled vCPU gets a crack. In MTTCG mode we
5874 * just skip this instruction. Currently the SEV/SEVL instructions,
5875 * which are *one* of many ways to wake the CPU from WFE, are not
5876 * implemented so we can't sleep like WFI does.
5878 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
5879 gen_set_pc_im(s, s->base.pc_next);
5880 s->base.is_jmp = DISAS_WFE;
5882 return true;
5885 static bool trans_WFI(DisasContext *s, arg_WFI *a)
5887 /* For WFI, halt the vCPU until an IRQ. */
5888 gen_set_pc_im(s, s->base.pc_next);
5889 s->base.is_jmp = DISAS_WFI;
5890 return true;
5893 static bool trans_NOP(DisasContext *s, arg_NOP *a)
5895 return true;
5898 static bool trans_MSR_imm(DisasContext *s, arg_MSR_imm *a)
5900 uint32_t val = ror32(a->imm, a->rot * 2);
5901 uint32_t mask = msr_mask(s, a->mask, a->r);
5903 if (gen_set_psr_im(s, mask, a->r, val)) {
5904 unallocated_encoding(s);
5906 return true;
5910 * Cyclic Redundancy Check
5913 static bool op_crc32(DisasContext *s, arg_rrr *a, bool c, MemOp sz)
5915 TCGv_i32 t1, t2, t3;
5917 if (!dc_isar_feature(aa32_crc32, s)) {
5918 return false;
5921 t1 = load_reg(s, a->rn);
5922 t2 = load_reg(s, a->rm);
5923 switch (sz) {
5924 case MO_8:
5925 gen_uxtb(t2);
5926 break;
5927 case MO_16:
5928 gen_uxth(t2);
5929 break;
5930 case MO_32:
5931 break;
5932 default:
5933 g_assert_not_reached();
5935 t3 = tcg_const_i32(1 << sz);
5936 if (c) {
5937 gen_helper_crc32c(t1, t1, t2, t3);
5938 } else {
5939 gen_helper_crc32(t1, t1, t2, t3);
5941 tcg_temp_free_i32(t2);
5942 tcg_temp_free_i32(t3);
5943 store_reg(s, a->rd, t1);
5944 return true;
5947 #define DO_CRC32(NAME, c, sz) \
5948 static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
5949 { return op_crc32(s, a, c, sz); }
5951 DO_CRC32(CRC32B, false, MO_8)
5952 DO_CRC32(CRC32H, false, MO_16)
5953 DO_CRC32(CRC32W, false, MO_32)
5954 DO_CRC32(CRC32CB, true, MO_8)
5955 DO_CRC32(CRC32CH, true, MO_16)
5956 DO_CRC32(CRC32CW, true, MO_32)
5958 #undef DO_CRC32
5961 * Miscellaneous instructions
5964 static bool trans_MRS_bank(DisasContext *s, arg_MRS_bank *a)
5966 if (arm_dc_feature(s, ARM_FEATURE_M)) {
5967 return false;
5969 gen_mrs_banked(s, a->r, a->sysm, a->rd);
5970 return true;
5973 static bool trans_MSR_bank(DisasContext *s, arg_MSR_bank *a)
5975 if (arm_dc_feature(s, ARM_FEATURE_M)) {
5976 return false;
5978 gen_msr_banked(s, a->r, a->sysm, a->rn);
5979 return true;
5982 static bool trans_MRS_reg(DisasContext *s, arg_MRS_reg *a)
5984 TCGv_i32 tmp;
5986 if (arm_dc_feature(s, ARM_FEATURE_M)) {
5987 return false;
5989 if (a->r) {
5990 if (IS_USER(s)) {
5991 unallocated_encoding(s);
5992 return true;
5994 tmp = load_cpu_field(spsr);
5995 } else {
5996 tmp = tcg_temp_new_i32();
5997 gen_helper_cpsr_read(tmp, cpu_env);
5999 store_reg(s, a->rd, tmp);
6000 return true;
6003 static bool trans_MSR_reg(DisasContext *s, arg_MSR_reg *a)
6005 TCGv_i32 tmp;
6006 uint32_t mask = msr_mask(s, a->mask, a->r);
6008 if (arm_dc_feature(s, ARM_FEATURE_M)) {
6009 return false;
6011 tmp = load_reg(s, a->rn);
6012 if (gen_set_psr(s, mask, a->r, tmp)) {
6013 unallocated_encoding(s);
6015 return true;
6018 static bool trans_MRS_v7m(DisasContext *s, arg_MRS_v7m *a)
6020 TCGv_i32 tmp;
6022 if (!arm_dc_feature(s, ARM_FEATURE_M)) {
6023 return false;
6025 tmp = tcg_const_i32(a->sysm);
6026 gen_helper_v7m_mrs(tmp, cpu_env, tmp);
6027 store_reg(s, a->rd, tmp);
6028 return true;
6031 static bool trans_MSR_v7m(DisasContext *s, arg_MSR_v7m *a)
6033 TCGv_i32 addr, reg;
6035 if (!arm_dc_feature(s, ARM_FEATURE_M)) {
6036 return false;
6038 addr = tcg_const_i32((a->mask << 10) | a->sysm);
6039 reg = load_reg(s, a->rn);
6040 gen_helper_v7m_msr(cpu_env, addr, reg);
6041 tcg_temp_free_i32(addr);
6042 tcg_temp_free_i32(reg);
6043 /* If we wrote to CONTROL, the EL might have changed */
6044 gen_helper_rebuild_hflags_m32_newel(cpu_env);
6045 gen_lookup_tb(s);
6046 return true;
6049 static bool trans_BX(DisasContext *s, arg_BX *a)
6051 if (!ENABLE_ARCH_4T) {
6052 return false;
6054 gen_bx_excret(s, load_reg(s, a->rm));
6055 return true;
6058 static bool trans_BXJ(DisasContext *s, arg_BXJ *a)
6060 if (!ENABLE_ARCH_5J || arm_dc_feature(s, ARM_FEATURE_M)) {
6061 return false;
6063 /* Trivial implementation equivalent to bx. */
6064 gen_bx(s, load_reg(s, a->rm));
6065 return true;
6068 static bool trans_BLX_r(DisasContext *s, arg_BLX_r *a)
6070 TCGv_i32 tmp;
6072 if (!ENABLE_ARCH_5) {
6073 return false;
6075 tmp = load_reg(s, a->rm);
6076 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
6077 gen_bx(s, tmp);
6078 return true;
6082 * BXNS/BLXNS: only exist for v8M with the security extensions,
6083 * and always UNDEF if NonSecure. We don't implement these in
6084 * the user-only mode either (in theory you can use them from
6085 * Secure User mode but they are too tied in to system emulation).
6087 static bool trans_BXNS(DisasContext *s, arg_BXNS *a)
6089 if (!s->v8m_secure || IS_USER_ONLY) {
6090 unallocated_encoding(s);
6091 } else {
6092 gen_bxns(s, a->rm);
6094 return true;
6097 static bool trans_BLXNS(DisasContext *s, arg_BLXNS *a)
6099 if (!s->v8m_secure || IS_USER_ONLY) {
6100 unallocated_encoding(s);
6101 } else {
6102 gen_blxns(s, a->rm);
6104 return true;
6107 static bool trans_CLZ(DisasContext *s, arg_CLZ *a)
6109 TCGv_i32 tmp;
6111 if (!ENABLE_ARCH_5) {
6112 return false;
6114 tmp = load_reg(s, a->rm);
6115 tcg_gen_clzi_i32(tmp, tmp, 32);
6116 store_reg(s, a->rd, tmp);
6117 return true;
6120 static bool trans_ERET(DisasContext *s, arg_ERET *a)
6122 TCGv_i32 tmp;
6124 if (!arm_dc_feature(s, ARM_FEATURE_V7VE)) {
6125 return false;
6127 if (IS_USER(s)) {
6128 unallocated_encoding(s);
6129 return true;
6131 if (s->current_el == 2) {
6132 /* ERET from Hyp uses ELR_Hyp, not LR */
6133 tmp = load_cpu_field(elr_el[2]);
6134 } else {
6135 tmp = load_reg(s, 14);
6137 gen_exception_return(s, tmp);
6138 return true;
6141 static bool trans_HLT(DisasContext *s, arg_HLT *a)
6143 gen_hlt(s, a->imm);
6144 return true;
6147 static bool trans_BKPT(DisasContext *s, arg_BKPT *a)
6149 if (!ENABLE_ARCH_5) {
6150 return false;
6152 if (arm_dc_feature(s, ARM_FEATURE_M) &&
6153 semihosting_enabled() &&
6154 #ifndef CONFIG_USER_ONLY
6155 !IS_USER(s) &&
6156 #endif
6157 (a->imm == 0xab)) {
6158 gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
6159 } else {
6160 gen_exception_bkpt_insn(s, syn_aa32_bkpt(a->imm, false));
6162 return true;
6165 static bool trans_HVC(DisasContext *s, arg_HVC *a)
6167 if (!ENABLE_ARCH_7 || arm_dc_feature(s, ARM_FEATURE_M)) {
6168 return false;
6170 if (IS_USER(s)) {
6171 unallocated_encoding(s);
6172 } else {
6173 gen_hvc(s, a->imm);
6175 return true;
6178 static bool trans_SMC(DisasContext *s, arg_SMC *a)
6180 if (!ENABLE_ARCH_6K || arm_dc_feature(s, ARM_FEATURE_M)) {
6181 return false;
6183 if (IS_USER(s)) {
6184 unallocated_encoding(s);
6185 } else {
6186 gen_smc(s);
6188 return true;
6191 static bool trans_SG(DisasContext *s, arg_SG *a)
6193 if (!arm_dc_feature(s, ARM_FEATURE_M) ||
6194 !arm_dc_feature(s, ARM_FEATURE_V8)) {
6195 return false;
6198 * SG (v8M only)
6199 * The bulk of the behaviour for this instruction is implemented
6200 * in v7m_handle_execute_nsc(), which deals with the insn when
6201 * it is executed by a CPU in non-secure state from memory
6202 * which is Secure & NonSecure-Callable.
6203 * Here we only need to handle the remaining cases:
6204 * * in NS memory (including the "security extension not
6205 * implemented" case) : NOP
6206 * * in S memory but CPU already secure (clear IT bits)
6207 * We know that the attribute for the memory this insn is
6208 * in must match the current CPU state, because otherwise
6209 * get_phys_addr_pmsav8 would have generated an exception.
6211 if (s->v8m_secure) {
6212 /* Like the IT insn, we don't need to generate any code */
6213 s->condexec_cond = 0;
6214 s->condexec_mask = 0;
6216 return true;
6219 static bool trans_TT(DisasContext *s, arg_TT *a)
6221 TCGv_i32 addr, tmp;
6223 if (!arm_dc_feature(s, ARM_FEATURE_M) ||
6224 !arm_dc_feature(s, ARM_FEATURE_V8)) {
6225 return false;
6227 if (a->rd == 13 || a->rd == 15 || a->rn == 15) {
6228 /* We UNDEF for these UNPREDICTABLE cases */
6229 unallocated_encoding(s);
6230 return true;
6232 if (a->A && !s->v8m_secure) {
6233 /* This case is UNDEFINED. */
6234 unallocated_encoding(s);
6235 return true;
6238 addr = load_reg(s, a->rn);
6239 tmp = tcg_const_i32((a->A << 1) | a->T);
6240 gen_helper_v7m_tt(tmp, cpu_env, addr, tmp);
6241 tcg_temp_free_i32(addr);
6242 store_reg(s, a->rd, tmp);
6243 return true;
6247 * Load/store register index
6250 static ISSInfo make_issinfo(DisasContext *s, int rd, bool p, bool w)
6252 ISSInfo ret;
6254 /* ISS not valid if writeback */
6255 if (p && !w) {
6256 ret = rd;
6257 if (s->base.pc_next - s->pc_curr == 2) {
6258 ret |= ISSIs16Bit;
6260 } else {
6261 ret = ISSInvalid;
6263 return ret;
6266 static TCGv_i32 op_addr_rr_pre(DisasContext *s, arg_ldst_rr *a)
6268 TCGv_i32 addr = load_reg(s, a->rn);
6270 if (s->v8m_stackcheck && a->rn == 13 && a->w) {
6271 gen_helper_v8m_stackcheck(cpu_env, addr);
6274 if (a->p) {
6275 TCGv_i32 ofs = load_reg(s, a->rm);
6276 gen_arm_shift_im(ofs, a->shtype, a->shimm, 0);
6277 if (a->u) {
6278 tcg_gen_add_i32(addr, addr, ofs);
6279 } else {
6280 tcg_gen_sub_i32(addr, addr, ofs);
6282 tcg_temp_free_i32(ofs);
6284 return addr;
6287 static void op_addr_rr_post(DisasContext *s, arg_ldst_rr *a,
6288 TCGv_i32 addr, int address_offset)
6290 if (!a->p) {
6291 TCGv_i32 ofs = load_reg(s, a->rm);
6292 gen_arm_shift_im(ofs, a->shtype, a->shimm, 0);
6293 if (a->u) {
6294 tcg_gen_add_i32(addr, addr, ofs);
6295 } else {
6296 tcg_gen_sub_i32(addr, addr, ofs);
6298 tcg_temp_free_i32(ofs);
6299 } else if (!a->w) {
6300 tcg_temp_free_i32(addr);
6301 return;
6303 tcg_gen_addi_i32(addr, addr, address_offset);
6304 store_reg(s, a->rn, addr);
6307 static bool op_load_rr(DisasContext *s, arg_ldst_rr *a,
6308 MemOp mop, int mem_idx)
6310 ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w);
6311 TCGv_i32 addr, tmp;
6313 addr = op_addr_rr_pre(s, a);
6315 tmp = tcg_temp_new_i32();
6316 gen_aa32_ld_i32(s, tmp, addr, mem_idx, mop | s->be_data);
6317 disas_set_da_iss(s, mop, issinfo);
6320 * Perform base writeback before the loaded value to
6321 * ensure correct behavior with overlapping index registers.
6323 op_addr_rr_post(s, a, addr, 0);
6324 store_reg_from_load(s, a->rt, tmp);
6325 return true;
6328 static bool op_store_rr(DisasContext *s, arg_ldst_rr *a,
6329 MemOp mop, int mem_idx)
6331 ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w) | ISSIsWrite;
6332 TCGv_i32 addr, tmp;
6334 addr = op_addr_rr_pre(s, a);
6336 tmp = load_reg(s, a->rt);
6337 gen_aa32_st_i32(s, tmp, addr, mem_idx, mop | s->be_data);
6338 disas_set_da_iss(s, mop, issinfo);
6339 tcg_temp_free_i32(tmp);
6341 op_addr_rr_post(s, a, addr, 0);
6342 return true;
6345 static bool trans_LDRD_rr(DisasContext *s, arg_ldst_rr *a)
6347 int mem_idx = get_mem_index(s);
6348 TCGv_i32 addr, tmp;
6350 if (!ENABLE_ARCH_5TE) {
6351 return false;
6353 if (a->rt & 1) {
6354 unallocated_encoding(s);
6355 return true;
6357 addr = op_addr_rr_pre(s, a);
6359 tmp = tcg_temp_new_i32();
6360 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
6361 store_reg(s, a->rt, tmp);
6363 tcg_gen_addi_i32(addr, addr, 4);
6365 tmp = tcg_temp_new_i32();
6366 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
6367 store_reg(s, a->rt + 1, tmp);
6369 /* LDRD w/ base writeback is undefined if the registers overlap. */
6370 op_addr_rr_post(s, a, addr, -4);
6371 return true;
6374 static bool trans_STRD_rr(DisasContext *s, arg_ldst_rr *a)
6376 int mem_idx = get_mem_index(s);
6377 TCGv_i32 addr, tmp;
6379 if (!ENABLE_ARCH_5TE) {
6380 return false;
6382 if (a->rt & 1) {
6383 unallocated_encoding(s);
6384 return true;
6386 addr = op_addr_rr_pre(s, a);
6388 tmp = load_reg(s, a->rt);
6389 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
6390 tcg_temp_free_i32(tmp);
6392 tcg_gen_addi_i32(addr, addr, 4);
6394 tmp = load_reg(s, a->rt + 1);
6395 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
6396 tcg_temp_free_i32(tmp);
6398 op_addr_rr_post(s, a, addr, -4);
6399 return true;
6403 * Load/store immediate index
6406 static TCGv_i32 op_addr_ri_pre(DisasContext *s, arg_ldst_ri *a)
6408 int ofs = a->imm;
6410 if (!a->u) {
6411 ofs = -ofs;
6414 if (s->v8m_stackcheck && a->rn == 13 && a->w) {
6416 * Stackcheck. Here we know 'addr' is the current SP;
6417 * U is set if we're moving SP up, else down. It is
6418 * UNKNOWN whether the limit check triggers when SP starts
6419 * below the limit and ends up above it; we chose to do so.
6421 if (!a->u) {
6422 TCGv_i32 newsp = tcg_temp_new_i32();
6423 tcg_gen_addi_i32(newsp, cpu_R[13], ofs);
6424 gen_helper_v8m_stackcheck(cpu_env, newsp);
6425 tcg_temp_free_i32(newsp);
6426 } else {
6427 gen_helper_v8m_stackcheck(cpu_env, cpu_R[13]);
6431 return add_reg_for_lit(s, a->rn, a->p ? ofs : 0);
6434 static void op_addr_ri_post(DisasContext *s, arg_ldst_ri *a,
6435 TCGv_i32 addr, int address_offset)
6437 if (!a->p) {
6438 if (a->u) {
6439 address_offset += a->imm;
6440 } else {
6441 address_offset -= a->imm;
6443 } else if (!a->w) {
6444 tcg_temp_free_i32(addr);
6445 return;
6447 tcg_gen_addi_i32(addr, addr, address_offset);
6448 store_reg(s, a->rn, addr);
6451 static bool op_load_ri(DisasContext *s, arg_ldst_ri *a,
6452 MemOp mop, int mem_idx)
6454 ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w);
6455 TCGv_i32 addr, tmp;
6457 addr = op_addr_ri_pre(s, a);
6459 tmp = tcg_temp_new_i32();
6460 gen_aa32_ld_i32(s, tmp, addr, mem_idx, mop | s->be_data);
6461 disas_set_da_iss(s, mop, issinfo);
6464 * Perform base writeback before the loaded value to
6465 * ensure correct behavior with overlapping index registers.
6467 op_addr_ri_post(s, a, addr, 0);
6468 store_reg_from_load(s, a->rt, tmp);
6469 return true;
6472 static bool op_store_ri(DisasContext *s, arg_ldst_ri *a,
6473 MemOp mop, int mem_idx)
6475 ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w) | ISSIsWrite;
6476 TCGv_i32 addr, tmp;
6478 addr = op_addr_ri_pre(s, a);
6480 tmp = load_reg(s, a->rt);
6481 gen_aa32_st_i32(s, tmp, addr, mem_idx, mop | s->be_data);
6482 disas_set_da_iss(s, mop, issinfo);
6483 tcg_temp_free_i32(tmp);
6485 op_addr_ri_post(s, a, addr, 0);
6486 return true;
6489 static bool op_ldrd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
6491 int mem_idx = get_mem_index(s);
6492 TCGv_i32 addr, tmp;
6494 addr = op_addr_ri_pre(s, a);
6496 tmp = tcg_temp_new_i32();
6497 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
6498 store_reg(s, a->rt, tmp);
6500 tcg_gen_addi_i32(addr, addr, 4);
6502 tmp = tcg_temp_new_i32();
6503 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
6504 store_reg(s, rt2, tmp);
6506 /* LDRD w/ base writeback is undefined if the registers overlap. */
6507 op_addr_ri_post(s, a, addr, -4);
6508 return true;
6511 static bool trans_LDRD_ri_a32(DisasContext *s, arg_ldst_ri *a)
6513 if (!ENABLE_ARCH_5TE || (a->rt & 1)) {
6514 return false;
6516 return op_ldrd_ri(s, a, a->rt + 1);
6519 static bool trans_LDRD_ri_t32(DisasContext *s, arg_ldst_ri2 *a)
6521 arg_ldst_ri b = {
6522 .u = a->u, .w = a->w, .p = a->p,
6523 .rn = a->rn, .rt = a->rt, .imm = a->imm
6525 return op_ldrd_ri(s, &b, a->rt2);
6528 static bool op_strd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
6530 int mem_idx = get_mem_index(s);
6531 TCGv_i32 addr, tmp;
6533 addr = op_addr_ri_pre(s, a);
6535 tmp = load_reg(s, a->rt);
6536 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
6537 tcg_temp_free_i32(tmp);
6539 tcg_gen_addi_i32(addr, addr, 4);
6541 tmp = load_reg(s, rt2);
6542 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
6543 tcg_temp_free_i32(tmp);
6545 op_addr_ri_post(s, a, addr, -4);
6546 return true;
6549 static bool trans_STRD_ri_a32(DisasContext *s, arg_ldst_ri *a)
6551 if (!ENABLE_ARCH_5TE || (a->rt & 1)) {
6552 return false;
6554 return op_strd_ri(s, a, a->rt + 1);
6557 static bool trans_STRD_ri_t32(DisasContext *s, arg_ldst_ri2 *a)
6559 arg_ldst_ri b = {
6560 .u = a->u, .w = a->w, .p = a->p,
6561 .rn = a->rn, .rt = a->rt, .imm = a->imm
6563 return op_strd_ri(s, &b, a->rt2);
6566 #define DO_LDST(NAME, WHICH, MEMOP) \
6567 static bool trans_##NAME##_ri(DisasContext *s, arg_ldst_ri *a) \
6569 return op_##WHICH##_ri(s, a, MEMOP, get_mem_index(s)); \
6571 static bool trans_##NAME##T_ri(DisasContext *s, arg_ldst_ri *a) \
6573 return op_##WHICH##_ri(s, a, MEMOP, get_a32_user_mem_index(s)); \
6575 static bool trans_##NAME##_rr(DisasContext *s, arg_ldst_rr *a) \
6577 return op_##WHICH##_rr(s, a, MEMOP, get_mem_index(s)); \
6579 static bool trans_##NAME##T_rr(DisasContext *s, arg_ldst_rr *a) \
6581 return op_##WHICH##_rr(s, a, MEMOP, get_a32_user_mem_index(s)); \
6584 DO_LDST(LDR, load, MO_UL)
6585 DO_LDST(LDRB, load, MO_UB)
6586 DO_LDST(LDRH, load, MO_UW)
6587 DO_LDST(LDRSB, load, MO_SB)
6588 DO_LDST(LDRSH, load, MO_SW)
6590 DO_LDST(STR, store, MO_UL)
6591 DO_LDST(STRB, store, MO_UB)
6592 DO_LDST(STRH, store, MO_UW)
6594 #undef DO_LDST
6597 * Synchronization primitives
6600 static bool op_swp(DisasContext *s, arg_SWP *a, MemOp opc)
6602 TCGv_i32 addr, tmp;
6603 TCGv taddr;
6605 opc |= s->be_data;
6606 addr = load_reg(s, a->rn);
6607 taddr = gen_aa32_addr(s, addr, opc);
6608 tcg_temp_free_i32(addr);
6610 tmp = load_reg(s, a->rt2);
6611 tcg_gen_atomic_xchg_i32(tmp, taddr, tmp, get_mem_index(s), opc);
6612 tcg_temp_free(taddr);
6614 store_reg(s, a->rt, tmp);
6615 return true;
6618 static bool trans_SWP(DisasContext *s, arg_SWP *a)
6620 return op_swp(s, a, MO_UL | MO_ALIGN);
6623 static bool trans_SWPB(DisasContext *s, arg_SWP *a)
6625 return op_swp(s, a, MO_UB);
6629 * Load/Store Exclusive and Load-Acquire/Store-Release
6632 static bool op_strex(DisasContext *s, arg_STREX *a, MemOp mop, bool rel)
6634 TCGv_i32 addr;
6635 /* Some cases stopped being UNPREDICTABLE in v8A (but not v8M) */
6636 bool v8a = ENABLE_ARCH_8 && !arm_dc_feature(s, ARM_FEATURE_M);
6638 /* We UNDEF for these UNPREDICTABLE cases. */
6639 if (a->rd == 15 || a->rn == 15 || a->rt == 15
6640 || a->rd == a->rn || a->rd == a->rt
6641 || (!v8a && s->thumb && (a->rd == 13 || a->rt == 13))
6642 || (mop == MO_64
6643 && (a->rt2 == 15
6644 || a->rd == a->rt2
6645 || (!v8a && s->thumb && a->rt2 == 13)))) {
6646 unallocated_encoding(s);
6647 return true;
6650 if (rel) {
6651 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
6654 addr = tcg_temp_local_new_i32();
6655 load_reg_var(s, addr, a->rn);
6656 tcg_gen_addi_i32(addr, addr, a->imm);
6658 gen_store_exclusive(s, a->rd, a->rt, a->rt2, addr, mop);
6659 tcg_temp_free_i32(addr);
6660 return true;
6663 static bool trans_STREX(DisasContext *s, arg_STREX *a)
6665 if (!ENABLE_ARCH_6) {
6666 return false;
6668 return op_strex(s, a, MO_32, false);
6671 static bool trans_STREXD_a32(DisasContext *s, arg_STREX *a)
6673 if (!ENABLE_ARCH_6K) {
6674 return false;
6676 /* We UNDEF for these UNPREDICTABLE cases. */
6677 if (a->rt & 1) {
6678 unallocated_encoding(s);
6679 return true;
6681 a->rt2 = a->rt + 1;
6682 return op_strex(s, a, MO_64, false);
6685 static bool trans_STREXD_t32(DisasContext *s, arg_STREX *a)
6687 return op_strex(s, a, MO_64, false);
6690 static bool trans_STREXB(DisasContext *s, arg_STREX *a)
6692 if (s->thumb ? !ENABLE_ARCH_7 : !ENABLE_ARCH_6K) {
6693 return false;
6695 return op_strex(s, a, MO_8, false);
6698 static bool trans_STREXH(DisasContext *s, arg_STREX *a)
6700 if (s->thumb ? !ENABLE_ARCH_7 : !ENABLE_ARCH_6K) {
6701 return false;
6703 return op_strex(s, a, MO_16, false);
6706 static bool trans_STLEX(DisasContext *s, arg_STREX *a)
6708 if (!ENABLE_ARCH_8) {
6709 return false;
6711 return op_strex(s, a, MO_32, true);
6714 static bool trans_STLEXD_a32(DisasContext *s, arg_STREX *a)
6716 if (!ENABLE_ARCH_8) {
6717 return false;
6719 /* We UNDEF for these UNPREDICTABLE cases. */
6720 if (a->rt & 1) {
6721 unallocated_encoding(s);
6722 return true;
6724 a->rt2 = a->rt + 1;
6725 return op_strex(s, a, MO_64, true);
6728 static bool trans_STLEXD_t32(DisasContext *s, arg_STREX *a)
6730 if (!ENABLE_ARCH_8) {
6731 return false;
6733 return op_strex(s, a, MO_64, true);
6736 static bool trans_STLEXB(DisasContext *s, arg_STREX *a)
6738 if (!ENABLE_ARCH_8) {
6739 return false;
6741 return op_strex(s, a, MO_8, true);
6744 static bool trans_STLEXH(DisasContext *s, arg_STREX *a)
6746 if (!ENABLE_ARCH_8) {
6747 return false;
6749 return op_strex(s, a, MO_16, true);
6752 static bool op_stl(DisasContext *s, arg_STL *a, MemOp mop)
6754 TCGv_i32 addr, tmp;
6756 if (!ENABLE_ARCH_8) {
6757 return false;
6759 /* We UNDEF for these UNPREDICTABLE cases. */
6760 if (a->rn == 15 || a->rt == 15) {
6761 unallocated_encoding(s);
6762 return true;
6765 addr = load_reg(s, a->rn);
6766 tmp = load_reg(s, a->rt);
6767 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
6768 gen_aa32_st_i32(s, tmp, addr, get_mem_index(s), mop | s->be_data);
6769 disas_set_da_iss(s, mop, a->rt | ISSIsAcqRel | ISSIsWrite);
6771 tcg_temp_free_i32(tmp);
6772 tcg_temp_free_i32(addr);
6773 return true;
6776 static bool trans_STL(DisasContext *s, arg_STL *a)
6778 return op_stl(s, a, MO_UL);
6781 static bool trans_STLB(DisasContext *s, arg_STL *a)
6783 return op_stl(s, a, MO_UB);
6786 static bool trans_STLH(DisasContext *s, arg_STL *a)
6788 return op_stl(s, a, MO_UW);
6791 static bool op_ldrex(DisasContext *s, arg_LDREX *a, MemOp mop, bool acq)
6793 TCGv_i32 addr;
6794 /* Some cases stopped being UNPREDICTABLE in v8A (but not v8M) */
6795 bool v8a = ENABLE_ARCH_8 && !arm_dc_feature(s, ARM_FEATURE_M);
6797 /* We UNDEF for these UNPREDICTABLE cases. */
6798 if (a->rn == 15 || a->rt == 15
6799 || (!v8a && s->thumb && a->rt == 13)
6800 || (mop == MO_64
6801 && (a->rt2 == 15 || a->rt == a->rt2
6802 || (!v8a && s->thumb && a->rt2 == 13)))) {
6803 unallocated_encoding(s);
6804 return true;
6807 addr = tcg_temp_local_new_i32();
6808 load_reg_var(s, addr, a->rn);
6809 tcg_gen_addi_i32(addr, addr, a->imm);
6811 gen_load_exclusive(s, a->rt, a->rt2, addr, mop);
6812 tcg_temp_free_i32(addr);
6814 if (acq) {
6815 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
6817 return true;
6820 static bool trans_LDREX(DisasContext *s, arg_LDREX *a)
6822 if (!ENABLE_ARCH_6) {
6823 return false;
6825 return op_ldrex(s, a, MO_32, false);
6828 static bool trans_LDREXD_a32(DisasContext *s, arg_LDREX *a)
6830 if (!ENABLE_ARCH_6K) {
6831 return false;
6833 /* We UNDEF for these UNPREDICTABLE cases. */
6834 if (a->rt & 1) {
6835 unallocated_encoding(s);
6836 return true;
6838 a->rt2 = a->rt + 1;
6839 return op_ldrex(s, a, MO_64, false);
6842 static bool trans_LDREXD_t32(DisasContext *s, arg_LDREX *a)
6844 return op_ldrex(s, a, MO_64, false);
6847 static bool trans_LDREXB(DisasContext *s, arg_LDREX *a)
6849 if (s->thumb ? !ENABLE_ARCH_7 : !ENABLE_ARCH_6K) {
6850 return false;
6852 return op_ldrex(s, a, MO_8, false);
6855 static bool trans_LDREXH(DisasContext *s, arg_LDREX *a)
6857 if (s->thumb ? !ENABLE_ARCH_7 : !ENABLE_ARCH_6K) {
6858 return false;
6860 return op_ldrex(s, a, MO_16, false);
6863 static bool trans_LDAEX(DisasContext *s, arg_LDREX *a)
6865 if (!ENABLE_ARCH_8) {
6866 return false;
6868 return op_ldrex(s, a, MO_32, true);
6871 static bool trans_LDAEXD_a32(DisasContext *s, arg_LDREX *a)
6873 if (!ENABLE_ARCH_8) {
6874 return false;
6876 /* We UNDEF for these UNPREDICTABLE cases. */
6877 if (a->rt & 1) {
6878 unallocated_encoding(s);
6879 return true;
6881 a->rt2 = a->rt + 1;
6882 return op_ldrex(s, a, MO_64, true);
6885 static bool trans_LDAEXD_t32(DisasContext *s, arg_LDREX *a)
6887 if (!ENABLE_ARCH_8) {
6888 return false;
6890 return op_ldrex(s, a, MO_64, true);
6893 static bool trans_LDAEXB(DisasContext *s, arg_LDREX *a)
6895 if (!ENABLE_ARCH_8) {
6896 return false;
6898 return op_ldrex(s, a, MO_8, true);
6901 static bool trans_LDAEXH(DisasContext *s, arg_LDREX *a)
6903 if (!ENABLE_ARCH_8) {
6904 return false;
6906 return op_ldrex(s, a, MO_16, true);
6909 static bool op_lda(DisasContext *s, arg_LDA *a, MemOp mop)
6911 TCGv_i32 addr, tmp;
6913 if (!ENABLE_ARCH_8) {
6914 return false;
6916 /* We UNDEF for these UNPREDICTABLE cases. */
6917 if (a->rn == 15 || a->rt == 15) {
6918 unallocated_encoding(s);
6919 return true;
6922 addr = load_reg(s, a->rn);
6923 tmp = tcg_temp_new_i32();
6924 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), mop | s->be_data);
6925 disas_set_da_iss(s, mop, a->rt | ISSIsAcqRel);
6926 tcg_temp_free_i32(addr);
6928 store_reg(s, a->rt, tmp);
6929 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
6930 return true;
6933 static bool trans_LDA(DisasContext *s, arg_LDA *a)
6935 return op_lda(s, a, MO_UL);
6938 static bool trans_LDAB(DisasContext *s, arg_LDA *a)
6940 return op_lda(s, a, MO_UB);
6943 static bool trans_LDAH(DisasContext *s, arg_LDA *a)
6945 return op_lda(s, a, MO_UW);
6949 * Media instructions
6952 static bool trans_USADA8(DisasContext *s, arg_USADA8 *a)
6954 TCGv_i32 t1, t2;
6956 if (!ENABLE_ARCH_6) {
6957 return false;
6960 t1 = load_reg(s, a->rn);
6961 t2 = load_reg(s, a->rm);
6962 gen_helper_usad8(t1, t1, t2);
6963 tcg_temp_free_i32(t2);
6964 if (a->ra != 15) {
6965 t2 = load_reg(s, a->ra);
6966 tcg_gen_add_i32(t1, t1, t2);
6967 tcg_temp_free_i32(t2);
6969 store_reg(s, a->rd, t1);
6970 return true;
6973 static bool op_bfx(DisasContext *s, arg_UBFX *a, bool u)
6975 TCGv_i32 tmp;
6976 int width = a->widthm1 + 1;
6977 int shift = a->lsb;
6979 if (!ENABLE_ARCH_6T2) {
6980 return false;
6982 if (shift + width > 32) {
6983 /* UNPREDICTABLE; we choose to UNDEF */
6984 unallocated_encoding(s);
6985 return true;
6988 tmp = load_reg(s, a->rn);
6989 if (u) {
6990 tcg_gen_extract_i32(tmp, tmp, shift, width);
6991 } else {
6992 tcg_gen_sextract_i32(tmp, tmp, shift, width);
6994 store_reg(s, a->rd, tmp);
6995 return true;
6998 static bool trans_SBFX(DisasContext *s, arg_SBFX *a)
7000 return op_bfx(s, a, false);
7003 static bool trans_UBFX(DisasContext *s, arg_UBFX *a)
7005 return op_bfx(s, a, true);
7008 static bool trans_BFCI(DisasContext *s, arg_BFCI *a)
7010 TCGv_i32 tmp;
7011 int msb = a->msb, lsb = a->lsb;
7012 int width;
7014 if (!ENABLE_ARCH_6T2) {
7015 return false;
7017 if (msb < lsb) {
7018 /* UNPREDICTABLE; we choose to UNDEF */
7019 unallocated_encoding(s);
7020 return true;
7023 width = msb + 1 - lsb;
7024 if (a->rn == 15) {
7025 /* BFC */
7026 tmp = tcg_const_i32(0);
7027 } else {
7028 /* BFI */
7029 tmp = load_reg(s, a->rn);
7031 if (width != 32) {
7032 TCGv_i32 tmp2 = load_reg(s, a->rd);
7033 tcg_gen_deposit_i32(tmp, tmp2, tmp, lsb, width);
7034 tcg_temp_free_i32(tmp2);
7036 store_reg(s, a->rd, tmp);
7037 return true;
7040 static bool trans_UDF(DisasContext *s, arg_UDF *a)
7042 unallocated_encoding(s);
7043 return true;
7047 * Parallel addition and subtraction
7050 static bool op_par_addsub(DisasContext *s, arg_rrr *a,
7051 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32))
7053 TCGv_i32 t0, t1;
7055 if (s->thumb
7056 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
7057 : !ENABLE_ARCH_6) {
7058 return false;
7061 t0 = load_reg(s, a->rn);
7062 t1 = load_reg(s, a->rm);
7064 gen(t0, t0, t1);
7066 tcg_temp_free_i32(t1);
7067 store_reg(s, a->rd, t0);
7068 return true;
7071 static bool op_par_addsub_ge(DisasContext *s, arg_rrr *a,
7072 void (*gen)(TCGv_i32, TCGv_i32,
7073 TCGv_i32, TCGv_ptr))
7075 TCGv_i32 t0, t1;
7076 TCGv_ptr ge;
7078 if (s->thumb
7079 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
7080 : !ENABLE_ARCH_6) {
7081 return false;
7084 t0 = load_reg(s, a->rn);
7085 t1 = load_reg(s, a->rm);
7087 ge = tcg_temp_new_ptr();
7088 tcg_gen_addi_ptr(ge, cpu_env, offsetof(CPUARMState, GE));
7089 gen(t0, t0, t1, ge);
7091 tcg_temp_free_ptr(ge);
7092 tcg_temp_free_i32(t1);
7093 store_reg(s, a->rd, t0);
7094 return true;
7097 #define DO_PAR_ADDSUB(NAME, helper) \
7098 static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
7100 return op_par_addsub(s, a, helper); \
7103 #define DO_PAR_ADDSUB_GE(NAME, helper) \
7104 static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
7106 return op_par_addsub_ge(s, a, helper); \
7109 DO_PAR_ADDSUB_GE(SADD16, gen_helper_sadd16)
7110 DO_PAR_ADDSUB_GE(SASX, gen_helper_saddsubx)
7111 DO_PAR_ADDSUB_GE(SSAX, gen_helper_ssubaddx)
7112 DO_PAR_ADDSUB_GE(SSUB16, gen_helper_ssub16)
7113 DO_PAR_ADDSUB_GE(SADD8, gen_helper_sadd8)
7114 DO_PAR_ADDSUB_GE(SSUB8, gen_helper_ssub8)
7116 DO_PAR_ADDSUB_GE(UADD16, gen_helper_uadd16)
7117 DO_PAR_ADDSUB_GE(UASX, gen_helper_uaddsubx)
7118 DO_PAR_ADDSUB_GE(USAX, gen_helper_usubaddx)
7119 DO_PAR_ADDSUB_GE(USUB16, gen_helper_usub16)
7120 DO_PAR_ADDSUB_GE(UADD8, gen_helper_uadd8)
7121 DO_PAR_ADDSUB_GE(USUB8, gen_helper_usub8)
7123 DO_PAR_ADDSUB(QADD16, gen_helper_qadd16)
7124 DO_PAR_ADDSUB(QASX, gen_helper_qaddsubx)
7125 DO_PAR_ADDSUB(QSAX, gen_helper_qsubaddx)
7126 DO_PAR_ADDSUB(QSUB16, gen_helper_qsub16)
7127 DO_PAR_ADDSUB(QADD8, gen_helper_qadd8)
7128 DO_PAR_ADDSUB(QSUB8, gen_helper_qsub8)
7130 DO_PAR_ADDSUB(UQADD16, gen_helper_uqadd16)
7131 DO_PAR_ADDSUB(UQASX, gen_helper_uqaddsubx)
7132 DO_PAR_ADDSUB(UQSAX, gen_helper_uqsubaddx)
7133 DO_PAR_ADDSUB(UQSUB16, gen_helper_uqsub16)
7134 DO_PAR_ADDSUB(UQADD8, gen_helper_uqadd8)
7135 DO_PAR_ADDSUB(UQSUB8, gen_helper_uqsub8)
7137 DO_PAR_ADDSUB(SHADD16, gen_helper_shadd16)
7138 DO_PAR_ADDSUB(SHASX, gen_helper_shaddsubx)
7139 DO_PAR_ADDSUB(SHSAX, gen_helper_shsubaddx)
7140 DO_PAR_ADDSUB(SHSUB16, gen_helper_shsub16)
7141 DO_PAR_ADDSUB(SHADD8, gen_helper_shadd8)
7142 DO_PAR_ADDSUB(SHSUB8, gen_helper_shsub8)
7144 DO_PAR_ADDSUB(UHADD16, gen_helper_uhadd16)
7145 DO_PAR_ADDSUB(UHASX, gen_helper_uhaddsubx)
7146 DO_PAR_ADDSUB(UHSAX, gen_helper_uhsubaddx)
7147 DO_PAR_ADDSUB(UHSUB16, gen_helper_uhsub16)
7148 DO_PAR_ADDSUB(UHADD8, gen_helper_uhadd8)
7149 DO_PAR_ADDSUB(UHSUB8, gen_helper_uhsub8)
7151 #undef DO_PAR_ADDSUB
7152 #undef DO_PAR_ADDSUB_GE
7155 * Packing, unpacking, saturation, and reversal
7158 static bool trans_PKH(DisasContext *s, arg_PKH *a)
7160 TCGv_i32 tn, tm;
7161 int shift = a->imm;
7163 if (s->thumb
7164 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
7165 : !ENABLE_ARCH_6) {
7166 return false;
7169 tn = load_reg(s, a->rn);
7170 tm = load_reg(s, a->rm);
7171 if (a->tb) {
7172 /* PKHTB */
7173 if (shift == 0) {
7174 shift = 31;
7176 tcg_gen_sari_i32(tm, tm, shift);
7177 tcg_gen_deposit_i32(tn, tn, tm, 0, 16);
7178 } else {
7179 /* PKHBT */
7180 tcg_gen_shli_i32(tm, tm, shift);
7181 tcg_gen_deposit_i32(tn, tm, tn, 0, 16);
7183 tcg_temp_free_i32(tm);
7184 store_reg(s, a->rd, tn);
7185 return true;
7188 static bool op_sat(DisasContext *s, arg_sat *a,
7189 void (*gen)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32))
7191 TCGv_i32 tmp, satimm;
7192 int shift = a->imm;
7194 if (!ENABLE_ARCH_6) {
7195 return false;
7198 tmp = load_reg(s, a->rn);
7199 if (a->sh) {
7200 tcg_gen_sari_i32(tmp, tmp, shift ? shift : 31);
7201 } else {
7202 tcg_gen_shli_i32(tmp, tmp, shift);
7205 satimm = tcg_const_i32(a->satimm);
7206 gen(tmp, cpu_env, tmp, satimm);
7207 tcg_temp_free_i32(satimm);
7209 store_reg(s, a->rd, tmp);
7210 return true;
7213 static bool trans_SSAT(DisasContext *s, arg_sat *a)
7215 return op_sat(s, a, gen_helper_ssat);
7218 static bool trans_USAT(DisasContext *s, arg_sat *a)
7220 return op_sat(s, a, gen_helper_usat);
7223 static bool trans_SSAT16(DisasContext *s, arg_sat *a)
7225 if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
7226 return false;
7228 return op_sat(s, a, gen_helper_ssat16);
7231 static bool trans_USAT16(DisasContext *s, arg_sat *a)
7233 if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
7234 return false;
7236 return op_sat(s, a, gen_helper_usat16);
7239 static bool op_xta(DisasContext *s, arg_rrr_rot *a,
7240 void (*gen_extract)(TCGv_i32, TCGv_i32),
7241 void (*gen_add)(TCGv_i32, TCGv_i32, TCGv_i32))
7243 TCGv_i32 tmp;
7245 if (!ENABLE_ARCH_6) {
7246 return false;
7249 tmp = load_reg(s, a->rm);
7251 * TODO: In many cases we could do a shift instead of a rotate.
7252 * Combined with a simple extend, that becomes an extract.
7254 tcg_gen_rotri_i32(tmp, tmp, a->rot * 8);
7255 gen_extract(tmp, tmp);
7257 if (a->rn != 15) {
7258 TCGv_i32 tmp2 = load_reg(s, a->rn);
7259 gen_add(tmp, tmp, tmp2);
7260 tcg_temp_free_i32(tmp2);
7262 store_reg(s, a->rd, tmp);
7263 return true;
7266 static bool trans_SXTAB(DisasContext *s, arg_rrr_rot *a)
7268 return op_xta(s, a, tcg_gen_ext8s_i32, tcg_gen_add_i32);
7271 static bool trans_SXTAH(DisasContext *s, arg_rrr_rot *a)
7273 return op_xta(s, a, tcg_gen_ext16s_i32, tcg_gen_add_i32);
7276 static bool trans_SXTAB16(DisasContext *s, arg_rrr_rot *a)
7278 if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
7279 return false;
7281 return op_xta(s, a, gen_helper_sxtb16, gen_add16);
7284 static bool trans_UXTAB(DisasContext *s, arg_rrr_rot *a)
7286 return op_xta(s, a, tcg_gen_ext8u_i32, tcg_gen_add_i32);
7289 static bool trans_UXTAH(DisasContext *s, arg_rrr_rot *a)
7291 return op_xta(s, a, tcg_gen_ext16u_i32, tcg_gen_add_i32);
7294 static bool trans_UXTAB16(DisasContext *s, arg_rrr_rot *a)
7296 if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
7297 return false;
7299 return op_xta(s, a, gen_helper_uxtb16, gen_add16);
7302 static bool trans_SEL(DisasContext *s, arg_rrr *a)
7304 TCGv_i32 t1, t2, t3;
7306 if (s->thumb
7307 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
7308 : !ENABLE_ARCH_6) {
7309 return false;
7312 t1 = load_reg(s, a->rn);
7313 t2 = load_reg(s, a->rm);
7314 t3 = tcg_temp_new_i32();
7315 tcg_gen_ld_i32(t3, cpu_env, offsetof(CPUARMState, GE));
7316 gen_helper_sel_flags(t1, t3, t1, t2);
7317 tcg_temp_free_i32(t3);
7318 tcg_temp_free_i32(t2);
7319 store_reg(s, a->rd, t1);
7320 return true;
7323 static bool op_rr(DisasContext *s, arg_rr *a,
7324 void (*gen)(TCGv_i32, TCGv_i32))
7326 TCGv_i32 tmp;
7328 tmp = load_reg(s, a->rm);
7329 gen(tmp, tmp);
7330 store_reg(s, a->rd, tmp);
7331 return true;
7334 static bool trans_REV(DisasContext *s, arg_rr *a)
7336 if (!ENABLE_ARCH_6) {
7337 return false;
7339 return op_rr(s, a, tcg_gen_bswap32_i32);
7342 static bool trans_REV16(DisasContext *s, arg_rr *a)
7344 if (!ENABLE_ARCH_6) {
7345 return false;
7347 return op_rr(s, a, gen_rev16);
7350 static bool trans_REVSH(DisasContext *s, arg_rr *a)
7352 if (!ENABLE_ARCH_6) {
7353 return false;
7355 return op_rr(s, a, gen_revsh);
7358 static bool trans_RBIT(DisasContext *s, arg_rr *a)
7360 if (!ENABLE_ARCH_6T2) {
7361 return false;
7363 return op_rr(s, a, gen_helper_rbit);
7367 * Signed multiply, signed and unsigned divide
7370 static bool op_smlad(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub)
7372 TCGv_i32 t1, t2;
7374 if (!ENABLE_ARCH_6) {
7375 return false;
7378 t1 = load_reg(s, a->rn);
7379 t2 = load_reg(s, a->rm);
7380 if (m_swap) {
7381 gen_swap_half(t2, t2);
7383 gen_smul_dual(t1, t2);
7385 if (sub) {
7386 /* This subtraction cannot overflow. */
7387 tcg_gen_sub_i32(t1, t1, t2);
7388 } else {
7390 * This addition cannot overflow 32 bits; however it may
7391 * overflow considered as a signed operation, in which case
7392 * we must set the Q flag.
7394 gen_helper_add_setq(t1, cpu_env, t1, t2);
7396 tcg_temp_free_i32(t2);
7398 if (a->ra != 15) {
7399 t2 = load_reg(s, a->ra);
7400 gen_helper_add_setq(t1, cpu_env, t1, t2);
7401 tcg_temp_free_i32(t2);
7403 store_reg(s, a->rd, t1);
7404 return true;
7407 static bool trans_SMLAD(DisasContext *s, arg_rrrr *a)
7409 return op_smlad(s, a, false, false);
7412 static bool trans_SMLADX(DisasContext *s, arg_rrrr *a)
7414 return op_smlad(s, a, true, false);
7417 static bool trans_SMLSD(DisasContext *s, arg_rrrr *a)
7419 return op_smlad(s, a, false, true);
7422 static bool trans_SMLSDX(DisasContext *s, arg_rrrr *a)
7424 return op_smlad(s, a, true, true);
7427 static bool op_smlald(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub)
7429 TCGv_i32 t1, t2;
7430 TCGv_i64 l1, l2;
7432 if (!ENABLE_ARCH_6) {
7433 return false;
7436 t1 = load_reg(s, a->rn);
7437 t2 = load_reg(s, a->rm);
7438 if (m_swap) {
7439 gen_swap_half(t2, t2);
7441 gen_smul_dual(t1, t2);
7443 l1 = tcg_temp_new_i64();
7444 l2 = tcg_temp_new_i64();
7445 tcg_gen_ext_i32_i64(l1, t1);
7446 tcg_gen_ext_i32_i64(l2, t2);
7447 tcg_temp_free_i32(t1);
7448 tcg_temp_free_i32(t2);
7450 if (sub) {
7451 tcg_gen_sub_i64(l1, l1, l2);
7452 } else {
7453 tcg_gen_add_i64(l1, l1, l2);
7455 tcg_temp_free_i64(l2);
7457 gen_addq(s, l1, a->ra, a->rd);
7458 gen_storeq_reg(s, a->ra, a->rd, l1);
7459 tcg_temp_free_i64(l1);
7460 return true;
7463 static bool trans_SMLALD(DisasContext *s, arg_rrrr *a)
7465 return op_smlald(s, a, false, false);
7468 static bool trans_SMLALDX(DisasContext *s, arg_rrrr *a)
7470 return op_smlald(s, a, true, false);
7473 static bool trans_SMLSLD(DisasContext *s, arg_rrrr *a)
7475 return op_smlald(s, a, false, true);
7478 static bool trans_SMLSLDX(DisasContext *s, arg_rrrr *a)
7480 return op_smlald(s, a, true, true);
7483 static bool op_smmla(DisasContext *s, arg_rrrr *a, bool round, bool sub)
7485 TCGv_i32 t1, t2;
7487 if (s->thumb
7488 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
7489 : !ENABLE_ARCH_6) {
7490 return false;
7493 t1 = load_reg(s, a->rn);
7494 t2 = load_reg(s, a->rm);
7495 tcg_gen_muls2_i32(t2, t1, t1, t2);
7497 if (a->ra != 15) {
7498 TCGv_i32 t3 = load_reg(s, a->ra);
7499 if (sub) {
7501 * For SMMLS, we need a 64-bit subtract. Borrow caused by
7502 * a non-zero multiplicand lowpart, and the correct result
7503 * lowpart for rounding.
7505 TCGv_i32 zero = tcg_const_i32(0);
7506 tcg_gen_sub2_i32(t2, t1, zero, t3, t2, t1);
7507 tcg_temp_free_i32(zero);
7508 } else {
7509 tcg_gen_add_i32(t1, t1, t3);
7511 tcg_temp_free_i32(t3);
7513 if (round) {
7515 * Adding 0x80000000 to the 64-bit quantity means that we have
7516 * carry in to the high word when the low word has the msb set.
7518 tcg_gen_shri_i32(t2, t2, 31);
7519 tcg_gen_add_i32(t1, t1, t2);
7521 tcg_temp_free_i32(t2);
7522 store_reg(s, a->rd, t1);
7523 return true;
7526 static bool trans_SMMLA(DisasContext *s, arg_rrrr *a)
7528 return op_smmla(s, a, false, false);
7531 static bool trans_SMMLAR(DisasContext *s, arg_rrrr *a)
7533 return op_smmla(s, a, true, false);
7536 static bool trans_SMMLS(DisasContext *s, arg_rrrr *a)
7538 return op_smmla(s, a, false, true);
7541 static bool trans_SMMLSR(DisasContext *s, arg_rrrr *a)
7543 return op_smmla(s, a, true, true);
7546 static bool op_div(DisasContext *s, arg_rrr *a, bool u)
7548 TCGv_i32 t1, t2;
7550 if (s->thumb
7551 ? !dc_isar_feature(aa32_thumb_div, s)
7552 : !dc_isar_feature(aa32_arm_div, s)) {
7553 return false;
7556 t1 = load_reg(s, a->rn);
7557 t2 = load_reg(s, a->rm);
7558 if (u) {
7559 gen_helper_udiv(t1, t1, t2);
7560 } else {
7561 gen_helper_sdiv(t1, t1, t2);
7563 tcg_temp_free_i32(t2);
7564 store_reg(s, a->rd, t1);
7565 return true;
7568 static bool trans_SDIV(DisasContext *s, arg_rrr *a)
7570 return op_div(s, a, false);
7573 static bool trans_UDIV(DisasContext *s, arg_rrr *a)
7575 return op_div(s, a, true);
7579 * Block data transfer
7582 static TCGv_i32 op_addr_block_pre(DisasContext *s, arg_ldst_block *a, int n)
7584 TCGv_i32 addr = load_reg(s, a->rn);
7586 if (a->b) {
7587 if (a->i) {
7588 /* pre increment */
7589 tcg_gen_addi_i32(addr, addr, 4);
7590 } else {
7591 /* pre decrement */
7592 tcg_gen_addi_i32(addr, addr, -(n * 4));
7594 } else if (!a->i && n != 1) {
7595 /* post decrement */
7596 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7599 if (s->v8m_stackcheck && a->rn == 13 && a->w) {
7601 * If the writeback is incrementing SP rather than
7602 * decrementing it, and the initial SP is below the
7603 * stack limit but the final written-back SP would
7604 * be above, then then we must not perform any memory
7605 * accesses, but it is IMPDEF whether we generate
7606 * an exception. We choose to do so in this case.
7607 * At this point 'addr' is the lowest address, so
7608 * either the original SP (if incrementing) or our
7609 * final SP (if decrementing), so that's what we check.
7611 gen_helper_v8m_stackcheck(cpu_env, addr);
7614 return addr;
7617 static void op_addr_block_post(DisasContext *s, arg_ldst_block *a,
7618 TCGv_i32 addr, int n)
7620 if (a->w) {
7621 /* write back */
7622 if (!a->b) {
7623 if (a->i) {
7624 /* post increment */
7625 tcg_gen_addi_i32(addr, addr, 4);
7626 } else {
7627 /* post decrement */
7628 tcg_gen_addi_i32(addr, addr, -(n * 4));
7630 } else if (!a->i && n != 1) {
7631 /* pre decrement */
7632 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7634 store_reg(s, a->rn, addr);
7635 } else {
7636 tcg_temp_free_i32(addr);
7640 static bool op_stm(DisasContext *s, arg_ldst_block *a, int min_n)
7642 int i, j, n, list, mem_idx;
7643 bool user = a->u;
7644 TCGv_i32 addr, tmp, tmp2;
7646 if (user) {
7647 /* STM (user) */
7648 if (IS_USER(s)) {
7649 /* Only usable in supervisor mode. */
7650 unallocated_encoding(s);
7651 return true;
7655 list = a->list;
7656 n = ctpop16(list);
7657 if (n < min_n || a->rn == 15) {
7658 unallocated_encoding(s);
7659 return true;
7662 addr = op_addr_block_pre(s, a, n);
7663 mem_idx = get_mem_index(s);
7665 for (i = j = 0; i < 16; i++) {
7666 if (!(list & (1 << i))) {
7667 continue;
7670 if (user && i != 15) {
7671 tmp = tcg_temp_new_i32();
7672 tmp2 = tcg_const_i32(i);
7673 gen_helper_get_user_reg(tmp, cpu_env, tmp2);
7674 tcg_temp_free_i32(tmp2);
7675 } else {
7676 tmp = load_reg(s, i);
7678 gen_aa32_st32(s, tmp, addr, mem_idx);
7679 tcg_temp_free_i32(tmp);
7681 /* No need to add after the last transfer. */
7682 if (++j != n) {
7683 tcg_gen_addi_i32(addr, addr, 4);
7687 op_addr_block_post(s, a, addr, n);
7688 return true;
7691 static bool trans_STM(DisasContext *s, arg_ldst_block *a)
7693 /* BitCount(list) < 1 is UNPREDICTABLE */
7694 return op_stm(s, a, 1);
7697 static bool trans_STM_t32(DisasContext *s, arg_ldst_block *a)
7699 /* Writeback register in register list is UNPREDICTABLE for T32. */
7700 if (a->w && (a->list & (1 << a->rn))) {
7701 unallocated_encoding(s);
7702 return true;
7704 /* BitCount(list) < 2 is UNPREDICTABLE */
7705 return op_stm(s, a, 2);
7708 static bool do_ldm(DisasContext *s, arg_ldst_block *a, int min_n)
7710 int i, j, n, list, mem_idx;
7711 bool loaded_base;
7712 bool user = a->u;
7713 bool exc_return = false;
7714 TCGv_i32 addr, tmp, tmp2, loaded_var;
7716 if (user) {
7717 /* LDM (user), LDM (exception return) */
7718 if (IS_USER(s)) {
7719 /* Only usable in supervisor mode. */
7720 unallocated_encoding(s);
7721 return true;
7723 if (extract32(a->list, 15, 1)) {
7724 exc_return = true;
7725 user = false;
7726 } else {
7727 /* LDM (user) does not allow writeback. */
7728 if (a->w) {
7729 unallocated_encoding(s);
7730 return true;
7735 list = a->list;
7736 n = ctpop16(list);
7737 if (n < min_n || a->rn == 15) {
7738 unallocated_encoding(s);
7739 return true;
7742 addr = op_addr_block_pre(s, a, n);
7743 mem_idx = get_mem_index(s);
7744 loaded_base = false;
7745 loaded_var = NULL;
7747 for (i = j = 0; i < 16; i++) {
7748 if (!(list & (1 << i))) {
7749 continue;
7752 tmp = tcg_temp_new_i32();
7753 gen_aa32_ld32u(s, tmp, addr, mem_idx);
7754 if (user) {
7755 tmp2 = tcg_const_i32(i);
7756 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
7757 tcg_temp_free_i32(tmp2);
7758 tcg_temp_free_i32(tmp);
7759 } else if (i == a->rn) {
7760 loaded_var = tmp;
7761 loaded_base = true;
7762 } else if (i == 15 && exc_return) {
7763 store_pc_exc_ret(s, tmp);
7764 } else {
7765 store_reg_from_load(s, i, tmp);
7768 /* No need to add after the last transfer. */
7769 if (++j != n) {
7770 tcg_gen_addi_i32(addr, addr, 4);
7774 op_addr_block_post(s, a, addr, n);
7776 if (loaded_base) {
7777 /* Note that we reject base == pc above. */
7778 store_reg(s, a->rn, loaded_var);
7781 if (exc_return) {
7782 /* Restore CPSR from SPSR. */
7783 tmp = load_cpu_field(spsr);
7784 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
7785 gen_io_start();
7787 gen_helper_cpsr_write_eret(cpu_env, tmp);
7788 tcg_temp_free_i32(tmp);
7789 /* Must exit loop to check un-masked IRQs */
7790 s->base.is_jmp = DISAS_EXIT;
7792 return true;
7795 static bool trans_LDM_a32(DisasContext *s, arg_ldst_block *a)
7798 * Writeback register in register list is UNPREDICTABLE
7799 * for ArchVersion() >= 7. Prior to v7, A32 would write
7800 * an UNKNOWN value to the base register.
7802 if (ENABLE_ARCH_7 && a->w && (a->list & (1 << a->rn))) {
7803 unallocated_encoding(s);
7804 return true;
7806 /* BitCount(list) < 1 is UNPREDICTABLE */
7807 return do_ldm(s, a, 1);
7810 static bool trans_LDM_t32(DisasContext *s, arg_ldst_block *a)
7812 /* Writeback register in register list is UNPREDICTABLE for T32. */
7813 if (a->w && (a->list & (1 << a->rn))) {
7814 unallocated_encoding(s);
7815 return true;
7817 /* BitCount(list) < 2 is UNPREDICTABLE */
7818 return do_ldm(s, a, 2);
7821 static bool trans_LDM_t16(DisasContext *s, arg_ldst_block *a)
7823 /* Writeback is conditional on the base register not being loaded. */
7824 a->w = !(a->list & (1 << a->rn));
7825 /* BitCount(list) < 1 is UNPREDICTABLE */
7826 return do_ldm(s, a, 1);
7830 * Branch, branch with link
7833 static bool trans_B(DisasContext *s, arg_i *a)
7835 gen_jmp(s, read_pc(s) + a->imm);
7836 return true;
7839 static bool trans_B_cond_thumb(DisasContext *s, arg_ci *a)
7841 /* This has cond from encoding, required to be outside IT block. */
7842 if (a->cond >= 0xe) {
7843 return false;
7845 if (s->condexec_mask) {
7846 unallocated_encoding(s);
7847 return true;
7849 arm_skip_unless(s, a->cond);
7850 gen_jmp(s, read_pc(s) + a->imm);
7851 return true;
7854 static bool trans_BL(DisasContext *s, arg_i *a)
7856 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
7857 gen_jmp(s, read_pc(s) + a->imm);
7858 return true;
7861 static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
7863 TCGv_i32 tmp;
7865 /* For A32, ARCH(5) is checked near the start of the uncond block. */
7866 if (s->thumb && (a->imm & 2)) {
7867 return false;
7869 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
7870 tmp = tcg_const_i32(!s->thumb);
7871 store_cpu_field(tmp, thumb);
7872 gen_jmp(s, (read_pc(s) & ~3) + a->imm);
7873 return true;
7876 static bool trans_BL_BLX_prefix(DisasContext *s, arg_BL_BLX_prefix *a)
7878 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
7879 tcg_gen_movi_i32(cpu_R[14], read_pc(s) + (a->imm << 12));
7880 return true;
7883 static bool trans_BL_suffix(DisasContext *s, arg_BL_suffix *a)
7885 TCGv_i32 tmp = tcg_temp_new_i32();
7887 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
7888 tcg_gen_addi_i32(tmp, cpu_R[14], (a->imm << 1) | 1);
7889 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | 1);
7890 gen_bx(s, tmp);
7891 return true;
7894 static bool trans_BLX_suffix(DisasContext *s, arg_BLX_suffix *a)
7896 TCGv_i32 tmp;
7898 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
7899 if (!ENABLE_ARCH_5) {
7900 return false;
7902 tmp = tcg_temp_new_i32();
7903 tcg_gen_addi_i32(tmp, cpu_R[14], a->imm << 1);
7904 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
7905 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | 1);
7906 gen_bx(s, tmp);
7907 return true;
7910 static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
7912 TCGv_i32 addr, tmp;
7914 tmp = load_reg(s, a->rm);
7915 if (half) {
7916 tcg_gen_add_i32(tmp, tmp, tmp);
7918 addr = load_reg(s, a->rn);
7919 tcg_gen_add_i32(addr, addr, tmp);
7921 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s),
7922 half ? MO_UW | s->be_data : MO_UB);
7923 tcg_temp_free_i32(addr);
7925 tcg_gen_add_i32(tmp, tmp, tmp);
7926 tcg_gen_addi_i32(tmp, tmp, read_pc(s));
7927 store_reg(s, 15, tmp);
7928 return true;
7931 static bool trans_TBB(DisasContext *s, arg_tbranch *a)
7933 return op_tbranch(s, a, false);
7936 static bool trans_TBH(DisasContext *s, arg_tbranch *a)
7938 return op_tbranch(s, a, true);
7941 static bool trans_CBZ(DisasContext *s, arg_CBZ *a)
7943 TCGv_i32 tmp = load_reg(s, a->rn);
7945 arm_gen_condlabel(s);
7946 tcg_gen_brcondi_i32(a->nz ? TCG_COND_EQ : TCG_COND_NE,
7947 tmp, 0, s->condlabel);
7948 tcg_temp_free_i32(tmp);
7949 gen_jmp(s, read_pc(s) + a->imm);
7950 return true;
7954 * Supervisor call - both T32 & A32 come here so we need to check
7955 * which mode we are in when checking for semihosting.
7958 static bool trans_SVC(DisasContext *s, arg_SVC *a)
7960 const uint32_t semihost_imm = s->thumb ? 0xab : 0x123456;
7962 if (!arm_dc_feature(s, ARM_FEATURE_M) && semihosting_enabled() &&
7963 #ifndef CONFIG_USER_ONLY
7964 !IS_USER(s) &&
7965 #endif
7966 (a->imm == semihost_imm)) {
7967 gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
7968 } else {
7969 gen_set_pc_im(s, s->base.pc_next);
7970 s->svc_imm = a->imm;
7971 s->base.is_jmp = DISAS_SWI;
7973 return true;
7977 * Unconditional system instructions
7980 static bool trans_RFE(DisasContext *s, arg_RFE *a)
7982 static const int8_t pre_offset[4] = {
7983 /* DA */ -4, /* IA */ 0, /* DB */ -8, /* IB */ 4
7985 static const int8_t post_offset[4] = {
7986 /* DA */ -8, /* IA */ 4, /* DB */ -4, /* IB */ 0
7988 TCGv_i32 addr, t1, t2;
7990 if (!ENABLE_ARCH_6 || arm_dc_feature(s, ARM_FEATURE_M)) {
7991 return false;
7993 if (IS_USER(s)) {
7994 unallocated_encoding(s);
7995 return true;
7998 addr = load_reg(s, a->rn);
7999 tcg_gen_addi_i32(addr, addr, pre_offset[a->pu]);
8001 /* Load PC into tmp and CPSR into tmp2. */
8002 t1 = tcg_temp_new_i32();
8003 gen_aa32_ld32u(s, t1, addr, get_mem_index(s));
8004 tcg_gen_addi_i32(addr, addr, 4);
8005 t2 = tcg_temp_new_i32();
8006 gen_aa32_ld32u(s, t2, addr, get_mem_index(s));
8008 if (a->w) {
8009 /* Base writeback. */
8010 tcg_gen_addi_i32(addr, addr, post_offset[a->pu]);
8011 store_reg(s, a->rn, addr);
8012 } else {
8013 tcg_temp_free_i32(addr);
8015 gen_rfe(s, t1, t2);
8016 return true;
8019 static bool trans_SRS(DisasContext *s, arg_SRS *a)
8021 if (!ENABLE_ARCH_6 || arm_dc_feature(s, ARM_FEATURE_M)) {
8022 return false;
8024 gen_srs(s, a->mode, a->pu, a->w);
8025 return true;
8028 static bool trans_CPS(DisasContext *s, arg_CPS *a)
8030 uint32_t mask, val;
8032 if (!ENABLE_ARCH_6 || arm_dc_feature(s, ARM_FEATURE_M)) {
8033 return false;
8035 if (IS_USER(s)) {
8036 /* Implemented as NOP in user mode. */
8037 return true;
8039 /* TODO: There are quite a lot of UNPREDICTABLE argument combinations. */
8041 mask = val = 0;
8042 if (a->imod & 2) {
8043 if (a->A) {
8044 mask |= CPSR_A;
8046 if (a->I) {
8047 mask |= CPSR_I;
8049 if (a->F) {
8050 mask |= CPSR_F;
8052 if (a->imod & 1) {
8053 val |= mask;
8056 if (a->M) {
8057 mask |= CPSR_M;
8058 val |= a->mode;
8060 if (mask) {
8061 gen_set_psr_im(s, mask, 0, val);
8063 return true;
8066 static bool trans_CPS_v7m(DisasContext *s, arg_CPS_v7m *a)
8068 TCGv_i32 tmp, addr, el;
8070 if (!arm_dc_feature(s, ARM_FEATURE_M)) {
8071 return false;
8073 if (IS_USER(s)) {
8074 /* Implemented as NOP in user mode. */
8075 return true;
8078 tmp = tcg_const_i32(a->im);
8079 /* FAULTMASK */
8080 if (a->F) {
8081 addr = tcg_const_i32(19);
8082 gen_helper_v7m_msr(cpu_env, addr, tmp);
8083 tcg_temp_free_i32(addr);
8085 /* PRIMASK */
8086 if (a->I) {
8087 addr = tcg_const_i32(16);
8088 gen_helper_v7m_msr(cpu_env, addr, tmp);
8089 tcg_temp_free_i32(addr);
8091 el = tcg_const_i32(s->current_el);
8092 gen_helper_rebuild_hflags_m32(cpu_env, el);
8093 tcg_temp_free_i32(el);
8094 tcg_temp_free_i32(tmp);
8095 gen_lookup_tb(s);
8096 return true;
8100 * Clear-Exclusive, Barriers
8103 static bool trans_CLREX(DisasContext *s, arg_CLREX *a)
8105 if (s->thumb
8106 ? !ENABLE_ARCH_7 && !arm_dc_feature(s, ARM_FEATURE_M)
8107 : !ENABLE_ARCH_6K) {
8108 return false;
8110 gen_clrex(s);
8111 return true;
8114 static bool trans_DSB(DisasContext *s, arg_DSB *a)
8116 if (!ENABLE_ARCH_7 && !arm_dc_feature(s, ARM_FEATURE_M)) {
8117 return false;
8119 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
8120 return true;
8123 static bool trans_DMB(DisasContext *s, arg_DMB *a)
8125 return trans_DSB(s, NULL);
8128 static bool trans_ISB(DisasContext *s, arg_ISB *a)
8130 if (!ENABLE_ARCH_7 && !arm_dc_feature(s, ARM_FEATURE_M)) {
8131 return false;
8134 * We need to break the TB after this insn to execute
8135 * self-modifying code correctly and also to take
8136 * any pending interrupts immediately.
8138 gen_goto_tb(s, 0, s->base.pc_next);
8139 return true;
8142 static bool trans_SB(DisasContext *s, arg_SB *a)
8144 if (!dc_isar_feature(aa32_sb, s)) {
8145 return false;
8148 * TODO: There is no speculation barrier opcode
8149 * for TCG; MB and end the TB instead.
8151 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
8152 gen_goto_tb(s, 0, s->base.pc_next);
8153 return true;
8156 static bool trans_SETEND(DisasContext *s, arg_SETEND *a)
8158 if (!ENABLE_ARCH_6) {
8159 return false;
8161 if (a->E != (s->be_data == MO_BE)) {
8162 gen_helper_setend(cpu_env);
8163 s->base.is_jmp = DISAS_UPDATE_EXIT;
8165 return true;
8169 * Preload instructions
8170 * All are nops, contingent on the appropriate arch level.
8173 static bool trans_PLD(DisasContext *s, arg_PLD *a)
8175 return ENABLE_ARCH_5TE;
8178 static bool trans_PLDW(DisasContext *s, arg_PLD *a)
8180 return arm_dc_feature(s, ARM_FEATURE_V7MP);
8183 static bool trans_PLI(DisasContext *s, arg_PLD *a)
8185 return ENABLE_ARCH_7;
8189 * If-then
8192 static bool trans_IT(DisasContext *s, arg_IT *a)
8194 int cond_mask = a->cond_mask;
8197 * No actual code generated for this insn, just setup state.
8199 * Combinations of firstcond and mask which set up an 0b1111
8200 * condition are UNPREDICTABLE; we take the CONSTRAINED
8201 * UNPREDICTABLE choice to treat 0b1111 the same as 0b1110,
8202 * i.e. both meaning "execute always".
8204 s->condexec_cond = (cond_mask >> 4) & 0xe;
8205 s->condexec_mask = cond_mask & 0x1f;
8206 return true;
8210 * Legacy decoder.
8213 static void disas_arm_insn(DisasContext *s, unsigned int insn)
8215 unsigned int cond = insn >> 28;
8217 /* M variants do not implement ARM mode; this must raise the INVSTATE
8218 * UsageFault exception.
8220 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8221 gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
8222 default_exception_el(s));
8223 return;
8226 if (cond == 0xf) {
8227 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
8228 * choose to UNDEF. In ARMv5 and above the space is used
8229 * for miscellaneous unconditional instructions.
8231 ARCH(5);
8233 /* Unconditional instructions. */
8234 /* TODO: Perhaps merge these into one decodetree output file. */
8235 if (disas_a32_uncond(s, insn) ||
8236 disas_vfp_uncond(s, insn) ||
8237 disas_neon_dp(s, insn) ||
8238 disas_neon_ls(s, insn) ||
8239 disas_neon_shared(s, insn)) {
8240 return;
8242 /* fall back to legacy decoder */
8244 if ((insn & 0x0e000f00) == 0x0c000100) {
8245 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
8246 /* iWMMXt register transfer. */
8247 if (extract32(s->c15_cpar, 1, 1)) {
8248 if (!disas_iwmmxt_insn(s, insn)) {
8249 return;
8254 goto illegal_op;
8256 if (cond != 0xe) {
8257 /* if not always execute, we generate a conditional jump to
8258 next instruction */
8259 arm_skip_unless(s, cond);
8262 /* TODO: Perhaps merge these into one decodetree output file. */
8263 if (disas_a32(s, insn) ||
8264 disas_vfp(s, insn)) {
8265 return;
8267 /* fall back to legacy decoder */
8269 switch ((insn >> 24) & 0xf) {
8270 case 0xc:
8271 case 0xd:
8272 case 0xe:
8273 if (((insn >> 8) & 0xe) == 10) {
8274 /* VFP, but failed disas_vfp. */
8275 goto illegal_op;
8277 if (disas_coproc_insn(s, insn)) {
8278 /* Coprocessor. */
8279 goto illegal_op;
8281 break;
8282 default:
8283 illegal_op:
8284 unallocated_encoding(s);
8285 break;
8289 static bool thumb_insn_is_16bit(DisasContext *s, uint32_t pc, uint32_t insn)
8292 * Return true if this is a 16 bit instruction. We must be precise
8293 * about this (matching the decode).
8295 if ((insn >> 11) < 0x1d) {
8296 /* Definitely a 16-bit instruction */
8297 return true;
8300 /* Top five bits 0b11101 / 0b11110 / 0b11111 : this is the
8301 * first half of a 32-bit Thumb insn. Thumb-1 cores might
8302 * end up actually treating this as two 16-bit insns, though,
8303 * if it's half of a bl/blx pair that might span a page boundary.
8305 if (arm_dc_feature(s, ARM_FEATURE_THUMB2) ||
8306 arm_dc_feature(s, ARM_FEATURE_M)) {
8307 /* Thumb2 cores (including all M profile ones) always treat
8308 * 32-bit insns as 32-bit.
8310 return false;
8313 if ((insn >> 11) == 0x1e && pc - s->page_start < TARGET_PAGE_SIZE - 3) {
8314 /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix, and the suffix
8315 * is not on the next page; we merge this into a 32-bit
8316 * insn.
8318 return false;
8320 /* 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF);
8321 * 0b1111_1xxx_xxxx_xxxx : BL suffix;
8322 * 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix on the end of a page
8323 * -- handle as single 16 bit insn
8325 return true;
8328 /* Translate a 32-bit thumb instruction. */
8329 static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
8332 * ARMv6-M supports a limited subset of Thumb2 instructions.
8333 * Other Thumb1 architectures allow only 32-bit
8334 * combined BL/BLX prefix and suffix.
8336 if (arm_dc_feature(s, ARM_FEATURE_M) &&
8337 !arm_dc_feature(s, ARM_FEATURE_V7)) {
8338 int i;
8339 bool found = false;
8340 static const uint32_t armv6m_insn[] = {0xf3808000 /* msr */,
8341 0xf3b08040 /* dsb */,
8342 0xf3b08050 /* dmb */,
8343 0xf3b08060 /* isb */,
8344 0xf3e08000 /* mrs */,
8345 0xf000d000 /* bl */};
8346 static const uint32_t armv6m_mask[] = {0xffe0d000,
8347 0xfff0d0f0,
8348 0xfff0d0f0,
8349 0xfff0d0f0,
8350 0xffe0d000,
8351 0xf800d000};
8353 for (i = 0; i < ARRAY_SIZE(armv6m_insn); i++) {
8354 if ((insn & armv6m_mask[i]) == armv6m_insn[i]) {
8355 found = true;
8356 break;
8359 if (!found) {
8360 goto illegal_op;
8362 } else if ((insn & 0xf800e800) != 0xf000e800) {
8363 ARCH(6T2);
8366 if ((insn & 0xef000000) == 0xef000000) {
8368 * T32 encodings 0b111p_1111_qqqq_qqqq_qqqq_qqqq_qqqq_qqqq
8369 * transform into
8370 * A32 encodings 0b1111_001p_qqqq_qqqq_qqqq_qqqq_qqqq_qqqq
8372 uint32_t a32_insn = (insn & 0xe2ffffff) |
8373 ((insn & (1 << 28)) >> 4) | (1 << 28);
8375 if (disas_neon_dp(s, a32_insn)) {
8376 return;
8380 if ((insn & 0xff100000) == 0xf9000000) {
8382 * T32 encodings 0b1111_1001_ppp0_qqqq_qqqq_qqqq_qqqq_qqqq
8383 * transform into
8384 * A32 encodings 0b1111_0100_ppp0_qqqq_qqqq_qqqq_qqqq_qqqq
8386 uint32_t a32_insn = (insn & 0x00ffffff) | 0xf4000000;
8388 if (disas_neon_ls(s, a32_insn)) {
8389 return;
8394 * TODO: Perhaps merge these into one decodetree output file.
8395 * Note disas_vfp is written for a32 with cond field in the
8396 * top nibble. The t32 encoding requires 0xe in the top nibble.
8398 if (disas_t32(s, insn) ||
8399 disas_vfp_uncond(s, insn) ||
8400 disas_neon_shared(s, insn) ||
8401 ((insn >> 28) == 0xe && disas_vfp(s, insn))) {
8402 return;
8404 /* fall back to legacy decoder */
8406 switch ((insn >> 25) & 0xf) {
8407 case 0: case 1: case 2: case 3:
8408 /* 16-bit instructions. Should never happen. */
8409 abort();
8410 case 6: case 7: case 14: case 15:
8411 /* Coprocessor. */
8412 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8413 /* 0b111x_11xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx */
8414 if (extract32(insn, 24, 2) == 3) {
8415 goto illegal_op; /* op0 = 0b11 : unallocated */
8418 if (((insn >> 8) & 0xe) == 10 &&
8419 dc_isar_feature(aa32_fpsp_v2, s)) {
8420 /* FP, and the CPU supports it */
8421 goto illegal_op;
8422 } else {
8423 /* All other insns: NOCP */
8424 gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
8425 syn_uncategorized(),
8426 default_exception_el(s));
8428 break;
8430 if (((insn >> 24) & 3) == 3) {
8431 /* Neon DP, but failed disas_neon_dp() */
8432 goto illegal_op;
8433 } else if (((insn >> 8) & 0xe) == 10) {
8434 /* VFP, but failed disas_vfp. */
8435 goto illegal_op;
8436 } else {
8437 if (insn & (1 << 28))
8438 goto illegal_op;
8439 if (disas_coproc_insn(s, insn)) {
8440 goto illegal_op;
8443 break;
8444 case 12:
8445 goto illegal_op;
8446 default:
8447 illegal_op:
8448 unallocated_encoding(s);
8452 static void disas_thumb_insn(DisasContext *s, uint32_t insn)
8454 if (!disas_t16(s, insn)) {
8455 unallocated_encoding(s);
8459 static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
8461 /* Return true if the insn at dc->base.pc_next might cross a page boundary.
8462 * (False positives are OK, false negatives are not.)
8463 * We know this is a Thumb insn, and our caller ensures we are
8464 * only called if dc->base.pc_next is less than 4 bytes from the page
8465 * boundary, so we cross the page if the first 16 bits indicate
8466 * that this is a 32 bit insn.
8468 uint16_t insn = arm_lduw_code(env, s->base.pc_next, s->sctlr_b);
8470 return !thumb_insn_is_16bit(s, s->base.pc_next, insn);
8473 static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
8475 DisasContext *dc = container_of(dcbase, DisasContext, base);
8476 CPUARMState *env = cs->env_ptr;
8477 ARMCPU *cpu = env_archcpu(env);
8478 uint32_t tb_flags = dc->base.tb->flags;
8479 uint32_t condexec, core_mmu_idx;
8481 dc->isar = &cpu->isar;
8482 dc->condjmp = 0;
8484 dc->aarch64 = 0;
8485 /* If we are coming from secure EL0 in a system with a 32-bit EL3, then
8486 * there is no secure EL1, so we route exceptions to EL3.
8488 dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
8489 !arm_el_is_aa64(env, 3);
8490 dc->thumb = FIELD_EX32(tb_flags, TBFLAG_AM32, THUMB);
8491 dc->be_data = FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
8492 condexec = FIELD_EX32(tb_flags, TBFLAG_AM32, CONDEXEC);
8493 dc->condexec_mask = (condexec & 0xf) << 1;
8494 dc->condexec_cond = condexec >> 4;
8496 core_mmu_idx = FIELD_EX32(tb_flags, TBFLAG_ANY, MMUIDX);
8497 dc->mmu_idx = core_to_arm_mmu_idx(env, core_mmu_idx);
8498 dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
8499 #if !defined(CONFIG_USER_ONLY)
8500 dc->user = (dc->current_el == 0);
8501 #endif
8502 dc->fp_excp_el = FIELD_EX32(tb_flags, TBFLAG_ANY, FPEXC_EL);
8504 if (arm_feature(env, ARM_FEATURE_M)) {
8505 dc->vfp_enabled = 1;
8506 dc->be_data = MO_TE;
8507 dc->v7m_handler_mode = FIELD_EX32(tb_flags, TBFLAG_M32, HANDLER);
8508 dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
8509 regime_is_secure(env, dc->mmu_idx);
8510 dc->v8m_stackcheck = FIELD_EX32(tb_flags, TBFLAG_M32, STACKCHECK);
8511 dc->v8m_fpccr_s_wrong =
8512 FIELD_EX32(tb_flags, TBFLAG_M32, FPCCR_S_WRONG);
8513 dc->v7m_new_fp_ctxt_needed =
8514 FIELD_EX32(tb_flags, TBFLAG_M32, NEW_FP_CTXT_NEEDED);
8515 dc->v7m_lspact = FIELD_EX32(tb_flags, TBFLAG_M32, LSPACT);
8516 } else {
8517 dc->be_data =
8518 FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
8519 dc->debug_target_el =
8520 FIELD_EX32(tb_flags, TBFLAG_ANY, DEBUG_TARGET_EL);
8521 dc->sctlr_b = FIELD_EX32(tb_flags, TBFLAG_A32, SCTLR_B);
8522 dc->hstr_active = FIELD_EX32(tb_flags, TBFLAG_A32, HSTR_ACTIVE);
8523 dc->ns = FIELD_EX32(tb_flags, TBFLAG_A32, NS);
8524 dc->vfp_enabled = FIELD_EX32(tb_flags, TBFLAG_A32, VFPEN);
8525 if (arm_feature(env, ARM_FEATURE_XSCALE)) {
8526 dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR);
8527 } else {
8528 dc->vec_len = FIELD_EX32(tb_flags, TBFLAG_A32, VECLEN);
8529 dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE);
8532 dc->cp_regs = cpu->cp_regs;
8533 dc->features = env->features;
8535 /* Single step state. The code-generation logic here is:
8536 * SS_ACTIVE == 0:
8537 * generate code with no special handling for single-stepping (except
8538 * that anything that can make us go to SS_ACTIVE == 1 must end the TB;
8539 * this happens anyway because those changes are all system register or
8540 * PSTATE writes).
8541 * SS_ACTIVE == 1, PSTATE.SS == 1: (active-not-pending)
8542 * emit code for one insn
8543 * emit code to clear PSTATE.SS
8544 * emit code to generate software step exception for completed step
8545 * end TB (as usual for having generated an exception)
8546 * SS_ACTIVE == 1, PSTATE.SS == 0: (active-pending)
8547 * emit code to generate a software step exception
8548 * end the TB
8550 dc->ss_active = FIELD_EX32(tb_flags, TBFLAG_ANY, SS_ACTIVE);
8551 dc->pstate_ss = FIELD_EX32(tb_flags, TBFLAG_ANY, PSTATE_SS);
8552 dc->is_ldex = false;
8554 dc->page_start = dc->base.pc_first & TARGET_PAGE_MASK;
8556 /* If architectural single step active, limit to 1. */
8557 if (is_singlestepping(dc)) {
8558 dc->base.max_insns = 1;
8561 /* ARM is a fixed-length ISA. Bound the number of insns to execute
8562 to those left on the page. */
8563 if (!dc->thumb) {
8564 int bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
8565 dc->base.max_insns = MIN(dc->base.max_insns, bound);
8568 cpu_V0 = tcg_temp_new_i64();
8569 cpu_V1 = tcg_temp_new_i64();
8570 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8571 cpu_M0 = tcg_temp_new_i64();
8574 static void arm_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
8576 DisasContext *dc = container_of(dcbase, DisasContext, base);
8578 /* A note on handling of the condexec (IT) bits:
8580 * We want to avoid the overhead of having to write the updated condexec
8581 * bits back to the CPUARMState for every instruction in an IT block. So:
8582 * (1) if the condexec bits are not already zero then we write
8583 * zero back into the CPUARMState now. This avoids complications trying
8584 * to do it at the end of the block. (For example if we don't do this
8585 * it's hard to identify whether we can safely skip writing condexec
8586 * at the end of the TB, which we definitely want to do for the case
8587 * where a TB doesn't do anything with the IT state at all.)
8588 * (2) if we are going to leave the TB then we call gen_set_condexec()
8589 * which will write the correct value into CPUARMState if zero is wrong.
8590 * This is done both for leaving the TB at the end, and for leaving
8591 * it because of an exception we know will happen, which is done in
8592 * gen_exception_insn(). The latter is necessary because we need to
8593 * leave the TB with the PC/IT state just prior to execution of the
8594 * instruction which caused the exception.
8595 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
8596 * then the CPUARMState will be wrong and we need to reset it.
8597 * This is handled in the same way as restoration of the
8598 * PC in these situations; we save the value of the condexec bits
8599 * for each PC via tcg_gen_insn_start(), and restore_state_to_opc()
8600 * then uses this to restore them after an exception.
8602 * Note that there are no instructions which can read the condexec
8603 * bits, and none which can write non-static values to them, so
8604 * we don't need to care about whether CPUARMState is correct in the
8605 * middle of a TB.
8608 /* Reset the conditional execution bits immediately. This avoids
8609 complications trying to do it at the end of the block. */
8610 if (dc->condexec_mask || dc->condexec_cond) {
8611 TCGv_i32 tmp = tcg_temp_new_i32();
8612 tcg_gen_movi_i32(tmp, 0);
8613 store_cpu_field(tmp, condexec_bits);
8617 static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
8619 DisasContext *dc = container_of(dcbase, DisasContext, base);
8621 tcg_gen_insn_start(dc->base.pc_next,
8622 (dc->condexec_cond << 4) | (dc->condexec_mask >> 1),
8624 dc->insn_start = tcg_last_op();
8627 static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
8628 const CPUBreakpoint *bp)
8630 DisasContext *dc = container_of(dcbase, DisasContext, base);
8632 if (bp->flags & BP_CPU) {
8633 gen_set_condexec(dc);
8634 gen_set_pc_im(dc, dc->base.pc_next);
8635 gen_helper_check_breakpoints(cpu_env);
8636 /* End the TB early; it's likely not going to be executed */
8637 dc->base.is_jmp = DISAS_TOO_MANY;
8638 } else {
8639 gen_exception_internal_insn(dc, dc->base.pc_next, EXCP_DEBUG);
8640 /* The address covered by the breakpoint must be
8641 included in [tb->pc, tb->pc + tb->size) in order
8642 to for it to be properly cleared -- thus we
8643 increment the PC here so that the logic setting
8644 tb->size below does the right thing. */
8645 /* TODO: Advance PC by correct instruction length to
8646 * avoid disassembler error messages */
8647 dc->base.pc_next += 2;
8648 dc->base.is_jmp = DISAS_NORETURN;
8651 return true;
8654 static bool arm_pre_translate_insn(DisasContext *dc)
8656 #ifdef CONFIG_USER_ONLY
8657 /* Intercept jump to the magic kernel page. */
8658 if (dc->base.pc_next >= 0xffff0000) {
8659 /* We always get here via a jump, so know we are not in a
8660 conditional execution block. */
8661 gen_exception_internal(EXCP_KERNEL_TRAP);
8662 dc->base.is_jmp = DISAS_NORETURN;
8663 return true;
8665 #endif
8667 if (dc->ss_active && !dc->pstate_ss) {
8668 /* Singlestep state is Active-pending.
8669 * If we're in this state at the start of a TB then either
8670 * a) we just took an exception to an EL which is being debugged
8671 * and this is the first insn in the exception handler
8672 * b) debug exceptions were masked and we just unmasked them
8673 * without changing EL (eg by clearing PSTATE.D)
8674 * In either case we're going to take a swstep exception in the
8675 * "did not step an insn" case, and so the syndrome ISV and EX
8676 * bits should be zero.
8678 assert(dc->base.num_insns == 1);
8679 gen_swstep_exception(dc, 0, 0);
8680 dc->base.is_jmp = DISAS_NORETURN;
8681 return true;
8684 return false;
8687 static void arm_post_translate_insn(DisasContext *dc)
8689 if (dc->condjmp && !dc->base.is_jmp) {
8690 gen_set_label(dc->condlabel);
8691 dc->condjmp = 0;
8693 translator_loop_temp_check(&dc->base);
8696 static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
8698 DisasContext *dc = container_of(dcbase, DisasContext, base);
8699 CPUARMState *env = cpu->env_ptr;
8700 unsigned int insn;
8702 if (arm_pre_translate_insn(dc)) {
8703 return;
8706 dc->pc_curr = dc->base.pc_next;
8707 insn = arm_ldl_code(env, dc->base.pc_next, dc->sctlr_b);
8708 dc->insn = insn;
8709 dc->base.pc_next += 4;
8710 disas_arm_insn(dc, insn);
8712 arm_post_translate_insn(dc);
8714 /* ARM is a fixed-length ISA. We performed the cross-page check
8715 in init_disas_context by adjusting max_insns. */
8718 static bool thumb_insn_is_unconditional(DisasContext *s, uint32_t insn)
8720 /* Return true if this Thumb insn is always unconditional,
8721 * even inside an IT block. This is true of only a very few
8722 * instructions: BKPT, HLT, and SG.
8724 * A larger class of instructions are UNPREDICTABLE if used
8725 * inside an IT block; we do not need to detect those here, because
8726 * what we do by default (perform the cc check and update the IT
8727 * bits state machine) is a permitted CONSTRAINED UNPREDICTABLE
8728 * choice for those situations.
8730 * insn is either a 16-bit or a 32-bit instruction; the two are
8731 * distinguishable because for the 16-bit case the top 16 bits
8732 * are zeroes, and that isn't a valid 32-bit encoding.
8734 if ((insn & 0xffffff00) == 0xbe00) {
8735 /* BKPT */
8736 return true;
8739 if ((insn & 0xffffffc0) == 0xba80 && arm_dc_feature(s, ARM_FEATURE_V8) &&
8740 !arm_dc_feature(s, ARM_FEATURE_M)) {
8741 /* HLT: v8A only. This is unconditional even when it is going to
8742 * UNDEF; see the v8A ARM ARM DDI0487B.a H3.3.
8743 * For v7 cores this was a plain old undefined encoding and so
8744 * honours its cc check. (We might be using the encoding as
8745 * a semihosting trap, but we don't change the cc check behaviour
8746 * on that account, because a debugger connected to a real v7A
8747 * core and emulating semihosting traps by catching the UNDEF
8748 * exception would also only see cases where the cc check passed.
8749 * No guest code should be trying to do a HLT semihosting trap
8750 * in an IT block anyway.
8752 return true;
8755 if (insn == 0xe97fe97f && arm_dc_feature(s, ARM_FEATURE_V8) &&
8756 arm_dc_feature(s, ARM_FEATURE_M)) {
8757 /* SG: v8M only */
8758 return true;
8761 return false;
8764 static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
8766 DisasContext *dc = container_of(dcbase, DisasContext, base);
8767 CPUARMState *env = cpu->env_ptr;
8768 uint32_t insn;
8769 bool is_16bit;
8771 if (arm_pre_translate_insn(dc)) {
8772 return;
8775 dc->pc_curr = dc->base.pc_next;
8776 insn = arm_lduw_code(env, dc->base.pc_next, dc->sctlr_b);
8777 is_16bit = thumb_insn_is_16bit(dc, dc->base.pc_next, insn);
8778 dc->base.pc_next += 2;
8779 if (!is_16bit) {
8780 uint32_t insn2 = arm_lduw_code(env, dc->base.pc_next, dc->sctlr_b);
8782 insn = insn << 16 | insn2;
8783 dc->base.pc_next += 2;
8785 dc->insn = insn;
8787 if (dc->condexec_mask && !thumb_insn_is_unconditional(dc, insn)) {
8788 uint32_t cond = dc->condexec_cond;
8791 * Conditionally skip the insn. Note that both 0xe and 0xf mean
8792 * "always"; 0xf is not "never".
8794 if (cond < 0x0e) {
8795 arm_skip_unless(dc, cond);
8799 if (is_16bit) {
8800 disas_thumb_insn(dc, insn);
8801 } else {
8802 disas_thumb2_insn(dc, insn);
8805 /* Advance the Thumb condexec condition. */
8806 if (dc->condexec_mask) {
8807 dc->condexec_cond = ((dc->condexec_cond & 0xe) |
8808 ((dc->condexec_mask >> 4) & 1));
8809 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
8810 if (dc->condexec_mask == 0) {
8811 dc->condexec_cond = 0;
8815 arm_post_translate_insn(dc);
8817 /* Thumb is a variable-length ISA. Stop translation when the next insn
8818 * will touch a new page. This ensures that prefetch aborts occur at
8819 * the right place.
8821 * We want to stop the TB if the next insn starts in a new page,
8822 * or if it spans between this page and the next. This means that
8823 * if we're looking at the last halfword in the page we need to
8824 * see if it's a 16-bit Thumb insn (which will fit in this TB)
8825 * or a 32-bit Thumb insn (which won't).
8826 * This is to avoid generating a silly TB with a single 16-bit insn
8827 * in it at the end of this page (which would execute correctly
8828 * but isn't very efficient).
8830 if (dc->base.is_jmp == DISAS_NEXT
8831 && (dc->base.pc_next - dc->page_start >= TARGET_PAGE_SIZE
8832 || (dc->base.pc_next - dc->page_start >= TARGET_PAGE_SIZE - 3
8833 && insn_crosses_page(env, dc)))) {
8834 dc->base.is_jmp = DISAS_TOO_MANY;
8838 static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
8840 DisasContext *dc = container_of(dcbase, DisasContext, base);
8842 if (tb_cflags(dc->base.tb) & CF_LAST_IO && dc->condjmp) {
8843 /* FIXME: This can theoretically happen with self-modifying code. */
8844 cpu_abort(cpu, "IO on conditional branch instruction");
8847 /* At this stage dc->condjmp will only be set when the skipped
8848 instruction was a conditional branch or trap, and the PC has
8849 already been written. */
8850 gen_set_condexec(dc);
8851 if (dc->base.is_jmp == DISAS_BX_EXCRET) {
8852 /* Exception return branches need some special case code at the
8853 * end of the TB, which is complex enough that it has to
8854 * handle the single-step vs not and the condition-failed
8855 * insn codepath itself.
8857 gen_bx_excret_final_code(dc);
8858 } else if (unlikely(is_singlestepping(dc))) {
8859 /* Unconditional and "condition passed" instruction codepath. */
8860 switch (dc->base.is_jmp) {
8861 case DISAS_SWI:
8862 gen_ss_advance(dc);
8863 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
8864 default_exception_el(dc));
8865 break;
8866 case DISAS_HVC:
8867 gen_ss_advance(dc);
8868 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
8869 break;
8870 case DISAS_SMC:
8871 gen_ss_advance(dc);
8872 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
8873 break;
8874 case DISAS_NEXT:
8875 case DISAS_TOO_MANY:
8876 case DISAS_UPDATE_EXIT:
8877 case DISAS_UPDATE_NOCHAIN:
8878 gen_set_pc_im(dc, dc->base.pc_next);
8879 /* fall through */
8880 default:
8881 /* FIXME: Single stepping a WFI insn will not halt the CPU. */
8882 gen_singlestep_exception(dc);
8883 break;
8884 case DISAS_NORETURN:
8885 break;
8887 } else {
8888 /* While branches must always occur at the end of an IT block,
8889 there are a few other things that can cause us to terminate
8890 the TB in the middle of an IT block:
8891 - Exception generating instructions (bkpt, swi, undefined).
8892 - Page boundaries.
8893 - Hardware watchpoints.
8894 Hardware breakpoints have already been handled and skip this code.
8896 switch(dc->base.is_jmp) {
8897 case DISAS_NEXT:
8898 case DISAS_TOO_MANY:
8899 gen_goto_tb(dc, 1, dc->base.pc_next);
8900 break;
8901 case DISAS_UPDATE_NOCHAIN:
8902 gen_set_pc_im(dc, dc->base.pc_next);
8903 /* fall through */
8904 case DISAS_JUMP:
8905 gen_goto_ptr();
8906 break;
8907 case DISAS_UPDATE_EXIT:
8908 gen_set_pc_im(dc, dc->base.pc_next);
8909 /* fall through */
8910 default:
8911 /* indicate that the hash table must be used to find the next TB */
8912 tcg_gen_exit_tb(NULL, 0);
8913 break;
8914 case DISAS_NORETURN:
8915 /* nothing more to generate */
8916 break;
8917 case DISAS_WFI:
8919 TCGv_i32 tmp = tcg_const_i32((dc->thumb &&
8920 !(dc->insn & (1U << 31))) ? 2 : 4);
8922 gen_helper_wfi(cpu_env, tmp);
8923 tcg_temp_free_i32(tmp);
8924 /* The helper doesn't necessarily throw an exception, but we
8925 * must go back to the main loop to check for interrupts anyway.
8927 tcg_gen_exit_tb(NULL, 0);
8928 break;
8930 case DISAS_WFE:
8931 gen_helper_wfe(cpu_env);
8932 break;
8933 case DISAS_YIELD:
8934 gen_helper_yield(cpu_env);
8935 break;
8936 case DISAS_SWI:
8937 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
8938 default_exception_el(dc));
8939 break;
8940 case DISAS_HVC:
8941 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
8942 break;
8943 case DISAS_SMC:
8944 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
8945 break;
8949 if (dc->condjmp) {
8950 /* "Condition failed" instruction codepath for the branch/trap insn */
8951 gen_set_label(dc->condlabel);
8952 gen_set_condexec(dc);
8953 if (unlikely(is_singlestepping(dc))) {
8954 gen_set_pc_im(dc, dc->base.pc_next);
8955 gen_singlestep_exception(dc);
8956 } else {
8957 gen_goto_tb(dc, 1, dc->base.pc_next);
8962 static void arm_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
8964 DisasContext *dc = container_of(dcbase, DisasContext, base);
8966 qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
8967 log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size);
8970 static const TranslatorOps arm_translator_ops = {
8971 .init_disas_context = arm_tr_init_disas_context,
8972 .tb_start = arm_tr_tb_start,
8973 .insn_start = arm_tr_insn_start,
8974 .breakpoint_check = arm_tr_breakpoint_check,
8975 .translate_insn = arm_tr_translate_insn,
8976 .tb_stop = arm_tr_tb_stop,
8977 .disas_log = arm_tr_disas_log,
8980 static const TranslatorOps thumb_translator_ops = {
8981 .init_disas_context = arm_tr_init_disas_context,
8982 .tb_start = arm_tr_tb_start,
8983 .insn_start = arm_tr_insn_start,
8984 .breakpoint_check = arm_tr_breakpoint_check,
8985 .translate_insn = thumb_tr_translate_insn,
8986 .tb_stop = arm_tr_tb_stop,
8987 .disas_log = arm_tr_disas_log,
8990 /* generate intermediate code for basic block 'tb'. */
8991 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
8993 DisasContext dc = { };
8994 const TranslatorOps *ops = &arm_translator_ops;
8996 if (FIELD_EX32(tb->flags, TBFLAG_AM32, THUMB)) {
8997 ops = &thumb_translator_ops;
8999 #ifdef TARGET_AARCH64
9000 if (FIELD_EX32(tb->flags, TBFLAG_ANY, AARCH64_STATE)) {
9001 ops = &aarch64_translator_ops;
9003 #endif
9005 translator_loop(ops, &dc.base, cpu, tb, max_insns);
9008 void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb,
9009 target_ulong *data)
9011 if (is_a64(env)) {
9012 env->pc = data[0];
9013 env->condexec_bits = 0;
9014 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
9015 } else {
9016 env->regs[15] = data[0];
9017 env->condexec_bits = data[1];
9018 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;