cpu: Directly use get_memory_mapping() fallback handlers in place
[qemu/ar7.git] / target / arm / translate.c
blob8e0e55c1e0f51d946e893eb408b0d3c6609f4c58
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.1 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 "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 #include "translate.h"
53 #include "translate-a32.h"
55 /* These are TCG temporaries used only by the legacy iwMMXt decoder */
56 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
57 /* These are TCG globals which alias CPUARMState fields */
58 static TCGv_i32 cpu_R[16];
59 TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
60 TCGv_i64 cpu_exclusive_addr;
61 TCGv_i64 cpu_exclusive_val;
63 #include "exec/gen-icount.h"
65 static const char * const regnames[] =
66 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
67 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
70 /* initialize TCG globals. */
71 void arm_translate_init(void)
73 int i;
75 for (i = 0; i < 16; i++) {
76 cpu_R[i] = tcg_global_mem_new_i32(cpu_env,
77 offsetof(CPUARMState, regs[i]),
78 regnames[i]);
80 cpu_CF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, CF), "CF");
81 cpu_NF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, NF), "NF");
82 cpu_VF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, VF), "VF");
83 cpu_ZF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, ZF), "ZF");
85 cpu_exclusive_addr = tcg_global_mem_new_i64(cpu_env,
86 offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
87 cpu_exclusive_val = tcg_global_mem_new_i64(cpu_env,
88 offsetof(CPUARMState, exclusive_val), "exclusive_val");
90 a64_translate_init();
93 /* Generate a label used for skipping this instruction */
94 void arm_gen_condlabel(DisasContext *s)
96 if (!s->condjmp) {
97 s->condlabel = gen_new_label();
98 s->condjmp = 1;
102 /* Flags for the disas_set_da_iss info argument:
103 * lower bits hold the Rt register number, higher bits are flags.
105 typedef enum ISSInfo {
106 ISSNone = 0,
107 ISSRegMask = 0x1f,
108 ISSInvalid = (1 << 5),
109 ISSIsAcqRel = (1 << 6),
110 ISSIsWrite = (1 << 7),
111 ISSIs16Bit = (1 << 8),
112 } ISSInfo;
114 /* Save the syndrome information for a Data Abort */
115 static void disas_set_da_iss(DisasContext *s, MemOp memop, ISSInfo issinfo)
117 uint32_t syn;
118 int sas = memop & MO_SIZE;
119 bool sse = memop & MO_SIGN;
120 bool is_acqrel = issinfo & ISSIsAcqRel;
121 bool is_write = issinfo & ISSIsWrite;
122 bool is_16bit = issinfo & ISSIs16Bit;
123 int srt = issinfo & ISSRegMask;
125 if (issinfo & ISSInvalid) {
126 /* Some callsites want to conditionally provide ISS info,
127 * eg "only if this was not a writeback"
129 return;
132 if (srt == 15) {
133 /* For AArch32, insns where the src/dest is R15 never generate
134 * ISS information. Catching that here saves checking at all
135 * the call sites.
137 return;
140 syn = syn_data_abort_with_iss(0, sas, sse, srt, 0, is_acqrel,
141 0, 0, 0, is_write, 0, is_16bit);
142 disas_set_insn_syndrome(s, syn);
145 static inline int get_a32_user_mem_index(DisasContext *s)
147 /* Return the core mmu_idx to use for A32/T32 "unprivileged load/store"
148 * insns:
149 * if PL2, UNPREDICTABLE (we choose to implement as if PL0)
150 * otherwise, access as if at PL0.
152 switch (s->mmu_idx) {
153 case ARMMMUIdx_E2: /* this one is UNPREDICTABLE */
154 case ARMMMUIdx_E10_0:
155 case ARMMMUIdx_E10_1:
156 case ARMMMUIdx_E10_1_PAN:
157 return arm_to_core_mmu_idx(ARMMMUIdx_E10_0);
158 case ARMMMUIdx_SE3:
159 case ARMMMUIdx_SE10_0:
160 case ARMMMUIdx_SE10_1:
161 case ARMMMUIdx_SE10_1_PAN:
162 return arm_to_core_mmu_idx(ARMMMUIdx_SE10_0);
163 case ARMMMUIdx_MUser:
164 case ARMMMUIdx_MPriv:
165 return arm_to_core_mmu_idx(ARMMMUIdx_MUser);
166 case ARMMMUIdx_MUserNegPri:
167 case ARMMMUIdx_MPrivNegPri:
168 return arm_to_core_mmu_idx(ARMMMUIdx_MUserNegPri);
169 case ARMMMUIdx_MSUser:
170 case ARMMMUIdx_MSPriv:
171 return arm_to_core_mmu_idx(ARMMMUIdx_MSUser);
172 case ARMMMUIdx_MSUserNegPri:
173 case ARMMMUIdx_MSPrivNegPri:
174 return arm_to_core_mmu_idx(ARMMMUIdx_MSUserNegPri);
175 default:
176 g_assert_not_reached();
180 /* The architectural value of PC. */
181 static uint32_t read_pc(DisasContext *s)
183 return s->pc_curr + (s->thumb ? 4 : 8);
186 /* Set a variable to the value of a CPU register. */
187 void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
189 if (reg == 15) {
190 tcg_gen_movi_i32(var, read_pc(s));
191 } else {
192 tcg_gen_mov_i32(var, cpu_R[reg]);
197 * Create a new temp, REG + OFS, except PC is ALIGN(PC, 4).
198 * This is used for load/store for which use of PC implies (literal),
199 * or ADD that implies ADR.
201 TCGv_i32 add_reg_for_lit(DisasContext *s, int reg, int ofs)
203 TCGv_i32 tmp = tcg_temp_new_i32();
205 if (reg == 15) {
206 tcg_gen_movi_i32(tmp, (read_pc(s) & ~3) + ofs);
207 } else {
208 tcg_gen_addi_i32(tmp, cpu_R[reg], ofs);
210 return tmp;
213 /* Set a CPU register. The source must be a temporary and will be
214 marked as dead. */
215 void store_reg(DisasContext *s, int reg, TCGv_i32 var)
217 if (reg == 15) {
218 /* In Thumb mode, we must ignore bit 0.
219 * In ARM mode, for ARMv4 and ARMv5, it is UNPREDICTABLE if bits [1:0]
220 * are not 0b00, but for ARMv6 and above, we must ignore bits [1:0].
221 * We choose to ignore [1:0] in ARM mode for all architecture versions.
223 tcg_gen_andi_i32(var, var, s->thumb ? ~1 : ~3);
224 s->base.is_jmp = DISAS_JUMP;
226 tcg_gen_mov_i32(cpu_R[reg], var);
227 tcg_temp_free_i32(var);
231 * Variant of store_reg which applies v8M stack-limit checks before updating
232 * SP. If the check fails this will result in an exception being taken.
233 * We disable the stack checks for CONFIG_USER_ONLY because we have
234 * no idea what the stack limits should be in that case.
235 * If stack checking is not being done this just acts like store_reg().
237 static void store_sp_checked(DisasContext *s, TCGv_i32 var)
239 #ifndef CONFIG_USER_ONLY
240 if (s->v8m_stackcheck) {
241 gen_helper_v8m_stackcheck(cpu_env, var);
243 #endif
244 store_reg(s, 13, var);
247 /* Value extensions. */
248 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
249 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
250 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
251 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
253 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
254 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
256 void gen_set_cpsr(TCGv_i32 var, uint32_t mask)
258 TCGv_i32 tmp_mask = tcg_const_i32(mask);
259 gen_helper_cpsr_write(cpu_env, var, tmp_mask);
260 tcg_temp_free_i32(tmp_mask);
263 static void gen_exception_internal(int excp)
265 TCGv_i32 tcg_excp = tcg_const_i32(excp);
267 assert(excp_is_internal(excp));
268 gen_helper_exception_internal(cpu_env, tcg_excp);
269 tcg_temp_free_i32(tcg_excp);
272 static void gen_step_complete_exception(DisasContext *s)
274 /* We just completed step of an insn. Move from Active-not-pending
275 * to Active-pending, and then also take the swstep exception.
276 * This corresponds to making the (IMPDEF) choice to prioritize
277 * swstep exceptions over asynchronous exceptions taken to an exception
278 * level where debug is disabled. This choice has the advantage that
279 * we do not need to maintain internal state corresponding to the
280 * ISV/EX syndrome bits between completion of the step and generation
281 * of the exception, and our syndrome information is always correct.
283 gen_ss_advance(s);
284 gen_swstep_exception(s, 1, s->is_ldex);
285 s->base.is_jmp = DISAS_NORETURN;
288 static void gen_singlestep_exception(DisasContext *s)
290 /* Generate the right kind of exception for singlestep, which is
291 * either the architectural singlestep or EXCP_DEBUG for QEMU's
292 * gdb singlestepping.
294 if (s->ss_active) {
295 gen_step_complete_exception(s);
296 } else {
297 gen_exception_internal(EXCP_DEBUG);
301 static inline bool is_singlestepping(DisasContext *s)
303 /* Return true if we are singlestepping either because of
304 * architectural singlestep or QEMU gdbstub singlestep. This does
305 * not include the command line '-singlestep' mode which is rather
306 * misnamed as it only means "one instruction per TB" and doesn't
307 * affect the code we generate.
309 return s->base.singlestep_enabled || s->ss_active;
312 static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
314 TCGv_i32 tmp1 = tcg_temp_new_i32();
315 TCGv_i32 tmp2 = tcg_temp_new_i32();
316 tcg_gen_ext16s_i32(tmp1, a);
317 tcg_gen_ext16s_i32(tmp2, b);
318 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
319 tcg_temp_free_i32(tmp2);
320 tcg_gen_sari_i32(a, a, 16);
321 tcg_gen_sari_i32(b, b, 16);
322 tcg_gen_mul_i32(b, b, a);
323 tcg_gen_mov_i32(a, tmp1);
324 tcg_temp_free_i32(tmp1);
327 /* Byteswap each halfword. */
328 void gen_rev16(TCGv_i32 dest, TCGv_i32 var)
330 TCGv_i32 tmp = tcg_temp_new_i32();
331 TCGv_i32 mask = tcg_const_i32(0x00ff00ff);
332 tcg_gen_shri_i32(tmp, var, 8);
333 tcg_gen_and_i32(tmp, tmp, mask);
334 tcg_gen_and_i32(var, var, mask);
335 tcg_gen_shli_i32(var, var, 8);
336 tcg_gen_or_i32(dest, var, tmp);
337 tcg_temp_free_i32(mask);
338 tcg_temp_free_i32(tmp);
341 /* Byteswap low halfword and sign extend. */
342 static void gen_revsh(TCGv_i32 dest, TCGv_i32 var)
344 tcg_gen_ext16u_i32(var, var);
345 tcg_gen_bswap16_i32(var, var);
346 tcg_gen_ext16s_i32(dest, var);
349 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
350 tmp = (t0 ^ t1) & 0x8000;
351 t0 &= ~0x8000;
352 t1 &= ~0x8000;
353 t0 = (t0 + t1) ^ tmp;
356 static void gen_add16(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
358 TCGv_i32 tmp = tcg_temp_new_i32();
359 tcg_gen_xor_i32(tmp, t0, t1);
360 tcg_gen_andi_i32(tmp, tmp, 0x8000);
361 tcg_gen_andi_i32(t0, t0, ~0x8000);
362 tcg_gen_andi_i32(t1, t1, ~0x8000);
363 tcg_gen_add_i32(t0, t0, t1);
364 tcg_gen_xor_i32(dest, t0, tmp);
365 tcg_temp_free_i32(tmp);
368 /* Set N and Z flags from var. */
369 static inline void gen_logic_CC(TCGv_i32 var)
371 tcg_gen_mov_i32(cpu_NF, var);
372 tcg_gen_mov_i32(cpu_ZF, var);
375 /* dest = T0 + T1 + CF. */
376 static void gen_add_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
378 tcg_gen_add_i32(dest, t0, t1);
379 tcg_gen_add_i32(dest, dest, cpu_CF);
382 /* dest = T0 - T1 + CF - 1. */
383 static void gen_sub_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
385 tcg_gen_sub_i32(dest, t0, t1);
386 tcg_gen_add_i32(dest, dest, cpu_CF);
387 tcg_gen_subi_i32(dest, dest, 1);
390 /* dest = T0 + T1. Compute C, N, V and Z flags */
391 static void gen_add_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
393 TCGv_i32 tmp = tcg_temp_new_i32();
394 tcg_gen_movi_i32(tmp, 0);
395 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, t1, tmp);
396 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
397 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
398 tcg_gen_xor_i32(tmp, t0, t1);
399 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
400 tcg_temp_free_i32(tmp);
401 tcg_gen_mov_i32(dest, cpu_NF);
404 /* dest = T0 + T1 + CF. Compute C, N, V and Z flags */
405 static void gen_adc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
407 TCGv_i32 tmp = tcg_temp_new_i32();
408 if (TCG_TARGET_HAS_add2_i32) {
409 tcg_gen_movi_i32(tmp, 0);
410 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, cpu_CF, tmp);
411 tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1, tmp);
412 } else {
413 TCGv_i64 q0 = tcg_temp_new_i64();
414 TCGv_i64 q1 = tcg_temp_new_i64();
415 tcg_gen_extu_i32_i64(q0, t0);
416 tcg_gen_extu_i32_i64(q1, t1);
417 tcg_gen_add_i64(q0, q0, q1);
418 tcg_gen_extu_i32_i64(q1, cpu_CF);
419 tcg_gen_add_i64(q0, q0, q1);
420 tcg_gen_extr_i64_i32(cpu_NF, cpu_CF, q0);
421 tcg_temp_free_i64(q0);
422 tcg_temp_free_i64(q1);
424 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
425 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
426 tcg_gen_xor_i32(tmp, t0, t1);
427 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
428 tcg_temp_free_i32(tmp);
429 tcg_gen_mov_i32(dest, cpu_NF);
432 /* dest = T0 - T1. Compute C, N, V and Z flags */
433 static void gen_sub_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
435 TCGv_i32 tmp;
436 tcg_gen_sub_i32(cpu_NF, t0, t1);
437 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
438 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0, t1);
439 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
440 tmp = tcg_temp_new_i32();
441 tcg_gen_xor_i32(tmp, t0, t1);
442 tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
443 tcg_temp_free_i32(tmp);
444 tcg_gen_mov_i32(dest, cpu_NF);
447 /* dest = T0 + ~T1 + CF. Compute C, N, V and Z flags */
448 static void gen_sbc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
450 TCGv_i32 tmp = tcg_temp_new_i32();
451 tcg_gen_not_i32(tmp, t1);
452 gen_adc_CC(dest, t0, tmp);
453 tcg_temp_free_i32(tmp);
456 #define GEN_SHIFT(name) \
457 static void gen_##name(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) \
459 TCGv_i32 tmp1, tmp2, tmp3; \
460 tmp1 = tcg_temp_new_i32(); \
461 tcg_gen_andi_i32(tmp1, t1, 0xff); \
462 tmp2 = tcg_const_i32(0); \
463 tmp3 = tcg_const_i32(0x1f); \
464 tcg_gen_movcond_i32(TCG_COND_GTU, tmp2, tmp1, tmp3, tmp2, t0); \
465 tcg_temp_free_i32(tmp3); \
466 tcg_gen_andi_i32(tmp1, tmp1, 0x1f); \
467 tcg_gen_##name##_i32(dest, tmp2, tmp1); \
468 tcg_temp_free_i32(tmp2); \
469 tcg_temp_free_i32(tmp1); \
471 GEN_SHIFT(shl)
472 GEN_SHIFT(shr)
473 #undef GEN_SHIFT
475 static void gen_sar(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
477 TCGv_i32 tmp1, tmp2;
478 tmp1 = tcg_temp_new_i32();
479 tcg_gen_andi_i32(tmp1, t1, 0xff);
480 tmp2 = tcg_const_i32(0x1f);
481 tcg_gen_movcond_i32(TCG_COND_GTU, tmp1, tmp1, tmp2, tmp2, tmp1);
482 tcg_temp_free_i32(tmp2);
483 tcg_gen_sar_i32(dest, t0, tmp1);
484 tcg_temp_free_i32(tmp1);
487 static void shifter_out_im(TCGv_i32 var, int shift)
489 tcg_gen_extract_i32(cpu_CF, var, shift, 1);
492 /* Shift by immediate. Includes special handling for shift == 0. */
493 static inline void gen_arm_shift_im(TCGv_i32 var, int shiftop,
494 int shift, int flags)
496 switch (shiftop) {
497 case 0: /* LSL */
498 if (shift != 0) {
499 if (flags)
500 shifter_out_im(var, 32 - shift);
501 tcg_gen_shli_i32(var, var, shift);
503 break;
504 case 1: /* LSR */
505 if (shift == 0) {
506 if (flags) {
507 tcg_gen_shri_i32(cpu_CF, var, 31);
509 tcg_gen_movi_i32(var, 0);
510 } else {
511 if (flags)
512 shifter_out_im(var, shift - 1);
513 tcg_gen_shri_i32(var, var, shift);
515 break;
516 case 2: /* ASR */
517 if (shift == 0)
518 shift = 32;
519 if (flags)
520 shifter_out_im(var, shift - 1);
521 if (shift == 32)
522 shift = 31;
523 tcg_gen_sari_i32(var, var, shift);
524 break;
525 case 3: /* ROR/RRX */
526 if (shift != 0) {
527 if (flags)
528 shifter_out_im(var, shift - 1);
529 tcg_gen_rotri_i32(var, var, shift); break;
530 } else {
531 TCGv_i32 tmp = tcg_temp_new_i32();
532 tcg_gen_shli_i32(tmp, cpu_CF, 31);
533 if (flags)
534 shifter_out_im(var, 0);
535 tcg_gen_shri_i32(var, var, 1);
536 tcg_gen_or_i32(var, var, tmp);
537 tcg_temp_free_i32(tmp);
542 static inline void gen_arm_shift_reg(TCGv_i32 var, int shiftop,
543 TCGv_i32 shift, int flags)
545 if (flags) {
546 switch (shiftop) {
547 case 0: gen_helper_shl_cc(var, cpu_env, var, shift); break;
548 case 1: gen_helper_shr_cc(var, cpu_env, var, shift); break;
549 case 2: gen_helper_sar_cc(var, cpu_env, var, shift); break;
550 case 3: gen_helper_ror_cc(var, cpu_env, var, shift); break;
552 } else {
553 switch (shiftop) {
554 case 0:
555 gen_shl(var, var, shift);
556 break;
557 case 1:
558 gen_shr(var, var, shift);
559 break;
560 case 2:
561 gen_sar(var, var, shift);
562 break;
563 case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
564 tcg_gen_rotr_i32(var, var, shift); break;
567 tcg_temp_free_i32(shift);
571 * Generate a conditional based on ARM condition code cc.
572 * This is common between ARM and Aarch64 targets.
574 void arm_test_cc(DisasCompare *cmp, int cc)
576 TCGv_i32 value;
577 TCGCond cond;
578 bool global = true;
580 switch (cc) {
581 case 0: /* eq: Z */
582 case 1: /* ne: !Z */
583 cond = TCG_COND_EQ;
584 value = cpu_ZF;
585 break;
587 case 2: /* cs: C */
588 case 3: /* cc: !C */
589 cond = TCG_COND_NE;
590 value = cpu_CF;
591 break;
593 case 4: /* mi: N */
594 case 5: /* pl: !N */
595 cond = TCG_COND_LT;
596 value = cpu_NF;
597 break;
599 case 6: /* vs: V */
600 case 7: /* vc: !V */
601 cond = TCG_COND_LT;
602 value = cpu_VF;
603 break;
605 case 8: /* hi: C && !Z */
606 case 9: /* ls: !C || Z -> !(C && !Z) */
607 cond = TCG_COND_NE;
608 value = tcg_temp_new_i32();
609 global = false;
610 /* CF is 1 for C, so -CF is an all-bits-set mask for C;
611 ZF is non-zero for !Z; so AND the two subexpressions. */
612 tcg_gen_neg_i32(value, cpu_CF);
613 tcg_gen_and_i32(value, value, cpu_ZF);
614 break;
616 case 10: /* ge: N == V -> N ^ V == 0 */
617 case 11: /* lt: N != V -> N ^ V != 0 */
618 /* Since we're only interested in the sign bit, == 0 is >= 0. */
619 cond = TCG_COND_GE;
620 value = tcg_temp_new_i32();
621 global = false;
622 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
623 break;
625 case 12: /* gt: !Z && N == V */
626 case 13: /* le: Z || N != V */
627 cond = TCG_COND_NE;
628 value = tcg_temp_new_i32();
629 global = false;
630 /* (N == V) is equal to the sign bit of ~(NF ^ VF). Propagate
631 * the sign bit then AND with ZF to yield the result. */
632 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
633 tcg_gen_sari_i32(value, value, 31);
634 tcg_gen_andc_i32(value, cpu_ZF, value);
635 break;
637 case 14: /* always */
638 case 15: /* always */
639 /* Use the ALWAYS condition, which will fold early.
640 * It doesn't matter what we use for the value. */
641 cond = TCG_COND_ALWAYS;
642 value = cpu_ZF;
643 goto no_invert;
645 default:
646 fprintf(stderr, "Bad condition code 0x%x\n", cc);
647 abort();
650 if (cc & 1) {
651 cond = tcg_invert_cond(cond);
654 no_invert:
655 cmp->cond = cond;
656 cmp->value = value;
657 cmp->value_global = global;
660 void arm_free_cc(DisasCompare *cmp)
662 if (!cmp->value_global) {
663 tcg_temp_free_i32(cmp->value);
667 void arm_jump_cc(DisasCompare *cmp, TCGLabel *label)
669 tcg_gen_brcondi_i32(cmp->cond, cmp->value, 0, label);
672 void arm_gen_test_cc(int cc, TCGLabel *label)
674 DisasCompare cmp;
675 arm_test_cc(&cmp, cc);
676 arm_jump_cc(&cmp, label);
677 arm_free_cc(&cmp);
680 void gen_set_condexec(DisasContext *s)
682 if (s->condexec_mask) {
683 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
684 TCGv_i32 tmp = tcg_temp_new_i32();
685 tcg_gen_movi_i32(tmp, val);
686 store_cpu_field(tmp, condexec_bits);
690 void gen_set_pc_im(DisasContext *s, target_ulong val)
692 tcg_gen_movi_i32(cpu_R[15], val);
695 /* Set PC and Thumb state from var. var is marked as dead. */
696 static inline void gen_bx(DisasContext *s, TCGv_i32 var)
698 s->base.is_jmp = DISAS_JUMP;
699 tcg_gen_andi_i32(cpu_R[15], var, ~1);
700 tcg_gen_andi_i32(var, var, 1);
701 store_cpu_field(var, thumb);
705 * Set PC and Thumb state from var. var is marked as dead.
706 * For M-profile CPUs, include logic to detect exception-return
707 * branches and handle them. This is needed for Thumb POP/LDM to PC, LDR to PC,
708 * and BX reg, and no others, and happens only for code in Handler mode.
709 * The Security Extension also requires us to check for the FNC_RETURN
710 * which signals a function return from non-secure state; this can happen
711 * in both Handler and Thread mode.
712 * To avoid having to do multiple comparisons in inline generated code,
713 * we make the check we do here loose, so it will match for EXC_RETURN
714 * in Thread mode. For system emulation do_v7m_exception_exit() checks
715 * for these spurious cases and returns without doing anything (giving
716 * the same behaviour as for a branch to a non-magic address).
718 * In linux-user mode it is unclear what the right behaviour for an
719 * attempted FNC_RETURN should be, because in real hardware this will go
720 * directly to Secure code (ie not the Linux kernel) which will then treat
721 * the error in any way it chooses. For QEMU we opt to make the FNC_RETURN
722 * attempt behave the way it would on a CPU without the security extension,
723 * which is to say "like a normal branch". That means we can simply treat
724 * all branches as normal with no magic address behaviour.
726 static inline void gen_bx_excret(DisasContext *s, TCGv_i32 var)
728 /* Generate the same code here as for a simple bx, but flag via
729 * s->base.is_jmp that we need to do the rest of the work later.
731 gen_bx(s, var);
732 #ifndef CONFIG_USER_ONLY
733 if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY) ||
734 (s->v7m_handler_mode && arm_dc_feature(s, ARM_FEATURE_M))) {
735 s->base.is_jmp = DISAS_BX_EXCRET;
737 #endif
740 static inline void gen_bx_excret_final_code(DisasContext *s)
742 /* Generate the code to finish possible exception return and end the TB */
743 TCGLabel *excret_label = gen_new_label();
744 uint32_t min_magic;
746 if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY)) {
747 /* Covers FNC_RETURN and EXC_RETURN magic */
748 min_magic = FNC_RETURN_MIN_MAGIC;
749 } else {
750 /* EXC_RETURN magic only */
751 min_magic = EXC_RETURN_MIN_MAGIC;
754 /* Is the new PC value in the magic range indicating exception return? */
755 tcg_gen_brcondi_i32(TCG_COND_GEU, cpu_R[15], min_magic, excret_label);
756 /* No: end the TB as we would for a DISAS_JMP */
757 if (is_singlestepping(s)) {
758 gen_singlestep_exception(s);
759 } else {
760 tcg_gen_exit_tb(NULL, 0);
762 gen_set_label(excret_label);
763 /* Yes: this is an exception return.
764 * At this point in runtime env->regs[15] and env->thumb will hold
765 * the exception-return magic number, which do_v7m_exception_exit()
766 * will read. Nothing else will be able to see those values because
767 * the cpu-exec main loop guarantees that we will always go straight
768 * from raising the exception to the exception-handling code.
770 * gen_ss_advance(s) does nothing on M profile currently but
771 * calling it is conceptually the right thing as we have executed
772 * this instruction (compare SWI, HVC, SMC handling).
774 gen_ss_advance(s);
775 gen_exception_internal(EXCP_EXCEPTION_EXIT);
778 static inline void gen_bxns(DisasContext *s, int rm)
780 TCGv_i32 var = load_reg(s, rm);
782 /* The bxns helper may raise an EXCEPTION_EXIT exception, so in theory
783 * we need to sync state before calling it, but:
784 * - we don't need to do gen_set_pc_im() because the bxns helper will
785 * always set the PC itself
786 * - we don't need to do gen_set_condexec() because BXNS is UNPREDICTABLE
787 * unless it's outside an IT block or the last insn in an IT block,
788 * so we know that condexec == 0 (already set at the top of the TB)
789 * is correct in the non-UNPREDICTABLE cases, and we can choose
790 * "zeroes the IT bits" as our UNPREDICTABLE behaviour otherwise.
792 gen_helper_v7m_bxns(cpu_env, var);
793 tcg_temp_free_i32(var);
794 s->base.is_jmp = DISAS_EXIT;
797 static inline void gen_blxns(DisasContext *s, int rm)
799 TCGv_i32 var = load_reg(s, rm);
801 /* We don't need to sync condexec state, for the same reason as bxns.
802 * We do however need to set the PC, because the blxns helper reads it.
803 * The blxns helper may throw an exception.
805 gen_set_pc_im(s, s->base.pc_next);
806 gen_helper_v7m_blxns(cpu_env, var);
807 tcg_temp_free_i32(var);
808 s->base.is_jmp = DISAS_EXIT;
811 /* Variant of store_reg which uses branch&exchange logic when storing
812 to r15 in ARM architecture v7 and above. The source must be a temporary
813 and will be marked as dead. */
814 static inline void store_reg_bx(DisasContext *s, int reg, TCGv_i32 var)
816 if (reg == 15 && ENABLE_ARCH_7) {
817 gen_bx(s, var);
818 } else {
819 store_reg(s, reg, var);
823 /* Variant of store_reg which uses branch&exchange logic when storing
824 * to r15 in ARM architecture v5T and above. This is used for storing
825 * the results of a LDR/LDM/POP into r15, and corresponds to the cases
826 * in the ARM ARM which use the LoadWritePC() pseudocode function. */
827 static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
829 if (reg == 15 && ENABLE_ARCH_5) {
830 gen_bx_excret(s, var);
831 } else {
832 store_reg(s, reg, var);
836 #ifdef CONFIG_USER_ONLY
837 #define IS_USER_ONLY 1
838 #else
839 #define IS_USER_ONLY 0
840 #endif
842 MemOp pow2_align(unsigned i)
844 static const MemOp mop_align[] = {
845 0, MO_ALIGN_2, MO_ALIGN_4, MO_ALIGN_8, MO_ALIGN_16,
847 * FIXME: TARGET_PAGE_BITS_MIN affects TLB_FLAGS_MASK such
848 * that 256-bit alignment (MO_ALIGN_32) cannot be supported:
849 * see get_alignment_bits(). Enforce only 128-bit alignment for now.
851 MO_ALIGN_16
853 g_assert(i < ARRAY_SIZE(mop_align));
854 return mop_align[i];
858 * Abstractions of "generate code to do a guest load/store for
859 * AArch32", where a vaddr is always 32 bits (and is zero
860 * extended if we're a 64 bit core) and data is also
861 * 32 bits unless specifically doing a 64 bit access.
862 * These functions work like tcg_gen_qemu_{ld,st}* except
863 * that the address argument is TCGv_i32 rather than TCGv.
866 static TCGv gen_aa32_addr(DisasContext *s, TCGv_i32 a32, MemOp op)
868 TCGv addr = tcg_temp_new();
869 tcg_gen_extu_i32_tl(addr, a32);
871 /* Not needed for user-mode BE32, where we use MO_BE instead. */
872 if (!IS_USER_ONLY && s->sctlr_b && (op & MO_SIZE) < MO_32) {
873 tcg_gen_xori_tl(addr, addr, 4 - (1 << (op & MO_SIZE)));
875 return addr;
879 * Internal routines are used for NEON cases where the endianness
880 * and/or alignment has already been taken into account and manipulated.
882 void gen_aa32_ld_internal_i32(DisasContext *s, TCGv_i32 val,
883 TCGv_i32 a32, int index, MemOp opc)
885 TCGv addr = gen_aa32_addr(s, a32, opc);
886 tcg_gen_qemu_ld_i32(val, addr, index, opc);
887 tcg_temp_free(addr);
890 void gen_aa32_st_internal_i32(DisasContext *s, TCGv_i32 val,
891 TCGv_i32 a32, int index, MemOp opc)
893 TCGv addr = gen_aa32_addr(s, a32, opc);
894 tcg_gen_qemu_st_i32(val, addr, index, opc);
895 tcg_temp_free(addr);
898 void gen_aa32_ld_internal_i64(DisasContext *s, TCGv_i64 val,
899 TCGv_i32 a32, int index, MemOp opc)
901 TCGv addr = gen_aa32_addr(s, a32, opc);
903 tcg_gen_qemu_ld_i64(val, addr, index, opc);
905 /* Not needed for user-mode BE32, where we use MO_BE instead. */
906 if (!IS_USER_ONLY && s->sctlr_b && (opc & MO_SIZE) == MO_64) {
907 tcg_gen_rotri_i64(val, val, 32);
909 tcg_temp_free(addr);
912 void gen_aa32_st_internal_i64(DisasContext *s, TCGv_i64 val,
913 TCGv_i32 a32, int index, MemOp opc)
915 TCGv addr = gen_aa32_addr(s, a32, opc);
917 /* Not needed for user-mode BE32, where we use MO_BE instead. */
918 if (!IS_USER_ONLY && s->sctlr_b && (opc & MO_SIZE) == MO_64) {
919 TCGv_i64 tmp = tcg_temp_new_i64();
920 tcg_gen_rotri_i64(tmp, val, 32);
921 tcg_gen_qemu_st_i64(tmp, addr, index, opc);
922 tcg_temp_free_i64(tmp);
923 } else {
924 tcg_gen_qemu_st_i64(val, addr, index, opc);
926 tcg_temp_free(addr);
929 void gen_aa32_ld_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
930 int index, MemOp opc)
932 gen_aa32_ld_internal_i32(s, val, a32, index, finalize_memop(s, opc));
935 void gen_aa32_st_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
936 int index, MemOp opc)
938 gen_aa32_st_internal_i32(s, val, a32, index, finalize_memop(s, opc));
941 void gen_aa32_ld_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
942 int index, MemOp opc)
944 gen_aa32_ld_internal_i64(s, val, a32, index, finalize_memop(s, opc));
947 void gen_aa32_st_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
948 int index, MemOp opc)
950 gen_aa32_st_internal_i64(s, val, a32, index, finalize_memop(s, opc));
953 #define DO_GEN_LD(SUFF, OPC) \
954 static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \
955 TCGv_i32 a32, int index) \
957 gen_aa32_ld_i32(s, val, a32, index, OPC); \
960 #define DO_GEN_ST(SUFF, OPC) \
961 static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, \
962 TCGv_i32 a32, int index) \
964 gen_aa32_st_i32(s, val, a32, index, OPC); \
967 static inline void gen_hvc(DisasContext *s, int imm16)
969 /* The pre HVC helper handles cases when HVC gets trapped
970 * as an undefined insn by runtime configuration (ie before
971 * the insn really executes).
973 gen_set_pc_im(s, s->pc_curr);
974 gen_helper_pre_hvc(cpu_env);
975 /* Otherwise we will treat this as a real exception which
976 * happens after execution of the insn. (The distinction matters
977 * for the PC value reported to the exception handler and also
978 * for single stepping.)
980 s->svc_imm = imm16;
981 gen_set_pc_im(s, s->base.pc_next);
982 s->base.is_jmp = DISAS_HVC;
985 static inline void gen_smc(DisasContext *s)
987 /* As with HVC, we may take an exception either before or after
988 * the insn executes.
990 TCGv_i32 tmp;
992 gen_set_pc_im(s, s->pc_curr);
993 tmp = tcg_const_i32(syn_aa32_smc());
994 gen_helper_pre_smc(cpu_env, tmp);
995 tcg_temp_free_i32(tmp);
996 gen_set_pc_im(s, s->base.pc_next);
997 s->base.is_jmp = DISAS_SMC;
1000 static void gen_exception_internal_insn(DisasContext *s, uint32_t pc, int excp)
1002 gen_set_condexec(s);
1003 gen_set_pc_im(s, pc);
1004 gen_exception_internal(excp);
1005 s->base.is_jmp = DISAS_NORETURN;
1008 void gen_exception_insn(DisasContext *s, uint64_t pc, int excp,
1009 uint32_t syn, uint32_t target_el)
1011 if (s->aarch64) {
1012 gen_a64_set_pc_im(pc);
1013 } else {
1014 gen_set_condexec(s);
1015 gen_set_pc_im(s, pc);
1017 gen_exception(excp, syn, target_el);
1018 s->base.is_jmp = DISAS_NORETURN;
1021 static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn)
1023 TCGv_i32 tcg_syn;
1025 gen_set_condexec(s);
1026 gen_set_pc_im(s, s->pc_curr);
1027 tcg_syn = tcg_const_i32(syn);
1028 gen_helper_exception_bkpt_insn(cpu_env, tcg_syn);
1029 tcg_temp_free_i32(tcg_syn);
1030 s->base.is_jmp = DISAS_NORETURN;
1033 void unallocated_encoding(DisasContext *s)
1035 /* Unallocated and reserved encodings are uncategorized */
1036 gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(),
1037 default_exception_el(s));
1040 static void gen_exception_el(DisasContext *s, int excp, uint32_t syn,
1041 TCGv_i32 tcg_el)
1043 TCGv_i32 tcg_excp;
1044 TCGv_i32 tcg_syn;
1046 gen_set_condexec(s);
1047 gen_set_pc_im(s, s->pc_curr);
1048 tcg_excp = tcg_const_i32(excp);
1049 tcg_syn = tcg_const_i32(syn);
1050 gen_helper_exception_with_syndrome(cpu_env, tcg_excp, tcg_syn, tcg_el);
1051 tcg_temp_free_i32(tcg_syn);
1052 tcg_temp_free_i32(tcg_excp);
1053 s->base.is_jmp = DISAS_NORETURN;
1056 /* Force a TB lookup after an instruction that changes the CPU state. */
1057 void gen_lookup_tb(DisasContext *s)
1059 tcg_gen_movi_i32(cpu_R[15], s->base.pc_next);
1060 s->base.is_jmp = DISAS_EXIT;
1063 static inline void gen_hlt(DisasContext *s, int imm)
1065 /* HLT. This has two purposes.
1066 * Architecturally, it is an external halting debug instruction.
1067 * Since QEMU doesn't implement external debug, we treat this as
1068 * it is required for halting debug disabled: it will UNDEF.
1069 * Secondly, "HLT 0x3C" is a T32 semihosting trap instruction,
1070 * and "HLT 0xF000" is an A32 semihosting syscall. These traps
1071 * must trigger semihosting even for ARMv7 and earlier, where
1072 * HLT was an undefined encoding.
1073 * In system mode, we don't allow userspace access to
1074 * semihosting, to provide some semblance of security
1075 * (and for consistency with our 32-bit semihosting).
1077 if (semihosting_enabled() &&
1078 #ifndef CONFIG_USER_ONLY
1079 s->current_el != 0 &&
1080 #endif
1081 (imm == (s->thumb ? 0x3c : 0xf000))) {
1082 gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
1083 return;
1086 unallocated_encoding(s);
1090 * Return the offset of a "full" NEON Dreg.
1092 long neon_full_reg_offset(unsigned reg)
1094 return offsetof(CPUARMState, vfp.zregs[reg >> 1].d[reg & 1]);
1098 * Return the offset of a 2**SIZE piece of a NEON register, at index ELE,
1099 * where 0 is the least significant end of the register.
1101 long neon_element_offset(int reg, int element, MemOp memop)
1103 int element_size = 1 << (memop & MO_SIZE);
1104 int ofs = element * element_size;
1105 #ifdef HOST_WORDS_BIGENDIAN
1107 * Calculate the offset assuming fully little-endian,
1108 * then XOR to account for the order of the 8-byte units.
1110 if (element_size < 8) {
1111 ofs ^= 8 - element_size;
1113 #endif
1114 return neon_full_reg_offset(reg) + ofs;
1117 /* Return the offset of a VFP Dreg (dp = true) or VFP Sreg (dp = false). */
1118 long vfp_reg_offset(bool dp, unsigned reg)
1120 if (dp) {
1121 return neon_element_offset(reg, 0, MO_64);
1122 } else {
1123 return neon_element_offset(reg >> 1, reg & 1, MO_32);
1127 void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp memop)
1129 long off = neon_element_offset(reg, ele, memop);
1131 switch (memop) {
1132 case MO_SB:
1133 tcg_gen_ld8s_i32(dest, cpu_env, off);
1134 break;
1135 case MO_UB:
1136 tcg_gen_ld8u_i32(dest, cpu_env, off);
1137 break;
1138 case MO_SW:
1139 tcg_gen_ld16s_i32(dest, cpu_env, off);
1140 break;
1141 case MO_UW:
1142 tcg_gen_ld16u_i32(dest, cpu_env, off);
1143 break;
1144 case MO_UL:
1145 case MO_SL:
1146 tcg_gen_ld_i32(dest, cpu_env, off);
1147 break;
1148 default:
1149 g_assert_not_reached();
1153 void read_neon_element64(TCGv_i64 dest, int reg, int ele, MemOp memop)
1155 long off = neon_element_offset(reg, ele, memop);
1157 switch (memop) {
1158 case MO_SL:
1159 tcg_gen_ld32s_i64(dest, cpu_env, off);
1160 break;
1161 case MO_UL:
1162 tcg_gen_ld32u_i64(dest, cpu_env, off);
1163 break;
1164 case MO_Q:
1165 tcg_gen_ld_i64(dest, cpu_env, off);
1166 break;
1167 default:
1168 g_assert_not_reached();
1172 void write_neon_element32(TCGv_i32 src, int reg, int ele, MemOp memop)
1174 long off = neon_element_offset(reg, ele, memop);
1176 switch (memop) {
1177 case MO_8:
1178 tcg_gen_st8_i32(src, cpu_env, off);
1179 break;
1180 case MO_16:
1181 tcg_gen_st16_i32(src, cpu_env, off);
1182 break;
1183 case MO_32:
1184 tcg_gen_st_i32(src, cpu_env, off);
1185 break;
1186 default:
1187 g_assert_not_reached();
1191 void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop)
1193 long off = neon_element_offset(reg, ele, memop);
1195 switch (memop) {
1196 case MO_32:
1197 tcg_gen_st32_i64(src, cpu_env, off);
1198 break;
1199 case MO_64:
1200 tcg_gen_st_i64(src, cpu_env, off);
1201 break;
1202 default:
1203 g_assert_not_reached();
1207 #define ARM_CP_RW_BIT (1 << 20)
1209 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1211 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1214 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1216 tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1219 static inline TCGv_i32 iwmmxt_load_creg(int reg)
1221 TCGv_i32 var = tcg_temp_new_i32();
1222 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1223 return var;
1226 static inline void iwmmxt_store_creg(int reg, TCGv_i32 var)
1228 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1229 tcg_temp_free_i32(var);
1232 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1234 iwmmxt_store_reg(cpu_M0, rn);
1237 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1239 iwmmxt_load_reg(cpu_M0, rn);
1242 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1244 iwmmxt_load_reg(cpu_V1, rn);
1245 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1248 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1250 iwmmxt_load_reg(cpu_V1, rn);
1251 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1254 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1256 iwmmxt_load_reg(cpu_V1, rn);
1257 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1260 #define IWMMXT_OP(name) \
1261 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1263 iwmmxt_load_reg(cpu_V1, rn); \
1264 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1267 #define IWMMXT_OP_ENV(name) \
1268 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1270 iwmmxt_load_reg(cpu_V1, rn); \
1271 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1274 #define IWMMXT_OP_ENV_SIZE(name) \
1275 IWMMXT_OP_ENV(name##b) \
1276 IWMMXT_OP_ENV(name##w) \
1277 IWMMXT_OP_ENV(name##l)
1279 #define IWMMXT_OP_ENV1(name) \
1280 static inline void gen_op_iwmmxt_##name##_M0(void) \
1282 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1285 IWMMXT_OP(maddsq)
1286 IWMMXT_OP(madduq)
1287 IWMMXT_OP(sadb)
1288 IWMMXT_OP(sadw)
1289 IWMMXT_OP(mulslw)
1290 IWMMXT_OP(mulshw)
1291 IWMMXT_OP(mululw)
1292 IWMMXT_OP(muluhw)
1293 IWMMXT_OP(macsw)
1294 IWMMXT_OP(macuw)
1296 IWMMXT_OP_ENV_SIZE(unpackl)
1297 IWMMXT_OP_ENV_SIZE(unpackh)
1299 IWMMXT_OP_ENV1(unpacklub)
1300 IWMMXT_OP_ENV1(unpackluw)
1301 IWMMXT_OP_ENV1(unpacklul)
1302 IWMMXT_OP_ENV1(unpackhub)
1303 IWMMXT_OP_ENV1(unpackhuw)
1304 IWMMXT_OP_ENV1(unpackhul)
1305 IWMMXT_OP_ENV1(unpacklsb)
1306 IWMMXT_OP_ENV1(unpacklsw)
1307 IWMMXT_OP_ENV1(unpacklsl)
1308 IWMMXT_OP_ENV1(unpackhsb)
1309 IWMMXT_OP_ENV1(unpackhsw)
1310 IWMMXT_OP_ENV1(unpackhsl)
1312 IWMMXT_OP_ENV_SIZE(cmpeq)
1313 IWMMXT_OP_ENV_SIZE(cmpgtu)
1314 IWMMXT_OP_ENV_SIZE(cmpgts)
1316 IWMMXT_OP_ENV_SIZE(mins)
1317 IWMMXT_OP_ENV_SIZE(minu)
1318 IWMMXT_OP_ENV_SIZE(maxs)
1319 IWMMXT_OP_ENV_SIZE(maxu)
1321 IWMMXT_OP_ENV_SIZE(subn)
1322 IWMMXT_OP_ENV_SIZE(addn)
1323 IWMMXT_OP_ENV_SIZE(subu)
1324 IWMMXT_OP_ENV_SIZE(addu)
1325 IWMMXT_OP_ENV_SIZE(subs)
1326 IWMMXT_OP_ENV_SIZE(adds)
1328 IWMMXT_OP_ENV(avgb0)
1329 IWMMXT_OP_ENV(avgb1)
1330 IWMMXT_OP_ENV(avgw0)
1331 IWMMXT_OP_ENV(avgw1)
1333 IWMMXT_OP_ENV(packuw)
1334 IWMMXT_OP_ENV(packul)
1335 IWMMXT_OP_ENV(packuq)
1336 IWMMXT_OP_ENV(packsw)
1337 IWMMXT_OP_ENV(packsl)
1338 IWMMXT_OP_ENV(packsq)
1340 static void gen_op_iwmmxt_set_mup(void)
1342 TCGv_i32 tmp;
1343 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1344 tcg_gen_ori_i32(tmp, tmp, 2);
1345 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1348 static void gen_op_iwmmxt_set_cup(void)
1350 TCGv_i32 tmp;
1351 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1352 tcg_gen_ori_i32(tmp, tmp, 1);
1353 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1356 static void gen_op_iwmmxt_setpsr_nz(void)
1358 TCGv_i32 tmp = tcg_temp_new_i32();
1359 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1360 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1363 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1365 iwmmxt_load_reg(cpu_V1, rn);
1366 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1367 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1370 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn,
1371 TCGv_i32 dest)
1373 int rd;
1374 uint32_t offset;
1375 TCGv_i32 tmp;
1377 rd = (insn >> 16) & 0xf;
1378 tmp = load_reg(s, rd);
1380 offset = (insn & 0xff) << ((insn >> 7) & 2);
1381 if (insn & (1 << 24)) {
1382 /* Pre indexed */
1383 if (insn & (1 << 23))
1384 tcg_gen_addi_i32(tmp, tmp, offset);
1385 else
1386 tcg_gen_addi_i32(tmp, tmp, -offset);
1387 tcg_gen_mov_i32(dest, tmp);
1388 if (insn & (1 << 21))
1389 store_reg(s, rd, tmp);
1390 else
1391 tcg_temp_free_i32(tmp);
1392 } else if (insn & (1 << 21)) {
1393 /* Post indexed */
1394 tcg_gen_mov_i32(dest, tmp);
1395 if (insn & (1 << 23))
1396 tcg_gen_addi_i32(tmp, tmp, offset);
1397 else
1398 tcg_gen_addi_i32(tmp, tmp, -offset);
1399 store_reg(s, rd, tmp);
1400 } else if (!(insn & (1 << 23)))
1401 return 1;
1402 return 0;
1405 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv_i32 dest)
1407 int rd = (insn >> 0) & 0xf;
1408 TCGv_i32 tmp;
1410 if (insn & (1 << 8)) {
1411 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1412 return 1;
1413 } else {
1414 tmp = iwmmxt_load_creg(rd);
1416 } else {
1417 tmp = tcg_temp_new_i32();
1418 iwmmxt_load_reg(cpu_V0, rd);
1419 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
1421 tcg_gen_andi_i32(tmp, tmp, mask);
1422 tcg_gen_mov_i32(dest, tmp);
1423 tcg_temp_free_i32(tmp);
1424 return 0;
1427 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
1428 (ie. an undefined instruction). */
1429 static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
1431 int rd, wrd;
1432 int rdhi, rdlo, rd0, rd1, i;
1433 TCGv_i32 addr;
1434 TCGv_i32 tmp, tmp2, tmp3;
1436 if ((insn & 0x0e000e00) == 0x0c000000) {
1437 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1438 wrd = insn & 0xf;
1439 rdlo = (insn >> 12) & 0xf;
1440 rdhi = (insn >> 16) & 0xf;
1441 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1442 iwmmxt_load_reg(cpu_V0, wrd);
1443 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
1444 tcg_gen_extrh_i64_i32(cpu_R[rdhi], cpu_V0);
1445 } else { /* TMCRR */
1446 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1447 iwmmxt_store_reg(cpu_V0, wrd);
1448 gen_op_iwmmxt_set_mup();
1450 return 0;
1453 wrd = (insn >> 12) & 0xf;
1454 addr = tcg_temp_new_i32();
1455 if (gen_iwmmxt_address(s, insn, addr)) {
1456 tcg_temp_free_i32(addr);
1457 return 1;
1459 if (insn & ARM_CP_RW_BIT) {
1460 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1461 tmp = tcg_temp_new_i32();
1462 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
1463 iwmmxt_store_creg(wrd, tmp);
1464 } else {
1465 i = 1;
1466 if (insn & (1 << 8)) {
1467 if (insn & (1 << 22)) { /* WLDRD */
1468 gen_aa32_ld64(s, cpu_M0, addr, get_mem_index(s));
1469 i = 0;
1470 } else { /* WLDRW wRd */
1471 tmp = tcg_temp_new_i32();
1472 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
1474 } else {
1475 tmp = tcg_temp_new_i32();
1476 if (insn & (1 << 22)) { /* WLDRH */
1477 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
1478 } else { /* WLDRB */
1479 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
1482 if (i) {
1483 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1484 tcg_temp_free_i32(tmp);
1486 gen_op_iwmmxt_movq_wRn_M0(wrd);
1488 } else {
1489 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1490 tmp = iwmmxt_load_creg(wrd);
1491 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
1492 } else {
1493 gen_op_iwmmxt_movq_M0_wRn(wrd);
1494 tmp = tcg_temp_new_i32();
1495 if (insn & (1 << 8)) {
1496 if (insn & (1 << 22)) { /* WSTRD */
1497 gen_aa32_st64(s, cpu_M0, addr, get_mem_index(s));
1498 } else { /* WSTRW wRd */
1499 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1500 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
1502 } else {
1503 if (insn & (1 << 22)) { /* WSTRH */
1504 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1505 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
1506 } else { /* WSTRB */
1507 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1508 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
1512 tcg_temp_free_i32(tmp);
1514 tcg_temp_free_i32(addr);
1515 return 0;
1518 if ((insn & 0x0f000000) != 0x0e000000)
1519 return 1;
1521 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1522 case 0x000: /* WOR */
1523 wrd = (insn >> 12) & 0xf;
1524 rd0 = (insn >> 0) & 0xf;
1525 rd1 = (insn >> 16) & 0xf;
1526 gen_op_iwmmxt_movq_M0_wRn(rd0);
1527 gen_op_iwmmxt_orq_M0_wRn(rd1);
1528 gen_op_iwmmxt_setpsr_nz();
1529 gen_op_iwmmxt_movq_wRn_M0(wrd);
1530 gen_op_iwmmxt_set_mup();
1531 gen_op_iwmmxt_set_cup();
1532 break;
1533 case 0x011: /* TMCR */
1534 if (insn & 0xf)
1535 return 1;
1536 rd = (insn >> 12) & 0xf;
1537 wrd = (insn >> 16) & 0xf;
1538 switch (wrd) {
1539 case ARM_IWMMXT_wCID:
1540 case ARM_IWMMXT_wCASF:
1541 break;
1542 case ARM_IWMMXT_wCon:
1543 gen_op_iwmmxt_set_cup();
1544 /* Fall through. */
1545 case ARM_IWMMXT_wCSSF:
1546 tmp = iwmmxt_load_creg(wrd);
1547 tmp2 = load_reg(s, rd);
1548 tcg_gen_andc_i32(tmp, tmp, tmp2);
1549 tcg_temp_free_i32(tmp2);
1550 iwmmxt_store_creg(wrd, tmp);
1551 break;
1552 case ARM_IWMMXT_wCGR0:
1553 case ARM_IWMMXT_wCGR1:
1554 case ARM_IWMMXT_wCGR2:
1555 case ARM_IWMMXT_wCGR3:
1556 gen_op_iwmmxt_set_cup();
1557 tmp = load_reg(s, rd);
1558 iwmmxt_store_creg(wrd, tmp);
1559 break;
1560 default:
1561 return 1;
1563 break;
1564 case 0x100: /* WXOR */
1565 wrd = (insn >> 12) & 0xf;
1566 rd0 = (insn >> 0) & 0xf;
1567 rd1 = (insn >> 16) & 0xf;
1568 gen_op_iwmmxt_movq_M0_wRn(rd0);
1569 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1570 gen_op_iwmmxt_setpsr_nz();
1571 gen_op_iwmmxt_movq_wRn_M0(wrd);
1572 gen_op_iwmmxt_set_mup();
1573 gen_op_iwmmxt_set_cup();
1574 break;
1575 case 0x111: /* TMRC */
1576 if (insn & 0xf)
1577 return 1;
1578 rd = (insn >> 12) & 0xf;
1579 wrd = (insn >> 16) & 0xf;
1580 tmp = iwmmxt_load_creg(wrd);
1581 store_reg(s, rd, tmp);
1582 break;
1583 case 0x300: /* WANDN */
1584 wrd = (insn >> 12) & 0xf;
1585 rd0 = (insn >> 0) & 0xf;
1586 rd1 = (insn >> 16) & 0xf;
1587 gen_op_iwmmxt_movq_M0_wRn(rd0);
1588 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1589 gen_op_iwmmxt_andq_M0_wRn(rd1);
1590 gen_op_iwmmxt_setpsr_nz();
1591 gen_op_iwmmxt_movq_wRn_M0(wrd);
1592 gen_op_iwmmxt_set_mup();
1593 gen_op_iwmmxt_set_cup();
1594 break;
1595 case 0x200: /* WAND */
1596 wrd = (insn >> 12) & 0xf;
1597 rd0 = (insn >> 0) & 0xf;
1598 rd1 = (insn >> 16) & 0xf;
1599 gen_op_iwmmxt_movq_M0_wRn(rd0);
1600 gen_op_iwmmxt_andq_M0_wRn(rd1);
1601 gen_op_iwmmxt_setpsr_nz();
1602 gen_op_iwmmxt_movq_wRn_M0(wrd);
1603 gen_op_iwmmxt_set_mup();
1604 gen_op_iwmmxt_set_cup();
1605 break;
1606 case 0x810: case 0xa10: /* WMADD */
1607 wrd = (insn >> 12) & 0xf;
1608 rd0 = (insn >> 0) & 0xf;
1609 rd1 = (insn >> 16) & 0xf;
1610 gen_op_iwmmxt_movq_M0_wRn(rd0);
1611 if (insn & (1 << 21))
1612 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1613 else
1614 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1615 gen_op_iwmmxt_movq_wRn_M0(wrd);
1616 gen_op_iwmmxt_set_mup();
1617 break;
1618 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1619 wrd = (insn >> 12) & 0xf;
1620 rd0 = (insn >> 16) & 0xf;
1621 rd1 = (insn >> 0) & 0xf;
1622 gen_op_iwmmxt_movq_M0_wRn(rd0);
1623 switch ((insn >> 22) & 3) {
1624 case 0:
1625 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1626 break;
1627 case 1:
1628 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1629 break;
1630 case 2:
1631 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1632 break;
1633 case 3:
1634 return 1;
1636 gen_op_iwmmxt_movq_wRn_M0(wrd);
1637 gen_op_iwmmxt_set_mup();
1638 gen_op_iwmmxt_set_cup();
1639 break;
1640 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1641 wrd = (insn >> 12) & 0xf;
1642 rd0 = (insn >> 16) & 0xf;
1643 rd1 = (insn >> 0) & 0xf;
1644 gen_op_iwmmxt_movq_M0_wRn(rd0);
1645 switch ((insn >> 22) & 3) {
1646 case 0:
1647 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1648 break;
1649 case 1:
1650 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1651 break;
1652 case 2:
1653 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1654 break;
1655 case 3:
1656 return 1;
1658 gen_op_iwmmxt_movq_wRn_M0(wrd);
1659 gen_op_iwmmxt_set_mup();
1660 gen_op_iwmmxt_set_cup();
1661 break;
1662 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1663 wrd = (insn >> 12) & 0xf;
1664 rd0 = (insn >> 16) & 0xf;
1665 rd1 = (insn >> 0) & 0xf;
1666 gen_op_iwmmxt_movq_M0_wRn(rd0);
1667 if (insn & (1 << 22))
1668 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1669 else
1670 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1671 if (!(insn & (1 << 20)))
1672 gen_op_iwmmxt_addl_M0_wRn(wrd);
1673 gen_op_iwmmxt_movq_wRn_M0(wrd);
1674 gen_op_iwmmxt_set_mup();
1675 break;
1676 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1677 wrd = (insn >> 12) & 0xf;
1678 rd0 = (insn >> 16) & 0xf;
1679 rd1 = (insn >> 0) & 0xf;
1680 gen_op_iwmmxt_movq_M0_wRn(rd0);
1681 if (insn & (1 << 21)) {
1682 if (insn & (1 << 20))
1683 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1684 else
1685 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1686 } else {
1687 if (insn & (1 << 20))
1688 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1689 else
1690 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1692 gen_op_iwmmxt_movq_wRn_M0(wrd);
1693 gen_op_iwmmxt_set_mup();
1694 break;
1695 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1696 wrd = (insn >> 12) & 0xf;
1697 rd0 = (insn >> 16) & 0xf;
1698 rd1 = (insn >> 0) & 0xf;
1699 gen_op_iwmmxt_movq_M0_wRn(rd0);
1700 if (insn & (1 << 21))
1701 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1702 else
1703 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1704 if (!(insn & (1 << 20))) {
1705 iwmmxt_load_reg(cpu_V1, wrd);
1706 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1708 gen_op_iwmmxt_movq_wRn_M0(wrd);
1709 gen_op_iwmmxt_set_mup();
1710 break;
1711 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1712 wrd = (insn >> 12) & 0xf;
1713 rd0 = (insn >> 16) & 0xf;
1714 rd1 = (insn >> 0) & 0xf;
1715 gen_op_iwmmxt_movq_M0_wRn(rd0);
1716 switch ((insn >> 22) & 3) {
1717 case 0:
1718 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1719 break;
1720 case 1:
1721 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1722 break;
1723 case 2:
1724 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1725 break;
1726 case 3:
1727 return 1;
1729 gen_op_iwmmxt_movq_wRn_M0(wrd);
1730 gen_op_iwmmxt_set_mup();
1731 gen_op_iwmmxt_set_cup();
1732 break;
1733 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1734 wrd = (insn >> 12) & 0xf;
1735 rd0 = (insn >> 16) & 0xf;
1736 rd1 = (insn >> 0) & 0xf;
1737 gen_op_iwmmxt_movq_M0_wRn(rd0);
1738 if (insn & (1 << 22)) {
1739 if (insn & (1 << 20))
1740 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1741 else
1742 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1743 } else {
1744 if (insn & (1 << 20))
1745 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1746 else
1747 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1749 gen_op_iwmmxt_movq_wRn_M0(wrd);
1750 gen_op_iwmmxt_set_mup();
1751 gen_op_iwmmxt_set_cup();
1752 break;
1753 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1754 wrd = (insn >> 12) & 0xf;
1755 rd0 = (insn >> 16) & 0xf;
1756 rd1 = (insn >> 0) & 0xf;
1757 gen_op_iwmmxt_movq_M0_wRn(rd0);
1758 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1759 tcg_gen_andi_i32(tmp, tmp, 7);
1760 iwmmxt_load_reg(cpu_V1, rd1);
1761 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
1762 tcg_temp_free_i32(tmp);
1763 gen_op_iwmmxt_movq_wRn_M0(wrd);
1764 gen_op_iwmmxt_set_mup();
1765 break;
1766 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1767 if (((insn >> 6) & 3) == 3)
1768 return 1;
1769 rd = (insn >> 12) & 0xf;
1770 wrd = (insn >> 16) & 0xf;
1771 tmp = load_reg(s, rd);
1772 gen_op_iwmmxt_movq_M0_wRn(wrd);
1773 switch ((insn >> 6) & 3) {
1774 case 0:
1775 tmp2 = tcg_const_i32(0xff);
1776 tmp3 = tcg_const_i32((insn & 7) << 3);
1777 break;
1778 case 1:
1779 tmp2 = tcg_const_i32(0xffff);
1780 tmp3 = tcg_const_i32((insn & 3) << 4);
1781 break;
1782 case 2:
1783 tmp2 = tcg_const_i32(0xffffffff);
1784 tmp3 = tcg_const_i32((insn & 1) << 5);
1785 break;
1786 default:
1787 tmp2 = NULL;
1788 tmp3 = NULL;
1790 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
1791 tcg_temp_free_i32(tmp3);
1792 tcg_temp_free_i32(tmp2);
1793 tcg_temp_free_i32(tmp);
1794 gen_op_iwmmxt_movq_wRn_M0(wrd);
1795 gen_op_iwmmxt_set_mup();
1796 break;
1797 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1798 rd = (insn >> 12) & 0xf;
1799 wrd = (insn >> 16) & 0xf;
1800 if (rd == 15 || ((insn >> 22) & 3) == 3)
1801 return 1;
1802 gen_op_iwmmxt_movq_M0_wRn(wrd);
1803 tmp = tcg_temp_new_i32();
1804 switch ((insn >> 22) & 3) {
1805 case 0:
1806 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
1807 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1808 if (insn & 8) {
1809 tcg_gen_ext8s_i32(tmp, tmp);
1810 } else {
1811 tcg_gen_andi_i32(tmp, tmp, 0xff);
1813 break;
1814 case 1:
1815 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
1816 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1817 if (insn & 8) {
1818 tcg_gen_ext16s_i32(tmp, tmp);
1819 } else {
1820 tcg_gen_andi_i32(tmp, tmp, 0xffff);
1822 break;
1823 case 2:
1824 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
1825 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1826 break;
1828 store_reg(s, rd, tmp);
1829 break;
1830 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1831 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1832 return 1;
1833 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1834 switch ((insn >> 22) & 3) {
1835 case 0:
1836 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
1837 break;
1838 case 1:
1839 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
1840 break;
1841 case 2:
1842 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
1843 break;
1845 tcg_gen_shli_i32(tmp, tmp, 28);
1846 gen_set_nzcv(tmp);
1847 tcg_temp_free_i32(tmp);
1848 break;
1849 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1850 if (((insn >> 6) & 3) == 3)
1851 return 1;
1852 rd = (insn >> 12) & 0xf;
1853 wrd = (insn >> 16) & 0xf;
1854 tmp = load_reg(s, rd);
1855 switch ((insn >> 6) & 3) {
1856 case 0:
1857 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
1858 break;
1859 case 1:
1860 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
1861 break;
1862 case 2:
1863 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
1864 break;
1866 tcg_temp_free_i32(tmp);
1867 gen_op_iwmmxt_movq_wRn_M0(wrd);
1868 gen_op_iwmmxt_set_mup();
1869 break;
1870 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1871 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1872 return 1;
1873 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1874 tmp2 = tcg_temp_new_i32();
1875 tcg_gen_mov_i32(tmp2, tmp);
1876 switch ((insn >> 22) & 3) {
1877 case 0:
1878 for (i = 0; i < 7; i ++) {
1879 tcg_gen_shli_i32(tmp2, tmp2, 4);
1880 tcg_gen_and_i32(tmp, tmp, tmp2);
1882 break;
1883 case 1:
1884 for (i = 0; i < 3; i ++) {
1885 tcg_gen_shli_i32(tmp2, tmp2, 8);
1886 tcg_gen_and_i32(tmp, tmp, tmp2);
1888 break;
1889 case 2:
1890 tcg_gen_shli_i32(tmp2, tmp2, 16);
1891 tcg_gen_and_i32(tmp, tmp, tmp2);
1892 break;
1894 gen_set_nzcv(tmp);
1895 tcg_temp_free_i32(tmp2);
1896 tcg_temp_free_i32(tmp);
1897 break;
1898 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1899 wrd = (insn >> 12) & 0xf;
1900 rd0 = (insn >> 16) & 0xf;
1901 gen_op_iwmmxt_movq_M0_wRn(rd0);
1902 switch ((insn >> 22) & 3) {
1903 case 0:
1904 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1905 break;
1906 case 1:
1907 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1908 break;
1909 case 2:
1910 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1911 break;
1912 case 3:
1913 return 1;
1915 gen_op_iwmmxt_movq_wRn_M0(wrd);
1916 gen_op_iwmmxt_set_mup();
1917 break;
1918 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1919 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1920 return 1;
1921 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1922 tmp2 = tcg_temp_new_i32();
1923 tcg_gen_mov_i32(tmp2, tmp);
1924 switch ((insn >> 22) & 3) {
1925 case 0:
1926 for (i = 0; i < 7; i ++) {
1927 tcg_gen_shli_i32(tmp2, tmp2, 4);
1928 tcg_gen_or_i32(tmp, tmp, tmp2);
1930 break;
1931 case 1:
1932 for (i = 0; i < 3; i ++) {
1933 tcg_gen_shli_i32(tmp2, tmp2, 8);
1934 tcg_gen_or_i32(tmp, tmp, tmp2);
1936 break;
1937 case 2:
1938 tcg_gen_shli_i32(tmp2, tmp2, 16);
1939 tcg_gen_or_i32(tmp, tmp, tmp2);
1940 break;
1942 gen_set_nzcv(tmp);
1943 tcg_temp_free_i32(tmp2);
1944 tcg_temp_free_i32(tmp);
1945 break;
1946 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1947 rd = (insn >> 12) & 0xf;
1948 rd0 = (insn >> 16) & 0xf;
1949 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
1950 return 1;
1951 gen_op_iwmmxt_movq_M0_wRn(rd0);
1952 tmp = tcg_temp_new_i32();
1953 switch ((insn >> 22) & 3) {
1954 case 0:
1955 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
1956 break;
1957 case 1:
1958 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
1959 break;
1960 case 2:
1961 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
1962 break;
1964 store_reg(s, rd, tmp);
1965 break;
1966 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1967 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1968 wrd = (insn >> 12) & 0xf;
1969 rd0 = (insn >> 16) & 0xf;
1970 rd1 = (insn >> 0) & 0xf;
1971 gen_op_iwmmxt_movq_M0_wRn(rd0);
1972 switch ((insn >> 22) & 3) {
1973 case 0:
1974 if (insn & (1 << 21))
1975 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
1976 else
1977 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
1978 break;
1979 case 1:
1980 if (insn & (1 << 21))
1981 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
1982 else
1983 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
1984 break;
1985 case 2:
1986 if (insn & (1 << 21))
1987 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
1988 else
1989 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
1990 break;
1991 case 3:
1992 return 1;
1994 gen_op_iwmmxt_movq_wRn_M0(wrd);
1995 gen_op_iwmmxt_set_mup();
1996 gen_op_iwmmxt_set_cup();
1997 break;
1998 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
1999 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2000 wrd = (insn >> 12) & 0xf;
2001 rd0 = (insn >> 16) & 0xf;
2002 gen_op_iwmmxt_movq_M0_wRn(rd0);
2003 switch ((insn >> 22) & 3) {
2004 case 0:
2005 if (insn & (1 << 21))
2006 gen_op_iwmmxt_unpacklsb_M0();
2007 else
2008 gen_op_iwmmxt_unpacklub_M0();
2009 break;
2010 case 1:
2011 if (insn & (1 << 21))
2012 gen_op_iwmmxt_unpacklsw_M0();
2013 else
2014 gen_op_iwmmxt_unpackluw_M0();
2015 break;
2016 case 2:
2017 if (insn & (1 << 21))
2018 gen_op_iwmmxt_unpacklsl_M0();
2019 else
2020 gen_op_iwmmxt_unpacklul_M0();
2021 break;
2022 case 3:
2023 return 1;
2025 gen_op_iwmmxt_movq_wRn_M0(wrd);
2026 gen_op_iwmmxt_set_mup();
2027 gen_op_iwmmxt_set_cup();
2028 break;
2029 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2030 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2031 wrd = (insn >> 12) & 0xf;
2032 rd0 = (insn >> 16) & 0xf;
2033 gen_op_iwmmxt_movq_M0_wRn(rd0);
2034 switch ((insn >> 22) & 3) {
2035 case 0:
2036 if (insn & (1 << 21))
2037 gen_op_iwmmxt_unpackhsb_M0();
2038 else
2039 gen_op_iwmmxt_unpackhub_M0();
2040 break;
2041 case 1:
2042 if (insn & (1 << 21))
2043 gen_op_iwmmxt_unpackhsw_M0();
2044 else
2045 gen_op_iwmmxt_unpackhuw_M0();
2046 break;
2047 case 2:
2048 if (insn & (1 << 21))
2049 gen_op_iwmmxt_unpackhsl_M0();
2050 else
2051 gen_op_iwmmxt_unpackhul_M0();
2052 break;
2053 case 3:
2054 return 1;
2056 gen_op_iwmmxt_movq_wRn_M0(wrd);
2057 gen_op_iwmmxt_set_mup();
2058 gen_op_iwmmxt_set_cup();
2059 break;
2060 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2061 case 0x214: case 0x614: case 0xa14: case 0xe14:
2062 if (((insn >> 22) & 3) == 0)
2063 return 1;
2064 wrd = (insn >> 12) & 0xf;
2065 rd0 = (insn >> 16) & 0xf;
2066 gen_op_iwmmxt_movq_M0_wRn(rd0);
2067 tmp = tcg_temp_new_i32();
2068 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2069 tcg_temp_free_i32(tmp);
2070 return 1;
2072 switch ((insn >> 22) & 3) {
2073 case 1:
2074 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
2075 break;
2076 case 2:
2077 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
2078 break;
2079 case 3:
2080 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
2081 break;
2083 tcg_temp_free_i32(tmp);
2084 gen_op_iwmmxt_movq_wRn_M0(wrd);
2085 gen_op_iwmmxt_set_mup();
2086 gen_op_iwmmxt_set_cup();
2087 break;
2088 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2089 case 0x014: case 0x414: case 0x814: case 0xc14:
2090 if (((insn >> 22) & 3) == 0)
2091 return 1;
2092 wrd = (insn >> 12) & 0xf;
2093 rd0 = (insn >> 16) & 0xf;
2094 gen_op_iwmmxt_movq_M0_wRn(rd0);
2095 tmp = tcg_temp_new_i32();
2096 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2097 tcg_temp_free_i32(tmp);
2098 return 1;
2100 switch ((insn >> 22) & 3) {
2101 case 1:
2102 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
2103 break;
2104 case 2:
2105 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
2106 break;
2107 case 3:
2108 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
2109 break;
2111 tcg_temp_free_i32(tmp);
2112 gen_op_iwmmxt_movq_wRn_M0(wrd);
2113 gen_op_iwmmxt_set_mup();
2114 gen_op_iwmmxt_set_cup();
2115 break;
2116 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2117 case 0x114: case 0x514: case 0x914: case 0xd14:
2118 if (((insn >> 22) & 3) == 0)
2119 return 1;
2120 wrd = (insn >> 12) & 0xf;
2121 rd0 = (insn >> 16) & 0xf;
2122 gen_op_iwmmxt_movq_M0_wRn(rd0);
2123 tmp = tcg_temp_new_i32();
2124 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2125 tcg_temp_free_i32(tmp);
2126 return 1;
2128 switch ((insn >> 22) & 3) {
2129 case 1:
2130 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2131 break;
2132 case 2:
2133 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2134 break;
2135 case 3:
2136 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2137 break;
2139 tcg_temp_free_i32(tmp);
2140 gen_op_iwmmxt_movq_wRn_M0(wrd);
2141 gen_op_iwmmxt_set_mup();
2142 gen_op_iwmmxt_set_cup();
2143 break;
2144 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2145 case 0x314: case 0x714: case 0xb14: case 0xf14:
2146 if (((insn >> 22) & 3) == 0)
2147 return 1;
2148 wrd = (insn >> 12) & 0xf;
2149 rd0 = (insn >> 16) & 0xf;
2150 gen_op_iwmmxt_movq_M0_wRn(rd0);
2151 tmp = tcg_temp_new_i32();
2152 switch ((insn >> 22) & 3) {
2153 case 1:
2154 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2155 tcg_temp_free_i32(tmp);
2156 return 1;
2158 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2159 break;
2160 case 2:
2161 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2162 tcg_temp_free_i32(tmp);
2163 return 1;
2165 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2166 break;
2167 case 3:
2168 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2169 tcg_temp_free_i32(tmp);
2170 return 1;
2172 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2173 break;
2175 tcg_temp_free_i32(tmp);
2176 gen_op_iwmmxt_movq_wRn_M0(wrd);
2177 gen_op_iwmmxt_set_mup();
2178 gen_op_iwmmxt_set_cup();
2179 break;
2180 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2181 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2182 wrd = (insn >> 12) & 0xf;
2183 rd0 = (insn >> 16) & 0xf;
2184 rd1 = (insn >> 0) & 0xf;
2185 gen_op_iwmmxt_movq_M0_wRn(rd0);
2186 switch ((insn >> 22) & 3) {
2187 case 0:
2188 if (insn & (1 << 21))
2189 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2190 else
2191 gen_op_iwmmxt_minub_M0_wRn(rd1);
2192 break;
2193 case 1:
2194 if (insn & (1 << 21))
2195 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2196 else
2197 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2198 break;
2199 case 2:
2200 if (insn & (1 << 21))
2201 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2202 else
2203 gen_op_iwmmxt_minul_M0_wRn(rd1);
2204 break;
2205 case 3:
2206 return 1;
2208 gen_op_iwmmxt_movq_wRn_M0(wrd);
2209 gen_op_iwmmxt_set_mup();
2210 break;
2211 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2212 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2213 wrd = (insn >> 12) & 0xf;
2214 rd0 = (insn >> 16) & 0xf;
2215 rd1 = (insn >> 0) & 0xf;
2216 gen_op_iwmmxt_movq_M0_wRn(rd0);
2217 switch ((insn >> 22) & 3) {
2218 case 0:
2219 if (insn & (1 << 21))
2220 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2221 else
2222 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2223 break;
2224 case 1:
2225 if (insn & (1 << 21))
2226 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2227 else
2228 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2229 break;
2230 case 2:
2231 if (insn & (1 << 21))
2232 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2233 else
2234 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2235 break;
2236 case 3:
2237 return 1;
2239 gen_op_iwmmxt_movq_wRn_M0(wrd);
2240 gen_op_iwmmxt_set_mup();
2241 break;
2242 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2243 case 0x402: case 0x502: case 0x602: case 0x702:
2244 wrd = (insn >> 12) & 0xf;
2245 rd0 = (insn >> 16) & 0xf;
2246 rd1 = (insn >> 0) & 0xf;
2247 gen_op_iwmmxt_movq_M0_wRn(rd0);
2248 tmp = tcg_const_i32((insn >> 20) & 3);
2249 iwmmxt_load_reg(cpu_V1, rd1);
2250 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2251 tcg_temp_free_i32(tmp);
2252 gen_op_iwmmxt_movq_wRn_M0(wrd);
2253 gen_op_iwmmxt_set_mup();
2254 break;
2255 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2256 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2257 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2258 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2259 wrd = (insn >> 12) & 0xf;
2260 rd0 = (insn >> 16) & 0xf;
2261 rd1 = (insn >> 0) & 0xf;
2262 gen_op_iwmmxt_movq_M0_wRn(rd0);
2263 switch ((insn >> 20) & 0xf) {
2264 case 0x0:
2265 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2266 break;
2267 case 0x1:
2268 gen_op_iwmmxt_subub_M0_wRn(rd1);
2269 break;
2270 case 0x3:
2271 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2272 break;
2273 case 0x4:
2274 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2275 break;
2276 case 0x5:
2277 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2278 break;
2279 case 0x7:
2280 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2281 break;
2282 case 0x8:
2283 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2284 break;
2285 case 0x9:
2286 gen_op_iwmmxt_subul_M0_wRn(rd1);
2287 break;
2288 case 0xb:
2289 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2290 break;
2291 default:
2292 return 1;
2294 gen_op_iwmmxt_movq_wRn_M0(wrd);
2295 gen_op_iwmmxt_set_mup();
2296 gen_op_iwmmxt_set_cup();
2297 break;
2298 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2299 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2300 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2301 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2302 wrd = (insn >> 12) & 0xf;
2303 rd0 = (insn >> 16) & 0xf;
2304 gen_op_iwmmxt_movq_M0_wRn(rd0);
2305 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2306 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2307 tcg_temp_free_i32(tmp);
2308 gen_op_iwmmxt_movq_wRn_M0(wrd);
2309 gen_op_iwmmxt_set_mup();
2310 gen_op_iwmmxt_set_cup();
2311 break;
2312 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2313 case 0x418: case 0x518: case 0x618: case 0x718:
2314 case 0x818: case 0x918: case 0xa18: case 0xb18:
2315 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2316 wrd = (insn >> 12) & 0xf;
2317 rd0 = (insn >> 16) & 0xf;
2318 rd1 = (insn >> 0) & 0xf;
2319 gen_op_iwmmxt_movq_M0_wRn(rd0);
2320 switch ((insn >> 20) & 0xf) {
2321 case 0x0:
2322 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2323 break;
2324 case 0x1:
2325 gen_op_iwmmxt_addub_M0_wRn(rd1);
2326 break;
2327 case 0x3:
2328 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2329 break;
2330 case 0x4:
2331 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2332 break;
2333 case 0x5:
2334 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2335 break;
2336 case 0x7:
2337 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2338 break;
2339 case 0x8:
2340 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2341 break;
2342 case 0x9:
2343 gen_op_iwmmxt_addul_M0_wRn(rd1);
2344 break;
2345 case 0xb:
2346 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2347 break;
2348 default:
2349 return 1;
2351 gen_op_iwmmxt_movq_wRn_M0(wrd);
2352 gen_op_iwmmxt_set_mup();
2353 gen_op_iwmmxt_set_cup();
2354 break;
2355 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2356 case 0x408: case 0x508: case 0x608: case 0x708:
2357 case 0x808: case 0x908: case 0xa08: case 0xb08:
2358 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2359 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2360 return 1;
2361 wrd = (insn >> 12) & 0xf;
2362 rd0 = (insn >> 16) & 0xf;
2363 rd1 = (insn >> 0) & 0xf;
2364 gen_op_iwmmxt_movq_M0_wRn(rd0);
2365 switch ((insn >> 22) & 3) {
2366 case 1:
2367 if (insn & (1 << 21))
2368 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2369 else
2370 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2371 break;
2372 case 2:
2373 if (insn & (1 << 21))
2374 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2375 else
2376 gen_op_iwmmxt_packul_M0_wRn(rd1);
2377 break;
2378 case 3:
2379 if (insn & (1 << 21))
2380 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2381 else
2382 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2383 break;
2385 gen_op_iwmmxt_movq_wRn_M0(wrd);
2386 gen_op_iwmmxt_set_mup();
2387 gen_op_iwmmxt_set_cup();
2388 break;
2389 case 0x201: case 0x203: case 0x205: case 0x207:
2390 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2391 case 0x211: case 0x213: case 0x215: case 0x217:
2392 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2393 wrd = (insn >> 5) & 0xf;
2394 rd0 = (insn >> 12) & 0xf;
2395 rd1 = (insn >> 0) & 0xf;
2396 if (rd0 == 0xf || rd1 == 0xf)
2397 return 1;
2398 gen_op_iwmmxt_movq_M0_wRn(wrd);
2399 tmp = load_reg(s, rd0);
2400 tmp2 = load_reg(s, rd1);
2401 switch ((insn >> 16) & 0xf) {
2402 case 0x0: /* TMIA */
2403 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2404 break;
2405 case 0x8: /* TMIAPH */
2406 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2407 break;
2408 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2409 if (insn & (1 << 16))
2410 tcg_gen_shri_i32(tmp, tmp, 16);
2411 if (insn & (1 << 17))
2412 tcg_gen_shri_i32(tmp2, tmp2, 16);
2413 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2414 break;
2415 default:
2416 tcg_temp_free_i32(tmp2);
2417 tcg_temp_free_i32(tmp);
2418 return 1;
2420 tcg_temp_free_i32(tmp2);
2421 tcg_temp_free_i32(tmp);
2422 gen_op_iwmmxt_movq_wRn_M0(wrd);
2423 gen_op_iwmmxt_set_mup();
2424 break;
2425 default:
2426 return 1;
2429 return 0;
2432 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
2433 (ie. an undefined instruction). */
2434 static int disas_dsp_insn(DisasContext *s, uint32_t insn)
2436 int acc, rd0, rd1, rdhi, rdlo;
2437 TCGv_i32 tmp, tmp2;
2439 if ((insn & 0x0ff00f10) == 0x0e200010) {
2440 /* Multiply with Internal Accumulate Format */
2441 rd0 = (insn >> 12) & 0xf;
2442 rd1 = insn & 0xf;
2443 acc = (insn >> 5) & 7;
2445 if (acc != 0)
2446 return 1;
2448 tmp = load_reg(s, rd0);
2449 tmp2 = load_reg(s, rd1);
2450 switch ((insn >> 16) & 0xf) {
2451 case 0x0: /* MIA */
2452 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2453 break;
2454 case 0x8: /* MIAPH */
2455 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2456 break;
2457 case 0xc: /* MIABB */
2458 case 0xd: /* MIABT */
2459 case 0xe: /* MIATB */
2460 case 0xf: /* MIATT */
2461 if (insn & (1 << 16))
2462 tcg_gen_shri_i32(tmp, tmp, 16);
2463 if (insn & (1 << 17))
2464 tcg_gen_shri_i32(tmp2, tmp2, 16);
2465 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2466 break;
2467 default:
2468 return 1;
2470 tcg_temp_free_i32(tmp2);
2471 tcg_temp_free_i32(tmp);
2473 gen_op_iwmmxt_movq_wRn_M0(acc);
2474 return 0;
2477 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2478 /* Internal Accumulator Access Format */
2479 rdhi = (insn >> 16) & 0xf;
2480 rdlo = (insn >> 12) & 0xf;
2481 acc = insn & 7;
2483 if (acc != 0)
2484 return 1;
2486 if (insn & ARM_CP_RW_BIT) { /* MRA */
2487 iwmmxt_load_reg(cpu_V0, acc);
2488 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
2489 tcg_gen_extrh_i64_i32(cpu_R[rdhi], cpu_V0);
2490 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
2491 } else { /* MAR */
2492 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2493 iwmmxt_store_reg(cpu_V0, acc);
2495 return 0;
2498 return 1;
2501 static inline bool use_goto_tb(DisasContext *s, target_ulong dest)
2503 #ifndef CONFIG_USER_ONLY
2504 return (s->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
2505 ((s->base.pc_next - 1) & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
2506 #else
2507 return true;
2508 #endif
2511 static void gen_goto_ptr(void)
2513 tcg_gen_lookup_and_goto_ptr();
2516 /* This will end the TB but doesn't guarantee we'll return to
2517 * cpu_loop_exec. Any live exit_requests will be processed as we
2518 * enter the next TB.
2520 static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
2522 if (use_goto_tb(s, dest)) {
2523 tcg_gen_goto_tb(n);
2524 gen_set_pc_im(s, dest);
2525 tcg_gen_exit_tb(s->base.tb, n);
2526 } else {
2527 gen_set_pc_im(s, dest);
2528 gen_goto_ptr();
2530 s->base.is_jmp = DISAS_NORETURN;
2533 /* Jump, specifying which TB number to use if we gen_goto_tb() */
2534 static inline void gen_jmp_tb(DisasContext *s, uint32_t dest, int tbno)
2536 if (unlikely(is_singlestepping(s))) {
2537 /* An indirect jump so that we still trigger the debug exception. */
2538 gen_set_pc_im(s, dest);
2539 s->base.is_jmp = DISAS_JUMP;
2540 } else {
2541 gen_goto_tb(s, tbno, dest);
2545 static inline void gen_jmp(DisasContext *s, uint32_t dest)
2547 gen_jmp_tb(s, dest, 0);
2550 static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
2552 if (x)
2553 tcg_gen_sari_i32(t0, t0, 16);
2554 else
2555 gen_sxth(t0);
2556 if (y)
2557 tcg_gen_sari_i32(t1, t1, 16);
2558 else
2559 gen_sxth(t1);
2560 tcg_gen_mul_i32(t0, t0, t1);
2563 /* Return the mask of PSR bits set by a MSR instruction. */
2564 static uint32_t msr_mask(DisasContext *s, int flags, int spsr)
2566 uint32_t mask = 0;
2568 if (flags & (1 << 0)) {
2569 mask |= 0xff;
2571 if (flags & (1 << 1)) {
2572 mask |= 0xff00;
2574 if (flags & (1 << 2)) {
2575 mask |= 0xff0000;
2577 if (flags & (1 << 3)) {
2578 mask |= 0xff000000;
2581 /* Mask out undefined and reserved bits. */
2582 mask &= aarch32_cpsr_valid_mask(s->features, s->isar);
2584 /* Mask out execution state. */
2585 if (!spsr) {
2586 mask &= ~CPSR_EXEC;
2589 /* Mask out privileged bits. */
2590 if (IS_USER(s)) {
2591 mask &= CPSR_USER;
2593 return mask;
2596 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
2597 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv_i32 t0)
2599 TCGv_i32 tmp;
2600 if (spsr) {
2601 /* ??? This is also undefined in system mode. */
2602 if (IS_USER(s))
2603 return 1;
2605 tmp = load_cpu_field(spsr);
2606 tcg_gen_andi_i32(tmp, tmp, ~mask);
2607 tcg_gen_andi_i32(t0, t0, mask);
2608 tcg_gen_or_i32(tmp, tmp, t0);
2609 store_cpu_field(tmp, spsr);
2610 } else {
2611 gen_set_cpsr(t0, mask);
2613 tcg_temp_free_i32(t0);
2614 gen_lookup_tb(s);
2615 return 0;
2618 /* Returns nonzero if access to the PSR is not permitted. */
2619 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
2621 TCGv_i32 tmp;
2622 tmp = tcg_temp_new_i32();
2623 tcg_gen_movi_i32(tmp, val);
2624 return gen_set_psr(s, mask, spsr, tmp);
2627 static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
2628 int *tgtmode, int *regno)
2630 /* Decode the r and sysm fields of MSR/MRS banked accesses into
2631 * the target mode and register number, and identify the various
2632 * unpredictable cases.
2633 * MSR (banked) and MRS (banked) are CONSTRAINED UNPREDICTABLE if:
2634 * + executed in user mode
2635 * + using R15 as the src/dest register
2636 * + accessing an unimplemented register
2637 * + accessing a register that's inaccessible at current PL/security state*
2638 * + accessing a register that you could access with a different insn
2639 * We choose to UNDEF in all these cases.
2640 * Since we don't know which of the various AArch32 modes we are in
2641 * we have to defer some checks to runtime.
2642 * Accesses to Monitor mode registers from Secure EL1 (which implies
2643 * that EL3 is AArch64) must trap to EL3.
2645 * If the access checks fail this function will emit code to take
2646 * an exception and return false. Otherwise it will return true,
2647 * and set *tgtmode and *regno appropriately.
2649 int exc_target = default_exception_el(s);
2651 /* These instructions are present only in ARMv8, or in ARMv7 with the
2652 * Virtualization Extensions.
2654 if (!arm_dc_feature(s, ARM_FEATURE_V8) &&
2655 !arm_dc_feature(s, ARM_FEATURE_EL2)) {
2656 goto undef;
2659 if (IS_USER(s) || rn == 15) {
2660 goto undef;
2663 /* The table in the v8 ARM ARM section F5.2.3 describes the encoding
2664 * of registers into (r, sysm).
2666 if (r) {
2667 /* SPSRs for other modes */
2668 switch (sysm) {
2669 case 0xe: /* SPSR_fiq */
2670 *tgtmode = ARM_CPU_MODE_FIQ;
2671 break;
2672 case 0x10: /* SPSR_irq */
2673 *tgtmode = ARM_CPU_MODE_IRQ;
2674 break;
2675 case 0x12: /* SPSR_svc */
2676 *tgtmode = ARM_CPU_MODE_SVC;
2677 break;
2678 case 0x14: /* SPSR_abt */
2679 *tgtmode = ARM_CPU_MODE_ABT;
2680 break;
2681 case 0x16: /* SPSR_und */
2682 *tgtmode = ARM_CPU_MODE_UND;
2683 break;
2684 case 0x1c: /* SPSR_mon */
2685 *tgtmode = ARM_CPU_MODE_MON;
2686 break;
2687 case 0x1e: /* SPSR_hyp */
2688 *tgtmode = ARM_CPU_MODE_HYP;
2689 break;
2690 default: /* unallocated */
2691 goto undef;
2693 /* We arbitrarily assign SPSR a register number of 16. */
2694 *regno = 16;
2695 } else {
2696 /* general purpose registers for other modes */
2697 switch (sysm) {
2698 case 0x0 ... 0x6: /* 0b00xxx : r8_usr ... r14_usr */
2699 *tgtmode = ARM_CPU_MODE_USR;
2700 *regno = sysm + 8;
2701 break;
2702 case 0x8 ... 0xe: /* 0b01xxx : r8_fiq ... r14_fiq */
2703 *tgtmode = ARM_CPU_MODE_FIQ;
2704 *regno = sysm;
2705 break;
2706 case 0x10 ... 0x11: /* 0b1000x : r14_irq, r13_irq */
2707 *tgtmode = ARM_CPU_MODE_IRQ;
2708 *regno = sysm & 1 ? 13 : 14;
2709 break;
2710 case 0x12 ... 0x13: /* 0b1001x : r14_svc, r13_svc */
2711 *tgtmode = ARM_CPU_MODE_SVC;
2712 *regno = sysm & 1 ? 13 : 14;
2713 break;
2714 case 0x14 ... 0x15: /* 0b1010x : r14_abt, r13_abt */
2715 *tgtmode = ARM_CPU_MODE_ABT;
2716 *regno = sysm & 1 ? 13 : 14;
2717 break;
2718 case 0x16 ... 0x17: /* 0b1011x : r14_und, r13_und */
2719 *tgtmode = ARM_CPU_MODE_UND;
2720 *regno = sysm & 1 ? 13 : 14;
2721 break;
2722 case 0x1c ... 0x1d: /* 0b1110x : r14_mon, r13_mon */
2723 *tgtmode = ARM_CPU_MODE_MON;
2724 *regno = sysm & 1 ? 13 : 14;
2725 break;
2726 case 0x1e ... 0x1f: /* 0b1111x : elr_hyp, r13_hyp */
2727 *tgtmode = ARM_CPU_MODE_HYP;
2728 /* Arbitrarily pick 17 for ELR_Hyp (which is not a banked LR!) */
2729 *regno = sysm & 1 ? 13 : 17;
2730 break;
2731 default: /* unallocated */
2732 goto undef;
2736 /* Catch the 'accessing inaccessible register' cases we can detect
2737 * at translate time.
2739 switch (*tgtmode) {
2740 case ARM_CPU_MODE_MON:
2741 if (!arm_dc_feature(s, ARM_FEATURE_EL3) || s->ns) {
2742 goto undef;
2744 if (s->current_el == 1) {
2745 /* If we're in Secure EL1 (which implies that EL3 is AArch64)
2746 * then accesses to Mon registers trap to Secure EL2, if it exists,
2747 * otherwise EL3.
2749 TCGv_i32 tcg_el;
2751 if (arm_dc_feature(s, ARM_FEATURE_AARCH64) &&
2752 dc_isar_feature(aa64_sel2, s)) {
2753 /* Target EL is EL<3 minus SCR_EL3.EEL2> */
2754 tcg_el = load_cpu_field(cp15.scr_el3);
2755 tcg_gen_sextract_i32(tcg_el, tcg_el, ctz32(SCR_EEL2), 1);
2756 tcg_gen_addi_i32(tcg_el, tcg_el, 3);
2757 } else {
2758 tcg_el = tcg_const_i32(3);
2761 gen_exception_el(s, EXCP_UDEF, syn_uncategorized(), tcg_el);
2762 tcg_temp_free_i32(tcg_el);
2763 return false;
2765 break;
2766 case ARM_CPU_MODE_HYP:
2768 * SPSR_hyp and r13_hyp can only be accessed from Monitor mode
2769 * (and so we can forbid accesses from EL2 or below). elr_hyp
2770 * can be accessed also from Hyp mode, so forbid accesses from
2771 * EL0 or EL1.
2773 if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_el < 2 ||
2774 (s->current_el < 3 && *regno != 17)) {
2775 goto undef;
2777 break;
2778 default:
2779 break;
2782 return true;
2784 undef:
2785 /* If we get here then some access check did not pass */
2786 gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
2787 syn_uncategorized(), exc_target);
2788 return false;
2791 static void gen_msr_banked(DisasContext *s, int r, int sysm, int rn)
2793 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
2794 int tgtmode = 0, regno = 0;
2796 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
2797 return;
2800 /* Sync state because msr_banked() can raise exceptions */
2801 gen_set_condexec(s);
2802 gen_set_pc_im(s, s->pc_curr);
2803 tcg_reg = load_reg(s, rn);
2804 tcg_tgtmode = tcg_const_i32(tgtmode);
2805 tcg_regno = tcg_const_i32(regno);
2806 gen_helper_msr_banked(cpu_env, tcg_reg, tcg_tgtmode, tcg_regno);
2807 tcg_temp_free_i32(tcg_tgtmode);
2808 tcg_temp_free_i32(tcg_regno);
2809 tcg_temp_free_i32(tcg_reg);
2810 s->base.is_jmp = DISAS_UPDATE_EXIT;
2813 static void gen_mrs_banked(DisasContext *s, int r, int sysm, int rn)
2815 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
2816 int tgtmode = 0, regno = 0;
2818 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
2819 return;
2822 /* Sync state because mrs_banked() can raise exceptions */
2823 gen_set_condexec(s);
2824 gen_set_pc_im(s, s->pc_curr);
2825 tcg_reg = tcg_temp_new_i32();
2826 tcg_tgtmode = tcg_const_i32(tgtmode);
2827 tcg_regno = tcg_const_i32(regno);
2828 gen_helper_mrs_banked(tcg_reg, cpu_env, tcg_tgtmode, tcg_regno);
2829 tcg_temp_free_i32(tcg_tgtmode);
2830 tcg_temp_free_i32(tcg_regno);
2831 store_reg(s, rn, tcg_reg);
2832 s->base.is_jmp = DISAS_UPDATE_EXIT;
2835 /* Store value to PC as for an exception return (ie don't
2836 * mask bits). The subsequent call to gen_helper_cpsr_write_eret()
2837 * will do the masking based on the new value of the Thumb bit.
2839 static void store_pc_exc_ret(DisasContext *s, TCGv_i32 pc)
2841 tcg_gen_mov_i32(cpu_R[15], pc);
2842 tcg_temp_free_i32(pc);
2845 /* Generate a v6 exception return. Marks both values as dead. */
2846 static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
2848 store_pc_exc_ret(s, pc);
2849 /* The cpsr_write_eret helper will mask the low bits of PC
2850 * appropriately depending on the new Thumb bit, so it must
2851 * be called after storing the new PC.
2853 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
2854 gen_io_start();
2856 gen_helper_cpsr_write_eret(cpu_env, cpsr);
2857 tcg_temp_free_i32(cpsr);
2858 /* Must exit loop to check un-masked IRQs */
2859 s->base.is_jmp = DISAS_EXIT;
2862 /* Generate an old-style exception return. Marks pc as dead. */
2863 static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
2865 gen_rfe(s, pc, load_cpu_field(spsr));
2868 static void gen_gvec_fn3_qc(uint32_t rd_ofs, uint32_t rn_ofs, uint32_t rm_ofs,
2869 uint32_t opr_sz, uint32_t max_sz,
2870 gen_helper_gvec_3_ptr *fn)
2872 TCGv_ptr qc_ptr = tcg_temp_new_ptr();
2874 tcg_gen_addi_ptr(qc_ptr, cpu_env, offsetof(CPUARMState, vfp.qc));
2875 tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, qc_ptr,
2876 opr_sz, max_sz, 0, fn);
2877 tcg_temp_free_ptr(qc_ptr);
2880 void gen_gvec_sqrdmlah_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
2881 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
2883 static gen_helper_gvec_3_ptr * const fns[2] = {
2884 gen_helper_gvec_qrdmlah_s16, gen_helper_gvec_qrdmlah_s32
2886 tcg_debug_assert(vece >= 1 && vece <= 2);
2887 gen_gvec_fn3_qc(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, fns[vece - 1]);
2890 void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
2891 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
2893 static gen_helper_gvec_3_ptr * const fns[2] = {
2894 gen_helper_gvec_qrdmlsh_s16, gen_helper_gvec_qrdmlsh_s32
2896 tcg_debug_assert(vece >= 1 && vece <= 2);
2897 gen_gvec_fn3_qc(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, fns[vece - 1]);
2900 #define GEN_CMP0(NAME, COND) \
2901 static void gen_##NAME##0_i32(TCGv_i32 d, TCGv_i32 a) \
2903 tcg_gen_setcondi_i32(COND, d, a, 0); \
2904 tcg_gen_neg_i32(d, d); \
2906 static void gen_##NAME##0_i64(TCGv_i64 d, TCGv_i64 a) \
2908 tcg_gen_setcondi_i64(COND, d, a, 0); \
2909 tcg_gen_neg_i64(d, d); \
2911 static void gen_##NAME##0_vec(unsigned vece, TCGv_vec d, TCGv_vec a) \
2913 TCGv_vec zero = tcg_const_zeros_vec_matching(d); \
2914 tcg_gen_cmp_vec(COND, vece, d, a, zero); \
2915 tcg_temp_free_vec(zero); \
2917 void gen_gvec_##NAME##0(unsigned vece, uint32_t d, uint32_t m, \
2918 uint32_t opr_sz, uint32_t max_sz) \
2920 const GVecGen2 op[4] = { \
2921 { .fno = gen_helper_gvec_##NAME##0_b, \
2922 .fniv = gen_##NAME##0_vec, \
2923 .opt_opc = vecop_list_cmp, \
2924 .vece = MO_8 }, \
2925 { .fno = gen_helper_gvec_##NAME##0_h, \
2926 .fniv = gen_##NAME##0_vec, \
2927 .opt_opc = vecop_list_cmp, \
2928 .vece = MO_16 }, \
2929 { .fni4 = gen_##NAME##0_i32, \
2930 .fniv = gen_##NAME##0_vec, \
2931 .opt_opc = vecop_list_cmp, \
2932 .vece = MO_32 }, \
2933 { .fni8 = gen_##NAME##0_i64, \
2934 .fniv = gen_##NAME##0_vec, \
2935 .opt_opc = vecop_list_cmp, \
2936 .prefer_i64 = TCG_TARGET_REG_BITS == 64, \
2937 .vece = MO_64 }, \
2938 }; \
2939 tcg_gen_gvec_2(d, m, opr_sz, max_sz, &op[vece]); \
2942 static const TCGOpcode vecop_list_cmp[] = {
2943 INDEX_op_cmp_vec, 0
2946 GEN_CMP0(ceq, TCG_COND_EQ)
2947 GEN_CMP0(cle, TCG_COND_LE)
2948 GEN_CMP0(cge, TCG_COND_GE)
2949 GEN_CMP0(clt, TCG_COND_LT)
2950 GEN_CMP0(cgt, TCG_COND_GT)
2952 #undef GEN_CMP0
2954 static void gen_ssra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
2956 tcg_gen_vec_sar8i_i64(a, a, shift);
2957 tcg_gen_vec_add8_i64(d, d, a);
2960 static void gen_ssra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
2962 tcg_gen_vec_sar16i_i64(a, a, shift);
2963 tcg_gen_vec_add16_i64(d, d, a);
2966 static void gen_ssra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
2968 tcg_gen_sari_i32(a, a, shift);
2969 tcg_gen_add_i32(d, d, a);
2972 static void gen_ssra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
2974 tcg_gen_sari_i64(a, a, shift);
2975 tcg_gen_add_i64(d, d, a);
2978 static void gen_ssra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
2980 tcg_gen_sari_vec(vece, a, a, sh);
2981 tcg_gen_add_vec(vece, d, d, a);
2984 void gen_gvec_ssra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
2985 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
2987 static const TCGOpcode vecop_list[] = {
2988 INDEX_op_sari_vec, INDEX_op_add_vec, 0
2990 static const GVecGen2i ops[4] = {
2991 { .fni8 = gen_ssra8_i64,
2992 .fniv = gen_ssra_vec,
2993 .fno = gen_helper_gvec_ssra_b,
2994 .load_dest = true,
2995 .opt_opc = vecop_list,
2996 .vece = MO_8 },
2997 { .fni8 = gen_ssra16_i64,
2998 .fniv = gen_ssra_vec,
2999 .fno = gen_helper_gvec_ssra_h,
3000 .load_dest = true,
3001 .opt_opc = vecop_list,
3002 .vece = MO_16 },
3003 { .fni4 = gen_ssra32_i32,
3004 .fniv = gen_ssra_vec,
3005 .fno = gen_helper_gvec_ssra_s,
3006 .load_dest = true,
3007 .opt_opc = vecop_list,
3008 .vece = MO_32 },
3009 { .fni8 = gen_ssra64_i64,
3010 .fniv = gen_ssra_vec,
3011 .fno = gen_helper_gvec_ssra_b,
3012 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3013 .opt_opc = vecop_list,
3014 .load_dest = true,
3015 .vece = MO_64 },
3018 /* tszimm encoding produces immediates in the range [1..esize]. */
3019 tcg_debug_assert(shift > 0);
3020 tcg_debug_assert(shift <= (8 << vece));
3023 * Shifts larger than the element size are architecturally valid.
3024 * Signed results in all sign bits.
3026 shift = MIN(shift, (8 << vece) - 1);
3027 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3030 static void gen_usra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3032 tcg_gen_vec_shr8i_i64(a, a, shift);
3033 tcg_gen_vec_add8_i64(d, d, a);
3036 static void gen_usra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3038 tcg_gen_vec_shr16i_i64(a, a, shift);
3039 tcg_gen_vec_add16_i64(d, d, a);
3042 static void gen_usra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
3044 tcg_gen_shri_i32(a, a, shift);
3045 tcg_gen_add_i32(d, d, a);
3048 static void gen_usra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3050 tcg_gen_shri_i64(a, a, shift);
3051 tcg_gen_add_i64(d, d, a);
3054 static void gen_usra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3056 tcg_gen_shri_vec(vece, a, a, sh);
3057 tcg_gen_add_vec(vece, d, d, a);
3060 void gen_gvec_usra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3061 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3063 static const TCGOpcode vecop_list[] = {
3064 INDEX_op_shri_vec, INDEX_op_add_vec, 0
3066 static const GVecGen2i ops[4] = {
3067 { .fni8 = gen_usra8_i64,
3068 .fniv = gen_usra_vec,
3069 .fno = gen_helper_gvec_usra_b,
3070 .load_dest = true,
3071 .opt_opc = vecop_list,
3072 .vece = MO_8, },
3073 { .fni8 = gen_usra16_i64,
3074 .fniv = gen_usra_vec,
3075 .fno = gen_helper_gvec_usra_h,
3076 .load_dest = true,
3077 .opt_opc = vecop_list,
3078 .vece = MO_16, },
3079 { .fni4 = gen_usra32_i32,
3080 .fniv = gen_usra_vec,
3081 .fno = gen_helper_gvec_usra_s,
3082 .load_dest = true,
3083 .opt_opc = vecop_list,
3084 .vece = MO_32, },
3085 { .fni8 = gen_usra64_i64,
3086 .fniv = gen_usra_vec,
3087 .fno = gen_helper_gvec_usra_d,
3088 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3089 .load_dest = true,
3090 .opt_opc = vecop_list,
3091 .vece = MO_64, },
3094 /* tszimm encoding produces immediates in the range [1..esize]. */
3095 tcg_debug_assert(shift > 0);
3096 tcg_debug_assert(shift <= (8 << vece));
3099 * Shifts larger than the element size are architecturally valid.
3100 * Unsigned results in all zeros as input to accumulate: nop.
3102 if (shift < (8 << vece)) {
3103 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3104 } else {
3105 /* Nop, but we do need to clear the tail. */
3106 tcg_gen_gvec_mov(vece, rd_ofs, rd_ofs, opr_sz, max_sz);
3111 * Shift one less than the requested amount, and the low bit is
3112 * the rounding bit. For the 8 and 16-bit operations, because we
3113 * mask the low bit, we can perform a normal integer shift instead
3114 * of a vector shift.
3116 static void gen_srshr8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3118 TCGv_i64 t = tcg_temp_new_i64();
3120 tcg_gen_shri_i64(t, a, sh - 1);
3121 tcg_gen_andi_i64(t, t, dup_const(MO_8, 1));
3122 tcg_gen_vec_sar8i_i64(d, a, sh);
3123 tcg_gen_vec_add8_i64(d, d, t);
3124 tcg_temp_free_i64(t);
3127 static void gen_srshr16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3129 TCGv_i64 t = tcg_temp_new_i64();
3131 tcg_gen_shri_i64(t, a, sh - 1);
3132 tcg_gen_andi_i64(t, t, dup_const(MO_16, 1));
3133 tcg_gen_vec_sar16i_i64(d, a, sh);
3134 tcg_gen_vec_add16_i64(d, d, t);
3135 tcg_temp_free_i64(t);
3138 static void gen_srshr32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
3140 TCGv_i32 t = tcg_temp_new_i32();
3142 tcg_gen_extract_i32(t, a, sh - 1, 1);
3143 tcg_gen_sari_i32(d, a, sh);
3144 tcg_gen_add_i32(d, d, t);
3145 tcg_temp_free_i32(t);
3148 static void gen_srshr64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3150 TCGv_i64 t = tcg_temp_new_i64();
3152 tcg_gen_extract_i64(t, a, sh - 1, 1);
3153 tcg_gen_sari_i64(d, a, sh);
3154 tcg_gen_add_i64(d, d, t);
3155 tcg_temp_free_i64(t);
3158 static void gen_srshr_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3160 TCGv_vec t = tcg_temp_new_vec_matching(d);
3161 TCGv_vec ones = tcg_temp_new_vec_matching(d);
3163 tcg_gen_shri_vec(vece, t, a, sh - 1);
3164 tcg_gen_dupi_vec(vece, ones, 1);
3165 tcg_gen_and_vec(vece, t, t, ones);
3166 tcg_gen_sari_vec(vece, d, a, sh);
3167 tcg_gen_add_vec(vece, d, d, t);
3169 tcg_temp_free_vec(t);
3170 tcg_temp_free_vec(ones);
3173 void gen_gvec_srshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3174 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3176 static const TCGOpcode vecop_list[] = {
3177 INDEX_op_shri_vec, INDEX_op_sari_vec, INDEX_op_add_vec, 0
3179 static const GVecGen2i ops[4] = {
3180 { .fni8 = gen_srshr8_i64,
3181 .fniv = gen_srshr_vec,
3182 .fno = gen_helper_gvec_srshr_b,
3183 .opt_opc = vecop_list,
3184 .vece = MO_8 },
3185 { .fni8 = gen_srshr16_i64,
3186 .fniv = gen_srshr_vec,
3187 .fno = gen_helper_gvec_srshr_h,
3188 .opt_opc = vecop_list,
3189 .vece = MO_16 },
3190 { .fni4 = gen_srshr32_i32,
3191 .fniv = gen_srshr_vec,
3192 .fno = gen_helper_gvec_srshr_s,
3193 .opt_opc = vecop_list,
3194 .vece = MO_32 },
3195 { .fni8 = gen_srshr64_i64,
3196 .fniv = gen_srshr_vec,
3197 .fno = gen_helper_gvec_srshr_d,
3198 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3199 .opt_opc = vecop_list,
3200 .vece = MO_64 },
3203 /* tszimm encoding produces immediates in the range [1..esize] */
3204 tcg_debug_assert(shift > 0);
3205 tcg_debug_assert(shift <= (8 << vece));
3207 if (shift == (8 << vece)) {
3209 * Shifts larger than the element size are architecturally valid.
3210 * Signed results in all sign bits. With rounding, this produces
3211 * (-1 + 1) >> 1 == 0, or (0 + 1) >> 1 == 0.
3212 * I.e. always zero.
3214 tcg_gen_gvec_dup_imm(vece, rd_ofs, opr_sz, max_sz, 0);
3215 } else {
3216 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3220 static void gen_srsra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3222 TCGv_i64 t = tcg_temp_new_i64();
3224 gen_srshr8_i64(t, a, sh);
3225 tcg_gen_vec_add8_i64(d, d, t);
3226 tcg_temp_free_i64(t);
3229 static void gen_srsra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3231 TCGv_i64 t = tcg_temp_new_i64();
3233 gen_srshr16_i64(t, a, sh);
3234 tcg_gen_vec_add16_i64(d, d, t);
3235 tcg_temp_free_i64(t);
3238 static void gen_srsra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
3240 TCGv_i32 t = tcg_temp_new_i32();
3242 gen_srshr32_i32(t, a, sh);
3243 tcg_gen_add_i32(d, d, t);
3244 tcg_temp_free_i32(t);
3247 static void gen_srsra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3249 TCGv_i64 t = tcg_temp_new_i64();
3251 gen_srshr64_i64(t, a, sh);
3252 tcg_gen_add_i64(d, d, t);
3253 tcg_temp_free_i64(t);
3256 static void gen_srsra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3258 TCGv_vec t = tcg_temp_new_vec_matching(d);
3260 gen_srshr_vec(vece, t, a, sh);
3261 tcg_gen_add_vec(vece, d, d, t);
3262 tcg_temp_free_vec(t);
3265 void gen_gvec_srsra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3266 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3268 static const TCGOpcode vecop_list[] = {
3269 INDEX_op_shri_vec, INDEX_op_sari_vec, INDEX_op_add_vec, 0
3271 static const GVecGen2i ops[4] = {
3272 { .fni8 = gen_srsra8_i64,
3273 .fniv = gen_srsra_vec,
3274 .fno = gen_helper_gvec_srsra_b,
3275 .opt_opc = vecop_list,
3276 .load_dest = true,
3277 .vece = MO_8 },
3278 { .fni8 = gen_srsra16_i64,
3279 .fniv = gen_srsra_vec,
3280 .fno = gen_helper_gvec_srsra_h,
3281 .opt_opc = vecop_list,
3282 .load_dest = true,
3283 .vece = MO_16 },
3284 { .fni4 = gen_srsra32_i32,
3285 .fniv = gen_srsra_vec,
3286 .fno = gen_helper_gvec_srsra_s,
3287 .opt_opc = vecop_list,
3288 .load_dest = true,
3289 .vece = MO_32 },
3290 { .fni8 = gen_srsra64_i64,
3291 .fniv = gen_srsra_vec,
3292 .fno = gen_helper_gvec_srsra_d,
3293 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3294 .opt_opc = vecop_list,
3295 .load_dest = true,
3296 .vece = MO_64 },
3299 /* tszimm encoding produces immediates in the range [1..esize] */
3300 tcg_debug_assert(shift > 0);
3301 tcg_debug_assert(shift <= (8 << vece));
3304 * Shifts larger than the element size are architecturally valid.
3305 * Signed results in all sign bits. With rounding, this produces
3306 * (-1 + 1) >> 1 == 0, or (0 + 1) >> 1 == 0.
3307 * I.e. always zero. With accumulation, this leaves D unchanged.
3309 if (shift == (8 << vece)) {
3310 /* Nop, but we do need to clear the tail. */
3311 tcg_gen_gvec_mov(vece, rd_ofs, rd_ofs, opr_sz, max_sz);
3312 } else {
3313 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3317 static void gen_urshr8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3319 TCGv_i64 t = tcg_temp_new_i64();
3321 tcg_gen_shri_i64(t, a, sh - 1);
3322 tcg_gen_andi_i64(t, t, dup_const(MO_8, 1));
3323 tcg_gen_vec_shr8i_i64(d, a, sh);
3324 tcg_gen_vec_add8_i64(d, d, t);
3325 tcg_temp_free_i64(t);
3328 static void gen_urshr16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3330 TCGv_i64 t = tcg_temp_new_i64();
3332 tcg_gen_shri_i64(t, a, sh - 1);
3333 tcg_gen_andi_i64(t, t, dup_const(MO_16, 1));
3334 tcg_gen_vec_shr16i_i64(d, a, sh);
3335 tcg_gen_vec_add16_i64(d, d, t);
3336 tcg_temp_free_i64(t);
3339 static void gen_urshr32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
3341 TCGv_i32 t = tcg_temp_new_i32();
3343 tcg_gen_extract_i32(t, a, sh - 1, 1);
3344 tcg_gen_shri_i32(d, a, sh);
3345 tcg_gen_add_i32(d, d, t);
3346 tcg_temp_free_i32(t);
3349 static void gen_urshr64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3351 TCGv_i64 t = tcg_temp_new_i64();
3353 tcg_gen_extract_i64(t, a, sh - 1, 1);
3354 tcg_gen_shri_i64(d, a, sh);
3355 tcg_gen_add_i64(d, d, t);
3356 tcg_temp_free_i64(t);
3359 static void gen_urshr_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t shift)
3361 TCGv_vec t = tcg_temp_new_vec_matching(d);
3362 TCGv_vec ones = tcg_temp_new_vec_matching(d);
3364 tcg_gen_shri_vec(vece, t, a, shift - 1);
3365 tcg_gen_dupi_vec(vece, ones, 1);
3366 tcg_gen_and_vec(vece, t, t, ones);
3367 tcg_gen_shri_vec(vece, d, a, shift);
3368 tcg_gen_add_vec(vece, d, d, t);
3370 tcg_temp_free_vec(t);
3371 tcg_temp_free_vec(ones);
3374 void gen_gvec_urshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3375 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3377 static const TCGOpcode vecop_list[] = {
3378 INDEX_op_shri_vec, INDEX_op_add_vec, 0
3380 static const GVecGen2i ops[4] = {
3381 { .fni8 = gen_urshr8_i64,
3382 .fniv = gen_urshr_vec,
3383 .fno = gen_helper_gvec_urshr_b,
3384 .opt_opc = vecop_list,
3385 .vece = MO_8 },
3386 { .fni8 = gen_urshr16_i64,
3387 .fniv = gen_urshr_vec,
3388 .fno = gen_helper_gvec_urshr_h,
3389 .opt_opc = vecop_list,
3390 .vece = MO_16 },
3391 { .fni4 = gen_urshr32_i32,
3392 .fniv = gen_urshr_vec,
3393 .fno = gen_helper_gvec_urshr_s,
3394 .opt_opc = vecop_list,
3395 .vece = MO_32 },
3396 { .fni8 = gen_urshr64_i64,
3397 .fniv = gen_urshr_vec,
3398 .fno = gen_helper_gvec_urshr_d,
3399 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3400 .opt_opc = vecop_list,
3401 .vece = MO_64 },
3404 /* tszimm encoding produces immediates in the range [1..esize] */
3405 tcg_debug_assert(shift > 0);
3406 tcg_debug_assert(shift <= (8 << vece));
3408 if (shift == (8 << vece)) {
3410 * Shifts larger than the element size are architecturally valid.
3411 * Unsigned results in zero. With rounding, this produces a
3412 * copy of the most significant bit.
3414 tcg_gen_gvec_shri(vece, rd_ofs, rm_ofs, shift - 1, opr_sz, max_sz);
3415 } else {
3416 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3420 static void gen_ursra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3422 TCGv_i64 t = tcg_temp_new_i64();
3424 if (sh == 8) {
3425 tcg_gen_vec_shr8i_i64(t, a, 7);
3426 } else {
3427 gen_urshr8_i64(t, a, sh);
3429 tcg_gen_vec_add8_i64(d, d, t);
3430 tcg_temp_free_i64(t);
3433 static void gen_ursra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3435 TCGv_i64 t = tcg_temp_new_i64();
3437 if (sh == 16) {
3438 tcg_gen_vec_shr16i_i64(t, a, 15);
3439 } else {
3440 gen_urshr16_i64(t, a, sh);
3442 tcg_gen_vec_add16_i64(d, d, t);
3443 tcg_temp_free_i64(t);
3446 static void gen_ursra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
3448 TCGv_i32 t = tcg_temp_new_i32();
3450 if (sh == 32) {
3451 tcg_gen_shri_i32(t, a, 31);
3452 } else {
3453 gen_urshr32_i32(t, a, sh);
3455 tcg_gen_add_i32(d, d, t);
3456 tcg_temp_free_i32(t);
3459 static void gen_ursra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3461 TCGv_i64 t = tcg_temp_new_i64();
3463 if (sh == 64) {
3464 tcg_gen_shri_i64(t, a, 63);
3465 } else {
3466 gen_urshr64_i64(t, a, sh);
3468 tcg_gen_add_i64(d, d, t);
3469 tcg_temp_free_i64(t);
3472 static void gen_ursra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3474 TCGv_vec t = tcg_temp_new_vec_matching(d);
3476 if (sh == (8 << vece)) {
3477 tcg_gen_shri_vec(vece, t, a, sh - 1);
3478 } else {
3479 gen_urshr_vec(vece, t, a, sh);
3481 tcg_gen_add_vec(vece, d, d, t);
3482 tcg_temp_free_vec(t);
3485 void gen_gvec_ursra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3486 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3488 static const TCGOpcode vecop_list[] = {
3489 INDEX_op_shri_vec, INDEX_op_add_vec, 0
3491 static const GVecGen2i ops[4] = {
3492 { .fni8 = gen_ursra8_i64,
3493 .fniv = gen_ursra_vec,
3494 .fno = gen_helper_gvec_ursra_b,
3495 .opt_opc = vecop_list,
3496 .load_dest = true,
3497 .vece = MO_8 },
3498 { .fni8 = gen_ursra16_i64,
3499 .fniv = gen_ursra_vec,
3500 .fno = gen_helper_gvec_ursra_h,
3501 .opt_opc = vecop_list,
3502 .load_dest = true,
3503 .vece = MO_16 },
3504 { .fni4 = gen_ursra32_i32,
3505 .fniv = gen_ursra_vec,
3506 .fno = gen_helper_gvec_ursra_s,
3507 .opt_opc = vecop_list,
3508 .load_dest = true,
3509 .vece = MO_32 },
3510 { .fni8 = gen_ursra64_i64,
3511 .fniv = gen_ursra_vec,
3512 .fno = gen_helper_gvec_ursra_d,
3513 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3514 .opt_opc = vecop_list,
3515 .load_dest = true,
3516 .vece = MO_64 },
3519 /* tszimm encoding produces immediates in the range [1..esize] */
3520 tcg_debug_assert(shift > 0);
3521 tcg_debug_assert(shift <= (8 << vece));
3523 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3526 static void gen_shr8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3528 uint64_t mask = dup_const(MO_8, 0xff >> shift);
3529 TCGv_i64 t = tcg_temp_new_i64();
3531 tcg_gen_shri_i64(t, a, shift);
3532 tcg_gen_andi_i64(t, t, mask);
3533 tcg_gen_andi_i64(d, d, ~mask);
3534 tcg_gen_or_i64(d, d, t);
3535 tcg_temp_free_i64(t);
3538 static void gen_shr16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3540 uint64_t mask = dup_const(MO_16, 0xffff >> shift);
3541 TCGv_i64 t = tcg_temp_new_i64();
3543 tcg_gen_shri_i64(t, a, shift);
3544 tcg_gen_andi_i64(t, t, mask);
3545 tcg_gen_andi_i64(d, d, ~mask);
3546 tcg_gen_or_i64(d, d, t);
3547 tcg_temp_free_i64(t);
3550 static void gen_shr32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
3552 tcg_gen_shri_i32(a, a, shift);
3553 tcg_gen_deposit_i32(d, d, a, 0, 32 - shift);
3556 static void gen_shr64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3558 tcg_gen_shri_i64(a, a, shift);
3559 tcg_gen_deposit_i64(d, d, a, 0, 64 - shift);
3562 static void gen_shr_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3564 TCGv_vec t = tcg_temp_new_vec_matching(d);
3565 TCGv_vec m = tcg_temp_new_vec_matching(d);
3567 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK((8 << vece) - sh, sh));
3568 tcg_gen_shri_vec(vece, t, a, sh);
3569 tcg_gen_and_vec(vece, d, d, m);
3570 tcg_gen_or_vec(vece, d, d, t);
3572 tcg_temp_free_vec(t);
3573 tcg_temp_free_vec(m);
3576 void gen_gvec_sri(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3577 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3579 static const TCGOpcode vecop_list[] = { INDEX_op_shri_vec, 0 };
3580 const GVecGen2i ops[4] = {
3581 { .fni8 = gen_shr8_ins_i64,
3582 .fniv = gen_shr_ins_vec,
3583 .fno = gen_helper_gvec_sri_b,
3584 .load_dest = true,
3585 .opt_opc = vecop_list,
3586 .vece = MO_8 },
3587 { .fni8 = gen_shr16_ins_i64,
3588 .fniv = gen_shr_ins_vec,
3589 .fno = gen_helper_gvec_sri_h,
3590 .load_dest = true,
3591 .opt_opc = vecop_list,
3592 .vece = MO_16 },
3593 { .fni4 = gen_shr32_ins_i32,
3594 .fniv = gen_shr_ins_vec,
3595 .fno = gen_helper_gvec_sri_s,
3596 .load_dest = true,
3597 .opt_opc = vecop_list,
3598 .vece = MO_32 },
3599 { .fni8 = gen_shr64_ins_i64,
3600 .fniv = gen_shr_ins_vec,
3601 .fno = gen_helper_gvec_sri_d,
3602 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3603 .load_dest = true,
3604 .opt_opc = vecop_list,
3605 .vece = MO_64 },
3608 /* tszimm encoding produces immediates in the range [1..esize]. */
3609 tcg_debug_assert(shift > 0);
3610 tcg_debug_assert(shift <= (8 << vece));
3612 /* Shift of esize leaves destination unchanged. */
3613 if (shift < (8 << vece)) {
3614 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3615 } else {
3616 /* Nop, but we do need to clear the tail. */
3617 tcg_gen_gvec_mov(vece, rd_ofs, rd_ofs, opr_sz, max_sz);
3621 static void gen_shl8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3623 uint64_t mask = dup_const(MO_8, 0xff << shift);
3624 TCGv_i64 t = tcg_temp_new_i64();
3626 tcg_gen_shli_i64(t, a, shift);
3627 tcg_gen_andi_i64(t, t, mask);
3628 tcg_gen_andi_i64(d, d, ~mask);
3629 tcg_gen_or_i64(d, d, t);
3630 tcg_temp_free_i64(t);
3633 static void gen_shl16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3635 uint64_t mask = dup_const(MO_16, 0xffff << shift);
3636 TCGv_i64 t = tcg_temp_new_i64();
3638 tcg_gen_shli_i64(t, a, shift);
3639 tcg_gen_andi_i64(t, t, mask);
3640 tcg_gen_andi_i64(d, d, ~mask);
3641 tcg_gen_or_i64(d, d, t);
3642 tcg_temp_free_i64(t);
3645 static void gen_shl32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
3647 tcg_gen_deposit_i32(d, d, a, shift, 32 - shift);
3650 static void gen_shl64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3652 tcg_gen_deposit_i64(d, d, a, shift, 64 - shift);
3655 static void gen_shl_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3657 TCGv_vec t = tcg_temp_new_vec_matching(d);
3658 TCGv_vec m = tcg_temp_new_vec_matching(d);
3660 tcg_gen_shli_vec(vece, t, a, sh);
3661 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK(0, sh));
3662 tcg_gen_and_vec(vece, d, d, m);
3663 tcg_gen_or_vec(vece, d, d, t);
3665 tcg_temp_free_vec(t);
3666 tcg_temp_free_vec(m);
3669 void gen_gvec_sli(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3670 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3672 static const TCGOpcode vecop_list[] = { INDEX_op_shli_vec, 0 };
3673 const GVecGen2i ops[4] = {
3674 { .fni8 = gen_shl8_ins_i64,
3675 .fniv = gen_shl_ins_vec,
3676 .fno = gen_helper_gvec_sli_b,
3677 .load_dest = true,
3678 .opt_opc = vecop_list,
3679 .vece = MO_8 },
3680 { .fni8 = gen_shl16_ins_i64,
3681 .fniv = gen_shl_ins_vec,
3682 .fno = gen_helper_gvec_sli_h,
3683 .load_dest = true,
3684 .opt_opc = vecop_list,
3685 .vece = MO_16 },
3686 { .fni4 = gen_shl32_ins_i32,
3687 .fniv = gen_shl_ins_vec,
3688 .fno = gen_helper_gvec_sli_s,
3689 .load_dest = true,
3690 .opt_opc = vecop_list,
3691 .vece = MO_32 },
3692 { .fni8 = gen_shl64_ins_i64,
3693 .fniv = gen_shl_ins_vec,
3694 .fno = gen_helper_gvec_sli_d,
3695 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3696 .load_dest = true,
3697 .opt_opc = vecop_list,
3698 .vece = MO_64 },
3701 /* tszimm encoding produces immediates in the range [0..esize-1]. */
3702 tcg_debug_assert(shift >= 0);
3703 tcg_debug_assert(shift < (8 << vece));
3705 if (shift == 0) {
3706 tcg_gen_gvec_mov(vece, rd_ofs, rm_ofs, opr_sz, max_sz);
3707 } else {
3708 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3712 static void gen_mla8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3714 gen_helper_neon_mul_u8(a, a, b);
3715 gen_helper_neon_add_u8(d, d, a);
3718 static void gen_mls8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3720 gen_helper_neon_mul_u8(a, a, b);
3721 gen_helper_neon_sub_u8(d, d, a);
3724 static void gen_mla16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3726 gen_helper_neon_mul_u16(a, a, b);
3727 gen_helper_neon_add_u16(d, d, a);
3730 static void gen_mls16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3732 gen_helper_neon_mul_u16(a, a, b);
3733 gen_helper_neon_sub_u16(d, d, a);
3736 static void gen_mla32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3738 tcg_gen_mul_i32(a, a, b);
3739 tcg_gen_add_i32(d, d, a);
3742 static void gen_mls32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3744 tcg_gen_mul_i32(a, a, b);
3745 tcg_gen_sub_i32(d, d, a);
3748 static void gen_mla64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
3750 tcg_gen_mul_i64(a, a, b);
3751 tcg_gen_add_i64(d, d, a);
3754 static void gen_mls64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
3756 tcg_gen_mul_i64(a, a, b);
3757 tcg_gen_sub_i64(d, d, a);
3760 static void gen_mla_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
3762 tcg_gen_mul_vec(vece, a, a, b);
3763 tcg_gen_add_vec(vece, d, d, a);
3766 static void gen_mls_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
3768 tcg_gen_mul_vec(vece, a, a, b);
3769 tcg_gen_sub_vec(vece, d, d, a);
3772 /* Note that while NEON does not support VMLA and VMLS as 64-bit ops,
3773 * these tables are shared with AArch64 which does support them.
3775 void gen_gvec_mla(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_add_vec, 0
3781 static const GVecGen3 ops[4] = {
3782 { .fni4 = gen_mla8_i32,
3783 .fniv = gen_mla_vec,
3784 .load_dest = true,
3785 .opt_opc = vecop_list,
3786 .vece = MO_8 },
3787 { .fni4 = gen_mla16_i32,
3788 .fniv = gen_mla_vec,
3789 .load_dest = true,
3790 .opt_opc = vecop_list,
3791 .vece = MO_16 },
3792 { .fni4 = gen_mla32_i32,
3793 .fniv = gen_mla_vec,
3794 .load_dest = true,
3795 .opt_opc = vecop_list,
3796 .vece = MO_32 },
3797 { .fni8 = gen_mla64_i64,
3798 .fniv = gen_mla_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 void gen_gvec_mls(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
3808 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
3810 static const TCGOpcode vecop_list[] = {
3811 INDEX_op_mul_vec, INDEX_op_sub_vec, 0
3813 static const GVecGen3 ops[4] = {
3814 { .fni4 = gen_mls8_i32,
3815 .fniv = gen_mls_vec,
3816 .load_dest = true,
3817 .opt_opc = vecop_list,
3818 .vece = MO_8 },
3819 { .fni4 = gen_mls16_i32,
3820 .fniv = gen_mls_vec,
3821 .load_dest = true,
3822 .opt_opc = vecop_list,
3823 .vece = MO_16 },
3824 { .fni4 = gen_mls32_i32,
3825 .fniv = gen_mls_vec,
3826 .load_dest = true,
3827 .opt_opc = vecop_list,
3828 .vece = MO_32 },
3829 { .fni8 = gen_mls64_i64,
3830 .fniv = gen_mls_vec,
3831 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3832 .load_dest = true,
3833 .opt_opc = vecop_list,
3834 .vece = MO_64 },
3836 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
3839 /* CMTST : test is "if (X & Y != 0)". */
3840 static void gen_cmtst_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3842 tcg_gen_and_i32(d, a, b);
3843 tcg_gen_setcondi_i32(TCG_COND_NE, d, d, 0);
3844 tcg_gen_neg_i32(d, d);
3847 void gen_cmtst_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
3849 tcg_gen_and_i64(d, a, b);
3850 tcg_gen_setcondi_i64(TCG_COND_NE, d, d, 0);
3851 tcg_gen_neg_i64(d, d);
3854 static void gen_cmtst_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
3856 tcg_gen_and_vec(vece, d, a, b);
3857 tcg_gen_dupi_vec(vece, a, 0);
3858 tcg_gen_cmp_vec(TCG_COND_NE, vece, d, d, a);
3861 void gen_gvec_cmtst(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
3862 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
3864 static const TCGOpcode vecop_list[] = { INDEX_op_cmp_vec, 0 };
3865 static const GVecGen3 ops[4] = {
3866 { .fni4 = gen_helper_neon_tst_u8,
3867 .fniv = gen_cmtst_vec,
3868 .opt_opc = vecop_list,
3869 .vece = MO_8 },
3870 { .fni4 = gen_helper_neon_tst_u16,
3871 .fniv = gen_cmtst_vec,
3872 .opt_opc = vecop_list,
3873 .vece = MO_16 },
3874 { .fni4 = gen_cmtst_i32,
3875 .fniv = gen_cmtst_vec,
3876 .opt_opc = vecop_list,
3877 .vece = MO_32 },
3878 { .fni8 = gen_cmtst_i64,
3879 .fniv = gen_cmtst_vec,
3880 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3881 .opt_opc = vecop_list,
3882 .vece = MO_64 },
3884 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
3887 void gen_ushl_i32(TCGv_i32 dst, TCGv_i32 src, TCGv_i32 shift)
3889 TCGv_i32 lval = tcg_temp_new_i32();
3890 TCGv_i32 rval = tcg_temp_new_i32();
3891 TCGv_i32 lsh = tcg_temp_new_i32();
3892 TCGv_i32 rsh = tcg_temp_new_i32();
3893 TCGv_i32 zero = tcg_const_i32(0);
3894 TCGv_i32 max = tcg_const_i32(32);
3897 * Rely on the TCG guarantee that out of range shifts produce
3898 * unspecified results, not undefined behaviour (i.e. no trap).
3899 * Discard out-of-range results after the fact.
3901 tcg_gen_ext8s_i32(lsh, shift);
3902 tcg_gen_neg_i32(rsh, lsh);
3903 tcg_gen_shl_i32(lval, src, lsh);
3904 tcg_gen_shr_i32(rval, src, rsh);
3905 tcg_gen_movcond_i32(TCG_COND_LTU, dst, lsh, max, lval, zero);
3906 tcg_gen_movcond_i32(TCG_COND_LTU, dst, rsh, max, rval, dst);
3908 tcg_temp_free_i32(lval);
3909 tcg_temp_free_i32(rval);
3910 tcg_temp_free_i32(lsh);
3911 tcg_temp_free_i32(rsh);
3912 tcg_temp_free_i32(zero);
3913 tcg_temp_free_i32(max);
3916 void gen_ushl_i64(TCGv_i64 dst, TCGv_i64 src, TCGv_i64 shift)
3918 TCGv_i64 lval = tcg_temp_new_i64();
3919 TCGv_i64 rval = tcg_temp_new_i64();
3920 TCGv_i64 lsh = tcg_temp_new_i64();
3921 TCGv_i64 rsh = tcg_temp_new_i64();
3922 TCGv_i64 zero = tcg_const_i64(0);
3923 TCGv_i64 max = tcg_const_i64(64);
3926 * Rely on the TCG guarantee that out of range shifts produce
3927 * unspecified results, not undefined behaviour (i.e. no trap).
3928 * Discard out-of-range results after the fact.
3930 tcg_gen_ext8s_i64(lsh, shift);
3931 tcg_gen_neg_i64(rsh, lsh);
3932 tcg_gen_shl_i64(lval, src, lsh);
3933 tcg_gen_shr_i64(rval, src, rsh);
3934 tcg_gen_movcond_i64(TCG_COND_LTU, dst, lsh, max, lval, zero);
3935 tcg_gen_movcond_i64(TCG_COND_LTU, dst, rsh, max, rval, dst);
3937 tcg_temp_free_i64(lval);
3938 tcg_temp_free_i64(rval);
3939 tcg_temp_free_i64(lsh);
3940 tcg_temp_free_i64(rsh);
3941 tcg_temp_free_i64(zero);
3942 tcg_temp_free_i64(max);
3945 static void gen_ushl_vec(unsigned vece, TCGv_vec dst,
3946 TCGv_vec src, TCGv_vec shift)
3948 TCGv_vec lval = tcg_temp_new_vec_matching(dst);
3949 TCGv_vec rval = tcg_temp_new_vec_matching(dst);
3950 TCGv_vec lsh = tcg_temp_new_vec_matching(dst);
3951 TCGv_vec rsh = tcg_temp_new_vec_matching(dst);
3952 TCGv_vec msk, max;
3954 tcg_gen_neg_vec(vece, rsh, shift);
3955 if (vece == MO_8) {
3956 tcg_gen_mov_vec(lsh, shift);
3957 } else {
3958 msk = tcg_temp_new_vec_matching(dst);
3959 tcg_gen_dupi_vec(vece, msk, 0xff);
3960 tcg_gen_and_vec(vece, lsh, shift, msk);
3961 tcg_gen_and_vec(vece, rsh, rsh, msk);
3962 tcg_temp_free_vec(msk);
3966 * Rely on the TCG guarantee that out of range shifts produce
3967 * unspecified results, not undefined behaviour (i.e. no trap).
3968 * Discard out-of-range results after the fact.
3970 tcg_gen_shlv_vec(vece, lval, src, lsh);
3971 tcg_gen_shrv_vec(vece, rval, src, rsh);
3973 max = tcg_temp_new_vec_matching(dst);
3974 tcg_gen_dupi_vec(vece, max, 8 << vece);
3977 * The choice of LT (signed) and GEU (unsigned) are biased toward
3978 * the instructions of the x86_64 host. For MO_8, the whole byte
3979 * is significant so we must use an unsigned compare; otherwise we
3980 * have already masked to a byte and so a signed compare works.
3981 * Other tcg hosts have a full set of comparisons and do not care.
3983 if (vece == MO_8) {
3984 tcg_gen_cmp_vec(TCG_COND_GEU, vece, lsh, lsh, max);
3985 tcg_gen_cmp_vec(TCG_COND_GEU, vece, rsh, rsh, max);
3986 tcg_gen_andc_vec(vece, lval, lval, lsh);
3987 tcg_gen_andc_vec(vece, rval, rval, rsh);
3988 } else {
3989 tcg_gen_cmp_vec(TCG_COND_LT, vece, lsh, lsh, max);
3990 tcg_gen_cmp_vec(TCG_COND_LT, vece, rsh, rsh, max);
3991 tcg_gen_and_vec(vece, lval, lval, lsh);
3992 tcg_gen_and_vec(vece, rval, rval, rsh);
3994 tcg_gen_or_vec(vece, dst, lval, rval);
3996 tcg_temp_free_vec(max);
3997 tcg_temp_free_vec(lval);
3998 tcg_temp_free_vec(rval);
3999 tcg_temp_free_vec(lsh);
4000 tcg_temp_free_vec(rsh);
4003 void gen_gvec_ushl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4004 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4006 static const TCGOpcode vecop_list[] = {
4007 INDEX_op_neg_vec, INDEX_op_shlv_vec,
4008 INDEX_op_shrv_vec, INDEX_op_cmp_vec, 0
4010 static const GVecGen3 ops[4] = {
4011 { .fniv = gen_ushl_vec,
4012 .fno = gen_helper_gvec_ushl_b,
4013 .opt_opc = vecop_list,
4014 .vece = MO_8 },
4015 { .fniv = gen_ushl_vec,
4016 .fno = gen_helper_gvec_ushl_h,
4017 .opt_opc = vecop_list,
4018 .vece = MO_16 },
4019 { .fni4 = gen_ushl_i32,
4020 .fniv = gen_ushl_vec,
4021 .opt_opc = vecop_list,
4022 .vece = MO_32 },
4023 { .fni8 = gen_ushl_i64,
4024 .fniv = gen_ushl_vec,
4025 .opt_opc = vecop_list,
4026 .vece = MO_64 },
4028 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4031 void gen_sshl_i32(TCGv_i32 dst, TCGv_i32 src, TCGv_i32 shift)
4033 TCGv_i32 lval = tcg_temp_new_i32();
4034 TCGv_i32 rval = tcg_temp_new_i32();
4035 TCGv_i32 lsh = tcg_temp_new_i32();
4036 TCGv_i32 rsh = tcg_temp_new_i32();
4037 TCGv_i32 zero = tcg_const_i32(0);
4038 TCGv_i32 max = tcg_const_i32(31);
4041 * Rely on the TCG guarantee that out of range shifts produce
4042 * unspecified results, not undefined behaviour (i.e. no trap).
4043 * Discard out-of-range results after the fact.
4045 tcg_gen_ext8s_i32(lsh, shift);
4046 tcg_gen_neg_i32(rsh, lsh);
4047 tcg_gen_shl_i32(lval, src, lsh);
4048 tcg_gen_umin_i32(rsh, rsh, max);
4049 tcg_gen_sar_i32(rval, src, rsh);
4050 tcg_gen_movcond_i32(TCG_COND_LEU, lval, lsh, max, lval, zero);
4051 tcg_gen_movcond_i32(TCG_COND_LT, dst, lsh, zero, rval, lval);
4053 tcg_temp_free_i32(lval);
4054 tcg_temp_free_i32(rval);
4055 tcg_temp_free_i32(lsh);
4056 tcg_temp_free_i32(rsh);
4057 tcg_temp_free_i32(zero);
4058 tcg_temp_free_i32(max);
4061 void gen_sshl_i64(TCGv_i64 dst, TCGv_i64 src, TCGv_i64 shift)
4063 TCGv_i64 lval = tcg_temp_new_i64();
4064 TCGv_i64 rval = tcg_temp_new_i64();
4065 TCGv_i64 lsh = tcg_temp_new_i64();
4066 TCGv_i64 rsh = tcg_temp_new_i64();
4067 TCGv_i64 zero = tcg_const_i64(0);
4068 TCGv_i64 max = tcg_const_i64(63);
4071 * Rely on the TCG guarantee that out of range shifts produce
4072 * unspecified results, not undefined behaviour (i.e. no trap).
4073 * Discard out-of-range results after the fact.
4075 tcg_gen_ext8s_i64(lsh, shift);
4076 tcg_gen_neg_i64(rsh, lsh);
4077 tcg_gen_shl_i64(lval, src, lsh);
4078 tcg_gen_umin_i64(rsh, rsh, max);
4079 tcg_gen_sar_i64(rval, src, rsh);
4080 tcg_gen_movcond_i64(TCG_COND_LEU, lval, lsh, max, lval, zero);
4081 tcg_gen_movcond_i64(TCG_COND_LT, dst, lsh, zero, rval, lval);
4083 tcg_temp_free_i64(lval);
4084 tcg_temp_free_i64(rval);
4085 tcg_temp_free_i64(lsh);
4086 tcg_temp_free_i64(rsh);
4087 tcg_temp_free_i64(zero);
4088 tcg_temp_free_i64(max);
4091 static void gen_sshl_vec(unsigned vece, TCGv_vec dst,
4092 TCGv_vec src, TCGv_vec shift)
4094 TCGv_vec lval = tcg_temp_new_vec_matching(dst);
4095 TCGv_vec rval = tcg_temp_new_vec_matching(dst);
4096 TCGv_vec lsh = tcg_temp_new_vec_matching(dst);
4097 TCGv_vec rsh = tcg_temp_new_vec_matching(dst);
4098 TCGv_vec tmp = tcg_temp_new_vec_matching(dst);
4101 * Rely on the TCG guarantee that out of range shifts produce
4102 * unspecified results, not undefined behaviour (i.e. no trap).
4103 * Discard out-of-range results after the fact.
4105 tcg_gen_neg_vec(vece, rsh, shift);
4106 if (vece == MO_8) {
4107 tcg_gen_mov_vec(lsh, shift);
4108 } else {
4109 tcg_gen_dupi_vec(vece, tmp, 0xff);
4110 tcg_gen_and_vec(vece, lsh, shift, tmp);
4111 tcg_gen_and_vec(vece, rsh, rsh, tmp);
4114 /* Bound rsh so out of bound right shift gets -1. */
4115 tcg_gen_dupi_vec(vece, tmp, (8 << vece) - 1);
4116 tcg_gen_umin_vec(vece, rsh, rsh, tmp);
4117 tcg_gen_cmp_vec(TCG_COND_GT, vece, tmp, lsh, tmp);
4119 tcg_gen_shlv_vec(vece, lval, src, lsh);
4120 tcg_gen_sarv_vec(vece, rval, src, rsh);
4122 /* Select in-bound left shift. */
4123 tcg_gen_andc_vec(vece, lval, lval, tmp);
4125 /* Select between left and right shift. */
4126 if (vece == MO_8) {
4127 tcg_gen_dupi_vec(vece, tmp, 0);
4128 tcg_gen_cmpsel_vec(TCG_COND_LT, vece, dst, lsh, tmp, rval, lval);
4129 } else {
4130 tcg_gen_dupi_vec(vece, tmp, 0x80);
4131 tcg_gen_cmpsel_vec(TCG_COND_LT, vece, dst, lsh, tmp, lval, rval);
4134 tcg_temp_free_vec(lval);
4135 tcg_temp_free_vec(rval);
4136 tcg_temp_free_vec(lsh);
4137 tcg_temp_free_vec(rsh);
4138 tcg_temp_free_vec(tmp);
4141 void gen_gvec_sshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4142 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4144 static const TCGOpcode vecop_list[] = {
4145 INDEX_op_neg_vec, INDEX_op_umin_vec, INDEX_op_shlv_vec,
4146 INDEX_op_sarv_vec, INDEX_op_cmp_vec, INDEX_op_cmpsel_vec, 0
4148 static const GVecGen3 ops[4] = {
4149 { .fniv = gen_sshl_vec,
4150 .fno = gen_helper_gvec_sshl_b,
4151 .opt_opc = vecop_list,
4152 .vece = MO_8 },
4153 { .fniv = gen_sshl_vec,
4154 .fno = gen_helper_gvec_sshl_h,
4155 .opt_opc = vecop_list,
4156 .vece = MO_16 },
4157 { .fni4 = gen_sshl_i32,
4158 .fniv = gen_sshl_vec,
4159 .opt_opc = vecop_list,
4160 .vece = MO_32 },
4161 { .fni8 = gen_sshl_i64,
4162 .fniv = gen_sshl_vec,
4163 .opt_opc = vecop_list,
4164 .vece = MO_64 },
4166 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4169 static void gen_uqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4170 TCGv_vec a, TCGv_vec b)
4172 TCGv_vec x = tcg_temp_new_vec_matching(t);
4173 tcg_gen_add_vec(vece, x, a, b);
4174 tcg_gen_usadd_vec(vece, t, a, b);
4175 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4176 tcg_gen_or_vec(vece, sat, sat, x);
4177 tcg_temp_free_vec(x);
4180 void gen_gvec_uqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4181 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4183 static const TCGOpcode vecop_list[] = {
4184 INDEX_op_usadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
4186 static const GVecGen4 ops[4] = {
4187 { .fniv = gen_uqadd_vec,
4188 .fno = gen_helper_gvec_uqadd_b,
4189 .write_aofs = true,
4190 .opt_opc = vecop_list,
4191 .vece = MO_8 },
4192 { .fniv = gen_uqadd_vec,
4193 .fno = gen_helper_gvec_uqadd_h,
4194 .write_aofs = true,
4195 .opt_opc = vecop_list,
4196 .vece = MO_16 },
4197 { .fniv = gen_uqadd_vec,
4198 .fno = gen_helper_gvec_uqadd_s,
4199 .write_aofs = true,
4200 .opt_opc = vecop_list,
4201 .vece = MO_32 },
4202 { .fniv = gen_uqadd_vec,
4203 .fno = gen_helper_gvec_uqadd_d,
4204 .write_aofs = true,
4205 .opt_opc = vecop_list,
4206 .vece = MO_64 },
4208 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
4209 rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4212 static void gen_sqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4213 TCGv_vec a, TCGv_vec b)
4215 TCGv_vec x = tcg_temp_new_vec_matching(t);
4216 tcg_gen_add_vec(vece, x, a, b);
4217 tcg_gen_ssadd_vec(vece, t, a, b);
4218 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4219 tcg_gen_or_vec(vece, sat, sat, x);
4220 tcg_temp_free_vec(x);
4223 void gen_gvec_sqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4224 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4226 static const TCGOpcode vecop_list[] = {
4227 INDEX_op_ssadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
4229 static const GVecGen4 ops[4] = {
4230 { .fniv = gen_sqadd_vec,
4231 .fno = gen_helper_gvec_sqadd_b,
4232 .opt_opc = vecop_list,
4233 .write_aofs = true,
4234 .vece = MO_8 },
4235 { .fniv = gen_sqadd_vec,
4236 .fno = gen_helper_gvec_sqadd_h,
4237 .opt_opc = vecop_list,
4238 .write_aofs = true,
4239 .vece = MO_16 },
4240 { .fniv = gen_sqadd_vec,
4241 .fno = gen_helper_gvec_sqadd_s,
4242 .opt_opc = vecop_list,
4243 .write_aofs = true,
4244 .vece = MO_32 },
4245 { .fniv = gen_sqadd_vec,
4246 .fno = gen_helper_gvec_sqadd_d,
4247 .opt_opc = vecop_list,
4248 .write_aofs = true,
4249 .vece = MO_64 },
4251 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
4252 rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4255 static void gen_uqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4256 TCGv_vec a, TCGv_vec b)
4258 TCGv_vec x = tcg_temp_new_vec_matching(t);
4259 tcg_gen_sub_vec(vece, x, a, b);
4260 tcg_gen_ussub_vec(vece, t, a, b);
4261 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4262 tcg_gen_or_vec(vece, sat, sat, x);
4263 tcg_temp_free_vec(x);
4266 void gen_gvec_uqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4267 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4269 static const TCGOpcode vecop_list[] = {
4270 INDEX_op_ussub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
4272 static const GVecGen4 ops[4] = {
4273 { .fniv = gen_uqsub_vec,
4274 .fno = gen_helper_gvec_uqsub_b,
4275 .opt_opc = vecop_list,
4276 .write_aofs = true,
4277 .vece = MO_8 },
4278 { .fniv = gen_uqsub_vec,
4279 .fno = gen_helper_gvec_uqsub_h,
4280 .opt_opc = vecop_list,
4281 .write_aofs = true,
4282 .vece = MO_16 },
4283 { .fniv = gen_uqsub_vec,
4284 .fno = gen_helper_gvec_uqsub_s,
4285 .opt_opc = vecop_list,
4286 .write_aofs = true,
4287 .vece = MO_32 },
4288 { .fniv = gen_uqsub_vec,
4289 .fno = gen_helper_gvec_uqsub_d,
4290 .opt_opc = vecop_list,
4291 .write_aofs = true,
4292 .vece = MO_64 },
4294 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
4295 rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4298 static void gen_sqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4299 TCGv_vec a, TCGv_vec b)
4301 TCGv_vec x = tcg_temp_new_vec_matching(t);
4302 tcg_gen_sub_vec(vece, x, a, b);
4303 tcg_gen_sssub_vec(vece, t, a, b);
4304 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4305 tcg_gen_or_vec(vece, sat, sat, x);
4306 tcg_temp_free_vec(x);
4309 void gen_gvec_sqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4310 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4312 static const TCGOpcode vecop_list[] = {
4313 INDEX_op_sssub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
4315 static const GVecGen4 ops[4] = {
4316 { .fniv = gen_sqsub_vec,
4317 .fno = gen_helper_gvec_sqsub_b,
4318 .opt_opc = vecop_list,
4319 .write_aofs = true,
4320 .vece = MO_8 },
4321 { .fniv = gen_sqsub_vec,
4322 .fno = gen_helper_gvec_sqsub_h,
4323 .opt_opc = vecop_list,
4324 .write_aofs = true,
4325 .vece = MO_16 },
4326 { .fniv = gen_sqsub_vec,
4327 .fno = gen_helper_gvec_sqsub_s,
4328 .opt_opc = vecop_list,
4329 .write_aofs = true,
4330 .vece = MO_32 },
4331 { .fniv = gen_sqsub_vec,
4332 .fno = gen_helper_gvec_sqsub_d,
4333 .opt_opc = vecop_list,
4334 .write_aofs = true,
4335 .vece = MO_64 },
4337 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
4338 rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4341 static void gen_sabd_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4343 TCGv_i32 t = tcg_temp_new_i32();
4345 tcg_gen_sub_i32(t, a, b);
4346 tcg_gen_sub_i32(d, b, a);
4347 tcg_gen_movcond_i32(TCG_COND_LT, d, a, b, d, t);
4348 tcg_temp_free_i32(t);
4351 static void gen_sabd_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4353 TCGv_i64 t = tcg_temp_new_i64();
4355 tcg_gen_sub_i64(t, a, b);
4356 tcg_gen_sub_i64(d, b, a);
4357 tcg_gen_movcond_i64(TCG_COND_LT, d, a, b, d, t);
4358 tcg_temp_free_i64(t);
4361 static void gen_sabd_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4363 TCGv_vec t = tcg_temp_new_vec_matching(d);
4365 tcg_gen_smin_vec(vece, t, a, b);
4366 tcg_gen_smax_vec(vece, d, a, b);
4367 tcg_gen_sub_vec(vece, d, d, t);
4368 tcg_temp_free_vec(t);
4371 void gen_gvec_sabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4372 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4374 static const TCGOpcode vecop_list[] = {
4375 INDEX_op_sub_vec, INDEX_op_smin_vec, INDEX_op_smax_vec, 0
4377 static const GVecGen3 ops[4] = {
4378 { .fniv = gen_sabd_vec,
4379 .fno = gen_helper_gvec_sabd_b,
4380 .opt_opc = vecop_list,
4381 .vece = MO_8 },
4382 { .fniv = gen_sabd_vec,
4383 .fno = gen_helper_gvec_sabd_h,
4384 .opt_opc = vecop_list,
4385 .vece = MO_16 },
4386 { .fni4 = gen_sabd_i32,
4387 .fniv = gen_sabd_vec,
4388 .fno = gen_helper_gvec_sabd_s,
4389 .opt_opc = vecop_list,
4390 .vece = MO_32 },
4391 { .fni8 = gen_sabd_i64,
4392 .fniv = gen_sabd_vec,
4393 .fno = gen_helper_gvec_sabd_d,
4394 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4395 .opt_opc = vecop_list,
4396 .vece = MO_64 },
4398 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4401 static void gen_uabd_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4403 TCGv_i32 t = tcg_temp_new_i32();
4405 tcg_gen_sub_i32(t, a, b);
4406 tcg_gen_sub_i32(d, b, a);
4407 tcg_gen_movcond_i32(TCG_COND_LTU, d, a, b, d, t);
4408 tcg_temp_free_i32(t);
4411 static void gen_uabd_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4413 TCGv_i64 t = tcg_temp_new_i64();
4415 tcg_gen_sub_i64(t, a, b);
4416 tcg_gen_sub_i64(d, b, a);
4417 tcg_gen_movcond_i64(TCG_COND_LTU, d, a, b, d, t);
4418 tcg_temp_free_i64(t);
4421 static void gen_uabd_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4423 TCGv_vec t = tcg_temp_new_vec_matching(d);
4425 tcg_gen_umin_vec(vece, t, a, b);
4426 tcg_gen_umax_vec(vece, d, a, b);
4427 tcg_gen_sub_vec(vece, d, d, t);
4428 tcg_temp_free_vec(t);
4431 void gen_gvec_uabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4432 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4434 static const TCGOpcode vecop_list[] = {
4435 INDEX_op_sub_vec, INDEX_op_umin_vec, INDEX_op_umax_vec, 0
4437 static const GVecGen3 ops[4] = {
4438 { .fniv = gen_uabd_vec,
4439 .fno = gen_helper_gvec_uabd_b,
4440 .opt_opc = vecop_list,
4441 .vece = MO_8 },
4442 { .fniv = gen_uabd_vec,
4443 .fno = gen_helper_gvec_uabd_h,
4444 .opt_opc = vecop_list,
4445 .vece = MO_16 },
4446 { .fni4 = gen_uabd_i32,
4447 .fniv = gen_uabd_vec,
4448 .fno = gen_helper_gvec_uabd_s,
4449 .opt_opc = vecop_list,
4450 .vece = MO_32 },
4451 { .fni8 = gen_uabd_i64,
4452 .fniv = gen_uabd_vec,
4453 .fno = gen_helper_gvec_uabd_d,
4454 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4455 .opt_opc = vecop_list,
4456 .vece = MO_64 },
4458 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4461 static void gen_saba_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4463 TCGv_i32 t = tcg_temp_new_i32();
4464 gen_sabd_i32(t, a, b);
4465 tcg_gen_add_i32(d, d, t);
4466 tcg_temp_free_i32(t);
4469 static void gen_saba_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4471 TCGv_i64 t = tcg_temp_new_i64();
4472 gen_sabd_i64(t, a, b);
4473 tcg_gen_add_i64(d, d, t);
4474 tcg_temp_free_i64(t);
4477 static void gen_saba_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4479 TCGv_vec t = tcg_temp_new_vec_matching(d);
4480 gen_sabd_vec(vece, t, a, b);
4481 tcg_gen_add_vec(vece, d, d, t);
4482 tcg_temp_free_vec(t);
4485 void gen_gvec_saba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4486 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4488 static const TCGOpcode vecop_list[] = {
4489 INDEX_op_sub_vec, INDEX_op_add_vec,
4490 INDEX_op_smin_vec, INDEX_op_smax_vec, 0
4492 static const GVecGen3 ops[4] = {
4493 { .fniv = gen_saba_vec,
4494 .fno = gen_helper_gvec_saba_b,
4495 .opt_opc = vecop_list,
4496 .load_dest = true,
4497 .vece = MO_8 },
4498 { .fniv = gen_saba_vec,
4499 .fno = gen_helper_gvec_saba_h,
4500 .opt_opc = vecop_list,
4501 .load_dest = true,
4502 .vece = MO_16 },
4503 { .fni4 = gen_saba_i32,
4504 .fniv = gen_saba_vec,
4505 .fno = gen_helper_gvec_saba_s,
4506 .opt_opc = vecop_list,
4507 .load_dest = true,
4508 .vece = MO_32 },
4509 { .fni8 = gen_saba_i64,
4510 .fniv = gen_saba_vec,
4511 .fno = gen_helper_gvec_saba_d,
4512 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4513 .opt_opc = vecop_list,
4514 .load_dest = true,
4515 .vece = MO_64 },
4517 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4520 static void gen_uaba_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4522 TCGv_i32 t = tcg_temp_new_i32();
4523 gen_uabd_i32(t, a, b);
4524 tcg_gen_add_i32(d, d, t);
4525 tcg_temp_free_i32(t);
4528 static void gen_uaba_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4530 TCGv_i64 t = tcg_temp_new_i64();
4531 gen_uabd_i64(t, a, b);
4532 tcg_gen_add_i64(d, d, t);
4533 tcg_temp_free_i64(t);
4536 static void gen_uaba_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4538 TCGv_vec t = tcg_temp_new_vec_matching(d);
4539 gen_uabd_vec(vece, t, a, b);
4540 tcg_gen_add_vec(vece, d, d, t);
4541 tcg_temp_free_vec(t);
4544 void gen_gvec_uaba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4545 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4547 static const TCGOpcode vecop_list[] = {
4548 INDEX_op_sub_vec, INDEX_op_add_vec,
4549 INDEX_op_umin_vec, INDEX_op_umax_vec, 0
4551 static const GVecGen3 ops[4] = {
4552 { .fniv = gen_uaba_vec,
4553 .fno = gen_helper_gvec_uaba_b,
4554 .opt_opc = vecop_list,
4555 .load_dest = true,
4556 .vece = MO_8 },
4557 { .fniv = gen_uaba_vec,
4558 .fno = gen_helper_gvec_uaba_h,
4559 .opt_opc = vecop_list,
4560 .load_dest = true,
4561 .vece = MO_16 },
4562 { .fni4 = gen_uaba_i32,
4563 .fniv = gen_uaba_vec,
4564 .fno = gen_helper_gvec_uaba_s,
4565 .opt_opc = vecop_list,
4566 .load_dest = true,
4567 .vece = MO_32 },
4568 { .fni8 = gen_uaba_i64,
4569 .fniv = gen_uaba_vec,
4570 .fno = gen_helper_gvec_uaba_d,
4571 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4572 .opt_opc = vecop_list,
4573 .load_dest = true,
4574 .vece = MO_64 },
4576 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4579 static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
4580 int opc1, int crn, int crm, int opc2,
4581 bool isread, int rt, int rt2)
4583 const ARMCPRegInfo *ri;
4585 ri = get_arm_cp_reginfo(s->cp_regs,
4586 ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2));
4587 if (ri) {
4588 bool need_exit_tb;
4590 /* Check access permissions */
4591 if (!cp_access_ok(s->current_el, ri, isread)) {
4592 unallocated_encoding(s);
4593 return;
4596 if (s->hstr_active || ri->accessfn ||
4597 (arm_dc_feature(s, ARM_FEATURE_XSCALE) && cpnum < 14)) {
4598 /* Emit code to perform further access permissions checks at
4599 * runtime; this may result in an exception.
4600 * Note that on XScale all cp0..c13 registers do an access check
4601 * call in order to handle c15_cpar.
4603 TCGv_ptr tmpptr;
4604 TCGv_i32 tcg_syn, tcg_isread;
4605 uint32_t syndrome;
4607 /* Note that since we are an implementation which takes an
4608 * exception on a trapped conditional instruction only if the
4609 * instruction passes its condition code check, we can take
4610 * advantage of the clause in the ARM ARM that allows us to set
4611 * the COND field in the instruction to 0xE in all cases.
4612 * We could fish the actual condition out of the insn (ARM)
4613 * or the condexec bits (Thumb) but it isn't necessary.
4615 switch (cpnum) {
4616 case 14:
4617 if (is64) {
4618 syndrome = syn_cp14_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
4619 isread, false);
4620 } else {
4621 syndrome = syn_cp14_rt_trap(1, 0xe, opc1, opc2, crn, crm,
4622 rt, isread, false);
4624 break;
4625 case 15:
4626 if (is64) {
4627 syndrome = syn_cp15_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
4628 isread, false);
4629 } else {
4630 syndrome = syn_cp15_rt_trap(1, 0xe, opc1, opc2, crn, crm,
4631 rt, isread, false);
4633 break;
4634 default:
4635 /* ARMv8 defines that only coprocessors 14 and 15 exist,
4636 * so this can only happen if this is an ARMv7 or earlier CPU,
4637 * in which case the syndrome information won't actually be
4638 * guest visible.
4640 assert(!arm_dc_feature(s, ARM_FEATURE_V8));
4641 syndrome = syn_uncategorized();
4642 break;
4645 gen_set_condexec(s);
4646 gen_set_pc_im(s, s->pc_curr);
4647 tmpptr = tcg_const_ptr(ri);
4648 tcg_syn = tcg_const_i32(syndrome);
4649 tcg_isread = tcg_const_i32(isread);
4650 gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn,
4651 tcg_isread);
4652 tcg_temp_free_ptr(tmpptr);
4653 tcg_temp_free_i32(tcg_syn);
4654 tcg_temp_free_i32(tcg_isread);
4655 } else if (ri->type & ARM_CP_RAISES_EXC) {
4657 * The readfn or writefn might raise an exception;
4658 * synchronize the CPU state in case it does.
4660 gen_set_condexec(s);
4661 gen_set_pc_im(s, s->pc_curr);
4664 /* Handle special cases first */
4665 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
4666 case ARM_CP_NOP:
4667 return;
4668 case ARM_CP_WFI:
4669 if (isread) {
4670 unallocated_encoding(s);
4671 return;
4673 gen_set_pc_im(s, s->base.pc_next);
4674 s->base.is_jmp = DISAS_WFI;
4675 return;
4676 default:
4677 break;
4680 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
4681 gen_io_start();
4684 if (isread) {
4685 /* Read */
4686 if (is64) {
4687 TCGv_i64 tmp64;
4688 TCGv_i32 tmp;
4689 if (ri->type & ARM_CP_CONST) {
4690 tmp64 = tcg_const_i64(ri->resetvalue);
4691 } else if (ri->readfn) {
4692 TCGv_ptr tmpptr;
4693 tmp64 = tcg_temp_new_i64();
4694 tmpptr = tcg_const_ptr(ri);
4695 gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr);
4696 tcg_temp_free_ptr(tmpptr);
4697 } else {
4698 tmp64 = tcg_temp_new_i64();
4699 tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
4701 tmp = tcg_temp_new_i32();
4702 tcg_gen_extrl_i64_i32(tmp, tmp64);
4703 store_reg(s, rt, tmp);
4704 tmp = tcg_temp_new_i32();
4705 tcg_gen_extrh_i64_i32(tmp, tmp64);
4706 tcg_temp_free_i64(tmp64);
4707 store_reg(s, rt2, tmp);
4708 } else {
4709 TCGv_i32 tmp;
4710 if (ri->type & ARM_CP_CONST) {
4711 tmp = tcg_const_i32(ri->resetvalue);
4712 } else if (ri->readfn) {
4713 TCGv_ptr tmpptr;
4714 tmp = tcg_temp_new_i32();
4715 tmpptr = tcg_const_ptr(ri);
4716 gen_helper_get_cp_reg(tmp, cpu_env, tmpptr);
4717 tcg_temp_free_ptr(tmpptr);
4718 } else {
4719 tmp = load_cpu_offset(ri->fieldoffset);
4721 if (rt == 15) {
4722 /* Destination register of r15 for 32 bit loads sets
4723 * the condition codes from the high 4 bits of the value
4725 gen_set_nzcv(tmp);
4726 tcg_temp_free_i32(tmp);
4727 } else {
4728 store_reg(s, rt, tmp);
4731 } else {
4732 /* Write */
4733 if (ri->type & ARM_CP_CONST) {
4734 /* If not forbidden by access permissions, treat as WI */
4735 return;
4738 if (is64) {
4739 TCGv_i32 tmplo, tmphi;
4740 TCGv_i64 tmp64 = tcg_temp_new_i64();
4741 tmplo = load_reg(s, rt);
4742 tmphi = load_reg(s, rt2);
4743 tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
4744 tcg_temp_free_i32(tmplo);
4745 tcg_temp_free_i32(tmphi);
4746 if (ri->writefn) {
4747 TCGv_ptr tmpptr = tcg_const_ptr(ri);
4748 gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64);
4749 tcg_temp_free_ptr(tmpptr);
4750 } else {
4751 tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
4753 tcg_temp_free_i64(tmp64);
4754 } else {
4755 if (ri->writefn) {
4756 TCGv_i32 tmp;
4757 TCGv_ptr tmpptr;
4758 tmp = load_reg(s, rt);
4759 tmpptr = tcg_const_ptr(ri);
4760 gen_helper_set_cp_reg(cpu_env, tmpptr, tmp);
4761 tcg_temp_free_ptr(tmpptr);
4762 tcg_temp_free_i32(tmp);
4763 } else {
4764 TCGv_i32 tmp = load_reg(s, rt);
4765 store_cpu_offset(tmp, ri->fieldoffset);
4770 /* I/O operations must end the TB here (whether read or write) */
4771 need_exit_tb = ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) &&
4772 (ri->type & ARM_CP_IO));
4774 if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
4776 * A write to any coprocessor register that ends a TB
4777 * must rebuild the hflags for the next TB.
4779 TCGv_i32 tcg_el = tcg_const_i32(s->current_el);
4780 if (arm_dc_feature(s, ARM_FEATURE_M)) {
4781 gen_helper_rebuild_hflags_m32(cpu_env, tcg_el);
4782 } else {
4783 if (ri->type & ARM_CP_NEWEL) {
4784 gen_helper_rebuild_hflags_a32_newel(cpu_env);
4785 } else {
4786 gen_helper_rebuild_hflags_a32(cpu_env, tcg_el);
4789 tcg_temp_free_i32(tcg_el);
4791 * We default to ending the TB on a coprocessor register write,
4792 * but allow this to be suppressed by the register definition
4793 * (usually only necessary to work around guest bugs).
4795 need_exit_tb = true;
4797 if (need_exit_tb) {
4798 gen_lookup_tb(s);
4801 return;
4804 /* Unknown register; this might be a guest error or a QEMU
4805 * unimplemented feature.
4807 if (is64) {
4808 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
4809 "64 bit system register cp:%d opc1: %d crm:%d "
4810 "(%s)\n",
4811 isread ? "read" : "write", cpnum, opc1, crm,
4812 s->ns ? "non-secure" : "secure");
4813 } else {
4814 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
4815 "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d "
4816 "(%s)\n",
4817 isread ? "read" : "write", cpnum, opc1, crn, crm, opc2,
4818 s->ns ? "non-secure" : "secure");
4821 unallocated_encoding(s);
4822 return;
4825 /* Decode XScale DSP or iWMMXt insn (in the copro space, cp=0 or 1) */
4826 static void disas_xscale_insn(DisasContext *s, uint32_t insn)
4828 int cpnum = (insn >> 8) & 0xf;
4830 if (extract32(s->c15_cpar, cpnum, 1) == 0) {
4831 unallocated_encoding(s);
4832 } else if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
4833 if (disas_iwmmxt_insn(s, insn)) {
4834 unallocated_encoding(s);
4836 } else if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) {
4837 if (disas_dsp_insn(s, insn)) {
4838 unallocated_encoding(s);
4843 /* Store a 64-bit value to a register pair. Clobbers val. */
4844 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
4846 TCGv_i32 tmp;
4847 tmp = tcg_temp_new_i32();
4848 tcg_gen_extrl_i64_i32(tmp, val);
4849 store_reg(s, rlow, tmp);
4850 tmp = tcg_temp_new_i32();
4851 tcg_gen_extrh_i64_i32(tmp, val);
4852 store_reg(s, rhigh, tmp);
4855 /* load and add a 64-bit value from a register pair. */
4856 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
4858 TCGv_i64 tmp;
4859 TCGv_i32 tmpl;
4860 TCGv_i32 tmph;
4862 /* Load 64-bit value rd:rn. */
4863 tmpl = load_reg(s, rlow);
4864 tmph = load_reg(s, rhigh);
4865 tmp = tcg_temp_new_i64();
4866 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
4867 tcg_temp_free_i32(tmpl);
4868 tcg_temp_free_i32(tmph);
4869 tcg_gen_add_i64(val, val, tmp);
4870 tcg_temp_free_i64(tmp);
4873 /* Set N and Z flags from hi|lo. */
4874 static void gen_logicq_cc(TCGv_i32 lo, TCGv_i32 hi)
4876 tcg_gen_mov_i32(cpu_NF, hi);
4877 tcg_gen_or_i32(cpu_ZF, lo, hi);
4880 /* Load/Store exclusive instructions are implemented by remembering
4881 the value/address loaded, and seeing if these are the same
4882 when the store is performed. This should be sufficient to implement
4883 the architecturally mandated semantics, and avoids having to monitor
4884 regular stores. The compare vs the remembered value is done during
4885 the cmpxchg operation, but we must compare the addresses manually. */
4886 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
4887 TCGv_i32 addr, int size)
4889 TCGv_i32 tmp = tcg_temp_new_i32();
4890 MemOp opc = size | MO_ALIGN | s->be_data;
4892 s->is_ldex = true;
4894 if (size == 3) {
4895 TCGv_i32 tmp2 = tcg_temp_new_i32();
4896 TCGv_i64 t64 = tcg_temp_new_i64();
4899 * For AArch32, architecturally the 32-bit word at the lowest
4900 * address is always Rt and the one at addr+4 is Rt2, even if
4901 * the CPU is big-endian. That means we don't want to do a
4902 * gen_aa32_ld_i64(), which checks SCTLR_B as if for an
4903 * architecturally 64-bit access, but instead do a 64-bit access
4904 * using MO_BE if appropriate and then split the two halves.
4906 TCGv taddr = gen_aa32_addr(s, addr, opc);
4908 tcg_gen_qemu_ld_i64(t64, taddr, get_mem_index(s), opc);
4909 tcg_temp_free(taddr);
4910 tcg_gen_mov_i64(cpu_exclusive_val, t64);
4911 if (s->be_data == MO_BE) {
4912 tcg_gen_extr_i64_i32(tmp2, tmp, t64);
4913 } else {
4914 tcg_gen_extr_i64_i32(tmp, tmp2, t64);
4916 tcg_temp_free_i64(t64);
4918 store_reg(s, rt2, tmp2);
4919 } else {
4920 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), opc);
4921 tcg_gen_extu_i32_i64(cpu_exclusive_val, tmp);
4924 store_reg(s, rt, tmp);
4925 tcg_gen_extu_i32_i64(cpu_exclusive_addr, addr);
4928 static void gen_clrex(DisasContext *s)
4930 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
4933 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
4934 TCGv_i32 addr, int size)
4936 TCGv_i32 t0, t1, t2;
4937 TCGv_i64 extaddr;
4938 TCGv taddr;
4939 TCGLabel *done_label;
4940 TCGLabel *fail_label;
4941 MemOp opc = size | MO_ALIGN | s->be_data;
4943 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
4944 [addr] = {Rt};
4945 {Rd} = 0;
4946 } else {
4947 {Rd} = 1;
4948 } */
4949 fail_label = gen_new_label();
4950 done_label = gen_new_label();
4951 extaddr = tcg_temp_new_i64();
4952 tcg_gen_extu_i32_i64(extaddr, addr);
4953 tcg_gen_brcond_i64(TCG_COND_NE, extaddr, cpu_exclusive_addr, fail_label);
4954 tcg_temp_free_i64(extaddr);
4956 taddr = gen_aa32_addr(s, addr, opc);
4957 t0 = tcg_temp_new_i32();
4958 t1 = load_reg(s, rt);
4959 if (size == 3) {
4960 TCGv_i64 o64 = tcg_temp_new_i64();
4961 TCGv_i64 n64 = tcg_temp_new_i64();
4963 t2 = load_reg(s, rt2);
4966 * For AArch32, architecturally the 32-bit word at the lowest
4967 * address is always Rt and the one at addr+4 is Rt2, even if
4968 * the CPU is big-endian. Since we're going to treat this as a
4969 * single 64-bit BE store, we need to put the two halves in the
4970 * opposite order for BE to LE, so that they end up in the right
4971 * places. We don't want gen_aa32_st_i64, because that checks
4972 * SCTLR_B as if for an architectural 64-bit access.
4974 if (s->be_data == MO_BE) {
4975 tcg_gen_concat_i32_i64(n64, t2, t1);
4976 } else {
4977 tcg_gen_concat_i32_i64(n64, t1, t2);
4979 tcg_temp_free_i32(t2);
4981 tcg_gen_atomic_cmpxchg_i64(o64, taddr, cpu_exclusive_val, n64,
4982 get_mem_index(s), opc);
4983 tcg_temp_free_i64(n64);
4985 tcg_gen_setcond_i64(TCG_COND_NE, o64, o64, cpu_exclusive_val);
4986 tcg_gen_extrl_i64_i32(t0, o64);
4988 tcg_temp_free_i64(o64);
4989 } else {
4990 t2 = tcg_temp_new_i32();
4991 tcg_gen_extrl_i64_i32(t2, cpu_exclusive_val);
4992 tcg_gen_atomic_cmpxchg_i32(t0, taddr, t2, t1, get_mem_index(s), opc);
4993 tcg_gen_setcond_i32(TCG_COND_NE, t0, t0, t2);
4994 tcg_temp_free_i32(t2);
4996 tcg_temp_free_i32(t1);
4997 tcg_temp_free(taddr);
4998 tcg_gen_mov_i32(cpu_R[rd], t0);
4999 tcg_temp_free_i32(t0);
5000 tcg_gen_br(done_label);
5002 gen_set_label(fail_label);
5003 tcg_gen_movi_i32(cpu_R[rd], 1);
5004 gen_set_label(done_label);
5005 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
5008 /* gen_srs:
5009 * @env: CPUARMState
5010 * @s: DisasContext
5011 * @mode: mode field from insn (which stack to store to)
5012 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
5013 * @writeback: true if writeback bit set
5015 * Generate code for the SRS (Store Return State) insn.
5017 static void gen_srs(DisasContext *s,
5018 uint32_t mode, uint32_t amode, bool writeback)
5020 int32_t offset;
5021 TCGv_i32 addr, tmp;
5022 bool undef = false;
5024 /* SRS is:
5025 * - trapped to EL3 if EL3 is AArch64 and we are at Secure EL1
5026 * and specified mode is monitor mode
5027 * - UNDEFINED in Hyp mode
5028 * - UNPREDICTABLE in User or System mode
5029 * - UNPREDICTABLE if the specified mode is:
5030 * -- not implemented
5031 * -- not a valid mode number
5032 * -- a mode that's at a higher exception level
5033 * -- Monitor, if we are Non-secure
5034 * For the UNPREDICTABLE cases we choose to UNDEF.
5036 if (s->current_el == 1 && !s->ns && mode == ARM_CPU_MODE_MON) {
5037 gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(), 3);
5038 return;
5041 if (s->current_el == 0 || s->current_el == 2) {
5042 undef = true;
5045 switch (mode) {
5046 case ARM_CPU_MODE_USR:
5047 case ARM_CPU_MODE_FIQ:
5048 case ARM_CPU_MODE_IRQ:
5049 case ARM_CPU_MODE_SVC:
5050 case ARM_CPU_MODE_ABT:
5051 case ARM_CPU_MODE_UND:
5052 case ARM_CPU_MODE_SYS:
5053 break;
5054 case ARM_CPU_MODE_HYP:
5055 if (s->current_el == 1 || !arm_dc_feature(s, ARM_FEATURE_EL2)) {
5056 undef = true;
5058 break;
5059 case ARM_CPU_MODE_MON:
5060 /* No need to check specifically for "are we non-secure" because
5061 * we've already made EL0 UNDEF and handled the trap for S-EL1;
5062 * so if this isn't EL3 then we must be non-secure.
5064 if (s->current_el != 3) {
5065 undef = true;
5067 break;
5068 default:
5069 undef = true;
5072 if (undef) {
5073 unallocated_encoding(s);
5074 return;
5077 addr = tcg_temp_new_i32();
5078 tmp = tcg_const_i32(mode);
5079 /* get_r13_banked() will raise an exception if called from System mode */
5080 gen_set_condexec(s);
5081 gen_set_pc_im(s, s->pc_curr);
5082 gen_helper_get_r13_banked(addr, cpu_env, tmp);
5083 tcg_temp_free_i32(tmp);
5084 switch (amode) {
5085 case 0: /* DA */
5086 offset = -4;
5087 break;
5088 case 1: /* IA */
5089 offset = 0;
5090 break;
5091 case 2: /* DB */
5092 offset = -8;
5093 break;
5094 case 3: /* IB */
5095 offset = 4;
5096 break;
5097 default:
5098 abort();
5100 tcg_gen_addi_i32(addr, addr, offset);
5101 tmp = load_reg(s, 14);
5102 gen_aa32_st_i32(s, tmp, addr, get_mem_index(s), MO_UL | MO_ALIGN);
5103 tcg_temp_free_i32(tmp);
5104 tmp = load_cpu_field(spsr);
5105 tcg_gen_addi_i32(addr, addr, 4);
5106 gen_aa32_st_i32(s, tmp, addr, get_mem_index(s), MO_UL | MO_ALIGN);
5107 tcg_temp_free_i32(tmp);
5108 if (writeback) {
5109 switch (amode) {
5110 case 0:
5111 offset = -8;
5112 break;
5113 case 1:
5114 offset = 4;
5115 break;
5116 case 2:
5117 offset = -4;
5118 break;
5119 case 3:
5120 offset = 0;
5121 break;
5122 default:
5123 abort();
5125 tcg_gen_addi_i32(addr, addr, offset);
5126 tmp = tcg_const_i32(mode);
5127 gen_helper_set_r13_banked(cpu_env, tmp, addr);
5128 tcg_temp_free_i32(tmp);
5130 tcg_temp_free_i32(addr);
5131 s->base.is_jmp = DISAS_UPDATE_EXIT;
5134 /* Skip this instruction if the ARM condition is false */
5135 static void arm_skip_unless(DisasContext *s, uint32_t cond)
5137 arm_gen_condlabel(s);
5138 arm_gen_test_cc(cond ^ 1, s->condlabel);
5143 * Constant expanders used by T16/T32 decode
5146 /* Return only the rotation part of T32ExpandImm. */
5147 static int t32_expandimm_rot(DisasContext *s, int x)
5149 return x & 0xc00 ? extract32(x, 7, 5) : 0;
5152 /* Return the unrotated immediate from T32ExpandImm. */
5153 static int t32_expandimm_imm(DisasContext *s, int x)
5155 int imm = extract32(x, 0, 8);
5157 switch (extract32(x, 8, 4)) {
5158 case 0: /* XY */
5159 /* Nothing to do. */
5160 break;
5161 case 1: /* 00XY00XY */
5162 imm *= 0x00010001;
5163 break;
5164 case 2: /* XY00XY00 */
5165 imm *= 0x01000100;
5166 break;
5167 case 3: /* XYXYXYXY */
5168 imm *= 0x01010101;
5169 break;
5170 default:
5171 /* Rotated constant. */
5172 imm |= 0x80;
5173 break;
5175 return imm;
5178 static int t32_branch24(DisasContext *s, int x)
5180 /* Convert J1:J2 at x[22:21] to I2:I1, which involves I=J^~S. */
5181 x ^= !(x < 0) * (3 << 21);
5182 /* Append the final zero. */
5183 return x << 1;
5186 static int t16_setflags(DisasContext *s)
5188 return s->condexec_mask == 0;
5191 static int t16_push_list(DisasContext *s, int x)
5193 return (x & 0xff) | (x & 0x100) << (14 - 8);
5196 static int t16_pop_list(DisasContext *s, int x)
5198 return (x & 0xff) | (x & 0x100) << (15 - 8);
5202 * Include the generated decoders.
5205 #include "decode-a32.c.inc"
5206 #include "decode-a32-uncond.c.inc"
5207 #include "decode-t32.c.inc"
5208 #include "decode-t16.c.inc"
5210 static bool valid_cp(DisasContext *s, int cp)
5213 * Return true if this coprocessor field indicates something
5214 * that's really a possible coprocessor.
5215 * For v7 and earlier, coprocessors 8..15 were reserved for Arm use,
5216 * and of those only cp14 and cp15 were used for registers.
5217 * cp10 and cp11 were used for VFP and Neon, whose decode is
5218 * dealt with elsewhere. With the advent of fp16, cp9 is also
5219 * now part of VFP.
5220 * For v8A and later, the encoding has been tightened so that
5221 * only cp14 and cp15 are valid, and other values aren't considered
5222 * to be in the coprocessor-instruction space at all. v8M still
5223 * permits coprocessors 0..7.
5224 * For XScale, we must not decode the XScale cp0, cp1 space as
5225 * a standard coprocessor insn, because we want to fall through to
5226 * the legacy disas_xscale_insn() decoder after decodetree is done.
5228 if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cp == 0 || cp == 1)) {
5229 return false;
5232 if (arm_dc_feature(s, ARM_FEATURE_V8) &&
5233 !arm_dc_feature(s, ARM_FEATURE_M)) {
5234 return cp >= 14;
5236 return cp < 8 || cp >= 14;
5239 static bool trans_MCR(DisasContext *s, arg_MCR *a)
5241 if (!valid_cp(s, a->cp)) {
5242 return false;
5244 do_coproc_insn(s, a->cp, false, a->opc1, a->crn, a->crm, a->opc2,
5245 false, a->rt, 0);
5246 return true;
5249 static bool trans_MRC(DisasContext *s, arg_MRC *a)
5251 if (!valid_cp(s, a->cp)) {
5252 return false;
5254 do_coproc_insn(s, a->cp, false, a->opc1, a->crn, a->crm, a->opc2,
5255 true, a->rt, 0);
5256 return true;
5259 static bool trans_MCRR(DisasContext *s, arg_MCRR *a)
5261 if (!valid_cp(s, a->cp)) {
5262 return false;
5264 do_coproc_insn(s, a->cp, true, a->opc1, 0, a->crm, 0,
5265 false, a->rt, a->rt2);
5266 return true;
5269 static bool trans_MRRC(DisasContext *s, arg_MRRC *a)
5271 if (!valid_cp(s, a->cp)) {
5272 return false;
5274 do_coproc_insn(s, a->cp, true, a->opc1, 0, a->crm, 0,
5275 true, a->rt, a->rt2);
5276 return true;
5279 /* Helpers to swap operands for reverse-subtract. */
5280 static void gen_rsb(TCGv_i32 dst, TCGv_i32 a, TCGv_i32 b)
5282 tcg_gen_sub_i32(dst, b, a);
5285 static void gen_rsb_CC(TCGv_i32 dst, TCGv_i32 a, TCGv_i32 b)
5287 gen_sub_CC(dst, b, a);
5290 static void gen_rsc(TCGv_i32 dest, TCGv_i32 a, TCGv_i32 b)
5292 gen_sub_carry(dest, b, a);
5295 static void gen_rsc_CC(TCGv_i32 dest, TCGv_i32 a, TCGv_i32 b)
5297 gen_sbc_CC(dest, b, a);
5301 * Helpers for the data processing routines.
5303 * After the computation store the results back.
5304 * This may be suppressed altogether (STREG_NONE), require a runtime
5305 * check against the stack limits (STREG_SP_CHECK), or generate an
5306 * exception return. Oh, or store into a register.
5308 * Always return true, indicating success for a trans_* function.
5310 typedef enum {
5311 STREG_NONE,
5312 STREG_NORMAL,
5313 STREG_SP_CHECK,
5314 STREG_EXC_RET,
5315 } StoreRegKind;
5317 static bool store_reg_kind(DisasContext *s, int rd,
5318 TCGv_i32 val, StoreRegKind kind)
5320 switch (kind) {
5321 case STREG_NONE:
5322 tcg_temp_free_i32(val);
5323 return true;
5324 case STREG_NORMAL:
5325 /* See ALUWritePC: Interworking only from a32 mode. */
5326 if (s->thumb) {
5327 store_reg(s, rd, val);
5328 } else {
5329 store_reg_bx(s, rd, val);
5331 return true;
5332 case STREG_SP_CHECK:
5333 store_sp_checked(s, val);
5334 return true;
5335 case STREG_EXC_RET:
5336 gen_exception_return(s, val);
5337 return true;
5339 g_assert_not_reached();
5343 * Data Processing (register)
5345 * Operate, with set flags, one register source,
5346 * one immediate shifted register source, and a destination.
5348 static bool op_s_rrr_shi(DisasContext *s, arg_s_rrr_shi *a,
5349 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32),
5350 int logic_cc, StoreRegKind kind)
5352 TCGv_i32 tmp1, tmp2;
5354 tmp2 = load_reg(s, a->rm);
5355 gen_arm_shift_im(tmp2, a->shty, a->shim, logic_cc);
5356 tmp1 = load_reg(s, a->rn);
5358 gen(tmp1, tmp1, tmp2);
5359 tcg_temp_free_i32(tmp2);
5361 if (logic_cc) {
5362 gen_logic_CC(tmp1);
5364 return store_reg_kind(s, a->rd, tmp1, kind);
5367 static bool op_s_rxr_shi(DisasContext *s, arg_s_rrr_shi *a,
5368 void (*gen)(TCGv_i32, TCGv_i32),
5369 int logic_cc, StoreRegKind kind)
5371 TCGv_i32 tmp;
5373 tmp = load_reg(s, a->rm);
5374 gen_arm_shift_im(tmp, a->shty, a->shim, logic_cc);
5376 gen(tmp, tmp);
5377 if (logic_cc) {
5378 gen_logic_CC(tmp);
5380 return store_reg_kind(s, a->rd, tmp, kind);
5384 * Data-processing (register-shifted register)
5386 * Operate, with set flags, one register source,
5387 * one register shifted register source, and a destination.
5389 static bool op_s_rrr_shr(DisasContext *s, arg_s_rrr_shr *a,
5390 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32),
5391 int logic_cc, StoreRegKind kind)
5393 TCGv_i32 tmp1, tmp2;
5395 tmp1 = load_reg(s, a->rs);
5396 tmp2 = load_reg(s, a->rm);
5397 gen_arm_shift_reg(tmp2, a->shty, tmp1, logic_cc);
5398 tmp1 = load_reg(s, a->rn);
5400 gen(tmp1, tmp1, tmp2);
5401 tcg_temp_free_i32(tmp2);
5403 if (logic_cc) {
5404 gen_logic_CC(tmp1);
5406 return store_reg_kind(s, a->rd, tmp1, kind);
5409 static bool op_s_rxr_shr(DisasContext *s, arg_s_rrr_shr *a,
5410 void (*gen)(TCGv_i32, TCGv_i32),
5411 int logic_cc, StoreRegKind kind)
5413 TCGv_i32 tmp1, tmp2;
5415 tmp1 = load_reg(s, a->rs);
5416 tmp2 = load_reg(s, a->rm);
5417 gen_arm_shift_reg(tmp2, a->shty, tmp1, logic_cc);
5419 gen(tmp2, tmp2);
5420 if (logic_cc) {
5421 gen_logic_CC(tmp2);
5423 return store_reg_kind(s, a->rd, tmp2, kind);
5427 * Data-processing (immediate)
5429 * Operate, with set flags, one register source,
5430 * one rotated immediate, and a destination.
5432 * Note that logic_cc && a->rot setting CF based on the msb of the
5433 * immediate is the reason why we must pass in the unrotated form
5434 * of the immediate.
5436 static bool op_s_rri_rot(DisasContext *s, arg_s_rri_rot *a,
5437 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32),
5438 int logic_cc, StoreRegKind kind)
5440 TCGv_i32 tmp1, tmp2;
5441 uint32_t imm;
5443 imm = ror32(a->imm, a->rot);
5444 if (logic_cc && a->rot) {
5445 tcg_gen_movi_i32(cpu_CF, imm >> 31);
5447 tmp2 = tcg_const_i32(imm);
5448 tmp1 = load_reg(s, a->rn);
5450 gen(tmp1, tmp1, tmp2);
5451 tcg_temp_free_i32(tmp2);
5453 if (logic_cc) {
5454 gen_logic_CC(tmp1);
5456 return store_reg_kind(s, a->rd, tmp1, kind);
5459 static bool op_s_rxi_rot(DisasContext *s, arg_s_rri_rot *a,
5460 void (*gen)(TCGv_i32, TCGv_i32),
5461 int logic_cc, StoreRegKind kind)
5463 TCGv_i32 tmp;
5464 uint32_t imm;
5466 imm = ror32(a->imm, a->rot);
5467 if (logic_cc && a->rot) {
5468 tcg_gen_movi_i32(cpu_CF, imm >> 31);
5470 tmp = tcg_const_i32(imm);
5472 gen(tmp, tmp);
5473 if (logic_cc) {
5474 gen_logic_CC(tmp);
5476 return store_reg_kind(s, a->rd, tmp, kind);
5479 #define DO_ANY3(NAME, OP, L, K) \
5480 static bool trans_##NAME##_rrri(DisasContext *s, arg_s_rrr_shi *a) \
5481 { StoreRegKind k = (K); return op_s_rrr_shi(s, a, OP, L, k); } \
5482 static bool trans_##NAME##_rrrr(DisasContext *s, arg_s_rrr_shr *a) \
5483 { StoreRegKind k = (K); return op_s_rrr_shr(s, a, OP, L, k); } \
5484 static bool trans_##NAME##_rri(DisasContext *s, arg_s_rri_rot *a) \
5485 { StoreRegKind k = (K); return op_s_rri_rot(s, a, OP, L, k); }
5487 #define DO_ANY2(NAME, OP, L, K) \
5488 static bool trans_##NAME##_rxri(DisasContext *s, arg_s_rrr_shi *a) \
5489 { StoreRegKind k = (K); return op_s_rxr_shi(s, a, OP, L, k); } \
5490 static bool trans_##NAME##_rxrr(DisasContext *s, arg_s_rrr_shr *a) \
5491 { StoreRegKind k = (K); return op_s_rxr_shr(s, a, OP, L, k); } \
5492 static bool trans_##NAME##_rxi(DisasContext *s, arg_s_rri_rot *a) \
5493 { StoreRegKind k = (K); return op_s_rxi_rot(s, a, OP, L, k); }
5495 #define DO_CMP2(NAME, OP, L) \
5496 static bool trans_##NAME##_xrri(DisasContext *s, arg_s_rrr_shi *a) \
5497 { return op_s_rrr_shi(s, a, OP, L, STREG_NONE); } \
5498 static bool trans_##NAME##_xrrr(DisasContext *s, arg_s_rrr_shr *a) \
5499 { return op_s_rrr_shr(s, a, OP, L, STREG_NONE); } \
5500 static bool trans_##NAME##_xri(DisasContext *s, arg_s_rri_rot *a) \
5501 { return op_s_rri_rot(s, a, OP, L, STREG_NONE); }
5503 DO_ANY3(AND, tcg_gen_and_i32, a->s, STREG_NORMAL)
5504 DO_ANY3(EOR, tcg_gen_xor_i32, a->s, STREG_NORMAL)
5505 DO_ANY3(ORR, tcg_gen_or_i32, a->s, STREG_NORMAL)
5506 DO_ANY3(BIC, tcg_gen_andc_i32, a->s, STREG_NORMAL)
5508 DO_ANY3(RSB, a->s ? gen_rsb_CC : gen_rsb, false, STREG_NORMAL)
5509 DO_ANY3(ADC, a->s ? gen_adc_CC : gen_add_carry, false, STREG_NORMAL)
5510 DO_ANY3(SBC, a->s ? gen_sbc_CC : gen_sub_carry, false, STREG_NORMAL)
5511 DO_ANY3(RSC, a->s ? gen_rsc_CC : gen_rsc, false, STREG_NORMAL)
5513 DO_CMP2(TST, tcg_gen_and_i32, true)
5514 DO_CMP2(TEQ, tcg_gen_xor_i32, true)
5515 DO_CMP2(CMN, gen_add_CC, false)
5516 DO_CMP2(CMP, gen_sub_CC, false)
5518 DO_ANY3(ADD, a->s ? gen_add_CC : tcg_gen_add_i32, false,
5519 a->rd == 13 && a->rn == 13 ? STREG_SP_CHECK : STREG_NORMAL)
5522 * Note for the computation of StoreRegKind we return out of the
5523 * middle of the functions that are expanded by DO_ANY3, and that
5524 * we modify a->s via that parameter before it is used by OP.
5526 DO_ANY3(SUB, a->s ? gen_sub_CC : tcg_gen_sub_i32, false,
5528 StoreRegKind ret = STREG_NORMAL;
5529 if (a->rd == 15 && a->s) {
5531 * See ALUExceptionReturn:
5532 * In User mode, UNPREDICTABLE; we choose UNDEF.
5533 * In Hyp mode, UNDEFINED.
5535 if (IS_USER(s) || s->current_el == 2) {
5536 unallocated_encoding(s);
5537 return true;
5539 /* There is no writeback of nzcv to PSTATE. */
5540 a->s = 0;
5541 ret = STREG_EXC_RET;
5542 } else if (a->rd == 13 && a->rn == 13) {
5543 ret = STREG_SP_CHECK;
5545 ret;
5548 DO_ANY2(MOV, tcg_gen_mov_i32, a->s,
5550 StoreRegKind ret = STREG_NORMAL;
5551 if (a->rd == 15 && a->s) {
5553 * See ALUExceptionReturn:
5554 * In User mode, UNPREDICTABLE; we choose UNDEF.
5555 * In Hyp mode, UNDEFINED.
5557 if (IS_USER(s) || s->current_el == 2) {
5558 unallocated_encoding(s);
5559 return true;
5561 /* There is no writeback of nzcv to PSTATE. */
5562 a->s = 0;
5563 ret = STREG_EXC_RET;
5564 } else if (a->rd == 13) {
5565 ret = STREG_SP_CHECK;
5567 ret;
5570 DO_ANY2(MVN, tcg_gen_not_i32, a->s, STREG_NORMAL)
5573 * ORN is only available with T32, so there is no register-shifted-register
5574 * form of the insn. Using the DO_ANY3 macro would create an unused function.
5576 static bool trans_ORN_rrri(DisasContext *s, arg_s_rrr_shi *a)
5578 return op_s_rrr_shi(s, a, tcg_gen_orc_i32, a->s, STREG_NORMAL);
5581 static bool trans_ORN_rri(DisasContext *s, arg_s_rri_rot *a)
5583 return op_s_rri_rot(s, a, tcg_gen_orc_i32, a->s, STREG_NORMAL);
5586 #undef DO_ANY3
5587 #undef DO_ANY2
5588 #undef DO_CMP2
5590 static bool trans_ADR(DisasContext *s, arg_ri *a)
5592 store_reg_bx(s, a->rd, add_reg_for_lit(s, 15, a->imm));
5593 return true;
5596 static bool trans_MOVW(DisasContext *s, arg_MOVW *a)
5598 TCGv_i32 tmp;
5600 if (!ENABLE_ARCH_6T2) {
5601 return false;
5604 tmp = tcg_const_i32(a->imm);
5605 store_reg(s, a->rd, tmp);
5606 return true;
5609 static bool trans_MOVT(DisasContext *s, arg_MOVW *a)
5611 TCGv_i32 tmp;
5613 if (!ENABLE_ARCH_6T2) {
5614 return false;
5617 tmp = load_reg(s, a->rd);
5618 tcg_gen_ext16u_i32(tmp, tmp);
5619 tcg_gen_ori_i32(tmp, tmp, a->imm << 16);
5620 store_reg(s, a->rd, tmp);
5621 return true;
5625 * Multiply and multiply accumulate
5628 static bool op_mla(DisasContext *s, arg_s_rrrr *a, bool add)
5630 TCGv_i32 t1, t2;
5632 t1 = load_reg(s, a->rn);
5633 t2 = load_reg(s, a->rm);
5634 tcg_gen_mul_i32(t1, t1, t2);
5635 tcg_temp_free_i32(t2);
5636 if (add) {
5637 t2 = load_reg(s, a->ra);
5638 tcg_gen_add_i32(t1, t1, t2);
5639 tcg_temp_free_i32(t2);
5641 if (a->s) {
5642 gen_logic_CC(t1);
5644 store_reg(s, a->rd, t1);
5645 return true;
5648 static bool trans_MUL(DisasContext *s, arg_MUL *a)
5650 return op_mla(s, a, false);
5653 static bool trans_MLA(DisasContext *s, arg_MLA *a)
5655 return op_mla(s, a, true);
5658 static bool trans_MLS(DisasContext *s, arg_MLS *a)
5660 TCGv_i32 t1, t2;
5662 if (!ENABLE_ARCH_6T2) {
5663 return false;
5665 t1 = load_reg(s, a->rn);
5666 t2 = load_reg(s, a->rm);
5667 tcg_gen_mul_i32(t1, t1, t2);
5668 tcg_temp_free_i32(t2);
5669 t2 = load_reg(s, a->ra);
5670 tcg_gen_sub_i32(t1, t2, t1);
5671 tcg_temp_free_i32(t2);
5672 store_reg(s, a->rd, t1);
5673 return true;
5676 static bool op_mlal(DisasContext *s, arg_s_rrrr *a, bool uns, bool add)
5678 TCGv_i32 t0, t1, t2, t3;
5680 t0 = load_reg(s, a->rm);
5681 t1 = load_reg(s, a->rn);
5682 if (uns) {
5683 tcg_gen_mulu2_i32(t0, t1, t0, t1);
5684 } else {
5685 tcg_gen_muls2_i32(t0, t1, t0, t1);
5687 if (add) {
5688 t2 = load_reg(s, a->ra);
5689 t3 = load_reg(s, a->rd);
5690 tcg_gen_add2_i32(t0, t1, t0, t1, t2, t3);
5691 tcg_temp_free_i32(t2);
5692 tcg_temp_free_i32(t3);
5694 if (a->s) {
5695 gen_logicq_cc(t0, t1);
5697 store_reg(s, a->ra, t0);
5698 store_reg(s, a->rd, t1);
5699 return true;
5702 static bool trans_UMULL(DisasContext *s, arg_UMULL *a)
5704 return op_mlal(s, a, true, false);
5707 static bool trans_SMULL(DisasContext *s, arg_SMULL *a)
5709 return op_mlal(s, a, false, false);
5712 static bool trans_UMLAL(DisasContext *s, arg_UMLAL *a)
5714 return op_mlal(s, a, true, true);
5717 static bool trans_SMLAL(DisasContext *s, arg_SMLAL *a)
5719 return op_mlal(s, a, false, true);
5722 static bool trans_UMAAL(DisasContext *s, arg_UMAAL *a)
5724 TCGv_i32 t0, t1, t2, zero;
5726 if (s->thumb
5727 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
5728 : !ENABLE_ARCH_6) {
5729 return false;
5732 t0 = load_reg(s, a->rm);
5733 t1 = load_reg(s, a->rn);
5734 tcg_gen_mulu2_i32(t0, t1, t0, t1);
5735 zero = tcg_const_i32(0);
5736 t2 = load_reg(s, a->ra);
5737 tcg_gen_add2_i32(t0, t1, t0, t1, t2, zero);
5738 tcg_temp_free_i32(t2);
5739 t2 = load_reg(s, a->rd);
5740 tcg_gen_add2_i32(t0, t1, t0, t1, t2, zero);
5741 tcg_temp_free_i32(t2);
5742 tcg_temp_free_i32(zero);
5743 store_reg(s, a->ra, t0);
5744 store_reg(s, a->rd, t1);
5745 return true;
5749 * Saturating addition and subtraction
5752 static bool op_qaddsub(DisasContext *s, arg_rrr *a, bool add, bool doub)
5754 TCGv_i32 t0, t1;
5756 if (s->thumb
5757 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
5758 : !ENABLE_ARCH_5TE) {
5759 return false;
5762 t0 = load_reg(s, a->rm);
5763 t1 = load_reg(s, a->rn);
5764 if (doub) {
5765 gen_helper_add_saturate(t1, cpu_env, t1, t1);
5767 if (add) {
5768 gen_helper_add_saturate(t0, cpu_env, t0, t1);
5769 } else {
5770 gen_helper_sub_saturate(t0, cpu_env, t0, t1);
5772 tcg_temp_free_i32(t1);
5773 store_reg(s, a->rd, t0);
5774 return true;
5777 #define DO_QADDSUB(NAME, ADD, DOUB) \
5778 static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
5780 return op_qaddsub(s, a, ADD, DOUB); \
5783 DO_QADDSUB(QADD, true, false)
5784 DO_QADDSUB(QSUB, false, false)
5785 DO_QADDSUB(QDADD, true, true)
5786 DO_QADDSUB(QDSUB, false, true)
5788 #undef DO_QADDSUB
5791 * Halfword multiply and multiply accumulate
5794 static bool op_smlaxxx(DisasContext *s, arg_rrrr *a,
5795 int add_long, bool nt, bool mt)
5797 TCGv_i32 t0, t1, tl, th;
5799 if (s->thumb
5800 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
5801 : !ENABLE_ARCH_5TE) {
5802 return false;
5805 t0 = load_reg(s, a->rn);
5806 t1 = load_reg(s, a->rm);
5807 gen_mulxy(t0, t1, nt, mt);
5808 tcg_temp_free_i32(t1);
5810 switch (add_long) {
5811 case 0:
5812 store_reg(s, a->rd, t0);
5813 break;
5814 case 1:
5815 t1 = load_reg(s, a->ra);
5816 gen_helper_add_setq(t0, cpu_env, t0, t1);
5817 tcg_temp_free_i32(t1);
5818 store_reg(s, a->rd, t0);
5819 break;
5820 case 2:
5821 tl = load_reg(s, a->ra);
5822 th = load_reg(s, a->rd);
5823 /* Sign-extend the 32-bit product to 64 bits. */
5824 t1 = tcg_temp_new_i32();
5825 tcg_gen_sari_i32(t1, t0, 31);
5826 tcg_gen_add2_i32(tl, th, tl, th, t0, t1);
5827 tcg_temp_free_i32(t0);
5828 tcg_temp_free_i32(t1);
5829 store_reg(s, a->ra, tl);
5830 store_reg(s, a->rd, th);
5831 break;
5832 default:
5833 g_assert_not_reached();
5835 return true;
5838 #define DO_SMLAX(NAME, add, nt, mt) \
5839 static bool trans_##NAME(DisasContext *s, arg_rrrr *a) \
5841 return op_smlaxxx(s, a, add, nt, mt); \
5844 DO_SMLAX(SMULBB, 0, 0, 0)
5845 DO_SMLAX(SMULBT, 0, 0, 1)
5846 DO_SMLAX(SMULTB, 0, 1, 0)
5847 DO_SMLAX(SMULTT, 0, 1, 1)
5849 DO_SMLAX(SMLABB, 1, 0, 0)
5850 DO_SMLAX(SMLABT, 1, 0, 1)
5851 DO_SMLAX(SMLATB, 1, 1, 0)
5852 DO_SMLAX(SMLATT, 1, 1, 1)
5854 DO_SMLAX(SMLALBB, 2, 0, 0)
5855 DO_SMLAX(SMLALBT, 2, 0, 1)
5856 DO_SMLAX(SMLALTB, 2, 1, 0)
5857 DO_SMLAX(SMLALTT, 2, 1, 1)
5859 #undef DO_SMLAX
5861 static bool op_smlawx(DisasContext *s, arg_rrrr *a, bool add, bool mt)
5863 TCGv_i32 t0, t1;
5865 if (!ENABLE_ARCH_5TE) {
5866 return false;
5869 t0 = load_reg(s, a->rn);
5870 t1 = load_reg(s, a->rm);
5872 * Since the nominal result is product<47:16>, shift the 16-bit
5873 * input up by 16 bits, so that the result is at product<63:32>.
5875 if (mt) {
5876 tcg_gen_andi_i32(t1, t1, 0xffff0000);
5877 } else {
5878 tcg_gen_shli_i32(t1, t1, 16);
5880 tcg_gen_muls2_i32(t0, t1, t0, t1);
5881 tcg_temp_free_i32(t0);
5882 if (add) {
5883 t0 = load_reg(s, a->ra);
5884 gen_helper_add_setq(t1, cpu_env, t1, t0);
5885 tcg_temp_free_i32(t0);
5887 store_reg(s, a->rd, t1);
5888 return true;
5891 #define DO_SMLAWX(NAME, add, mt) \
5892 static bool trans_##NAME(DisasContext *s, arg_rrrr *a) \
5894 return op_smlawx(s, a, add, mt); \
5897 DO_SMLAWX(SMULWB, 0, 0)
5898 DO_SMLAWX(SMULWT, 0, 1)
5899 DO_SMLAWX(SMLAWB, 1, 0)
5900 DO_SMLAWX(SMLAWT, 1, 1)
5902 #undef DO_SMLAWX
5905 * MSR (immediate) and hints
5908 static bool trans_YIELD(DisasContext *s, arg_YIELD *a)
5911 * When running single-threaded TCG code, use the helper to ensure that
5912 * the next round-robin scheduled vCPU gets a crack. When running in
5913 * MTTCG we don't generate jumps to the helper as it won't affect the
5914 * scheduling of other vCPUs.
5916 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
5917 gen_set_pc_im(s, s->base.pc_next);
5918 s->base.is_jmp = DISAS_YIELD;
5920 return true;
5923 static bool trans_WFE(DisasContext *s, arg_WFE *a)
5926 * When running single-threaded TCG code, use the helper to ensure that
5927 * the next round-robin scheduled vCPU gets a crack. In MTTCG mode we
5928 * just skip this instruction. Currently the SEV/SEVL instructions,
5929 * which are *one* of many ways to wake the CPU from WFE, are not
5930 * implemented so we can't sleep like WFI does.
5932 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
5933 gen_set_pc_im(s, s->base.pc_next);
5934 s->base.is_jmp = DISAS_WFE;
5936 return true;
5939 static bool trans_WFI(DisasContext *s, arg_WFI *a)
5941 /* For WFI, halt the vCPU until an IRQ. */
5942 gen_set_pc_im(s, s->base.pc_next);
5943 s->base.is_jmp = DISAS_WFI;
5944 return true;
5947 static bool trans_NOP(DisasContext *s, arg_NOP *a)
5949 return true;
5952 static bool trans_MSR_imm(DisasContext *s, arg_MSR_imm *a)
5954 uint32_t val = ror32(a->imm, a->rot * 2);
5955 uint32_t mask = msr_mask(s, a->mask, a->r);
5957 if (gen_set_psr_im(s, mask, a->r, val)) {
5958 unallocated_encoding(s);
5960 return true;
5964 * Cyclic Redundancy Check
5967 static bool op_crc32(DisasContext *s, arg_rrr *a, bool c, MemOp sz)
5969 TCGv_i32 t1, t2, t3;
5971 if (!dc_isar_feature(aa32_crc32, s)) {
5972 return false;
5975 t1 = load_reg(s, a->rn);
5976 t2 = load_reg(s, a->rm);
5977 switch (sz) {
5978 case MO_8:
5979 gen_uxtb(t2);
5980 break;
5981 case MO_16:
5982 gen_uxth(t2);
5983 break;
5984 case MO_32:
5985 break;
5986 default:
5987 g_assert_not_reached();
5989 t3 = tcg_const_i32(1 << sz);
5990 if (c) {
5991 gen_helper_crc32c(t1, t1, t2, t3);
5992 } else {
5993 gen_helper_crc32(t1, t1, t2, t3);
5995 tcg_temp_free_i32(t2);
5996 tcg_temp_free_i32(t3);
5997 store_reg(s, a->rd, t1);
5998 return true;
6001 #define DO_CRC32(NAME, c, sz) \
6002 static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
6003 { return op_crc32(s, a, c, sz); }
6005 DO_CRC32(CRC32B, false, MO_8)
6006 DO_CRC32(CRC32H, false, MO_16)
6007 DO_CRC32(CRC32W, false, MO_32)
6008 DO_CRC32(CRC32CB, true, MO_8)
6009 DO_CRC32(CRC32CH, true, MO_16)
6010 DO_CRC32(CRC32CW, true, MO_32)
6012 #undef DO_CRC32
6015 * Miscellaneous instructions
6018 static bool trans_MRS_bank(DisasContext *s, arg_MRS_bank *a)
6020 if (arm_dc_feature(s, ARM_FEATURE_M)) {
6021 return false;
6023 gen_mrs_banked(s, a->r, a->sysm, a->rd);
6024 return true;
6027 static bool trans_MSR_bank(DisasContext *s, arg_MSR_bank *a)
6029 if (arm_dc_feature(s, ARM_FEATURE_M)) {
6030 return false;
6032 gen_msr_banked(s, a->r, a->sysm, a->rn);
6033 return true;
6036 static bool trans_MRS_reg(DisasContext *s, arg_MRS_reg *a)
6038 TCGv_i32 tmp;
6040 if (arm_dc_feature(s, ARM_FEATURE_M)) {
6041 return false;
6043 if (a->r) {
6044 if (IS_USER(s)) {
6045 unallocated_encoding(s);
6046 return true;
6048 tmp = load_cpu_field(spsr);
6049 } else {
6050 tmp = tcg_temp_new_i32();
6051 gen_helper_cpsr_read(tmp, cpu_env);
6053 store_reg(s, a->rd, tmp);
6054 return true;
6057 static bool trans_MSR_reg(DisasContext *s, arg_MSR_reg *a)
6059 TCGv_i32 tmp;
6060 uint32_t mask = msr_mask(s, a->mask, a->r);
6062 if (arm_dc_feature(s, ARM_FEATURE_M)) {
6063 return false;
6065 tmp = load_reg(s, a->rn);
6066 if (gen_set_psr(s, mask, a->r, tmp)) {
6067 unallocated_encoding(s);
6069 return true;
6072 static bool trans_MRS_v7m(DisasContext *s, arg_MRS_v7m *a)
6074 TCGv_i32 tmp;
6076 if (!arm_dc_feature(s, ARM_FEATURE_M)) {
6077 return false;
6079 tmp = tcg_const_i32(a->sysm);
6080 gen_helper_v7m_mrs(tmp, cpu_env, tmp);
6081 store_reg(s, a->rd, tmp);
6082 return true;
6085 static bool trans_MSR_v7m(DisasContext *s, arg_MSR_v7m *a)
6087 TCGv_i32 addr, reg;
6089 if (!arm_dc_feature(s, ARM_FEATURE_M)) {
6090 return false;
6092 addr = tcg_const_i32((a->mask << 10) | a->sysm);
6093 reg = load_reg(s, a->rn);
6094 gen_helper_v7m_msr(cpu_env, addr, reg);
6095 tcg_temp_free_i32(addr);
6096 tcg_temp_free_i32(reg);
6097 /* If we wrote to CONTROL, the EL might have changed */
6098 gen_helper_rebuild_hflags_m32_newel(cpu_env);
6099 gen_lookup_tb(s);
6100 return true;
6103 static bool trans_BX(DisasContext *s, arg_BX *a)
6105 if (!ENABLE_ARCH_4T) {
6106 return false;
6108 gen_bx_excret(s, load_reg(s, a->rm));
6109 return true;
6112 static bool trans_BXJ(DisasContext *s, arg_BXJ *a)
6114 if (!ENABLE_ARCH_5J || arm_dc_feature(s, ARM_FEATURE_M)) {
6115 return false;
6117 /* Trivial implementation equivalent to bx. */
6118 gen_bx(s, load_reg(s, a->rm));
6119 return true;
6122 static bool trans_BLX_r(DisasContext *s, arg_BLX_r *a)
6124 TCGv_i32 tmp;
6126 if (!ENABLE_ARCH_5) {
6127 return false;
6129 tmp = load_reg(s, a->rm);
6130 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
6131 gen_bx(s, tmp);
6132 return true;
6136 * BXNS/BLXNS: only exist for v8M with the security extensions,
6137 * and always UNDEF if NonSecure. We don't implement these in
6138 * the user-only mode either (in theory you can use them from
6139 * Secure User mode but they are too tied in to system emulation).
6141 static bool trans_BXNS(DisasContext *s, arg_BXNS *a)
6143 if (!s->v8m_secure || IS_USER_ONLY) {
6144 unallocated_encoding(s);
6145 } else {
6146 gen_bxns(s, a->rm);
6148 return true;
6151 static bool trans_BLXNS(DisasContext *s, arg_BLXNS *a)
6153 if (!s->v8m_secure || IS_USER_ONLY) {
6154 unallocated_encoding(s);
6155 } else {
6156 gen_blxns(s, a->rm);
6158 return true;
6161 static bool trans_CLZ(DisasContext *s, arg_CLZ *a)
6163 TCGv_i32 tmp;
6165 if (!ENABLE_ARCH_5) {
6166 return false;
6168 tmp = load_reg(s, a->rm);
6169 tcg_gen_clzi_i32(tmp, tmp, 32);
6170 store_reg(s, a->rd, tmp);
6171 return true;
6174 static bool trans_ERET(DisasContext *s, arg_ERET *a)
6176 TCGv_i32 tmp;
6178 if (!arm_dc_feature(s, ARM_FEATURE_V7VE)) {
6179 return false;
6181 if (IS_USER(s)) {
6182 unallocated_encoding(s);
6183 return true;
6185 if (s->current_el == 2) {
6186 /* ERET from Hyp uses ELR_Hyp, not LR */
6187 tmp = load_cpu_field(elr_el[2]);
6188 } else {
6189 tmp = load_reg(s, 14);
6191 gen_exception_return(s, tmp);
6192 return true;
6195 static bool trans_HLT(DisasContext *s, arg_HLT *a)
6197 gen_hlt(s, a->imm);
6198 return true;
6201 static bool trans_BKPT(DisasContext *s, arg_BKPT *a)
6203 if (!ENABLE_ARCH_5) {
6204 return false;
6206 if (arm_dc_feature(s, ARM_FEATURE_M) &&
6207 semihosting_enabled() &&
6208 #ifndef CONFIG_USER_ONLY
6209 !IS_USER(s) &&
6210 #endif
6211 (a->imm == 0xab)) {
6212 gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
6213 } else {
6214 gen_exception_bkpt_insn(s, syn_aa32_bkpt(a->imm, false));
6216 return true;
6219 static bool trans_HVC(DisasContext *s, arg_HVC *a)
6221 if (!ENABLE_ARCH_7 || arm_dc_feature(s, ARM_FEATURE_M)) {
6222 return false;
6224 if (IS_USER(s)) {
6225 unallocated_encoding(s);
6226 } else {
6227 gen_hvc(s, a->imm);
6229 return true;
6232 static bool trans_SMC(DisasContext *s, arg_SMC *a)
6234 if (!ENABLE_ARCH_6K || arm_dc_feature(s, ARM_FEATURE_M)) {
6235 return false;
6237 if (IS_USER(s)) {
6238 unallocated_encoding(s);
6239 } else {
6240 gen_smc(s);
6242 return true;
6245 static bool trans_SG(DisasContext *s, arg_SG *a)
6247 if (!arm_dc_feature(s, ARM_FEATURE_M) ||
6248 !arm_dc_feature(s, ARM_FEATURE_V8)) {
6249 return false;
6252 * SG (v8M only)
6253 * The bulk of the behaviour for this instruction is implemented
6254 * in v7m_handle_execute_nsc(), which deals with the insn when
6255 * it is executed by a CPU in non-secure state from memory
6256 * which is Secure & NonSecure-Callable.
6257 * Here we only need to handle the remaining cases:
6258 * * in NS memory (including the "security extension not
6259 * implemented" case) : NOP
6260 * * in S memory but CPU already secure (clear IT bits)
6261 * We know that the attribute for the memory this insn is
6262 * in must match the current CPU state, because otherwise
6263 * get_phys_addr_pmsav8 would have generated an exception.
6265 if (s->v8m_secure) {
6266 /* Like the IT insn, we don't need to generate any code */
6267 s->condexec_cond = 0;
6268 s->condexec_mask = 0;
6270 return true;
6273 static bool trans_TT(DisasContext *s, arg_TT *a)
6275 TCGv_i32 addr, tmp;
6277 if (!arm_dc_feature(s, ARM_FEATURE_M) ||
6278 !arm_dc_feature(s, ARM_FEATURE_V8)) {
6279 return false;
6281 if (a->rd == 13 || a->rd == 15 || a->rn == 15) {
6282 /* We UNDEF for these UNPREDICTABLE cases */
6283 unallocated_encoding(s);
6284 return true;
6286 if (a->A && !s->v8m_secure) {
6287 /* This case is UNDEFINED. */
6288 unallocated_encoding(s);
6289 return true;
6292 addr = load_reg(s, a->rn);
6293 tmp = tcg_const_i32((a->A << 1) | a->T);
6294 gen_helper_v7m_tt(tmp, cpu_env, addr, tmp);
6295 tcg_temp_free_i32(addr);
6296 store_reg(s, a->rd, tmp);
6297 return true;
6301 * Load/store register index
6304 static ISSInfo make_issinfo(DisasContext *s, int rd, bool p, bool w)
6306 ISSInfo ret;
6308 /* ISS not valid if writeback */
6309 if (p && !w) {
6310 ret = rd;
6311 if (s->base.pc_next - s->pc_curr == 2) {
6312 ret |= ISSIs16Bit;
6314 } else {
6315 ret = ISSInvalid;
6317 return ret;
6320 static TCGv_i32 op_addr_rr_pre(DisasContext *s, arg_ldst_rr *a)
6322 TCGv_i32 addr = load_reg(s, a->rn);
6324 if (s->v8m_stackcheck && a->rn == 13 && a->w) {
6325 gen_helper_v8m_stackcheck(cpu_env, addr);
6328 if (a->p) {
6329 TCGv_i32 ofs = load_reg(s, a->rm);
6330 gen_arm_shift_im(ofs, a->shtype, a->shimm, 0);
6331 if (a->u) {
6332 tcg_gen_add_i32(addr, addr, ofs);
6333 } else {
6334 tcg_gen_sub_i32(addr, addr, ofs);
6336 tcg_temp_free_i32(ofs);
6338 return addr;
6341 static void op_addr_rr_post(DisasContext *s, arg_ldst_rr *a,
6342 TCGv_i32 addr, int address_offset)
6344 if (!a->p) {
6345 TCGv_i32 ofs = load_reg(s, a->rm);
6346 gen_arm_shift_im(ofs, a->shtype, a->shimm, 0);
6347 if (a->u) {
6348 tcg_gen_add_i32(addr, addr, ofs);
6349 } else {
6350 tcg_gen_sub_i32(addr, addr, ofs);
6352 tcg_temp_free_i32(ofs);
6353 } else if (!a->w) {
6354 tcg_temp_free_i32(addr);
6355 return;
6357 tcg_gen_addi_i32(addr, addr, address_offset);
6358 store_reg(s, a->rn, addr);
6361 static bool op_load_rr(DisasContext *s, arg_ldst_rr *a,
6362 MemOp mop, int mem_idx)
6364 ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w);
6365 TCGv_i32 addr, tmp;
6367 addr = op_addr_rr_pre(s, a);
6369 tmp = tcg_temp_new_i32();
6370 gen_aa32_ld_i32(s, tmp, addr, mem_idx, mop);
6371 disas_set_da_iss(s, mop, issinfo);
6374 * Perform base writeback before the loaded value to
6375 * ensure correct behavior with overlapping index registers.
6377 op_addr_rr_post(s, a, addr, 0);
6378 store_reg_from_load(s, a->rt, tmp);
6379 return true;
6382 static bool op_store_rr(DisasContext *s, arg_ldst_rr *a,
6383 MemOp mop, int mem_idx)
6385 ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w) | ISSIsWrite;
6386 TCGv_i32 addr, tmp;
6389 * In Thumb encodings of stores Rn=1111 is UNDEF; for Arm it
6390 * is either UNPREDICTABLE or has defined behaviour
6392 if (s->thumb && a->rn == 15) {
6393 return false;
6396 addr = op_addr_rr_pre(s, a);
6398 tmp = load_reg(s, a->rt);
6399 gen_aa32_st_i32(s, tmp, addr, mem_idx, mop);
6400 disas_set_da_iss(s, mop, issinfo);
6401 tcg_temp_free_i32(tmp);
6403 op_addr_rr_post(s, a, addr, 0);
6404 return true;
6407 static bool trans_LDRD_rr(DisasContext *s, arg_ldst_rr *a)
6409 int mem_idx = get_mem_index(s);
6410 TCGv_i32 addr, tmp;
6412 if (!ENABLE_ARCH_5TE) {
6413 return false;
6415 if (a->rt & 1) {
6416 unallocated_encoding(s);
6417 return true;
6419 addr = op_addr_rr_pre(s, a);
6421 tmp = tcg_temp_new_i32();
6422 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
6423 store_reg(s, a->rt, tmp);
6425 tcg_gen_addi_i32(addr, addr, 4);
6427 tmp = tcg_temp_new_i32();
6428 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
6429 store_reg(s, a->rt + 1, tmp);
6431 /* LDRD w/ base writeback is undefined if the registers overlap. */
6432 op_addr_rr_post(s, a, addr, -4);
6433 return true;
6436 static bool trans_STRD_rr(DisasContext *s, arg_ldst_rr *a)
6438 int mem_idx = get_mem_index(s);
6439 TCGv_i32 addr, tmp;
6441 if (!ENABLE_ARCH_5TE) {
6442 return false;
6444 if (a->rt & 1) {
6445 unallocated_encoding(s);
6446 return true;
6448 addr = op_addr_rr_pre(s, a);
6450 tmp = load_reg(s, a->rt);
6451 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
6452 tcg_temp_free_i32(tmp);
6454 tcg_gen_addi_i32(addr, addr, 4);
6456 tmp = load_reg(s, a->rt + 1);
6457 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
6458 tcg_temp_free_i32(tmp);
6460 op_addr_rr_post(s, a, addr, -4);
6461 return true;
6465 * Load/store immediate index
6468 static TCGv_i32 op_addr_ri_pre(DisasContext *s, arg_ldst_ri *a)
6470 int ofs = a->imm;
6472 if (!a->u) {
6473 ofs = -ofs;
6476 if (s->v8m_stackcheck && a->rn == 13 && a->w) {
6478 * Stackcheck. Here we know 'addr' is the current SP;
6479 * U is set if we're moving SP up, else down. It is
6480 * UNKNOWN whether the limit check triggers when SP starts
6481 * below the limit and ends up above it; we chose to do so.
6483 if (!a->u) {
6484 TCGv_i32 newsp = tcg_temp_new_i32();
6485 tcg_gen_addi_i32(newsp, cpu_R[13], ofs);
6486 gen_helper_v8m_stackcheck(cpu_env, newsp);
6487 tcg_temp_free_i32(newsp);
6488 } else {
6489 gen_helper_v8m_stackcheck(cpu_env, cpu_R[13]);
6493 return add_reg_for_lit(s, a->rn, a->p ? ofs : 0);
6496 static void op_addr_ri_post(DisasContext *s, arg_ldst_ri *a,
6497 TCGv_i32 addr, int address_offset)
6499 if (!a->p) {
6500 if (a->u) {
6501 address_offset += a->imm;
6502 } else {
6503 address_offset -= a->imm;
6505 } else if (!a->w) {
6506 tcg_temp_free_i32(addr);
6507 return;
6509 tcg_gen_addi_i32(addr, addr, address_offset);
6510 store_reg(s, a->rn, addr);
6513 static bool op_load_ri(DisasContext *s, arg_ldst_ri *a,
6514 MemOp mop, int mem_idx)
6516 ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w);
6517 TCGv_i32 addr, tmp;
6519 addr = op_addr_ri_pre(s, a);
6521 tmp = tcg_temp_new_i32();
6522 gen_aa32_ld_i32(s, tmp, addr, mem_idx, mop);
6523 disas_set_da_iss(s, mop, issinfo);
6526 * Perform base writeback before the loaded value to
6527 * ensure correct behavior with overlapping index registers.
6529 op_addr_ri_post(s, a, addr, 0);
6530 store_reg_from_load(s, a->rt, tmp);
6531 return true;
6534 static bool op_store_ri(DisasContext *s, arg_ldst_ri *a,
6535 MemOp mop, int mem_idx)
6537 ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w) | ISSIsWrite;
6538 TCGv_i32 addr, tmp;
6541 * In Thumb encodings of stores Rn=1111 is UNDEF; for Arm it
6542 * is either UNPREDICTABLE or has defined behaviour
6544 if (s->thumb && a->rn == 15) {
6545 return false;
6548 addr = op_addr_ri_pre(s, a);
6550 tmp = load_reg(s, a->rt);
6551 gen_aa32_st_i32(s, tmp, addr, mem_idx, mop);
6552 disas_set_da_iss(s, mop, issinfo);
6553 tcg_temp_free_i32(tmp);
6555 op_addr_ri_post(s, a, addr, 0);
6556 return true;
6559 static bool op_ldrd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
6561 int mem_idx = get_mem_index(s);
6562 TCGv_i32 addr, tmp;
6564 addr = op_addr_ri_pre(s, a);
6566 tmp = tcg_temp_new_i32();
6567 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
6568 store_reg(s, a->rt, tmp);
6570 tcg_gen_addi_i32(addr, addr, 4);
6572 tmp = tcg_temp_new_i32();
6573 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
6574 store_reg(s, rt2, tmp);
6576 /* LDRD w/ base writeback is undefined if the registers overlap. */
6577 op_addr_ri_post(s, a, addr, -4);
6578 return true;
6581 static bool trans_LDRD_ri_a32(DisasContext *s, arg_ldst_ri *a)
6583 if (!ENABLE_ARCH_5TE || (a->rt & 1)) {
6584 return false;
6586 return op_ldrd_ri(s, a, a->rt + 1);
6589 static bool trans_LDRD_ri_t32(DisasContext *s, arg_ldst_ri2 *a)
6591 arg_ldst_ri b = {
6592 .u = a->u, .w = a->w, .p = a->p,
6593 .rn = a->rn, .rt = a->rt, .imm = a->imm
6595 return op_ldrd_ri(s, &b, a->rt2);
6598 static bool op_strd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
6600 int mem_idx = get_mem_index(s);
6601 TCGv_i32 addr, tmp;
6603 addr = op_addr_ri_pre(s, a);
6605 tmp = load_reg(s, a->rt);
6606 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
6607 tcg_temp_free_i32(tmp);
6609 tcg_gen_addi_i32(addr, addr, 4);
6611 tmp = load_reg(s, rt2);
6612 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
6613 tcg_temp_free_i32(tmp);
6615 op_addr_ri_post(s, a, addr, -4);
6616 return true;
6619 static bool trans_STRD_ri_a32(DisasContext *s, arg_ldst_ri *a)
6621 if (!ENABLE_ARCH_5TE || (a->rt & 1)) {
6622 return false;
6624 return op_strd_ri(s, a, a->rt + 1);
6627 static bool trans_STRD_ri_t32(DisasContext *s, arg_ldst_ri2 *a)
6629 arg_ldst_ri b = {
6630 .u = a->u, .w = a->w, .p = a->p,
6631 .rn = a->rn, .rt = a->rt, .imm = a->imm
6633 return op_strd_ri(s, &b, a->rt2);
6636 #define DO_LDST(NAME, WHICH, MEMOP) \
6637 static bool trans_##NAME##_ri(DisasContext *s, arg_ldst_ri *a) \
6639 return op_##WHICH##_ri(s, a, MEMOP, get_mem_index(s)); \
6641 static bool trans_##NAME##T_ri(DisasContext *s, arg_ldst_ri *a) \
6643 return op_##WHICH##_ri(s, a, MEMOP, get_a32_user_mem_index(s)); \
6645 static bool trans_##NAME##_rr(DisasContext *s, arg_ldst_rr *a) \
6647 return op_##WHICH##_rr(s, a, MEMOP, get_mem_index(s)); \
6649 static bool trans_##NAME##T_rr(DisasContext *s, arg_ldst_rr *a) \
6651 return op_##WHICH##_rr(s, a, MEMOP, get_a32_user_mem_index(s)); \
6654 DO_LDST(LDR, load, MO_UL)
6655 DO_LDST(LDRB, load, MO_UB)
6656 DO_LDST(LDRH, load, MO_UW)
6657 DO_LDST(LDRSB, load, MO_SB)
6658 DO_LDST(LDRSH, load, MO_SW)
6660 DO_LDST(STR, store, MO_UL)
6661 DO_LDST(STRB, store, MO_UB)
6662 DO_LDST(STRH, store, MO_UW)
6664 #undef DO_LDST
6667 * Synchronization primitives
6670 static bool op_swp(DisasContext *s, arg_SWP *a, MemOp opc)
6672 TCGv_i32 addr, tmp;
6673 TCGv taddr;
6675 opc |= s->be_data;
6676 addr = load_reg(s, a->rn);
6677 taddr = gen_aa32_addr(s, addr, opc);
6678 tcg_temp_free_i32(addr);
6680 tmp = load_reg(s, a->rt2);
6681 tcg_gen_atomic_xchg_i32(tmp, taddr, tmp, get_mem_index(s), opc);
6682 tcg_temp_free(taddr);
6684 store_reg(s, a->rt, tmp);
6685 return true;
6688 static bool trans_SWP(DisasContext *s, arg_SWP *a)
6690 return op_swp(s, a, MO_UL | MO_ALIGN);
6693 static bool trans_SWPB(DisasContext *s, arg_SWP *a)
6695 return op_swp(s, a, MO_UB);
6699 * Load/Store Exclusive and Load-Acquire/Store-Release
6702 static bool op_strex(DisasContext *s, arg_STREX *a, MemOp mop, bool rel)
6704 TCGv_i32 addr;
6705 /* Some cases stopped being UNPREDICTABLE in v8A (but not v8M) */
6706 bool v8a = ENABLE_ARCH_8 && !arm_dc_feature(s, ARM_FEATURE_M);
6708 /* We UNDEF for these UNPREDICTABLE cases. */
6709 if (a->rd == 15 || a->rn == 15 || a->rt == 15
6710 || a->rd == a->rn || a->rd == a->rt
6711 || (!v8a && s->thumb && (a->rd == 13 || a->rt == 13))
6712 || (mop == MO_64
6713 && (a->rt2 == 15
6714 || a->rd == a->rt2
6715 || (!v8a && s->thumb && a->rt2 == 13)))) {
6716 unallocated_encoding(s);
6717 return true;
6720 if (rel) {
6721 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
6724 addr = tcg_temp_local_new_i32();
6725 load_reg_var(s, addr, a->rn);
6726 tcg_gen_addi_i32(addr, addr, a->imm);
6728 gen_store_exclusive(s, a->rd, a->rt, a->rt2, addr, mop);
6729 tcg_temp_free_i32(addr);
6730 return true;
6733 static bool trans_STREX(DisasContext *s, arg_STREX *a)
6735 if (!ENABLE_ARCH_6) {
6736 return false;
6738 return op_strex(s, a, MO_32, false);
6741 static bool trans_STREXD_a32(DisasContext *s, arg_STREX *a)
6743 if (!ENABLE_ARCH_6K) {
6744 return false;
6746 /* We UNDEF for these UNPREDICTABLE cases. */
6747 if (a->rt & 1) {
6748 unallocated_encoding(s);
6749 return true;
6751 a->rt2 = a->rt + 1;
6752 return op_strex(s, a, MO_64, false);
6755 static bool trans_STREXD_t32(DisasContext *s, arg_STREX *a)
6757 return op_strex(s, a, MO_64, false);
6760 static bool trans_STREXB(DisasContext *s, arg_STREX *a)
6762 if (s->thumb ? !ENABLE_ARCH_7 : !ENABLE_ARCH_6K) {
6763 return false;
6765 return op_strex(s, a, MO_8, false);
6768 static bool trans_STREXH(DisasContext *s, arg_STREX *a)
6770 if (s->thumb ? !ENABLE_ARCH_7 : !ENABLE_ARCH_6K) {
6771 return false;
6773 return op_strex(s, a, MO_16, false);
6776 static bool trans_STLEX(DisasContext *s, arg_STREX *a)
6778 if (!ENABLE_ARCH_8) {
6779 return false;
6781 return op_strex(s, a, MO_32, true);
6784 static bool trans_STLEXD_a32(DisasContext *s, arg_STREX *a)
6786 if (!ENABLE_ARCH_8) {
6787 return false;
6789 /* We UNDEF for these UNPREDICTABLE cases. */
6790 if (a->rt & 1) {
6791 unallocated_encoding(s);
6792 return true;
6794 a->rt2 = a->rt + 1;
6795 return op_strex(s, a, MO_64, true);
6798 static bool trans_STLEXD_t32(DisasContext *s, arg_STREX *a)
6800 if (!ENABLE_ARCH_8) {
6801 return false;
6803 return op_strex(s, a, MO_64, true);
6806 static bool trans_STLEXB(DisasContext *s, arg_STREX *a)
6808 if (!ENABLE_ARCH_8) {
6809 return false;
6811 return op_strex(s, a, MO_8, true);
6814 static bool trans_STLEXH(DisasContext *s, arg_STREX *a)
6816 if (!ENABLE_ARCH_8) {
6817 return false;
6819 return op_strex(s, a, MO_16, true);
6822 static bool op_stl(DisasContext *s, arg_STL *a, MemOp mop)
6824 TCGv_i32 addr, tmp;
6826 if (!ENABLE_ARCH_8) {
6827 return false;
6829 /* We UNDEF for these UNPREDICTABLE cases. */
6830 if (a->rn == 15 || a->rt == 15) {
6831 unallocated_encoding(s);
6832 return true;
6835 addr = load_reg(s, a->rn);
6836 tmp = load_reg(s, a->rt);
6837 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
6838 gen_aa32_st_i32(s, tmp, addr, get_mem_index(s), mop | MO_ALIGN);
6839 disas_set_da_iss(s, mop, a->rt | ISSIsAcqRel | ISSIsWrite);
6841 tcg_temp_free_i32(tmp);
6842 tcg_temp_free_i32(addr);
6843 return true;
6846 static bool trans_STL(DisasContext *s, arg_STL *a)
6848 return op_stl(s, a, MO_UL);
6851 static bool trans_STLB(DisasContext *s, arg_STL *a)
6853 return op_stl(s, a, MO_UB);
6856 static bool trans_STLH(DisasContext *s, arg_STL *a)
6858 return op_stl(s, a, MO_UW);
6861 static bool op_ldrex(DisasContext *s, arg_LDREX *a, MemOp mop, bool acq)
6863 TCGv_i32 addr;
6864 /* Some cases stopped being UNPREDICTABLE in v8A (but not v8M) */
6865 bool v8a = ENABLE_ARCH_8 && !arm_dc_feature(s, ARM_FEATURE_M);
6867 /* We UNDEF for these UNPREDICTABLE cases. */
6868 if (a->rn == 15 || a->rt == 15
6869 || (!v8a && s->thumb && a->rt == 13)
6870 || (mop == MO_64
6871 && (a->rt2 == 15 || a->rt == a->rt2
6872 || (!v8a && s->thumb && a->rt2 == 13)))) {
6873 unallocated_encoding(s);
6874 return true;
6877 addr = tcg_temp_local_new_i32();
6878 load_reg_var(s, addr, a->rn);
6879 tcg_gen_addi_i32(addr, addr, a->imm);
6881 gen_load_exclusive(s, a->rt, a->rt2, addr, mop);
6882 tcg_temp_free_i32(addr);
6884 if (acq) {
6885 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
6887 return true;
6890 static bool trans_LDREX(DisasContext *s, arg_LDREX *a)
6892 if (!ENABLE_ARCH_6) {
6893 return false;
6895 return op_ldrex(s, a, MO_32, false);
6898 static bool trans_LDREXD_a32(DisasContext *s, arg_LDREX *a)
6900 if (!ENABLE_ARCH_6K) {
6901 return false;
6903 /* We UNDEF for these UNPREDICTABLE cases. */
6904 if (a->rt & 1) {
6905 unallocated_encoding(s);
6906 return true;
6908 a->rt2 = a->rt + 1;
6909 return op_ldrex(s, a, MO_64, false);
6912 static bool trans_LDREXD_t32(DisasContext *s, arg_LDREX *a)
6914 return op_ldrex(s, a, MO_64, false);
6917 static bool trans_LDREXB(DisasContext *s, arg_LDREX *a)
6919 if (s->thumb ? !ENABLE_ARCH_7 : !ENABLE_ARCH_6K) {
6920 return false;
6922 return op_ldrex(s, a, MO_8, false);
6925 static bool trans_LDREXH(DisasContext *s, arg_LDREX *a)
6927 if (s->thumb ? !ENABLE_ARCH_7 : !ENABLE_ARCH_6K) {
6928 return false;
6930 return op_ldrex(s, a, MO_16, false);
6933 static bool trans_LDAEX(DisasContext *s, arg_LDREX *a)
6935 if (!ENABLE_ARCH_8) {
6936 return false;
6938 return op_ldrex(s, a, MO_32, true);
6941 static bool trans_LDAEXD_a32(DisasContext *s, arg_LDREX *a)
6943 if (!ENABLE_ARCH_8) {
6944 return false;
6946 /* We UNDEF for these UNPREDICTABLE cases. */
6947 if (a->rt & 1) {
6948 unallocated_encoding(s);
6949 return true;
6951 a->rt2 = a->rt + 1;
6952 return op_ldrex(s, a, MO_64, true);
6955 static bool trans_LDAEXD_t32(DisasContext *s, arg_LDREX *a)
6957 if (!ENABLE_ARCH_8) {
6958 return false;
6960 return op_ldrex(s, a, MO_64, true);
6963 static bool trans_LDAEXB(DisasContext *s, arg_LDREX *a)
6965 if (!ENABLE_ARCH_8) {
6966 return false;
6968 return op_ldrex(s, a, MO_8, true);
6971 static bool trans_LDAEXH(DisasContext *s, arg_LDREX *a)
6973 if (!ENABLE_ARCH_8) {
6974 return false;
6976 return op_ldrex(s, a, MO_16, true);
6979 static bool op_lda(DisasContext *s, arg_LDA *a, MemOp mop)
6981 TCGv_i32 addr, tmp;
6983 if (!ENABLE_ARCH_8) {
6984 return false;
6986 /* We UNDEF for these UNPREDICTABLE cases. */
6987 if (a->rn == 15 || a->rt == 15) {
6988 unallocated_encoding(s);
6989 return true;
6992 addr = load_reg(s, a->rn);
6993 tmp = tcg_temp_new_i32();
6994 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), mop | MO_ALIGN);
6995 disas_set_da_iss(s, mop, a->rt | ISSIsAcqRel);
6996 tcg_temp_free_i32(addr);
6998 store_reg(s, a->rt, tmp);
6999 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
7000 return true;
7003 static bool trans_LDA(DisasContext *s, arg_LDA *a)
7005 return op_lda(s, a, MO_UL);
7008 static bool trans_LDAB(DisasContext *s, arg_LDA *a)
7010 return op_lda(s, a, MO_UB);
7013 static bool trans_LDAH(DisasContext *s, arg_LDA *a)
7015 return op_lda(s, a, MO_UW);
7019 * Media instructions
7022 static bool trans_USADA8(DisasContext *s, arg_USADA8 *a)
7024 TCGv_i32 t1, t2;
7026 if (!ENABLE_ARCH_6) {
7027 return false;
7030 t1 = load_reg(s, a->rn);
7031 t2 = load_reg(s, a->rm);
7032 gen_helper_usad8(t1, t1, t2);
7033 tcg_temp_free_i32(t2);
7034 if (a->ra != 15) {
7035 t2 = load_reg(s, a->ra);
7036 tcg_gen_add_i32(t1, t1, t2);
7037 tcg_temp_free_i32(t2);
7039 store_reg(s, a->rd, t1);
7040 return true;
7043 static bool op_bfx(DisasContext *s, arg_UBFX *a, bool u)
7045 TCGv_i32 tmp;
7046 int width = a->widthm1 + 1;
7047 int shift = a->lsb;
7049 if (!ENABLE_ARCH_6T2) {
7050 return false;
7052 if (shift + width > 32) {
7053 /* UNPREDICTABLE; we choose to UNDEF */
7054 unallocated_encoding(s);
7055 return true;
7058 tmp = load_reg(s, a->rn);
7059 if (u) {
7060 tcg_gen_extract_i32(tmp, tmp, shift, width);
7061 } else {
7062 tcg_gen_sextract_i32(tmp, tmp, shift, width);
7064 store_reg(s, a->rd, tmp);
7065 return true;
7068 static bool trans_SBFX(DisasContext *s, arg_SBFX *a)
7070 return op_bfx(s, a, false);
7073 static bool trans_UBFX(DisasContext *s, arg_UBFX *a)
7075 return op_bfx(s, a, true);
7078 static bool trans_BFCI(DisasContext *s, arg_BFCI *a)
7080 TCGv_i32 tmp;
7081 int msb = a->msb, lsb = a->lsb;
7082 int width;
7084 if (!ENABLE_ARCH_6T2) {
7085 return false;
7087 if (msb < lsb) {
7088 /* UNPREDICTABLE; we choose to UNDEF */
7089 unallocated_encoding(s);
7090 return true;
7093 width = msb + 1 - lsb;
7094 if (a->rn == 15) {
7095 /* BFC */
7096 tmp = tcg_const_i32(0);
7097 } else {
7098 /* BFI */
7099 tmp = load_reg(s, a->rn);
7101 if (width != 32) {
7102 TCGv_i32 tmp2 = load_reg(s, a->rd);
7103 tcg_gen_deposit_i32(tmp, tmp2, tmp, lsb, width);
7104 tcg_temp_free_i32(tmp2);
7106 store_reg(s, a->rd, tmp);
7107 return true;
7110 static bool trans_UDF(DisasContext *s, arg_UDF *a)
7112 unallocated_encoding(s);
7113 return true;
7117 * Parallel addition and subtraction
7120 static bool op_par_addsub(DisasContext *s, arg_rrr *a,
7121 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32))
7123 TCGv_i32 t0, t1;
7125 if (s->thumb
7126 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
7127 : !ENABLE_ARCH_6) {
7128 return false;
7131 t0 = load_reg(s, a->rn);
7132 t1 = load_reg(s, a->rm);
7134 gen(t0, t0, t1);
7136 tcg_temp_free_i32(t1);
7137 store_reg(s, a->rd, t0);
7138 return true;
7141 static bool op_par_addsub_ge(DisasContext *s, arg_rrr *a,
7142 void (*gen)(TCGv_i32, TCGv_i32,
7143 TCGv_i32, TCGv_ptr))
7145 TCGv_i32 t0, t1;
7146 TCGv_ptr ge;
7148 if (s->thumb
7149 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
7150 : !ENABLE_ARCH_6) {
7151 return false;
7154 t0 = load_reg(s, a->rn);
7155 t1 = load_reg(s, a->rm);
7157 ge = tcg_temp_new_ptr();
7158 tcg_gen_addi_ptr(ge, cpu_env, offsetof(CPUARMState, GE));
7159 gen(t0, t0, t1, ge);
7161 tcg_temp_free_ptr(ge);
7162 tcg_temp_free_i32(t1);
7163 store_reg(s, a->rd, t0);
7164 return true;
7167 #define DO_PAR_ADDSUB(NAME, helper) \
7168 static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
7170 return op_par_addsub(s, a, helper); \
7173 #define DO_PAR_ADDSUB_GE(NAME, helper) \
7174 static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
7176 return op_par_addsub_ge(s, a, helper); \
7179 DO_PAR_ADDSUB_GE(SADD16, gen_helper_sadd16)
7180 DO_PAR_ADDSUB_GE(SASX, gen_helper_saddsubx)
7181 DO_PAR_ADDSUB_GE(SSAX, gen_helper_ssubaddx)
7182 DO_PAR_ADDSUB_GE(SSUB16, gen_helper_ssub16)
7183 DO_PAR_ADDSUB_GE(SADD8, gen_helper_sadd8)
7184 DO_PAR_ADDSUB_GE(SSUB8, gen_helper_ssub8)
7186 DO_PAR_ADDSUB_GE(UADD16, gen_helper_uadd16)
7187 DO_PAR_ADDSUB_GE(UASX, gen_helper_uaddsubx)
7188 DO_PAR_ADDSUB_GE(USAX, gen_helper_usubaddx)
7189 DO_PAR_ADDSUB_GE(USUB16, gen_helper_usub16)
7190 DO_PAR_ADDSUB_GE(UADD8, gen_helper_uadd8)
7191 DO_PAR_ADDSUB_GE(USUB8, gen_helper_usub8)
7193 DO_PAR_ADDSUB(QADD16, gen_helper_qadd16)
7194 DO_PAR_ADDSUB(QASX, gen_helper_qaddsubx)
7195 DO_PAR_ADDSUB(QSAX, gen_helper_qsubaddx)
7196 DO_PAR_ADDSUB(QSUB16, gen_helper_qsub16)
7197 DO_PAR_ADDSUB(QADD8, gen_helper_qadd8)
7198 DO_PAR_ADDSUB(QSUB8, gen_helper_qsub8)
7200 DO_PAR_ADDSUB(UQADD16, gen_helper_uqadd16)
7201 DO_PAR_ADDSUB(UQASX, gen_helper_uqaddsubx)
7202 DO_PAR_ADDSUB(UQSAX, gen_helper_uqsubaddx)
7203 DO_PAR_ADDSUB(UQSUB16, gen_helper_uqsub16)
7204 DO_PAR_ADDSUB(UQADD8, gen_helper_uqadd8)
7205 DO_PAR_ADDSUB(UQSUB8, gen_helper_uqsub8)
7207 DO_PAR_ADDSUB(SHADD16, gen_helper_shadd16)
7208 DO_PAR_ADDSUB(SHASX, gen_helper_shaddsubx)
7209 DO_PAR_ADDSUB(SHSAX, gen_helper_shsubaddx)
7210 DO_PAR_ADDSUB(SHSUB16, gen_helper_shsub16)
7211 DO_PAR_ADDSUB(SHADD8, gen_helper_shadd8)
7212 DO_PAR_ADDSUB(SHSUB8, gen_helper_shsub8)
7214 DO_PAR_ADDSUB(UHADD16, gen_helper_uhadd16)
7215 DO_PAR_ADDSUB(UHASX, gen_helper_uhaddsubx)
7216 DO_PAR_ADDSUB(UHSAX, gen_helper_uhsubaddx)
7217 DO_PAR_ADDSUB(UHSUB16, gen_helper_uhsub16)
7218 DO_PAR_ADDSUB(UHADD8, gen_helper_uhadd8)
7219 DO_PAR_ADDSUB(UHSUB8, gen_helper_uhsub8)
7221 #undef DO_PAR_ADDSUB
7222 #undef DO_PAR_ADDSUB_GE
7225 * Packing, unpacking, saturation, and reversal
7228 static bool trans_PKH(DisasContext *s, arg_PKH *a)
7230 TCGv_i32 tn, tm;
7231 int shift = a->imm;
7233 if (s->thumb
7234 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
7235 : !ENABLE_ARCH_6) {
7236 return false;
7239 tn = load_reg(s, a->rn);
7240 tm = load_reg(s, a->rm);
7241 if (a->tb) {
7242 /* PKHTB */
7243 if (shift == 0) {
7244 shift = 31;
7246 tcg_gen_sari_i32(tm, tm, shift);
7247 tcg_gen_deposit_i32(tn, tn, tm, 0, 16);
7248 } else {
7249 /* PKHBT */
7250 tcg_gen_shli_i32(tm, tm, shift);
7251 tcg_gen_deposit_i32(tn, tm, tn, 0, 16);
7253 tcg_temp_free_i32(tm);
7254 store_reg(s, a->rd, tn);
7255 return true;
7258 static bool op_sat(DisasContext *s, arg_sat *a,
7259 void (*gen)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32))
7261 TCGv_i32 tmp, satimm;
7262 int shift = a->imm;
7264 if (!ENABLE_ARCH_6) {
7265 return false;
7268 tmp = load_reg(s, a->rn);
7269 if (a->sh) {
7270 tcg_gen_sari_i32(tmp, tmp, shift ? shift : 31);
7271 } else {
7272 tcg_gen_shli_i32(tmp, tmp, shift);
7275 satimm = tcg_const_i32(a->satimm);
7276 gen(tmp, cpu_env, tmp, satimm);
7277 tcg_temp_free_i32(satimm);
7279 store_reg(s, a->rd, tmp);
7280 return true;
7283 static bool trans_SSAT(DisasContext *s, arg_sat *a)
7285 return op_sat(s, a, gen_helper_ssat);
7288 static bool trans_USAT(DisasContext *s, arg_sat *a)
7290 return op_sat(s, a, gen_helper_usat);
7293 static bool trans_SSAT16(DisasContext *s, arg_sat *a)
7295 if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
7296 return false;
7298 return op_sat(s, a, gen_helper_ssat16);
7301 static bool trans_USAT16(DisasContext *s, arg_sat *a)
7303 if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
7304 return false;
7306 return op_sat(s, a, gen_helper_usat16);
7309 static bool op_xta(DisasContext *s, arg_rrr_rot *a,
7310 void (*gen_extract)(TCGv_i32, TCGv_i32),
7311 void (*gen_add)(TCGv_i32, TCGv_i32, TCGv_i32))
7313 TCGv_i32 tmp;
7315 if (!ENABLE_ARCH_6) {
7316 return false;
7319 tmp = load_reg(s, a->rm);
7321 * TODO: In many cases we could do a shift instead of a rotate.
7322 * Combined with a simple extend, that becomes an extract.
7324 tcg_gen_rotri_i32(tmp, tmp, a->rot * 8);
7325 gen_extract(tmp, tmp);
7327 if (a->rn != 15) {
7328 TCGv_i32 tmp2 = load_reg(s, a->rn);
7329 gen_add(tmp, tmp, tmp2);
7330 tcg_temp_free_i32(tmp2);
7332 store_reg(s, a->rd, tmp);
7333 return true;
7336 static bool trans_SXTAB(DisasContext *s, arg_rrr_rot *a)
7338 return op_xta(s, a, tcg_gen_ext8s_i32, tcg_gen_add_i32);
7341 static bool trans_SXTAH(DisasContext *s, arg_rrr_rot *a)
7343 return op_xta(s, a, tcg_gen_ext16s_i32, tcg_gen_add_i32);
7346 static bool trans_SXTAB16(DisasContext *s, arg_rrr_rot *a)
7348 if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
7349 return false;
7351 return op_xta(s, a, gen_helper_sxtb16, gen_add16);
7354 static bool trans_UXTAB(DisasContext *s, arg_rrr_rot *a)
7356 return op_xta(s, a, tcg_gen_ext8u_i32, tcg_gen_add_i32);
7359 static bool trans_UXTAH(DisasContext *s, arg_rrr_rot *a)
7361 return op_xta(s, a, tcg_gen_ext16u_i32, tcg_gen_add_i32);
7364 static bool trans_UXTAB16(DisasContext *s, arg_rrr_rot *a)
7366 if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
7367 return false;
7369 return op_xta(s, a, gen_helper_uxtb16, gen_add16);
7372 static bool trans_SEL(DisasContext *s, arg_rrr *a)
7374 TCGv_i32 t1, t2, t3;
7376 if (s->thumb
7377 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
7378 : !ENABLE_ARCH_6) {
7379 return false;
7382 t1 = load_reg(s, a->rn);
7383 t2 = load_reg(s, a->rm);
7384 t3 = tcg_temp_new_i32();
7385 tcg_gen_ld_i32(t3, cpu_env, offsetof(CPUARMState, GE));
7386 gen_helper_sel_flags(t1, t3, t1, t2);
7387 tcg_temp_free_i32(t3);
7388 tcg_temp_free_i32(t2);
7389 store_reg(s, a->rd, t1);
7390 return true;
7393 static bool op_rr(DisasContext *s, arg_rr *a,
7394 void (*gen)(TCGv_i32, TCGv_i32))
7396 TCGv_i32 tmp;
7398 tmp = load_reg(s, a->rm);
7399 gen(tmp, tmp);
7400 store_reg(s, a->rd, tmp);
7401 return true;
7404 static bool trans_REV(DisasContext *s, arg_rr *a)
7406 if (!ENABLE_ARCH_6) {
7407 return false;
7409 return op_rr(s, a, tcg_gen_bswap32_i32);
7412 static bool trans_REV16(DisasContext *s, arg_rr *a)
7414 if (!ENABLE_ARCH_6) {
7415 return false;
7417 return op_rr(s, a, gen_rev16);
7420 static bool trans_REVSH(DisasContext *s, arg_rr *a)
7422 if (!ENABLE_ARCH_6) {
7423 return false;
7425 return op_rr(s, a, gen_revsh);
7428 static bool trans_RBIT(DisasContext *s, arg_rr *a)
7430 if (!ENABLE_ARCH_6T2) {
7431 return false;
7433 return op_rr(s, a, gen_helper_rbit);
7437 * Signed multiply, signed and unsigned divide
7440 static bool op_smlad(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub)
7442 TCGv_i32 t1, t2;
7444 if (!ENABLE_ARCH_6) {
7445 return false;
7448 t1 = load_reg(s, a->rn);
7449 t2 = load_reg(s, a->rm);
7450 if (m_swap) {
7451 gen_swap_half(t2, t2);
7453 gen_smul_dual(t1, t2);
7455 if (sub) {
7457 * This subtraction cannot overflow, so we can do a simple
7458 * 32-bit subtraction and then a possible 32-bit saturating
7459 * addition of Ra.
7461 tcg_gen_sub_i32(t1, t1, t2);
7462 tcg_temp_free_i32(t2);
7464 if (a->ra != 15) {
7465 t2 = load_reg(s, a->ra);
7466 gen_helper_add_setq(t1, cpu_env, t1, t2);
7467 tcg_temp_free_i32(t2);
7469 } else if (a->ra == 15) {
7470 /* Single saturation-checking addition */
7471 gen_helper_add_setq(t1, cpu_env, t1, t2);
7472 tcg_temp_free_i32(t2);
7473 } else {
7475 * We need to add the products and Ra together and then
7476 * determine whether the final result overflowed. Doing
7477 * this as two separate add-and-check-overflow steps incorrectly
7478 * sets Q for cases like (-32768 * -32768) + (-32768 * -32768) + -1.
7479 * Do all the arithmetic at 64-bits and then check for overflow.
7481 TCGv_i64 p64, q64;
7482 TCGv_i32 t3, qf, one;
7484 p64 = tcg_temp_new_i64();
7485 q64 = tcg_temp_new_i64();
7486 tcg_gen_ext_i32_i64(p64, t1);
7487 tcg_gen_ext_i32_i64(q64, t2);
7488 tcg_gen_add_i64(p64, p64, q64);
7489 load_reg_var(s, t2, a->ra);
7490 tcg_gen_ext_i32_i64(q64, t2);
7491 tcg_gen_add_i64(p64, p64, q64);
7492 tcg_temp_free_i64(q64);
7494 tcg_gen_extr_i64_i32(t1, t2, p64);
7495 tcg_temp_free_i64(p64);
7497 * t1 is the low half of the result which goes into Rd.
7498 * We have overflow and must set Q if the high half (t2)
7499 * is different from the sign-extension of t1.
7501 t3 = tcg_temp_new_i32();
7502 tcg_gen_sari_i32(t3, t1, 31);
7503 qf = load_cpu_field(QF);
7504 one = tcg_const_i32(1);
7505 tcg_gen_movcond_i32(TCG_COND_NE, qf, t2, t3, one, qf);
7506 store_cpu_field(qf, QF);
7507 tcg_temp_free_i32(one);
7508 tcg_temp_free_i32(t3);
7509 tcg_temp_free_i32(t2);
7511 store_reg(s, a->rd, t1);
7512 return true;
7515 static bool trans_SMLAD(DisasContext *s, arg_rrrr *a)
7517 return op_smlad(s, a, false, false);
7520 static bool trans_SMLADX(DisasContext *s, arg_rrrr *a)
7522 return op_smlad(s, a, true, false);
7525 static bool trans_SMLSD(DisasContext *s, arg_rrrr *a)
7527 return op_smlad(s, a, false, true);
7530 static bool trans_SMLSDX(DisasContext *s, arg_rrrr *a)
7532 return op_smlad(s, a, true, true);
7535 static bool op_smlald(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub)
7537 TCGv_i32 t1, t2;
7538 TCGv_i64 l1, l2;
7540 if (!ENABLE_ARCH_6) {
7541 return false;
7544 t1 = load_reg(s, a->rn);
7545 t2 = load_reg(s, a->rm);
7546 if (m_swap) {
7547 gen_swap_half(t2, t2);
7549 gen_smul_dual(t1, t2);
7551 l1 = tcg_temp_new_i64();
7552 l2 = tcg_temp_new_i64();
7553 tcg_gen_ext_i32_i64(l1, t1);
7554 tcg_gen_ext_i32_i64(l2, t2);
7555 tcg_temp_free_i32(t1);
7556 tcg_temp_free_i32(t2);
7558 if (sub) {
7559 tcg_gen_sub_i64(l1, l1, l2);
7560 } else {
7561 tcg_gen_add_i64(l1, l1, l2);
7563 tcg_temp_free_i64(l2);
7565 gen_addq(s, l1, a->ra, a->rd);
7566 gen_storeq_reg(s, a->ra, a->rd, l1);
7567 tcg_temp_free_i64(l1);
7568 return true;
7571 static bool trans_SMLALD(DisasContext *s, arg_rrrr *a)
7573 return op_smlald(s, a, false, false);
7576 static bool trans_SMLALDX(DisasContext *s, arg_rrrr *a)
7578 return op_smlald(s, a, true, false);
7581 static bool trans_SMLSLD(DisasContext *s, arg_rrrr *a)
7583 return op_smlald(s, a, false, true);
7586 static bool trans_SMLSLDX(DisasContext *s, arg_rrrr *a)
7588 return op_smlald(s, a, true, true);
7591 static bool op_smmla(DisasContext *s, arg_rrrr *a, bool round, bool sub)
7593 TCGv_i32 t1, t2;
7595 if (s->thumb
7596 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
7597 : !ENABLE_ARCH_6) {
7598 return false;
7601 t1 = load_reg(s, a->rn);
7602 t2 = load_reg(s, a->rm);
7603 tcg_gen_muls2_i32(t2, t1, t1, t2);
7605 if (a->ra != 15) {
7606 TCGv_i32 t3 = load_reg(s, a->ra);
7607 if (sub) {
7609 * For SMMLS, we need a 64-bit subtract. Borrow caused by
7610 * a non-zero multiplicand lowpart, and the correct result
7611 * lowpart for rounding.
7613 TCGv_i32 zero = tcg_const_i32(0);
7614 tcg_gen_sub2_i32(t2, t1, zero, t3, t2, t1);
7615 tcg_temp_free_i32(zero);
7616 } else {
7617 tcg_gen_add_i32(t1, t1, t3);
7619 tcg_temp_free_i32(t3);
7621 if (round) {
7623 * Adding 0x80000000 to the 64-bit quantity means that we have
7624 * carry in to the high word when the low word has the msb set.
7626 tcg_gen_shri_i32(t2, t2, 31);
7627 tcg_gen_add_i32(t1, t1, t2);
7629 tcg_temp_free_i32(t2);
7630 store_reg(s, a->rd, t1);
7631 return true;
7634 static bool trans_SMMLA(DisasContext *s, arg_rrrr *a)
7636 return op_smmla(s, a, false, false);
7639 static bool trans_SMMLAR(DisasContext *s, arg_rrrr *a)
7641 return op_smmla(s, a, true, false);
7644 static bool trans_SMMLS(DisasContext *s, arg_rrrr *a)
7646 return op_smmla(s, a, false, true);
7649 static bool trans_SMMLSR(DisasContext *s, arg_rrrr *a)
7651 return op_smmla(s, a, true, true);
7654 static bool op_div(DisasContext *s, arg_rrr *a, bool u)
7656 TCGv_i32 t1, t2;
7658 if (s->thumb
7659 ? !dc_isar_feature(aa32_thumb_div, s)
7660 : !dc_isar_feature(aa32_arm_div, s)) {
7661 return false;
7664 t1 = load_reg(s, a->rn);
7665 t2 = load_reg(s, a->rm);
7666 if (u) {
7667 gen_helper_udiv(t1, t1, t2);
7668 } else {
7669 gen_helper_sdiv(t1, t1, t2);
7671 tcg_temp_free_i32(t2);
7672 store_reg(s, a->rd, t1);
7673 return true;
7676 static bool trans_SDIV(DisasContext *s, arg_rrr *a)
7678 return op_div(s, a, false);
7681 static bool trans_UDIV(DisasContext *s, arg_rrr *a)
7683 return op_div(s, a, true);
7687 * Block data transfer
7690 static TCGv_i32 op_addr_block_pre(DisasContext *s, arg_ldst_block *a, int n)
7692 TCGv_i32 addr = load_reg(s, a->rn);
7694 if (a->b) {
7695 if (a->i) {
7696 /* pre increment */
7697 tcg_gen_addi_i32(addr, addr, 4);
7698 } else {
7699 /* pre decrement */
7700 tcg_gen_addi_i32(addr, addr, -(n * 4));
7702 } else if (!a->i && n != 1) {
7703 /* post decrement */
7704 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7707 if (s->v8m_stackcheck && a->rn == 13 && a->w) {
7709 * If the writeback is incrementing SP rather than
7710 * decrementing it, and the initial SP is below the
7711 * stack limit but the final written-back SP would
7712 * be above, then then we must not perform any memory
7713 * accesses, but it is IMPDEF whether we generate
7714 * an exception. We choose to do so in this case.
7715 * At this point 'addr' is the lowest address, so
7716 * either the original SP (if incrementing) or our
7717 * final SP (if decrementing), so that's what we check.
7719 gen_helper_v8m_stackcheck(cpu_env, addr);
7722 return addr;
7725 static void op_addr_block_post(DisasContext *s, arg_ldst_block *a,
7726 TCGv_i32 addr, int n)
7728 if (a->w) {
7729 /* write back */
7730 if (!a->b) {
7731 if (a->i) {
7732 /* post increment */
7733 tcg_gen_addi_i32(addr, addr, 4);
7734 } else {
7735 /* post decrement */
7736 tcg_gen_addi_i32(addr, addr, -(n * 4));
7738 } else if (!a->i && n != 1) {
7739 /* pre decrement */
7740 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7742 store_reg(s, a->rn, addr);
7743 } else {
7744 tcg_temp_free_i32(addr);
7748 static bool op_stm(DisasContext *s, arg_ldst_block *a, int min_n)
7750 int i, j, n, list, mem_idx;
7751 bool user = a->u;
7752 TCGv_i32 addr, tmp, tmp2;
7754 if (user) {
7755 /* STM (user) */
7756 if (IS_USER(s)) {
7757 /* Only usable in supervisor mode. */
7758 unallocated_encoding(s);
7759 return true;
7763 list = a->list;
7764 n = ctpop16(list);
7765 if (n < min_n || a->rn == 15) {
7766 unallocated_encoding(s);
7767 return true;
7770 addr = op_addr_block_pre(s, a, n);
7771 mem_idx = get_mem_index(s);
7773 for (i = j = 0; i < 16; i++) {
7774 if (!(list & (1 << i))) {
7775 continue;
7778 if (user && i != 15) {
7779 tmp = tcg_temp_new_i32();
7780 tmp2 = tcg_const_i32(i);
7781 gen_helper_get_user_reg(tmp, cpu_env, tmp2);
7782 tcg_temp_free_i32(tmp2);
7783 } else {
7784 tmp = load_reg(s, i);
7786 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
7787 tcg_temp_free_i32(tmp);
7789 /* No need to add after the last transfer. */
7790 if (++j != n) {
7791 tcg_gen_addi_i32(addr, addr, 4);
7795 op_addr_block_post(s, a, addr, n);
7796 return true;
7799 static bool trans_STM(DisasContext *s, arg_ldst_block *a)
7801 /* BitCount(list) < 1 is UNPREDICTABLE */
7802 return op_stm(s, a, 1);
7805 static bool trans_STM_t32(DisasContext *s, arg_ldst_block *a)
7807 /* Writeback register in register list is UNPREDICTABLE for T32. */
7808 if (a->w && (a->list & (1 << a->rn))) {
7809 unallocated_encoding(s);
7810 return true;
7812 /* BitCount(list) < 2 is UNPREDICTABLE */
7813 return op_stm(s, a, 2);
7816 static bool do_ldm(DisasContext *s, arg_ldst_block *a, int min_n)
7818 int i, j, n, list, mem_idx;
7819 bool loaded_base;
7820 bool user = a->u;
7821 bool exc_return = false;
7822 TCGv_i32 addr, tmp, tmp2, loaded_var;
7824 if (user) {
7825 /* LDM (user), LDM (exception return) */
7826 if (IS_USER(s)) {
7827 /* Only usable in supervisor mode. */
7828 unallocated_encoding(s);
7829 return true;
7831 if (extract32(a->list, 15, 1)) {
7832 exc_return = true;
7833 user = false;
7834 } else {
7835 /* LDM (user) does not allow writeback. */
7836 if (a->w) {
7837 unallocated_encoding(s);
7838 return true;
7843 list = a->list;
7844 n = ctpop16(list);
7845 if (n < min_n || a->rn == 15) {
7846 unallocated_encoding(s);
7847 return true;
7850 addr = op_addr_block_pre(s, a, n);
7851 mem_idx = get_mem_index(s);
7852 loaded_base = false;
7853 loaded_var = NULL;
7855 for (i = j = 0; i < 16; i++) {
7856 if (!(list & (1 << i))) {
7857 continue;
7860 tmp = tcg_temp_new_i32();
7861 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
7862 if (user) {
7863 tmp2 = tcg_const_i32(i);
7864 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
7865 tcg_temp_free_i32(tmp2);
7866 tcg_temp_free_i32(tmp);
7867 } else if (i == a->rn) {
7868 loaded_var = tmp;
7869 loaded_base = true;
7870 } else if (i == 15 && exc_return) {
7871 store_pc_exc_ret(s, tmp);
7872 } else {
7873 store_reg_from_load(s, i, tmp);
7876 /* No need to add after the last transfer. */
7877 if (++j != n) {
7878 tcg_gen_addi_i32(addr, addr, 4);
7882 op_addr_block_post(s, a, addr, n);
7884 if (loaded_base) {
7885 /* Note that we reject base == pc above. */
7886 store_reg(s, a->rn, loaded_var);
7889 if (exc_return) {
7890 /* Restore CPSR from SPSR. */
7891 tmp = load_cpu_field(spsr);
7892 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
7893 gen_io_start();
7895 gen_helper_cpsr_write_eret(cpu_env, tmp);
7896 tcg_temp_free_i32(tmp);
7897 /* Must exit loop to check un-masked IRQs */
7898 s->base.is_jmp = DISAS_EXIT;
7900 return true;
7903 static bool trans_LDM_a32(DisasContext *s, arg_ldst_block *a)
7906 * Writeback register in register list is UNPREDICTABLE
7907 * for ArchVersion() >= 7. Prior to v7, A32 would write
7908 * an UNKNOWN value to the base register.
7910 if (ENABLE_ARCH_7 && a->w && (a->list & (1 << a->rn))) {
7911 unallocated_encoding(s);
7912 return true;
7914 /* BitCount(list) < 1 is UNPREDICTABLE */
7915 return do_ldm(s, a, 1);
7918 static bool trans_LDM_t32(DisasContext *s, arg_ldst_block *a)
7920 /* Writeback register in register list is UNPREDICTABLE for T32. */
7921 if (a->w && (a->list & (1 << a->rn))) {
7922 unallocated_encoding(s);
7923 return true;
7925 /* BitCount(list) < 2 is UNPREDICTABLE */
7926 return do_ldm(s, a, 2);
7929 static bool trans_LDM_t16(DisasContext *s, arg_ldst_block *a)
7931 /* Writeback is conditional on the base register not being loaded. */
7932 a->w = !(a->list & (1 << a->rn));
7933 /* BitCount(list) < 1 is UNPREDICTABLE */
7934 return do_ldm(s, a, 1);
7937 static bool trans_CLRM(DisasContext *s, arg_CLRM *a)
7939 int i;
7940 TCGv_i32 zero;
7942 if (!dc_isar_feature(aa32_m_sec_state, s)) {
7943 return false;
7946 if (extract32(a->list, 13, 1)) {
7947 return false;
7950 if (!a->list) {
7951 /* UNPREDICTABLE; we choose to UNDEF */
7952 return false;
7955 zero = tcg_const_i32(0);
7956 for (i = 0; i < 15; i++) {
7957 if (extract32(a->list, i, 1)) {
7958 /* Clear R[i] */
7959 tcg_gen_mov_i32(cpu_R[i], zero);
7962 if (extract32(a->list, 15, 1)) {
7964 * Clear APSR (by calling the MSR helper with the same argument
7965 * as for "MSR APSR_nzcvqg, Rn": mask = 0b1100, SYSM=0)
7967 TCGv_i32 maskreg = tcg_const_i32(0xc << 8);
7968 gen_helper_v7m_msr(cpu_env, maskreg, zero);
7969 tcg_temp_free_i32(maskreg);
7971 tcg_temp_free_i32(zero);
7972 return true;
7976 * Branch, branch with link
7979 static bool trans_B(DisasContext *s, arg_i *a)
7981 gen_jmp(s, read_pc(s) + a->imm);
7982 return true;
7985 static bool trans_B_cond_thumb(DisasContext *s, arg_ci *a)
7987 /* This has cond from encoding, required to be outside IT block. */
7988 if (a->cond >= 0xe) {
7989 return false;
7991 if (s->condexec_mask) {
7992 unallocated_encoding(s);
7993 return true;
7995 arm_skip_unless(s, a->cond);
7996 gen_jmp(s, read_pc(s) + a->imm);
7997 return true;
8000 static bool trans_BL(DisasContext *s, arg_i *a)
8002 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
8003 gen_jmp(s, read_pc(s) + a->imm);
8004 return true;
8007 static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
8009 TCGv_i32 tmp;
8012 * BLX <imm> would be useless on M-profile; the encoding space
8013 * is used for other insns from v8.1M onward, and UNDEFs before that.
8015 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8016 return false;
8019 /* For A32, ARM_FEATURE_V5 is checked near the start of the uncond block. */
8020 if (s->thumb && (a->imm & 2)) {
8021 return false;
8023 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
8024 tmp = tcg_const_i32(!s->thumb);
8025 store_cpu_field(tmp, thumb);
8026 gen_jmp(s, (read_pc(s) & ~3) + a->imm);
8027 return true;
8030 static bool trans_BL_BLX_prefix(DisasContext *s, arg_BL_BLX_prefix *a)
8032 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
8033 tcg_gen_movi_i32(cpu_R[14], read_pc(s) + (a->imm << 12));
8034 return true;
8037 static bool trans_BL_suffix(DisasContext *s, arg_BL_suffix *a)
8039 TCGv_i32 tmp = tcg_temp_new_i32();
8041 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
8042 tcg_gen_addi_i32(tmp, cpu_R[14], (a->imm << 1) | 1);
8043 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | 1);
8044 gen_bx(s, tmp);
8045 return true;
8048 static bool trans_BLX_suffix(DisasContext *s, arg_BLX_suffix *a)
8050 TCGv_i32 tmp;
8052 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
8053 if (!ENABLE_ARCH_5) {
8054 return false;
8056 tmp = tcg_temp_new_i32();
8057 tcg_gen_addi_i32(tmp, cpu_R[14], a->imm << 1);
8058 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
8059 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | 1);
8060 gen_bx(s, tmp);
8061 return true;
8064 static bool trans_BF(DisasContext *s, arg_BF *a)
8067 * M-profile branch future insns. The architecture permits an
8068 * implementation to implement these as NOPs (equivalent to
8069 * discarding the LO_BRANCH_INFO cache immediately), and we
8070 * take that IMPDEF option because for QEMU a "real" implementation
8071 * would be complicated and wouldn't execute any faster.
8073 if (!dc_isar_feature(aa32_lob, s)) {
8074 return false;
8076 if (a->boff == 0) {
8077 /* SEE "Related encodings" (loop insns) */
8078 return false;
8080 /* Handle as NOP */
8081 return true;
8084 static bool trans_DLS(DisasContext *s, arg_DLS *a)
8086 /* M-profile low-overhead loop start */
8087 TCGv_i32 tmp;
8089 if (!dc_isar_feature(aa32_lob, s)) {
8090 return false;
8092 if (a->rn == 13 || a->rn == 15) {
8093 /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
8094 return false;
8097 /* Not a while loop, no tail predication: just set LR to the count */
8098 tmp = load_reg(s, a->rn);
8099 store_reg(s, 14, tmp);
8100 return true;
8103 static bool trans_WLS(DisasContext *s, arg_WLS *a)
8105 /* M-profile low-overhead while-loop start */
8106 TCGv_i32 tmp;
8107 TCGLabel *nextlabel;
8109 if (!dc_isar_feature(aa32_lob, s)) {
8110 return false;
8112 if (a->rn == 13 || a->rn == 15) {
8113 /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
8114 return false;
8116 if (s->condexec_mask) {
8118 * WLS in an IT block is CONSTRAINED UNPREDICTABLE;
8119 * we choose to UNDEF, because otherwise our use of
8120 * gen_goto_tb(1) would clash with the use of TB exit 1
8121 * in the dc->condjmp condition-failed codepath in
8122 * arm_tr_tb_stop() and we'd get an assertion.
8124 return false;
8126 nextlabel = gen_new_label();
8127 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_R[a->rn], 0, nextlabel);
8128 tmp = load_reg(s, a->rn);
8129 store_reg(s, 14, tmp);
8130 gen_jmp_tb(s, s->base.pc_next, 1);
8132 gen_set_label(nextlabel);
8133 gen_jmp(s, read_pc(s) + a->imm);
8134 return true;
8137 static bool trans_LE(DisasContext *s, arg_LE *a)
8140 * M-profile low-overhead loop end. The architecture permits an
8141 * implementation to discard the LO_BRANCH_INFO cache at any time,
8142 * and we take the IMPDEF option to never set it in the first place
8143 * (equivalent to always discarding it immediately), because for QEMU
8144 * a "real" implementation would be complicated and wouldn't execute
8145 * any faster.
8147 TCGv_i32 tmp;
8149 if (!dc_isar_feature(aa32_lob, s)) {
8150 return false;
8153 if (!a->f) {
8154 /* Not loop-forever. If LR <= 1 this is the last loop: do nothing. */
8155 arm_gen_condlabel(s);
8156 tcg_gen_brcondi_i32(TCG_COND_LEU, cpu_R[14], 1, s->condlabel);
8157 /* Decrement LR */
8158 tmp = load_reg(s, 14);
8159 tcg_gen_addi_i32(tmp, tmp, -1);
8160 store_reg(s, 14, tmp);
8162 /* Jump back to the loop start */
8163 gen_jmp(s, read_pc(s) - a->imm);
8164 return true;
8167 static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
8169 TCGv_i32 addr, tmp;
8171 tmp = load_reg(s, a->rm);
8172 if (half) {
8173 tcg_gen_add_i32(tmp, tmp, tmp);
8175 addr = load_reg(s, a->rn);
8176 tcg_gen_add_i32(addr, addr, tmp);
8178 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), half ? MO_UW : MO_UB);
8179 tcg_temp_free_i32(addr);
8181 tcg_gen_add_i32(tmp, tmp, tmp);
8182 tcg_gen_addi_i32(tmp, tmp, read_pc(s));
8183 store_reg(s, 15, tmp);
8184 return true;
8187 static bool trans_TBB(DisasContext *s, arg_tbranch *a)
8189 return op_tbranch(s, a, false);
8192 static bool trans_TBH(DisasContext *s, arg_tbranch *a)
8194 return op_tbranch(s, a, true);
8197 static bool trans_CBZ(DisasContext *s, arg_CBZ *a)
8199 TCGv_i32 tmp = load_reg(s, a->rn);
8201 arm_gen_condlabel(s);
8202 tcg_gen_brcondi_i32(a->nz ? TCG_COND_EQ : TCG_COND_NE,
8203 tmp, 0, s->condlabel);
8204 tcg_temp_free_i32(tmp);
8205 gen_jmp(s, read_pc(s) + a->imm);
8206 return true;
8210 * Supervisor call - both T32 & A32 come here so we need to check
8211 * which mode we are in when checking for semihosting.
8214 static bool trans_SVC(DisasContext *s, arg_SVC *a)
8216 const uint32_t semihost_imm = s->thumb ? 0xab : 0x123456;
8218 if (!arm_dc_feature(s, ARM_FEATURE_M) && semihosting_enabled() &&
8219 #ifndef CONFIG_USER_ONLY
8220 !IS_USER(s) &&
8221 #endif
8222 (a->imm == semihost_imm)) {
8223 gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
8224 } else {
8225 gen_set_pc_im(s, s->base.pc_next);
8226 s->svc_imm = a->imm;
8227 s->base.is_jmp = DISAS_SWI;
8229 return true;
8233 * Unconditional system instructions
8236 static bool trans_RFE(DisasContext *s, arg_RFE *a)
8238 static const int8_t pre_offset[4] = {
8239 /* DA */ -4, /* IA */ 0, /* DB */ -8, /* IB */ 4
8241 static const int8_t post_offset[4] = {
8242 /* DA */ -8, /* IA */ 4, /* DB */ -4, /* IB */ 0
8244 TCGv_i32 addr, t1, t2;
8246 if (!ENABLE_ARCH_6 || arm_dc_feature(s, ARM_FEATURE_M)) {
8247 return false;
8249 if (IS_USER(s)) {
8250 unallocated_encoding(s);
8251 return true;
8254 addr = load_reg(s, a->rn);
8255 tcg_gen_addi_i32(addr, addr, pre_offset[a->pu]);
8257 /* Load PC into tmp and CPSR into tmp2. */
8258 t1 = tcg_temp_new_i32();
8259 gen_aa32_ld_i32(s, t1, addr, get_mem_index(s), MO_UL | MO_ALIGN);
8260 tcg_gen_addi_i32(addr, addr, 4);
8261 t2 = tcg_temp_new_i32();
8262 gen_aa32_ld_i32(s, t2, addr, get_mem_index(s), MO_UL | MO_ALIGN);
8264 if (a->w) {
8265 /* Base writeback. */
8266 tcg_gen_addi_i32(addr, addr, post_offset[a->pu]);
8267 store_reg(s, a->rn, addr);
8268 } else {
8269 tcg_temp_free_i32(addr);
8271 gen_rfe(s, t1, t2);
8272 return true;
8275 static bool trans_SRS(DisasContext *s, arg_SRS *a)
8277 if (!ENABLE_ARCH_6 || arm_dc_feature(s, ARM_FEATURE_M)) {
8278 return false;
8280 gen_srs(s, a->mode, a->pu, a->w);
8281 return true;
8284 static bool trans_CPS(DisasContext *s, arg_CPS *a)
8286 uint32_t mask, val;
8288 if (!ENABLE_ARCH_6 || arm_dc_feature(s, ARM_FEATURE_M)) {
8289 return false;
8291 if (IS_USER(s)) {
8292 /* Implemented as NOP in user mode. */
8293 return true;
8295 /* TODO: There are quite a lot of UNPREDICTABLE argument combinations. */
8297 mask = val = 0;
8298 if (a->imod & 2) {
8299 if (a->A) {
8300 mask |= CPSR_A;
8302 if (a->I) {
8303 mask |= CPSR_I;
8305 if (a->F) {
8306 mask |= CPSR_F;
8308 if (a->imod & 1) {
8309 val |= mask;
8312 if (a->M) {
8313 mask |= CPSR_M;
8314 val |= a->mode;
8316 if (mask) {
8317 gen_set_psr_im(s, mask, 0, val);
8319 return true;
8322 static bool trans_CPS_v7m(DisasContext *s, arg_CPS_v7m *a)
8324 TCGv_i32 tmp, addr, el;
8326 if (!arm_dc_feature(s, ARM_FEATURE_M)) {
8327 return false;
8329 if (IS_USER(s)) {
8330 /* Implemented as NOP in user mode. */
8331 return true;
8334 tmp = tcg_const_i32(a->im);
8335 /* FAULTMASK */
8336 if (a->F) {
8337 addr = tcg_const_i32(19);
8338 gen_helper_v7m_msr(cpu_env, addr, tmp);
8339 tcg_temp_free_i32(addr);
8341 /* PRIMASK */
8342 if (a->I) {
8343 addr = tcg_const_i32(16);
8344 gen_helper_v7m_msr(cpu_env, addr, tmp);
8345 tcg_temp_free_i32(addr);
8347 el = tcg_const_i32(s->current_el);
8348 gen_helper_rebuild_hflags_m32(cpu_env, el);
8349 tcg_temp_free_i32(el);
8350 tcg_temp_free_i32(tmp);
8351 gen_lookup_tb(s);
8352 return true;
8356 * Clear-Exclusive, Barriers
8359 static bool trans_CLREX(DisasContext *s, arg_CLREX *a)
8361 if (s->thumb
8362 ? !ENABLE_ARCH_7 && !arm_dc_feature(s, ARM_FEATURE_M)
8363 : !ENABLE_ARCH_6K) {
8364 return false;
8366 gen_clrex(s);
8367 return true;
8370 static bool trans_DSB(DisasContext *s, arg_DSB *a)
8372 if (!ENABLE_ARCH_7 && !arm_dc_feature(s, ARM_FEATURE_M)) {
8373 return false;
8375 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
8376 return true;
8379 static bool trans_DMB(DisasContext *s, arg_DMB *a)
8381 return trans_DSB(s, NULL);
8384 static bool trans_ISB(DisasContext *s, arg_ISB *a)
8386 if (!ENABLE_ARCH_7 && !arm_dc_feature(s, ARM_FEATURE_M)) {
8387 return false;
8390 * We need to break the TB after this insn to execute
8391 * self-modifying code correctly and also to take
8392 * any pending interrupts immediately.
8394 gen_goto_tb(s, 0, s->base.pc_next);
8395 return true;
8398 static bool trans_SB(DisasContext *s, arg_SB *a)
8400 if (!dc_isar_feature(aa32_sb, s)) {
8401 return false;
8404 * TODO: There is no speculation barrier opcode
8405 * for TCG; MB and end the TB instead.
8407 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
8408 gen_goto_tb(s, 0, s->base.pc_next);
8409 return true;
8412 static bool trans_SETEND(DisasContext *s, arg_SETEND *a)
8414 if (!ENABLE_ARCH_6) {
8415 return false;
8417 if (a->E != (s->be_data == MO_BE)) {
8418 gen_helper_setend(cpu_env);
8419 s->base.is_jmp = DISAS_UPDATE_EXIT;
8421 return true;
8425 * Preload instructions
8426 * All are nops, contingent on the appropriate arch level.
8429 static bool trans_PLD(DisasContext *s, arg_PLD *a)
8431 return ENABLE_ARCH_5TE;
8434 static bool trans_PLDW(DisasContext *s, arg_PLD *a)
8436 return arm_dc_feature(s, ARM_FEATURE_V7MP);
8439 static bool trans_PLI(DisasContext *s, arg_PLD *a)
8441 return ENABLE_ARCH_7;
8445 * If-then
8448 static bool trans_IT(DisasContext *s, arg_IT *a)
8450 int cond_mask = a->cond_mask;
8453 * No actual code generated for this insn, just setup state.
8455 * Combinations of firstcond and mask which set up an 0b1111
8456 * condition are UNPREDICTABLE; we take the CONSTRAINED
8457 * UNPREDICTABLE choice to treat 0b1111 the same as 0b1110,
8458 * i.e. both meaning "execute always".
8460 s->condexec_cond = (cond_mask >> 4) & 0xe;
8461 s->condexec_mask = cond_mask & 0x1f;
8462 return true;
8465 /* v8.1M CSEL/CSINC/CSNEG/CSINV */
8466 static bool trans_CSEL(DisasContext *s, arg_CSEL *a)
8468 TCGv_i32 rn, rm, zero;
8469 DisasCompare c;
8471 if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
8472 return false;
8475 if (a->rm == 13) {
8476 /* SEE "Related encodings" (MVE shifts) */
8477 return false;
8480 if (a->rd == 13 || a->rd == 15 || a->rn == 13 || a->fcond >= 14) {
8481 /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
8482 return false;
8485 /* In this insn input reg fields of 0b1111 mean "zero", not "PC" */
8486 if (a->rn == 15) {
8487 rn = tcg_const_i32(0);
8488 } else {
8489 rn = load_reg(s, a->rn);
8491 if (a->rm == 15) {
8492 rm = tcg_const_i32(0);
8493 } else {
8494 rm = load_reg(s, a->rm);
8497 switch (a->op) {
8498 case 0: /* CSEL */
8499 break;
8500 case 1: /* CSINC */
8501 tcg_gen_addi_i32(rm, rm, 1);
8502 break;
8503 case 2: /* CSINV */
8504 tcg_gen_not_i32(rm, rm);
8505 break;
8506 case 3: /* CSNEG */
8507 tcg_gen_neg_i32(rm, rm);
8508 break;
8509 default:
8510 g_assert_not_reached();
8513 arm_test_cc(&c, a->fcond);
8514 zero = tcg_const_i32(0);
8515 tcg_gen_movcond_i32(c.cond, rn, c.value, zero, rn, rm);
8516 arm_free_cc(&c);
8517 tcg_temp_free_i32(zero);
8519 store_reg(s, a->rd, rn);
8520 tcg_temp_free_i32(rm);
8522 return true;
8526 * Legacy decoder.
8529 static void disas_arm_insn(DisasContext *s, unsigned int insn)
8531 unsigned int cond = insn >> 28;
8533 /* M variants do not implement ARM mode; this must raise the INVSTATE
8534 * UsageFault exception.
8536 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8537 gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
8538 default_exception_el(s));
8539 return;
8542 if (cond == 0xf) {
8543 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
8544 * choose to UNDEF. In ARMv5 and above the space is used
8545 * for miscellaneous unconditional instructions.
8547 if (!arm_dc_feature(s, ARM_FEATURE_V5)) {
8548 unallocated_encoding(s);
8549 return;
8552 /* Unconditional instructions. */
8553 /* TODO: Perhaps merge these into one decodetree output file. */
8554 if (disas_a32_uncond(s, insn) ||
8555 disas_vfp_uncond(s, insn) ||
8556 disas_neon_dp(s, insn) ||
8557 disas_neon_ls(s, insn) ||
8558 disas_neon_shared(s, insn)) {
8559 return;
8561 /* fall back to legacy decoder */
8563 if ((insn & 0x0e000f00) == 0x0c000100) {
8564 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
8565 /* iWMMXt register transfer. */
8566 if (extract32(s->c15_cpar, 1, 1)) {
8567 if (!disas_iwmmxt_insn(s, insn)) {
8568 return;
8573 goto illegal_op;
8575 if (cond != 0xe) {
8576 /* if not always execute, we generate a conditional jump to
8577 next instruction */
8578 arm_skip_unless(s, cond);
8581 /* TODO: Perhaps merge these into one decodetree output file. */
8582 if (disas_a32(s, insn) ||
8583 disas_vfp(s, insn)) {
8584 return;
8586 /* fall back to legacy decoder */
8587 /* TODO: convert xscale/iwmmxt decoder to decodetree ?? */
8588 if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) {
8589 if (((insn & 0x0c000e00) == 0x0c000000)
8590 && ((insn & 0x03000000) != 0x03000000)) {
8591 /* Coprocessor insn, coprocessor 0 or 1 */
8592 disas_xscale_insn(s, insn);
8593 return;
8597 illegal_op:
8598 unallocated_encoding(s);
8601 static bool thumb_insn_is_16bit(DisasContext *s, uint32_t pc, uint32_t insn)
8604 * Return true if this is a 16 bit instruction. We must be precise
8605 * about this (matching the decode).
8607 if ((insn >> 11) < 0x1d) {
8608 /* Definitely a 16-bit instruction */
8609 return true;
8612 /* Top five bits 0b11101 / 0b11110 / 0b11111 : this is the
8613 * first half of a 32-bit Thumb insn. Thumb-1 cores might
8614 * end up actually treating this as two 16-bit insns, though,
8615 * if it's half of a bl/blx pair that might span a page boundary.
8617 if (arm_dc_feature(s, ARM_FEATURE_THUMB2) ||
8618 arm_dc_feature(s, ARM_FEATURE_M)) {
8619 /* Thumb2 cores (including all M profile ones) always treat
8620 * 32-bit insns as 32-bit.
8622 return false;
8625 if ((insn >> 11) == 0x1e && pc - s->page_start < TARGET_PAGE_SIZE - 3) {
8626 /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix, and the suffix
8627 * is not on the next page; we merge this into a 32-bit
8628 * insn.
8630 return false;
8632 /* 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF);
8633 * 0b1111_1xxx_xxxx_xxxx : BL suffix;
8634 * 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix on the end of a page
8635 * -- handle as single 16 bit insn
8637 return true;
8640 /* Translate a 32-bit thumb instruction. */
8641 static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
8644 * ARMv6-M supports a limited subset of Thumb2 instructions.
8645 * Other Thumb1 architectures allow only 32-bit
8646 * combined BL/BLX prefix and suffix.
8648 if (arm_dc_feature(s, ARM_FEATURE_M) &&
8649 !arm_dc_feature(s, ARM_FEATURE_V7)) {
8650 int i;
8651 bool found = false;
8652 static const uint32_t armv6m_insn[] = {0xf3808000 /* msr */,
8653 0xf3b08040 /* dsb */,
8654 0xf3b08050 /* dmb */,
8655 0xf3b08060 /* isb */,
8656 0xf3e08000 /* mrs */,
8657 0xf000d000 /* bl */};
8658 static const uint32_t armv6m_mask[] = {0xffe0d000,
8659 0xfff0d0f0,
8660 0xfff0d0f0,
8661 0xfff0d0f0,
8662 0xffe0d000,
8663 0xf800d000};
8665 for (i = 0; i < ARRAY_SIZE(armv6m_insn); i++) {
8666 if ((insn & armv6m_mask[i]) == armv6m_insn[i]) {
8667 found = true;
8668 break;
8671 if (!found) {
8672 goto illegal_op;
8674 } else if ((insn & 0xf800e800) != 0xf000e800) {
8675 if (!arm_dc_feature(s, ARM_FEATURE_THUMB2)) {
8676 unallocated_encoding(s);
8677 return;
8681 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8683 * NOCP takes precedence over any UNDEF for (almost) the
8684 * entire wide range of coprocessor-space encodings, so check
8685 * for it first before proceeding to actually decode eg VFP
8686 * insns. This decode also handles the few insns which are
8687 * in copro space but do not have NOCP checks (eg VLLDM, VLSTM).
8689 if (disas_m_nocp(s, insn)) {
8690 return;
8694 if ((insn & 0xef000000) == 0xef000000) {
8696 * T32 encodings 0b111p_1111_qqqq_qqqq_qqqq_qqqq_qqqq_qqqq
8697 * transform into
8698 * A32 encodings 0b1111_001p_qqqq_qqqq_qqqq_qqqq_qqqq_qqqq
8700 uint32_t a32_insn = (insn & 0xe2ffffff) |
8701 ((insn & (1 << 28)) >> 4) | (1 << 28);
8703 if (disas_neon_dp(s, a32_insn)) {
8704 return;
8708 if ((insn & 0xff100000) == 0xf9000000) {
8710 * T32 encodings 0b1111_1001_ppp0_qqqq_qqqq_qqqq_qqqq_qqqq
8711 * transform into
8712 * A32 encodings 0b1111_0100_ppp0_qqqq_qqqq_qqqq_qqqq_qqqq
8714 uint32_t a32_insn = (insn & 0x00ffffff) | 0xf4000000;
8716 if (disas_neon_ls(s, a32_insn)) {
8717 return;
8722 * TODO: Perhaps merge these into one decodetree output file.
8723 * Note disas_vfp is written for a32 with cond field in the
8724 * top nibble. The t32 encoding requires 0xe in the top nibble.
8726 if (disas_t32(s, insn) ||
8727 disas_vfp_uncond(s, insn) ||
8728 disas_neon_shared(s, insn) ||
8729 ((insn >> 28) == 0xe && disas_vfp(s, insn))) {
8730 return;
8733 illegal_op:
8734 unallocated_encoding(s);
8737 static void disas_thumb_insn(DisasContext *s, uint32_t insn)
8739 if (!disas_t16(s, insn)) {
8740 unallocated_encoding(s);
8744 static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
8746 /* Return true if the insn at dc->base.pc_next might cross a page boundary.
8747 * (False positives are OK, false negatives are not.)
8748 * We know this is a Thumb insn, and our caller ensures we are
8749 * only called if dc->base.pc_next is less than 4 bytes from the page
8750 * boundary, so we cross the page if the first 16 bits indicate
8751 * that this is a 32 bit insn.
8753 uint16_t insn = arm_lduw_code(env, s->base.pc_next, s->sctlr_b);
8755 return !thumb_insn_is_16bit(s, s->base.pc_next, insn);
8758 static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
8760 DisasContext *dc = container_of(dcbase, DisasContext, base);
8761 CPUARMState *env = cs->env_ptr;
8762 ARMCPU *cpu = env_archcpu(env);
8763 CPUARMTBFlags tb_flags = arm_tbflags_from_tb(dc->base.tb);
8764 uint32_t condexec, core_mmu_idx;
8766 dc->isar = &cpu->isar;
8767 dc->condjmp = 0;
8769 dc->aarch64 = 0;
8770 /* If we are coming from secure EL0 in a system with a 32-bit EL3, then
8771 * there is no secure EL1, so we route exceptions to EL3.
8773 dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
8774 !arm_el_is_aa64(env, 3);
8775 dc->thumb = EX_TBFLAG_AM32(tb_flags, THUMB);
8776 dc->be_data = EX_TBFLAG_ANY(tb_flags, BE_DATA) ? MO_BE : MO_LE;
8777 condexec = EX_TBFLAG_AM32(tb_flags, CONDEXEC);
8778 dc->condexec_mask = (condexec & 0xf) << 1;
8779 dc->condexec_cond = condexec >> 4;
8781 core_mmu_idx = EX_TBFLAG_ANY(tb_flags, MMUIDX);
8782 dc->mmu_idx = core_to_arm_mmu_idx(env, core_mmu_idx);
8783 dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
8784 #if !defined(CONFIG_USER_ONLY)
8785 dc->user = (dc->current_el == 0);
8786 #endif
8787 dc->fp_excp_el = EX_TBFLAG_ANY(tb_flags, FPEXC_EL);
8788 dc->align_mem = EX_TBFLAG_ANY(tb_flags, ALIGN_MEM);
8790 if (arm_feature(env, ARM_FEATURE_M)) {
8791 dc->vfp_enabled = 1;
8792 dc->be_data = MO_TE;
8793 dc->v7m_handler_mode = EX_TBFLAG_M32(tb_flags, HANDLER);
8794 dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
8795 regime_is_secure(env, dc->mmu_idx);
8796 dc->v8m_stackcheck = EX_TBFLAG_M32(tb_flags, STACKCHECK);
8797 dc->v8m_fpccr_s_wrong = EX_TBFLAG_M32(tb_flags, FPCCR_S_WRONG);
8798 dc->v7m_new_fp_ctxt_needed =
8799 EX_TBFLAG_M32(tb_flags, NEW_FP_CTXT_NEEDED);
8800 dc->v7m_lspact = EX_TBFLAG_M32(tb_flags, LSPACT);
8801 } else {
8802 dc->debug_target_el = EX_TBFLAG_ANY(tb_flags, DEBUG_TARGET_EL);
8803 dc->sctlr_b = EX_TBFLAG_A32(tb_flags, SCTLR__B);
8804 dc->hstr_active = EX_TBFLAG_A32(tb_flags, HSTR_ACTIVE);
8805 dc->ns = EX_TBFLAG_A32(tb_flags, NS);
8806 dc->vfp_enabled = EX_TBFLAG_A32(tb_flags, VFPEN);
8807 if (arm_feature(env, ARM_FEATURE_XSCALE)) {
8808 dc->c15_cpar = EX_TBFLAG_A32(tb_flags, XSCALE_CPAR);
8809 } else {
8810 dc->vec_len = EX_TBFLAG_A32(tb_flags, VECLEN);
8811 dc->vec_stride = EX_TBFLAG_A32(tb_flags, VECSTRIDE);
8814 dc->cp_regs = cpu->cp_regs;
8815 dc->features = env->features;
8817 /* Single step state. The code-generation logic here is:
8818 * SS_ACTIVE == 0:
8819 * generate code with no special handling for single-stepping (except
8820 * that anything that can make us go to SS_ACTIVE == 1 must end the TB;
8821 * this happens anyway because those changes are all system register or
8822 * PSTATE writes).
8823 * SS_ACTIVE == 1, PSTATE.SS == 1: (active-not-pending)
8824 * emit code for one insn
8825 * emit code to clear PSTATE.SS
8826 * emit code to generate software step exception for completed step
8827 * end TB (as usual for having generated an exception)
8828 * SS_ACTIVE == 1, PSTATE.SS == 0: (active-pending)
8829 * emit code to generate a software step exception
8830 * end the TB
8832 dc->ss_active = EX_TBFLAG_ANY(tb_flags, SS_ACTIVE);
8833 dc->pstate_ss = EX_TBFLAG_ANY(tb_flags, PSTATE__SS);
8834 dc->is_ldex = false;
8836 dc->page_start = dc->base.pc_first & TARGET_PAGE_MASK;
8838 /* If architectural single step active, limit to 1. */
8839 if (is_singlestepping(dc)) {
8840 dc->base.max_insns = 1;
8843 /* ARM is a fixed-length ISA. Bound the number of insns to execute
8844 to those left on the page. */
8845 if (!dc->thumb) {
8846 int bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
8847 dc->base.max_insns = MIN(dc->base.max_insns, bound);
8850 cpu_V0 = tcg_temp_new_i64();
8851 cpu_V1 = tcg_temp_new_i64();
8852 cpu_M0 = tcg_temp_new_i64();
8855 static void arm_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
8857 DisasContext *dc = container_of(dcbase, DisasContext, base);
8859 /* A note on handling of the condexec (IT) bits:
8861 * We want to avoid the overhead of having to write the updated condexec
8862 * bits back to the CPUARMState for every instruction in an IT block. So:
8863 * (1) if the condexec bits are not already zero then we write
8864 * zero back into the CPUARMState now. This avoids complications trying
8865 * to do it at the end of the block. (For example if we don't do this
8866 * it's hard to identify whether we can safely skip writing condexec
8867 * at the end of the TB, which we definitely want to do for the case
8868 * where a TB doesn't do anything with the IT state at all.)
8869 * (2) if we are going to leave the TB then we call gen_set_condexec()
8870 * which will write the correct value into CPUARMState if zero is wrong.
8871 * This is done both for leaving the TB at the end, and for leaving
8872 * it because of an exception we know will happen, which is done in
8873 * gen_exception_insn(). The latter is necessary because we need to
8874 * leave the TB with the PC/IT state just prior to execution of the
8875 * instruction which caused the exception.
8876 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
8877 * then the CPUARMState will be wrong and we need to reset it.
8878 * This is handled in the same way as restoration of the
8879 * PC in these situations; we save the value of the condexec bits
8880 * for each PC via tcg_gen_insn_start(), and restore_state_to_opc()
8881 * then uses this to restore them after an exception.
8883 * Note that there are no instructions which can read the condexec
8884 * bits, and none which can write non-static values to them, so
8885 * we don't need to care about whether CPUARMState is correct in the
8886 * middle of a TB.
8889 /* Reset the conditional execution bits immediately. This avoids
8890 complications trying to do it at the end of the block. */
8891 if (dc->condexec_mask || dc->condexec_cond) {
8892 TCGv_i32 tmp = tcg_temp_new_i32();
8893 tcg_gen_movi_i32(tmp, 0);
8894 store_cpu_field(tmp, condexec_bits);
8898 static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
8900 DisasContext *dc = container_of(dcbase, DisasContext, base);
8902 tcg_gen_insn_start(dc->base.pc_next,
8903 (dc->condexec_cond << 4) | (dc->condexec_mask >> 1),
8905 dc->insn_start = tcg_last_op();
8908 static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
8909 const CPUBreakpoint *bp)
8911 DisasContext *dc = container_of(dcbase, DisasContext, base);
8913 if (bp->flags & BP_CPU) {
8914 gen_set_condexec(dc);
8915 gen_set_pc_im(dc, dc->base.pc_next);
8916 gen_helper_check_breakpoints(cpu_env);
8917 /* End the TB early; it's likely not going to be executed */
8918 dc->base.is_jmp = DISAS_TOO_MANY;
8919 } else {
8920 gen_exception_internal_insn(dc, dc->base.pc_next, EXCP_DEBUG);
8921 /* The address covered by the breakpoint must be
8922 included in [tb->pc, tb->pc + tb->size) in order
8923 to for it to be properly cleared -- thus we
8924 increment the PC here so that the logic setting
8925 tb->size below does the right thing. */
8926 /* TODO: Advance PC by correct instruction length to
8927 * avoid disassembler error messages */
8928 dc->base.pc_next += 2;
8929 dc->base.is_jmp = DISAS_NORETURN;
8932 return true;
8935 static bool arm_pre_translate_insn(DisasContext *dc)
8937 #ifdef CONFIG_USER_ONLY
8938 /* Intercept jump to the magic kernel page. */
8939 if (dc->base.pc_next >= 0xffff0000) {
8940 /* We always get here via a jump, so know we are not in a
8941 conditional execution block. */
8942 gen_exception_internal(EXCP_KERNEL_TRAP);
8943 dc->base.is_jmp = DISAS_NORETURN;
8944 return true;
8946 #endif
8948 if (dc->ss_active && !dc->pstate_ss) {
8949 /* Singlestep state is Active-pending.
8950 * If we're in this state at the start of a TB then either
8951 * a) we just took an exception to an EL which is being debugged
8952 * and this is the first insn in the exception handler
8953 * b) debug exceptions were masked and we just unmasked them
8954 * without changing EL (eg by clearing PSTATE.D)
8955 * In either case we're going to take a swstep exception in the
8956 * "did not step an insn" case, and so the syndrome ISV and EX
8957 * bits should be zero.
8959 assert(dc->base.num_insns == 1);
8960 gen_swstep_exception(dc, 0, 0);
8961 dc->base.is_jmp = DISAS_NORETURN;
8962 return true;
8965 return false;
8968 static void arm_post_translate_insn(DisasContext *dc)
8970 if (dc->condjmp && !dc->base.is_jmp) {
8971 gen_set_label(dc->condlabel);
8972 dc->condjmp = 0;
8974 translator_loop_temp_check(&dc->base);
8977 static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
8979 DisasContext *dc = container_of(dcbase, DisasContext, base);
8980 CPUARMState *env = cpu->env_ptr;
8981 unsigned int insn;
8983 if (arm_pre_translate_insn(dc)) {
8984 dc->base.pc_next += 4;
8985 return;
8988 dc->pc_curr = dc->base.pc_next;
8989 insn = arm_ldl_code(env, dc->base.pc_next, dc->sctlr_b);
8990 dc->insn = insn;
8991 dc->base.pc_next += 4;
8992 disas_arm_insn(dc, insn);
8994 arm_post_translate_insn(dc);
8996 /* ARM is a fixed-length ISA. We performed the cross-page check
8997 in init_disas_context by adjusting max_insns. */
9000 static bool thumb_insn_is_unconditional(DisasContext *s, uint32_t insn)
9002 /* Return true if this Thumb insn is always unconditional,
9003 * even inside an IT block. This is true of only a very few
9004 * instructions: BKPT, HLT, and SG.
9006 * A larger class of instructions are UNPREDICTABLE if used
9007 * inside an IT block; we do not need to detect those here, because
9008 * what we do by default (perform the cc check and update the IT
9009 * bits state machine) is a permitted CONSTRAINED UNPREDICTABLE
9010 * choice for those situations.
9012 * insn is either a 16-bit or a 32-bit instruction; the two are
9013 * distinguishable because for the 16-bit case the top 16 bits
9014 * are zeroes, and that isn't a valid 32-bit encoding.
9016 if ((insn & 0xffffff00) == 0xbe00) {
9017 /* BKPT */
9018 return true;
9021 if ((insn & 0xffffffc0) == 0xba80 && arm_dc_feature(s, ARM_FEATURE_V8) &&
9022 !arm_dc_feature(s, ARM_FEATURE_M)) {
9023 /* HLT: v8A only. This is unconditional even when it is going to
9024 * UNDEF; see the v8A ARM ARM DDI0487B.a H3.3.
9025 * For v7 cores this was a plain old undefined encoding and so
9026 * honours its cc check. (We might be using the encoding as
9027 * a semihosting trap, but we don't change the cc check behaviour
9028 * on that account, because a debugger connected to a real v7A
9029 * core and emulating semihosting traps by catching the UNDEF
9030 * exception would also only see cases where the cc check passed.
9031 * No guest code should be trying to do a HLT semihosting trap
9032 * in an IT block anyway.
9034 return true;
9037 if (insn == 0xe97fe97f && arm_dc_feature(s, ARM_FEATURE_V8) &&
9038 arm_dc_feature(s, ARM_FEATURE_M)) {
9039 /* SG: v8M only */
9040 return true;
9043 return false;
9046 static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
9048 DisasContext *dc = container_of(dcbase, DisasContext, base);
9049 CPUARMState *env = cpu->env_ptr;
9050 uint32_t insn;
9051 bool is_16bit;
9053 if (arm_pre_translate_insn(dc)) {
9054 dc->base.pc_next += 2;
9055 return;
9058 dc->pc_curr = dc->base.pc_next;
9059 insn = arm_lduw_code(env, dc->base.pc_next, dc->sctlr_b);
9060 is_16bit = thumb_insn_is_16bit(dc, dc->base.pc_next, insn);
9061 dc->base.pc_next += 2;
9062 if (!is_16bit) {
9063 uint32_t insn2 = arm_lduw_code(env, dc->base.pc_next, dc->sctlr_b);
9065 insn = insn << 16 | insn2;
9066 dc->base.pc_next += 2;
9068 dc->insn = insn;
9070 if (dc->condexec_mask && !thumb_insn_is_unconditional(dc, insn)) {
9071 uint32_t cond = dc->condexec_cond;
9074 * Conditionally skip the insn. Note that both 0xe and 0xf mean
9075 * "always"; 0xf is not "never".
9077 if (cond < 0x0e) {
9078 arm_skip_unless(dc, cond);
9082 if (is_16bit) {
9083 disas_thumb_insn(dc, insn);
9084 } else {
9085 disas_thumb2_insn(dc, insn);
9088 /* Advance the Thumb condexec condition. */
9089 if (dc->condexec_mask) {
9090 dc->condexec_cond = ((dc->condexec_cond & 0xe) |
9091 ((dc->condexec_mask >> 4) & 1));
9092 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
9093 if (dc->condexec_mask == 0) {
9094 dc->condexec_cond = 0;
9098 arm_post_translate_insn(dc);
9100 /* Thumb is a variable-length ISA. Stop translation when the next insn
9101 * will touch a new page. This ensures that prefetch aborts occur at
9102 * the right place.
9104 * We want to stop the TB if the next insn starts in a new page,
9105 * or if it spans between this page and the next. This means that
9106 * if we're looking at the last halfword in the page we need to
9107 * see if it's a 16-bit Thumb insn (which will fit in this TB)
9108 * or a 32-bit Thumb insn (which won't).
9109 * This is to avoid generating a silly TB with a single 16-bit insn
9110 * in it at the end of this page (which would execute correctly
9111 * but isn't very efficient).
9113 if (dc->base.is_jmp == DISAS_NEXT
9114 && (dc->base.pc_next - dc->page_start >= TARGET_PAGE_SIZE
9115 || (dc->base.pc_next - dc->page_start >= TARGET_PAGE_SIZE - 3
9116 && insn_crosses_page(env, dc)))) {
9117 dc->base.is_jmp = DISAS_TOO_MANY;
9121 static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
9123 DisasContext *dc = container_of(dcbase, DisasContext, base);
9125 /* At this stage dc->condjmp will only be set when the skipped
9126 instruction was a conditional branch or trap, and the PC has
9127 already been written. */
9128 gen_set_condexec(dc);
9129 if (dc->base.is_jmp == DISAS_BX_EXCRET) {
9130 /* Exception return branches need some special case code at the
9131 * end of the TB, which is complex enough that it has to
9132 * handle the single-step vs not and the condition-failed
9133 * insn codepath itself.
9135 gen_bx_excret_final_code(dc);
9136 } else if (unlikely(is_singlestepping(dc))) {
9137 /* Unconditional and "condition passed" instruction codepath. */
9138 switch (dc->base.is_jmp) {
9139 case DISAS_SWI:
9140 gen_ss_advance(dc);
9141 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
9142 default_exception_el(dc));
9143 break;
9144 case DISAS_HVC:
9145 gen_ss_advance(dc);
9146 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
9147 break;
9148 case DISAS_SMC:
9149 gen_ss_advance(dc);
9150 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
9151 break;
9152 case DISAS_NEXT:
9153 case DISAS_TOO_MANY:
9154 case DISAS_UPDATE_EXIT:
9155 case DISAS_UPDATE_NOCHAIN:
9156 gen_set_pc_im(dc, dc->base.pc_next);
9157 /* fall through */
9158 default:
9159 /* FIXME: Single stepping a WFI insn will not halt the CPU. */
9160 gen_singlestep_exception(dc);
9161 break;
9162 case DISAS_NORETURN:
9163 break;
9165 } else {
9166 /* While branches must always occur at the end of an IT block,
9167 there are a few other things that can cause us to terminate
9168 the TB in the middle of an IT block:
9169 - Exception generating instructions (bkpt, swi, undefined).
9170 - Page boundaries.
9171 - Hardware watchpoints.
9172 Hardware breakpoints have already been handled and skip this code.
9174 switch (dc->base.is_jmp) {
9175 case DISAS_NEXT:
9176 case DISAS_TOO_MANY:
9177 gen_goto_tb(dc, 1, dc->base.pc_next);
9178 break;
9179 case DISAS_UPDATE_NOCHAIN:
9180 gen_set_pc_im(dc, dc->base.pc_next);
9181 /* fall through */
9182 case DISAS_JUMP:
9183 gen_goto_ptr();
9184 break;
9185 case DISAS_UPDATE_EXIT:
9186 gen_set_pc_im(dc, dc->base.pc_next);
9187 /* fall through */
9188 default:
9189 /* indicate that the hash table must be used to find the next TB */
9190 tcg_gen_exit_tb(NULL, 0);
9191 break;
9192 case DISAS_NORETURN:
9193 /* nothing more to generate */
9194 break;
9195 case DISAS_WFI:
9197 TCGv_i32 tmp = tcg_const_i32((dc->thumb &&
9198 !(dc->insn & (1U << 31))) ? 2 : 4);
9200 gen_helper_wfi(cpu_env, tmp);
9201 tcg_temp_free_i32(tmp);
9202 /* The helper doesn't necessarily throw an exception, but we
9203 * must go back to the main loop to check for interrupts anyway.
9205 tcg_gen_exit_tb(NULL, 0);
9206 break;
9208 case DISAS_WFE:
9209 gen_helper_wfe(cpu_env);
9210 break;
9211 case DISAS_YIELD:
9212 gen_helper_yield(cpu_env);
9213 break;
9214 case DISAS_SWI:
9215 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
9216 default_exception_el(dc));
9217 break;
9218 case DISAS_HVC:
9219 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
9220 break;
9221 case DISAS_SMC:
9222 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
9223 break;
9227 if (dc->condjmp) {
9228 /* "Condition failed" instruction codepath for the branch/trap insn */
9229 gen_set_label(dc->condlabel);
9230 gen_set_condexec(dc);
9231 if (unlikely(is_singlestepping(dc))) {
9232 gen_set_pc_im(dc, dc->base.pc_next);
9233 gen_singlestep_exception(dc);
9234 } else {
9235 gen_goto_tb(dc, 1, dc->base.pc_next);
9240 static void arm_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
9242 DisasContext *dc = container_of(dcbase, DisasContext, base);
9244 qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
9245 log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size);
9248 static const TranslatorOps arm_translator_ops = {
9249 .init_disas_context = arm_tr_init_disas_context,
9250 .tb_start = arm_tr_tb_start,
9251 .insn_start = arm_tr_insn_start,
9252 .breakpoint_check = arm_tr_breakpoint_check,
9253 .translate_insn = arm_tr_translate_insn,
9254 .tb_stop = arm_tr_tb_stop,
9255 .disas_log = arm_tr_disas_log,
9258 static const TranslatorOps thumb_translator_ops = {
9259 .init_disas_context = arm_tr_init_disas_context,
9260 .tb_start = arm_tr_tb_start,
9261 .insn_start = arm_tr_insn_start,
9262 .breakpoint_check = arm_tr_breakpoint_check,
9263 .translate_insn = thumb_tr_translate_insn,
9264 .tb_stop = arm_tr_tb_stop,
9265 .disas_log = arm_tr_disas_log,
9268 /* generate intermediate code for basic block 'tb'. */
9269 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
9271 DisasContext dc = { };
9272 const TranslatorOps *ops = &arm_translator_ops;
9273 CPUARMTBFlags tb_flags = arm_tbflags_from_tb(tb);
9275 if (EX_TBFLAG_AM32(tb_flags, THUMB)) {
9276 ops = &thumb_translator_ops;
9278 #ifdef TARGET_AARCH64
9279 if (EX_TBFLAG_ANY(tb_flags, AARCH64_STATE)) {
9280 ops = &aarch64_translator_ops;
9282 #endif
9284 translator_loop(ops, &dc.base, cpu, tb, max_insns);
9287 void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb,
9288 target_ulong *data)
9290 if (is_a64(env)) {
9291 env->pc = data[0];
9292 env->condexec_bits = 0;
9293 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
9294 } else {
9295 env->regs[15] = data[0];
9296 env->condexec_bits = data[1];
9297 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;