target/arm: Use tcg_constant in LDM, STM
[qemu/rayw.git] / target / arm / translate.c
blobe0469da0a16764c6d6448d78e66663d62e70d49d
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 "exec/log.h"
40 #define ENABLE_ARCH_4T arm_dc_feature(s, ARM_FEATURE_V4T)
41 #define ENABLE_ARCH_5 arm_dc_feature(s, ARM_FEATURE_V5)
42 /* currently all emulated v5 cores are also v5TE, so don't bother */
43 #define ENABLE_ARCH_5TE arm_dc_feature(s, ARM_FEATURE_V5)
44 #define ENABLE_ARCH_5J dc_isar_feature(aa32_jazelle, s)
45 #define ENABLE_ARCH_6 arm_dc_feature(s, ARM_FEATURE_V6)
46 #define ENABLE_ARCH_6K arm_dc_feature(s, ARM_FEATURE_V6K)
47 #define ENABLE_ARCH_6T2 arm_dc_feature(s, ARM_FEATURE_THUMB2)
48 #define ENABLE_ARCH_7 arm_dc_feature(s, ARM_FEATURE_V7)
49 #define ENABLE_ARCH_8 arm_dc_feature(s, ARM_FEATURE_V8)
51 #include "translate.h"
52 #include "translate-a32.h"
54 /* These are TCG temporaries used only by the legacy iwMMXt decoder */
55 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
56 /* These are TCG globals which alias CPUARMState fields */
57 static TCGv_i32 cpu_R[16];
58 TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
59 TCGv_i64 cpu_exclusive_addr;
60 TCGv_i64 cpu_exclusive_val;
62 #include "exec/gen-icount.h"
64 static const char * const regnames[] =
65 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
66 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
69 /* initialize TCG globals. */
70 void arm_translate_init(void)
72 int i;
74 for (i = 0; i < 16; i++) {
75 cpu_R[i] = tcg_global_mem_new_i32(cpu_env,
76 offsetof(CPUARMState, regs[i]),
77 regnames[i]);
79 cpu_CF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, CF), "CF");
80 cpu_NF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, NF), "NF");
81 cpu_VF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, VF), "VF");
82 cpu_ZF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, ZF), "ZF");
84 cpu_exclusive_addr = tcg_global_mem_new_i64(cpu_env,
85 offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
86 cpu_exclusive_val = tcg_global_mem_new_i64(cpu_env,
87 offsetof(CPUARMState, exclusive_val), "exclusive_val");
89 a64_translate_init();
92 uint64_t asimd_imm_const(uint32_t imm, int cmode, int op)
94 /* Expand the encoded constant as per AdvSIMDExpandImm pseudocode */
95 switch (cmode) {
96 case 0: case 1:
97 /* no-op */
98 break;
99 case 2: case 3:
100 imm <<= 8;
101 break;
102 case 4: case 5:
103 imm <<= 16;
104 break;
105 case 6: case 7:
106 imm <<= 24;
107 break;
108 case 8: case 9:
109 imm |= imm << 16;
110 break;
111 case 10: case 11:
112 imm = (imm << 8) | (imm << 24);
113 break;
114 case 12:
115 imm = (imm << 8) | 0xff;
116 break;
117 case 13:
118 imm = (imm << 16) | 0xffff;
119 break;
120 case 14:
121 if (op) {
123 * This and cmode == 15 op == 1 are the only cases where
124 * the top and bottom 32 bits of the encoded constant differ.
126 uint64_t imm64 = 0;
127 int n;
129 for (n = 0; n < 8; n++) {
130 if (imm & (1 << n)) {
131 imm64 |= (0xffULL << (n * 8));
134 return imm64;
136 imm |= (imm << 8) | (imm << 16) | (imm << 24);
137 break;
138 case 15:
139 if (op) {
140 /* Reserved encoding for AArch32; valid for AArch64 */
141 uint64_t imm64 = (uint64_t)(imm & 0x3f) << 48;
142 if (imm & 0x80) {
143 imm64 |= 0x8000000000000000ULL;
145 if (imm & 0x40) {
146 imm64 |= 0x3fc0000000000000ULL;
147 } else {
148 imm64 |= 0x4000000000000000ULL;
150 return imm64;
152 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
153 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
154 break;
156 if (op) {
157 imm = ~imm;
159 return dup_const(MO_32, imm);
162 /* Generate a label used for skipping this instruction */
163 void arm_gen_condlabel(DisasContext *s)
165 if (!s->condjmp) {
166 s->condlabel = gen_new_label();
167 s->condjmp = 1;
171 /* Flags for the disas_set_da_iss info argument:
172 * lower bits hold the Rt register number, higher bits are flags.
174 typedef enum ISSInfo {
175 ISSNone = 0,
176 ISSRegMask = 0x1f,
177 ISSInvalid = (1 << 5),
178 ISSIsAcqRel = (1 << 6),
179 ISSIsWrite = (1 << 7),
180 ISSIs16Bit = (1 << 8),
181 } ISSInfo;
184 * Store var into env + offset to a member with size bytes.
185 * Free var after use.
187 void store_cpu_offset(TCGv_i32 var, int offset, int size)
189 switch (size) {
190 case 1:
191 tcg_gen_st8_i32(var, cpu_env, offset);
192 break;
193 case 4:
194 tcg_gen_st_i32(var, cpu_env, offset);
195 break;
196 default:
197 g_assert_not_reached();
199 tcg_temp_free_i32(var);
202 /* Save the syndrome information for a Data Abort */
203 static void disas_set_da_iss(DisasContext *s, MemOp memop, ISSInfo issinfo)
205 uint32_t syn;
206 int sas = memop & MO_SIZE;
207 bool sse = memop & MO_SIGN;
208 bool is_acqrel = issinfo & ISSIsAcqRel;
209 bool is_write = issinfo & ISSIsWrite;
210 bool is_16bit = issinfo & ISSIs16Bit;
211 int srt = issinfo & ISSRegMask;
213 if (issinfo & ISSInvalid) {
214 /* Some callsites want to conditionally provide ISS info,
215 * eg "only if this was not a writeback"
217 return;
220 if (srt == 15) {
221 /* For AArch32, insns where the src/dest is R15 never generate
222 * ISS information. Catching that here saves checking at all
223 * the call sites.
225 return;
228 syn = syn_data_abort_with_iss(0, sas, sse, srt, 0, is_acqrel,
229 0, 0, 0, is_write, 0, is_16bit);
230 disas_set_insn_syndrome(s, syn);
233 static inline int get_a32_user_mem_index(DisasContext *s)
235 /* Return the core mmu_idx to use for A32/T32 "unprivileged load/store"
236 * insns:
237 * if PL2, UNPREDICTABLE (we choose to implement as if PL0)
238 * otherwise, access as if at PL0.
240 switch (s->mmu_idx) {
241 case ARMMMUIdx_E2: /* this one is UNPREDICTABLE */
242 case ARMMMUIdx_E10_0:
243 case ARMMMUIdx_E10_1:
244 case ARMMMUIdx_E10_1_PAN:
245 return arm_to_core_mmu_idx(ARMMMUIdx_E10_0);
246 case ARMMMUIdx_SE3:
247 case ARMMMUIdx_SE10_0:
248 case ARMMMUIdx_SE10_1:
249 case ARMMMUIdx_SE10_1_PAN:
250 return arm_to_core_mmu_idx(ARMMMUIdx_SE10_0);
251 case ARMMMUIdx_MUser:
252 case ARMMMUIdx_MPriv:
253 return arm_to_core_mmu_idx(ARMMMUIdx_MUser);
254 case ARMMMUIdx_MUserNegPri:
255 case ARMMMUIdx_MPrivNegPri:
256 return arm_to_core_mmu_idx(ARMMMUIdx_MUserNegPri);
257 case ARMMMUIdx_MSUser:
258 case ARMMMUIdx_MSPriv:
259 return arm_to_core_mmu_idx(ARMMMUIdx_MSUser);
260 case ARMMMUIdx_MSUserNegPri:
261 case ARMMMUIdx_MSPrivNegPri:
262 return arm_to_core_mmu_idx(ARMMMUIdx_MSUserNegPri);
263 default:
264 g_assert_not_reached();
268 /* The architectural value of PC. */
269 static uint32_t read_pc(DisasContext *s)
271 return s->pc_curr + (s->thumb ? 4 : 8);
274 /* Set a variable to the value of a CPU register. */
275 void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
277 if (reg == 15) {
278 tcg_gen_movi_i32(var, read_pc(s));
279 } else {
280 tcg_gen_mov_i32(var, cpu_R[reg]);
285 * Create a new temp, REG + OFS, except PC is ALIGN(PC, 4).
286 * This is used for load/store for which use of PC implies (literal),
287 * or ADD that implies ADR.
289 TCGv_i32 add_reg_for_lit(DisasContext *s, int reg, int ofs)
291 TCGv_i32 tmp = tcg_temp_new_i32();
293 if (reg == 15) {
294 tcg_gen_movi_i32(tmp, (read_pc(s) & ~3) + ofs);
295 } else {
296 tcg_gen_addi_i32(tmp, cpu_R[reg], ofs);
298 return tmp;
301 /* Set a CPU register. The source must be a temporary and will be
302 marked as dead. */
303 void store_reg(DisasContext *s, int reg, TCGv_i32 var)
305 if (reg == 15) {
306 /* In Thumb mode, we must ignore bit 0.
307 * In ARM mode, for ARMv4 and ARMv5, it is UNPREDICTABLE if bits [1:0]
308 * are not 0b00, but for ARMv6 and above, we must ignore bits [1:0].
309 * We choose to ignore [1:0] in ARM mode for all architecture versions.
311 tcg_gen_andi_i32(var, var, s->thumb ? ~1 : ~3);
312 s->base.is_jmp = DISAS_JUMP;
313 } else if (reg == 13 && arm_dc_feature(s, ARM_FEATURE_M)) {
314 /* For M-profile SP bits [1:0] are always zero */
315 tcg_gen_andi_i32(var, var, ~3);
317 tcg_gen_mov_i32(cpu_R[reg], var);
318 tcg_temp_free_i32(var);
322 * Variant of store_reg which applies v8M stack-limit checks before updating
323 * SP. If the check fails this will result in an exception being taken.
324 * We disable the stack checks for CONFIG_USER_ONLY because we have
325 * no idea what the stack limits should be in that case.
326 * If stack checking is not being done this just acts like store_reg().
328 static void store_sp_checked(DisasContext *s, TCGv_i32 var)
330 #ifndef CONFIG_USER_ONLY
331 if (s->v8m_stackcheck) {
332 gen_helper_v8m_stackcheck(cpu_env, var);
334 #endif
335 store_reg(s, 13, var);
338 /* Value extensions. */
339 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
340 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
341 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
342 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
344 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
345 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
347 void gen_set_cpsr(TCGv_i32 var, uint32_t mask)
349 gen_helper_cpsr_write(cpu_env, var, tcg_constant_i32(mask));
352 static void gen_rebuild_hflags(DisasContext *s, bool new_el)
354 bool m_profile = arm_dc_feature(s, ARM_FEATURE_M);
356 if (new_el) {
357 if (m_profile) {
358 gen_helper_rebuild_hflags_m32_newel(cpu_env);
359 } else {
360 gen_helper_rebuild_hflags_a32_newel(cpu_env);
362 } else {
363 TCGv_i32 tcg_el = tcg_constant_i32(s->current_el);
364 if (m_profile) {
365 gen_helper_rebuild_hflags_m32(cpu_env, tcg_el);
366 } else {
367 gen_helper_rebuild_hflags_a32(cpu_env, tcg_el);
372 static void gen_exception_internal(int excp)
374 assert(excp_is_internal(excp));
375 gen_helper_exception_internal(cpu_env, tcg_constant_i32(excp));
378 static void gen_singlestep_exception(DisasContext *s)
380 /* We just completed step of an insn. Move from Active-not-pending
381 * to Active-pending, and then also take the swstep exception.
382 * This corresponds to making the (IMPDEF) choice to prioritize
383 * swstep exceptions over asynchronous exceptions taken to an exception
384 * level where debug is disabled. This choice has the advantage that
385 * we do not need to maintain internal state corresponding to the
386 * ISV/EX syndrome bits between completion of the step and generation
387 * of the exception, and our syndrome information is always correct.
389 gen_ss_advance(s);
390 gen_swstep_exception(s, 1, s->is_ldex);
391 s->base.is_jmp = DISAS_NORETURN;
394 void clear_eci_state(DisasContext *s)
397 * Clear any ECI/ICI state: used when a load multiple/store
398 * multiple insn executes.
400 if (s->eci) {
401 store_cpu_field_constant(0, condexec_bits);
402 s->eci = 0;
406 static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
408 TCGv_i32 tmp1 = tcg_temp_new_i32();
409 TCGv_i32 tmp2 = tcg_temp_new_i32();
410 tcg_gen_ext16s_i32(tmp1, a);
411 tcg_gen_ext16s_i32(tmp2, b);
412 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
413 tcg_temp_free_i32(tmp2);
414 tcg_gen_sari_i32(a, a, 16);
415 tcg_gen_sari_i32(b, b, 16);
416 tcg_gen_mul_i32(b, b, a);
417 tcg_gen_mov_i32(a, tmp1);
418 tcg_temp_free_i32(tmp1);
421 /* Byteswap each halfword. */
422 void gen_rev16(TCGv_i32 dest, TCGv_i32 var)
424 TCGv_i32 tmp = tcg_temp_new_i32();
425 TCGv_i32 mask = tcg_constant_i32(0x00ff00ff);
426 tcg_gen_shri_i32(tmp, var, 8);
427 tcg_gen_and_i32(tmp, tmp, mask);
428 tcg_gen_and_i32(var, var, mask);
429 tcg_gen_shli_i32(var, var, 8);
430 tcg_gen_or_i32(dest, var, tmp);
431 tcg_temp_free_i32(tmp);
434 /* Byteswap low halfword and sign extend. */
435 static void gen_revsh(TCGv_i32 dest, TCGv_i32 var)
437 tcg_gen_bswap16_i32(var, var, TCG_BSWAP_OS);
440 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
441 tmp = (t0 ^ t1) & 0x8000;
442 t0 &= ~0x8000;
443 t1 &= ~0x8000;
444 t0 = (t0 + t1) ^ tmp;
447 static void gen_add16(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
449 TCGv_i32 tmp = tcg_temp_new_i32();
450 tcg_gen_xor_i32(tmp, t0, t1);
451 tcg_gen_andi_i32(tmp, tmp, 0x8000);
452 tcg_gen_andi_i32(t0, t0, ~0x8000);
453 tcg_gen_andi_i32(t1, t1, ~0x8000);
454 tcg_gen_add_i32(t0, t0, t1);
455 tcg_gen_xor_i32(dest, t0, tmp);
456 tcg_temp_free_i32(tmp);
459 /* Set N and Z flags from var. */
460 static inline void gen_logic_CC(TCGv_i32 var)
462 tcg_gen_mov_i32(cpu_NF, var);
463 tcg_gen_mov_i32(cpu_ZF, var);
466 /* dest = T0 + T1 + CF. */
467 static void gen_add_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
469 tcg_gen_add_i32(dest, t0, t1);
470 tcg_gen_add_i32(dest, dest, cpu_CF);
473 /* dest = T0 - T1 + CF - 1. */
474 static void gen_sub_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
476 tcg_gen_sub_i32(dest, t0, t1);
477 tcg_gen_add_i32(dest, dest, cpu_CF);
478 tcg_gen_subi_i32(dest, dest, 1);
481 /* dest = T0 + T1. Compute C, N, V and Z flags */
482 static void gen_add_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
484 TCGv_i32 tmp = tcg_temp_new_i32();
485 tcg_gen_movi_i32(tmp, 0);
486 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, t1, tmp);
487 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
488 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
489 tcg_gen_xor_i32(tmp, t0, t1);
490 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
491 tcg_temp_free_i32(tmp);
492 tcg_gen_mov_i32(dest, cpu_NF);
495 /* dest = T0 + T1 + CF. Compute C, N, V and Z flags */
496 static void gen_adc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
498 TCGv_i32 tmp = tcg_temp_new_i32();
499 if (TCG_TARGET_HAS_add2_i32) {
500 tcg_gen_movi_i32(tmp, 0);
501 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, cpu_CF, tmp);
502 tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1, tmp);
503 } else {
504 TCGv_i64 q0 = tcg_temp_new_i64();
505 TCGv_i64 q1 = tcg_temp_new_i64();
506 tcg_gen_extu_i32_i64(q0, t0);
507 tcg_gen_extu_i32_i64(q1, t1);
508 tcg_gen_add_i64(q0, q0, q1);
509 tcg_gen_extu_i32_i64(q1, cpu_CF);
510 tcg_gen_add_i64(q0, q0, q1);
511 tcg_gen_extr_i64_i32(cpu_NF, cpu_CF, q0);
512 tcg_temp_free_i64(q0);
513 tcg_temp_free_i64(q1);
515 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
516 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
517 tcg_gen_xor_i32(tmp, t0, t1);
518 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
519 tcg_temp_free_i32(tmp);
520 tcg_gen_mov_i32(dest, cpu_NF);
523 /* dest = T0 - T1. Compute C, N, V and Z flags */
524 static void gen_sub_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
526 TCGv_i32 tmp;
527 tcg_gen_sub_i32(cpu_NF, t0, t1);
528 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
529 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0, t1);
530 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
531 tmp = tcg_temp_new_i32();
532 tcg_gen_xor_i32(tmp, t0, t1);
533 tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
534 tcg_temp_free_i32(tmp);
535 tcg_gen_mov_i32(dest, cpu_NF);
538 /* dest = T0 + ~T1 + CF. Compute C, N, V and Z flags */
539 static void gen_sbc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
541 TCGv_i32 tmp = tcg_temp_new_i32();
542 tcg_gen_not_i32(tmp, t1);
543 gen_adc_CC(dest, t0, tmp);
544 tcg_temp_free_i32(tmp);
547 #define GEN_SHIFT(name) \
548 static void gen_##name(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) \
550 TCGv_i32 tmpd = tcg_temp_new_i32(); \
551 TCGv_i32 tmp1 = tcg_temp_new_i32(); \
552 TCGv_i32 zero = tcg_constant_i32(0); \
553 tcg_gen_andi_i32(tmp1, t1, 0x1f); \
554 tcg_gen_##name##_i32(tmpd, t0, tmp1); \
555 tcg_gen_andi_i32(tmp1, t1, 0xe0); \
556 tcg_gen_movcond_i32(TCG_COND_NE, dest, tmp1, zero, zero, tmpd); \
557 tcg_temp_free_i32(tmpd); \
558 tcg_temp_free_i32(tmp1); \
560 GEN_SHIFT(shl)
561 GEN_SHIFT(shr)
562 #undef GEN_SHIFT
564 static void gen_sar(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
566 TCGv_i32 tmp1 = tcg_temp_new_i32();
568 tcg_gen_andi_i32(tmp1, t1, 0xff);
569 tcg_gen_umin_i32(tmp1, tmp1, tcg_constant_i32(31));
570 tcg_gen_sar_i32(dest, t0, tmp1);
571 tcg_temp_free_i32(tmp1);
574 static void shifter_out_im(TCGv_i32 var, int shift)
576 tcg_gen_extract_i32(cpu_CF, var, shift, 1);
579 /* Shift by immediate. Includes special handling for shift == 0. */
580 static inline void gen_arm_shift_im(TCGv_i32 var, int shiftop,
581 int shift, int flags)
583 switch (shiftop) {
584 case 0: /* LSL */
585 if (shift != 0) {
586 if (flags)
587 shifter_out_im(var, 32 - shift);
588 tcg_gen_shli_i32(var, var, shift);
590 break;
591 case 1: /* LSR */
592 if (shift == 0) {
593 if (flags) {
594 tcg_gen_shri_i32(cpu_CF, var, 31);
596 tcg_gen_movi_i32(var, 0);
597 } else {
598 if (flags)
599 shifter_out_im(var, shift - 1);
600 tcg_gen_shri_i32(var, var, shift);
602 break;
603 case 2: /* ASR */
604 if (shift == 0)
605 shift = 32;
606 if (flags)
607 shifter_out_im(var, shift - 1);
608 if (shift == 32)
609 shift = 31;
610 tcg_gen_sari_i32(var, var, shift);
611 break;
612 case 3: /* ROR/RRX */
613 if (shift != 0) {
614 if (flags)
615 shifter_out_im(var, shift - 1);
616 tcg_gen_rotri_i32(var, var, shift); break;
617 } else {
618 TCGv_i32 tmp = tcg_temp_new_i32();
619 tcg_gen_shli_i32(tmp, cpu_CF, 31);
620 if (flags)
621 shifter_out_im(var, 0);
622 tcg_gen_shri_i32(var, var, 1);
623 tcg_gen_or_i32(var, var, tmp);
624 tcg_temp_free_i32(tmp);
629 static inline void gen_arm_shift_reg(TCGv_i32 var, int shiftop,
630 TCGv_i32 shift, int flags)
632 if (flags) {
633 switch (shiftop) {
634 case 0: gen_helper_shl_cc(var, cpu_env, var, shift); break;
635 case 1: gen_helper_shr_cc(var, cpu_env, var, shift); break;
636 case 2: gen_helper_sar_cc(var, cpu_env, var, shift); break;
637 case 3: gen_helper_ror_cc(var, cpu_env, var, shift); break;
639 } else {
640 switch (shiftop) {
641 case 0:
642 gen_shl(var, var, shift);
643 break;
644 case 1:
645 gen_shr(var, var, shift);
646 break;
647 case 2:
648 gen_sar(var, var, shift);
649 break;
650 case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
651 tcg_gen_rotr_i32(var, var, shift); break;
654 tcg_temp_free_i32(shift);
658 * Generate a conditional based on ARM condition code cc.
659 * This is common between ARM and Aarch64 targets.
661 void arm_test_cc(DisasCompare *cmp, int cc)
663 TCGv_i32 value;
664 TCGCond cond;
665 bool global = true;
667 switch (cc) {
668 case 0: /* eq: Z */
669 case 1: /* ne: !Z */
670 cond = TCG_COND_EQ;
671 value = cpu_ZF;
672 break;
674 case 2: /* cs: C */
675 case 3: /* cc: !C */
676 cond = TCG_COND_NE;
677 value = cpu_CF;
678 break;
680 case 4: /* mi: N */
681 case 5: /* pl: !N */
682 cond = TCG_COND_LT;
683 value = cpu_NF;
684 break;
686 case 6: /* vs: V */
687 case 7: /* vc: !V */
688 cond = TCG_COND_LT;
689 value = cpu_VF;
690 break;
692 case 8: /* hi: C && !Z */
693 case 9: /* ls: !C || Z -> !(C && !Z) */
694 cond = TCG_COND_NE;
695 value = tcg_temp_new_i32();
696 global = false;
697 /* CF is 1 for C, so -CF is an all-bits-set mask for C;
698 ZF is non-zero for !Z; so AND the two subexpressions. */
699 tcg_gen_neg_i32(value, cpu_CF);
700 tcg_gen_and_i32(value, value, cpu_ZF);
701 break;
703 case 10: /* ge: N == V -> N ^ V == 0 */
704 case 11: /* lt: N != V -> N ^ V != 0 */
705 /* Since we're only interested in the sign bit, == 0 is >= 0. */
706 cond = TCG_COND_GE;
707 value = tcg_temp_new_i32();
708 global = false;
709 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
710 break;
712 case 12: /* gt: !Z && N == V */
713 case 13: /* le: Z || N != V */
714 cond = TCG_COND_NE;
715 value = tcg_temp_new_i32();
716 global = false;
717 /* (N == V) is equal to the sign bit of ~(NF ^ VF). Propagate
718 * the sign bit then AND with ZF to yield the result. */
719 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
720 tcg_gen_sari_i32(value, value, 31);
721 tcg_gen_andc_i32(value, cpu_ZF, value);
722 break;
724 case 14: /* always */
725 case 15: /* always */
726 /* Use the ALWAYS condition, which will fold early.
727 * It doesn't matter what we use for the value. */
728 cond = TCG_COND_ALWAYS;
729 value = cpu_ZF;
730 goto no_invert;
732 default:
733 fprintf(stderr, "Bad condition code 0x%x\n", cc);
734 abort();
737 if (cc & 1) {
738 cond = tcg_invert_cond(cond);
741 no_invert:
742 cmp->cond = cond;
743 cmp->value = value;
744 cmp->value_global = global;
747 void arm_free_cc(DisasCompare *cmp)
749 if (!cmp->value_global) {
750 tcg_temp_free_i32(cmp->value);
754 void arm_jump_cc(DisasCompare *cmp, TCGLabel *label)
756 tcg_gen_brcondi_i32(cmp->cond, cmp->value, 0, label);
759 void arm_gen_test_cc(int cc, TCGLabel *label)
761 DisasCompare cmp;
762 arm_test_cc(&cmp, cc);
763 arm_jump_cc(&cmp, label);
764 arm_free_cc(&cmp);
767 void gen_set_condexec(DisasContext *s)
769 if (s->condexec_mask) {
770 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
772 store_cpu_field_constant(val, condexec_bits);
776 void gen_set_pc_im(DisasContext *s, target_ulong val)
778 tcg_gen_movi_i32(cpu_R[15], val);
781 /* Set PC and Thumb state from var. var is marked as dead. */
782 static inline void gen_bx(DisasContext *s, TCGv_i32 var)
784 s->base.is_jmp = DISAS_JUMP;
785 tcg_gen_andi_i32(cpu_R[15], var, ~1);
786 tcg_gen_andi_i32(var, var, 1);
787 store_cpu_field(var, thumb);
791 * Set PC and Thumb state from var. var is marked as dead.
792 * For M-profile CPUs, include logic to detect exception-return
793 * branches and handle them. This is needed for Thumb POP/LDM to PC, LDR to PC,
794 * and BX reg, and no others, and happens only for code in Handler mode.
795 * The Security Extension also requires us to check for the FNC_RETURN
796 * which signals a function return from non-secure state; this can happen
797 * in both Handler and Thread mode.
798 * To avoid having to do multiple comparisons in inline generated code,
799 * we make the check we do here loose, so it will match for EXC_RETURN
800 * in Thread mode. For system emulation do_v7m_exception_exit() checks
801 * for these spurious cases and returns without doing anything (giving
802 * the same behaviour as for a branch to a non-magic address).
804 * In linux-user mode it is unclear what the right behaviour for an
805 * attempted FNC_RETURN should be, because in real hardware this will go
806 * directly to Secure code (ie not the Linux kernel) which will then treat
807 * the error in any way it chooses. For QEMU we opt to make the FNC_RETURN
808 * attempt behave the way it would on a CPU without the security extension,
809 * which is to say "like a normal branch". That means we can simply treat
810 * all branches as normal with no magic address behaviour.
812 static inline void gen_bx_excret(DisasContext *s, TCGv_i32 var)
814 /* Generate the same code here as for a simple bx, but flag via
815 * s->base.is_jmp that we need to do the rest of the work later.
817 gen_bx(s, var);
818 #ifndef CONFIG_USER_ONLY
819 if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY) ||
820 (s->v7m_handler_mode && arm_dc_feature(s, ARM_FEATURE_M))) {
821 s->base.is_jmp = DISAS_BX_EXCRET;
823 #endif
826 static inline void gen_bx_excret_final_code(DisasContext *s)
828 /* Generate the code to finish possible exception return and end the TB */
829 TCGLabel *excret_label = gen_new_label();
830 uint32_t min_magic;
832 if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY)) {
833 /* Covers FNC_RETURN and EXC_RETURN magic */
834 min_magic = FNC_RETURN_MIN_MAGIC;
835 } else {
836 /* EXC_RETURN magic only */
837 min_magic = EXC_RETURN_MIN_MAGIC;
840 /* Is the new PC value in the magic range indicating exception return? */
841 tcg_gen_brcondi_i32(TCG_COND_GEU, cpu_R[15], min_magic, excret_label);
842 /* No: end the TB as we would for a DISAS_JMP */
843 if (s->ss_active) {
844 gen_singlestep_exception(s);
845 } else {
846 tcg_gen_exit_tb(NULL, 0);
848 gen_set_label(excret_label);
849 /* Yes: this is an exception return.
850 * At this point in runtime env->regs[15] and env->thumb will hold
851 * the exception-return magic number, which do_v7m_exception_exit()
852 * will read. Nothing else will be able to see those values because
853 * the cpu-exec main loop guarantees that we will always go straight
854 * from raising the exception to the exception-handling code.
856 * gen_ss_advance(s) does nothing on M profile currently but
857 * calling it is conceptually the right thing as we have executed
858 * this instruction (compare SWI, HVC, SMC handling).
860 gen_ss_advance(s);
861 gen_exception_internal(EXCP_EXCEPTION_EXIT);
864 static inline void gen_bxns(DisasContext *s, int rm)
866 TCGv_i32 var = load_reg(s, rm);
868 /* The bxns helper may raise an EXCEPTION_EXIT exception, so in theory
869 * we need to sync state before calling it, but:
870 * - we don't need to do gen_set_pc_im() because the bxns helper will
871 * always set the PC itself
872 * - we don't need to do gen_set_condexec() because BXNS is UNPREDICTABLE
873 * unless it's outside an IT block or the last insn in an IT block,
874 * so we know that condexec == 0 (already set at the top of the TB)
875 * is correct in the non-UNPREDICTABLE cases, and we can choose
876 * "zeroes the IT bits" as our UNPREDICTABLE behaviour otherwise.
878 gen_helper_v7m_bxns(cpu_env, var);
879 tcg_temp_free_i32(var);
880 s->base.is_jmp = DISAS_EXIT;
883 static inline void gen_blxns(DisasContext *s, int rm)
885 TCGv_i32 var = load_reg(s, rm);
887 /* We don't need to sync condexec state, for the same reason as bxns.
888 * We do however need to set the PC, because the blxns helper reads it.
889 * The blxns helper may throw an exception.
891 gen_set_pc_im(s, s->base.pc_next);
892 gen_helper_v7m_blxns(cpu_env, var);
893 tcg_temp_free_i32(var);
894 s->base.is_jmp = DISAS_EXIT;
897 /* Variant of store_reg which uses branch&exchange logic when storing
898 to r15 in ARM architecture v7 and above. The source must be a temporary
899 and will be marked as dead. */
900 static inline void store_reg_bx(DisasContext *s, int reg, TCGv_i32 var)
902 if (reg == 15 && ENABLE_ARCH_7) {
903 gen_bx(s, var);
904 } else {
905 store_reg(s, reg, var);
909 /* Variant of store_reg which uses branch&exchange logic when storing
910 * to r15 in ARM architecture v5T and above. This is used for storing
911 * the results of a LDR/LDM/POP into r15, and corresponds to the cases
912 * in the ARM ARM which use the LoadWritePC() pseudocode function. */
913 static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
915 if (reg == 15 && ENABLE_ARCH_5) {
916 gen_bx_excret(s, var);
917 } else {
918 store_reg(s, reg, var);
922 #ifdef CONFIG_USER_ONLY
923 #define IS_USER_ONLY 1
924 #else
925 #define IS_USER_ONLY 0
926 #endif
928 MemOp pow2_align(unsigned i)
930 static const MemOp mop_align[] = {
931 0, MO_ALIGN_2, MO_ALIGN_4, MO_ALIGN_8, MO_ALIGN_16,
933 * FIXME: TARGET_PAGE_BITS_MIN affects TLB_FLAGS_MASK such
934 * that 256-bit alignment (MO_ALIGN_32) cannot be supported:
935 * see get_alignment_bits(). Enforce only 128-bit alignment for now.
937 MO_ALIGN_16
939 g_assert(i < ARRAY_SIZE(mop_align));
940 return mop_align[i];
944 * Abstractions of "generate code to do a guest load/store for
945 * AArch32", where a vaddr is always 32 bits (and is zero
946 * extended if we're a 64 bit core) and data is also
947 * 32 bits unless specifically doing a 64 bit access.
948 * These functions work like tcg_gen_qemu_{ld,st}* except
949 * that the address argument is TCGv_i32 rather than TCGv.
952 static TCGv gen_aa32_addr(DisasContext *s, TCGv_i32 a32, MemOp op)
954 TCGv addr = tcg_temp_new();
955 tcg_gen_extu_i32_tl(addr, a32);
957 /* Not needed for user-mode BE32, where we use MO_BE instead. */
958 if (!IS_USER_ONLY && s->sctlr_b && (op & MO_SIZE) < MO_32) {
959 tcg_gen_xori_tl(addr, addr, 4 - (1 << (op & MO_SIZE)));
961 return addr;
965 * Internal routines are used for NEON cases where the endianness
966 * and/or alignment has already been taken into account and manipulated.
968 void gen_aa32_ld_internal_i32(DisasContext *s, TCGv_i32 val,
969 TCGv_i32 a32, int index, MemOp opc)
971 TCGv addr = gen_aa32_addr(s, a32, opc);
972 tcg_gen_qemu_ld_i32(val, addr, index, opc);
973 tcg_temp_free(addr);
976 void gen_aa32_st_internal_i32(DisasContext *s, TCGv_i32 val,
977 TCGv_i32 a32, int index, MemOp opc)
979 TCGv addr = gen_aa32_addr(s, a32, opc);
980 tcg_gen_qemu_st_i32(val, addr, index, opc);
981 tcg_temp_free(addr);
984 void gen_aa32_ld_internal_i64(DisasContext *s, TCGv_i64 val,
985 TCGv_i32 a32, int index, MemOp opc)
987 TCGv addr = gen_aa32_addr(s, a32, opc);
989 tcg_gen_qemu_ld_i64(val, addr, index, opc);
991 /* Not needed for user-mode BE32, where we use MO_BE instead. */
992 if (!IS_USER_ONLY && s->sctlr_b && (opc & MO_SIZE) == MO_64) {
993 tcg_gen_rotri_i64(val, val, 32);
995 tcg_temp_free(addr);
998 void gen_aa32_st_internal_i64(DisasContext *s, TCGv_i64 val,
999 TCGv_i32 a32, int index, MemOp opc)
1001 TCGv addr = gen_aa32_addr(s, a32, opc);
1003 /* Not needed for user-mode BE32, where we use MO_BE instead. */
1004 if (!IS_USER_ONLY && s->sctlr_b && (opc & MO_SIZE) == MO_64) {
1005 TCGv_i64 tmp = tcg_temp_new_i64();
1006 tcg_gen_rotri_i64(tmp, val, 32);
1007 tcg_gen_qemu_st_i64(tmp, addr, index, opc);
1008 tcg_temp_free_i64(tmp);
1009 } else {
1010 tcg_gen_qemu_st_i64(val, addr, index, opc);
1012 tcg_temp_free(addr);
1015 void gen_aa32_ld_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
1016 int index, MemOp opc)
1018 gen_aa32_ld_internal_i32(s, val, a32, index, finalize_memop(s, opc));
1021 void gen_aa32_st_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
1022 int index, MemOp opc)
1024 gen_aa32_st_internal_i32(s, val, a32, index, finalize_memop(s, opc));
1027 void gen_aa32_ld_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
1028 int index, MemOp opc)
1030 gen_aa32_ld_internal_i64(s, val, a32, index, finalize_memop(s, opc));
1033 void gen_aa32_st_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
1034 int index, MemOp opc)
1036 gen_aa32_st_internal_i64(s, val, a32, index, finalize_memop(s, opc));
1039 #define DO_GEN_LD(SUFF, OPC) \
1040 static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \
1041 TCGv_i32 a32, int index) \
1043 gen_aa32_ld_i32(s, val, a32, index, OPC); \
1046 #define DO_GEN_ST(SUFF, OPC) \
1047 static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, \
1048 TCGv_i32 a32, int index) \
1050 gen_aa32_st_i32(s, val, a32, index, OPC); \
1053 static inline void gen_hvc(DisasContext *s, int imm16)
1055 /* The pre HVC helper handles cases when HVC gets trapped
1056 * as an undefined insn by runtime configuration (ie before
1057 * the insn really executes).
1059 gen_set_pc_im(s, s->pc_curr);
1060 gen_helper_pre_hvc(cpu_env);
1061 /* Otherwise we will treat this as a real exception which
1062 * happens after execution of the insn. (The distinction matters
1063 * for the PC value reported to the exception handler and also
1064 * for single stepping.)
1066 s->svc_imm = imm16;
1067 gen_set_pc_im(s, s->base.pc_next);
1068 s->base.is_jmp = DISAS_HVC;
1071 static inline void gen_smc(DisasContext *s)
1073 /* As with HVC, we may take an exception either before or after
1074 * the insn executes.
1076 gen_set_pc_im(s, s->pc_curr);
1077 gen_helper_pre_smc(cpu_env, tcg_constant_i32(syn_aa32_smc()));
1078 gen_set_pc_im(s, s->base.pc_next);
1079 s->base.is_jmp = DISAS_SMC;
1082 static void gen_exception_internal_insn(DisasContext *s, uint32_t pc, int excp)
1084 gen_set_condexec(s);
1085 gen_set_pc_im(s, pc);
1086 gen_exception_internal(excp);
1087 s->base.is_jmp = DISAS_NORETURN;
1090 void gen_exception_insn(DisasContext *s, uint64_t pc, int excp,
1091 uint32_t syn, uint32_t target_el)
1093 if (s->aarch64) {
1094 gen_a64_set_pc_im(pc);
1095 } else {
1096 gen_set_condexec(s);
1097 gen_set_pc_im(s, pc);
1099 gen_exception(excp, syn, target_el);
1100 s->base.is_jmp = DISAS_NORETURN;
1103 static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn)
1105 gen_set_condexec(s);
1106 gen_set_pc_im(s, s->pc_curr);
1107 gen_helper_exception_bkpt_insn(cpu_env, tcg_constant_i32(syn));
1108 s->base.is_jmp = DISAS_NORETURN;
1111 void unallocated_encoding(DisasContext *s)
1113 /* Unallocated and reserved encodings are uncategorized */
1114 gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(),
1115 default_exception_el(s));
1118 static void gen_exception_el(DisasContext *s, int excp, uint32_t syn,
1119 TCGv_i32 tcg_el)
1121 gen_set_condexec(s);
1122 gen_set_pc_im(s, s->pc_curr);
1123 gen_helper_exception_with_syndrome(cpu_env,
1124 tcg_constant_i32(excp),
1125 tcg_constant_i32(syn), tcg_el);
1126 s->base.is_jmp = DISAS_NORETURN;
1129 /* Force a TB lookup after an instruction that changes the CPU state. */
1130 void gen_lookup_tb(DisasContext *s)
1132 tcg_gen_movi_i32(cpu_R[15], s->base.pc_next);
1133 s->base.is_jmp = DISAS_EXIT;
1136 static inline void gen_hlt(DisasContext *s, int imm)
1138 /* HLT. This has two purposes.
1139 * Architecturally, it is an external halting debug instruction.
1140 * Since QEMU doesn't implement external debug, we treat this as
1141 * it is required for halting debug disabled: it will UNDEF.
1142 * Secondly, "HLT 0x3C" is a T32 semihosting trap instruction,
1143 * and "HLT 0xF000" is an A32 semihosting syscall. These traps
1144 * must trigger semihosting even for ARMv7 and earlier, where
1145 * HLT was an undefined encoding.
1146 * In system mode, we don't allow userspace access to
1147 * semihosting, to provide some semblance of security
1148 * (and for consistency with our 32-bit semihosting).
1150 if (semihosting_enabled() &&
1151 #ifndef CONFIG_USER_ONLY
1152 s->current_el != 0 &&
1153 #endif
1154 (imm == (s->thumb ? 0x3c : 0xf000))) {
1155 gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
1156 return;
1159 unallocated_encoding(s);
1163 * Return the offset of a "full" NEON Dreg.
1165 long neon_full_reg_offset(unsigned reg)
1167 return offsetof(CPUARMState, vfp.zregs[reg >> 1].d[reg & 1]);
1171 * Return the offset of a 2**SIZE piece of a NEON register, at index ELE,
1172 * where 0 is the least significant end of the register.
1174 long neon_element_offset(int reg, int element, MemOp memop)
1176 int element_size = 1 << (memop & MO_SIZE);
1177 int ofs = element * element_size;
1178 #if HOST_BIG_ENDIAN
1180 * Calculate the offset assuming fully little-endian,
1181 * then XOR to account for the order of the 8-byte units.
1183 if (element_size < 8) {
1184 ofs ^= 8 - element_size;
1186 #endif
1187 return neon_full_reg_offset(reg) + ofs;
1190 /* Return the offset of a VFP Dreg (dp = true) or VFP Sreg (dp = false). */
1191 long vfp_reg_offset(bool dp, unsigned reg)
1193 if (dp) {
1194 return neon_element_offset(reg, 0, MO_64);
1195 } else {
1196 return neon_element_offset(reg >> 1, reg & 1, MO_32);
1200 void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp memop)
1202 long off = neon_element_offset(reg, ele, memop);
1204 switch (memop) {
1205 case MO_SB:
1206 tcg_gen_ld8s_i32(dest, cpu_env, off);
1207 break;
1208 case MO_UB:
1209 tcg_gen_ld8u_i32(dest, cpu_env, off);
1210 break;
1211 case MO_SW:
1212 tcg_gen_ld16s_i32(dest, cpu_env, off);
1213 break;
1214 case MO_UW:
1215 tcg_gen_ld16u_i32(dest, cpu_env, off);
1216 break;
1217 case MO_UL:
1218 case MO_SL:
1219 tcg_gen_ld_i32(dest, cpu_env, off);
1220 break;
1221 default:
1222 g_assert_not_reached();
1226 void read_neon_element64(TCGv_i64 dest, int reg, int ele, MemOp memop)
1228 long off = neon_element_offset(reg, ele, memop);
1230 switch (memop) {
1231 case MO_SL:
1232 tcg_gen_ld32s_i64(dest, cpu_env, off);
1233 break;
1234 case MO_UL:
1235 tcg_gen_ld32u_i64(dest, cpu_env, off);
1236 break;
1237 case MO_UQ:
1238 tcg_gen_ld_i64(dest, cpu_env, off);
1239 break;
1240 default:
1241 g_assert_not_reached();
1245 void write_neon_element32(TCGv_i32 src, int reg, int ele, MemOp memop)
1247 long off = neon_element_offset(reg, ele, memop);
1249 switch (memop) {
1250 case MO_8:
1251 tcg_gen_st8_i32(src, cpu_env, off);
1252 break;
1253 case MO_16:
1254 tcg_gen_st16_i32(src, cpu_env, off);
1255 break;
1256 case MO_32:
1257 tcg_gen_st_i32(src, cpu_env, off);
1258 break;
1259 default:
1260 g_assert_not_reached();
1264 void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop)
1266 long off = neon_element_offset(reg, ele, memop);
1268 switch (memop) {
1269 case MO_32:
1270 tcg_gen_st32_i64(src, cpu_env, off);
1271 break;
1272 case MO_64:
1273 tcg_gen_st_i64(src, cpu_env, off);
1274 break;
1275 default:
1276 g_assert_not_reached();
1280 #define ARM_CP_RW_BIT (1 << 20)
1282 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1284 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1287 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1289 tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1292 static inline TCGv_i32 iwmmxt_load_creg(int reg)
1294 TCGv_i32 var = tcg_temp_new_i32();
1295 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1296 return var;
1299 static inline void iwmmxt_store_creg(int reg, TCGv_i32 var)
1301 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1302 tcg_temp_free_i32(var);
1305 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1307 iwmmxt_store_reg(cpu_M0, rn);
1310 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1312 iwmmxt_load_reg(cpu_M0, rn);
1315 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1317 iwmmxt_load_reg(cpu_V1, rn);
1318 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1321 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1323 iwmmxt_load_reg(cpu_V1, rn);
1324 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1327 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1329 iwmmxt_load_reg(cpu_V1, rn);
1330 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1333 #define IWMMXT_OP(name) \
1334 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1336 iwmmxt_load_reg(cpu_V1, rn); \
1337 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1340 #define IWMMXT_OP_ENV(name) \
1341 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1343 iwmmxt_load_reg(cpu_V1, rn); \
1344 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1347 #define IWMMXT_OP_ENV_SIZE(name) \
1348 IWMMXT_OP_ENV(name##b) \
1349 IWMMXT_OP_ENV(name##w) \
1350 IWMMXT_OP_ENV(name##l)
1352 #define IWMMXT_OP_ENV1(name) \
1353 static inline void gen_op_iwmmxt_##name##_M0(void) \
1355 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1358 IWMMXT_OP(maddsq)
1359 IWMMXT_OP(madduq)
1360 IWMMXT_OP(sadb)
1361 IWMMXT_OP(sadw)
1362 IWMMXT_OP(mulslw)
1363 IWMMXT_OP(mulshw)
1364 IWMMXT_OP(mululw)
1365 IWMMXT_OP(muluhw)
1366 IWMMXT_OP(macsw)
1367 IWMMXT_OP(macuw)
1369 IWMMXT_OP_ENV_SIZE(unpackl)
1370 IWMMXT_OP_ENV_SIZE(unpackh)
1372 IWMMXT_OP_ENV1(unpacklub)
1373 IWMMXT_OP_ENV1(unpackluw)
1374 IWMMXT_OP_ENV1(unpacklul)
1375 IWMMXT_OP_ENV1(unpackhub)
1376 IWMMXT_OP_ENV1(unpackhuw)
1377 IWMMXT_OP_ENV1(unpackhul)
1378 IWMMXT_OP_ENV1(unpacklsb)
1379 IWMMXT_OP_ENV1(unpacklsw)
1380 IWMMXT_OP_ENV1(unpacklsl)
1381 IWMMXT_OP_ENV1(unpackhsb)
1382 IWMMXT_OP_ENV1(unpackhsw)
1383 IWMMXT_OP_ENV1(unpackhsl)
1385 IWMMXT_OP_ENV_SIZE(cmpeq)
1386 IWMMXT_OP_ENV_SIZE(cmpgtu)
1387 IWMMXT_OP_ENV_SIZE(cmpgts)
1389 IWMMXT_OP_ENV_SIZE(mins)
1390 IWMMXT_OP_ENV_SIZE(minu)
1391 IWMMXT_OP_ENV_SIZE(maxs)
1392 IWMMXT_OP_ENV_SIZE(maxu)
1394 IWMMXT_OP_ENV_SIZE(subn)
1395 IWMMXT_OP_ENV_SIZE(addn)
1396 IWMMXT_OP_ENV_SIZE(subu)
1397 IWMMXT_OP_ENV_SIZE(addu)
1398 IWMMXT_OP_ENV_SIZE(subs)
1399 IWMMXT_OP_ENV_SIZE(adds)
1401 IWMMXT_OP_ENV(avgb0)
1402 IWMMXT_OP_ENV(avgb1)
1403 IWMMXT_OP_ENV(avgw0)
1404 IWMMXT_OP_ENV(avgw1)
1406 IWMMXT_OP_ENV(packuw)
1407 IWMMXT_OP_ENV(packul)
1408 IWMMXT_OP_ENV(packuq)
1409 IWMMXT_OP_ENV(packsw)
1410 IWMMXT_OP_ENV(packsl)
1411 IWMMXT_OP_ENV(packsq)
1413 static void gen_op_iwmmxt_set_mup(void)
1415 TCGv_i32 tmp;
1416 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1417 tcg_gen_ori_i32(tmp, tmp, 2);
1418 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1421 static void gen_op_iwmmxt_set_cup(void)
1423 TCGv_i32 tmp;
1424 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1425 tcg_gen_ori_i32(tmp, tmp, 1);
1426 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1429 static void gen_op_iwmmxt_setpsr_nz(void)
1431 TCGv_i32 tmp = tcg_temp_new_i32();
1432 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1433 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1436 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1438 iwmmxt_load_reg(cpu_V1, rn);
1439 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1440 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1443 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn,
1444 TCGv_i32 dest)
1446 int rd;
1447 uint32_t offset;
1448 TCGv_i32 tmp;
1450 rd = (insn >> 16) & 0xf;
1451 tmp = load_reg(s, rd);
1453 offset = (insn & 0xff) << ((insn >> 7) & 2);
1454 if (insn & (1 << 24)) {
1455 /* Pre indexed */
1456 if (insn & (1 << 23))
1457 tcg_gen_addi_i32(tmp, tmp, offset);
1458 else
1459 tcg_gen_addi_i32(tmp, tmp, -offset);
1460 tcg_gen_mov_i32(dest, tmp);
1461 if (insn & (1 << 21))
1462 store_reg(s, rd, tmp);
1463 else
1464 tcg_temp_free_i32(tmp);
1465 } else if (insn & (1 << 21)) {
1466 /* Post indexed */
1467 tcg_gen_mov_i32(dest, tmp);
1468 if (insn & (1 << 23))
1469 tcg_gen_addi_i32(tmp, tmp, offset);
1470 else
1471 tcg_gen_addi_i32(tmp, tmp, -offset);
1472 store_reg(s, rd, tmp);
1473 } else if (!(insn & (1 << 23)))
1474 return 1;
1475 return 0;
1478 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv_i32 dest)
1480 int rd = (insn >> 0) & 0xf;
1481 TCGv_i32 tmp;
1483 if (insn & (1 << 8)) {
1484 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1485 return 1;
1486 } else {
1487 tmp = iwmmxt_load_creg(rd);
1489 } else {
1490 tmp = tcg_temp_new_i32();
1491 iwmmxt_load_reg(cpu_V0, rd);
1492 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
1494 tcg_gen_andi_i32(tmp, tmp, mask);
1495 tcg_gen_mov_i32(dest, tmp);
1496 tcg_temp_free_i32(tmp);
1497 return 0;
1500 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
1501 (ie. an undefined instruction). */
1502 static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
1504 int rd, wrd;
1505 int rdhi, rdlo, rd0, rd1, i;
1506 TCGv_i32 addr;
1507 TCGv_i32 tmp, tmp2, tmp3;
1509 if ((insn & 0x0e000e00) == 0x0c000000) {
1510 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1511 wrd = insn & 0xf;
1512 rdlo = (insn >> 12) & 0xf;
1513 rdhi = (insn >> 16) & 0xf;
1514 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1515 iwmmxt_load_reg(cpu_V0, wrd);
1516 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
1517 tcg_gen_extrh_i64_i32(cpu_R[rdhi], cpu_V0);
1518 } else { /* TMCRR */
1519 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1520 iwmmxt_store_reg(cpu_V0, wrd);
1521 gen_op_iwmmxt_set_mup();
1523 return 0;
1526 wrd = (insn >> 12) & 0xf;
1527 addr = tcg_temp_new_i32();
1528 if (gen_iwmmxt_address(s, insn, addr)) {
1529 tcg_temp_free_i32(addr);
1530 return 1;
1532 if (insn & ARM_CP_RW_BIT) {
1533 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1534 tmp = tcg_temp_new_i32();
1535 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
1536 iwmmxt_store_creg(wrd, tmp);
1537 } else {
1538 i = 1;
1539 if (insn & (1 << 8)) {
1540 if (insn & (1 << 22)) { /* WLDRD */
1541 gen_aa32_ld64(s, cpu_M0, addr, get_mem_index(s));
1542 i = 0;
1543 } else { /* WLDRW wRd */
1544 tmp = tcg_temp_new_i32();
1545 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
1547 } else {
1548 tmp = tcg_temp_new_i32();
1549 if (insn & (1 << 22)) { /* WLDRH */
1550 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
1551 } else { /* WLDRB */
1552 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
1555 if (i) {
1556 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1557 tcg_temp_free_i32(tmp);
1559 gen_op_iwmmxt_movq_wRn_M0(wrd);
1561 } else {
1562 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1563 tmp = iwmmxt_load_creg(wrd);
1564 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
1565 } else {
1566 gen_op_iwmmxt_movq_M0_wRn(wrd);
1567 tmp = tcg_temp_new_i32();
1568 if (insn & (1 << 8)) {
1569 if (insn & (1 << 22)) { /* WSTRD */
1570 gen_aa32_st64(s, cpu_M0, addr, get_mem_index(s));
1571 } else { /* WSTRW wRd */
1572 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1573 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
1575 } else {
1576 if (insn & (1 << 22)) { /* WSTRH */
1577 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1578 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
1579 } else { /* WSTRB */
1580 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1581 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
1585 tcg_temp_free_i32(tmp);
1587 tcg_temp_free_i32(addr);
1588 return 0;
1591 if ((insn & 0x0f000000) != 0x0e000000)
1592 return 1;
1594 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1595 case 0x000: /* WOR */
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_orq_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 0x011: /* TMCR */
1607 if (insn & 0xf)
1608 return 1;
1609 rd = (insn >> 12) & 0xf;
1610 wrd = (insn >> 16) & 0xf;
1611 switch (wrd) {
1612 case ARM_IWMMXT_wCID:
1613 case ARM_IWMMXT_wCASF:
1614 break;
1615 case ARM_IWMMXT_wCon:
1616 gen_op_iwmmxt_set_cup();
1617 /* Fall through. */
1618 case ARM_IWMMXT_wCSSF:
1619 tmp = iwmmxt_load_creg(wrd);
1620 tmp2 = load_reg(s, rd);
1621 tcg_gen_andc_i32(tmp, tmp, tmp2);
1622 tcg_temp_free_i32(tmp2);
1623 iwmmxt_store_creg(wrd, tmp);
1624 break;
1625 case ARM_IWMMXT_wCGR0:
1626 case ARM_IWMMXT_wCGR1:
1627 case ARM_IWMMXT_wCGR2:
1628 case ARM_IWMMXT_wCGR3:
1629 gen_op_iwmmxt_set_cup();
1630 tmp = load_reg(s, rd);
1631 iwmmxt_store_creg(wrd, tmp);
1632 break;
1633 default:
1634 return 1;
1636 break;
1637 case 0x100: /* WXOR */
1638 wrd = (insn >> 12) & 0xf;
1639 rd0 = (insn >> 0) & 0xf;
1640 rd1 = (insn >> 16) & 0xf;
1641 gen_op_iwmmxt_movq_M0_wRn(rd0);
1642 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1643 gen_op_iwmmxt_setpsr_nz();
1644 gen_op_iwmmxt_movq_wRn_M0(wrd);
1645 gen_op_iwmmxt_set_mup();
1646 gen_op_iwmmxt_set_cup();
1647 break;
1648 case 0x111: /* TMRC */
1649 if (insn & 0xf)
1650 return 1;
1651 rd = (insn >> 12) & 0xf;
1652 wrd = (insn >> 16) & 0xf;
1653 tmp = iwmmxt_load_creg(wrd);
1654 store_reg(s, rd, tmp);
1655 break;
1656 case 0x300: /* WANDN */
1657 wrd = (insn >> 12) & 0xf;
1658 rd0 = (insn >> 0) & 0xf;
1659 rd1 = (insn >> 16) & 0xf;
1660 gen_op_iwmmxt_movq_M0_wRn(rd0);
1661 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1662 gen_op_iwmmxt_andq_M0_wRn(rd1);
1663 gen_op_iwmmxt_setpsr_nz();
1664 gen_op_iwmmxt_movq_wRn_M0(wrd);
1665 gen_op_iwmmxt_set_mup();
1666 gen_op_iwmmxt_set_cup();
1667 break;
1668 case 0x200: /* WAND */
1669 wrd = (insn >> 12) & 0xf;
1670 rd0 = (insn >> 0) & 0xf;
1671 rd1 = (insn >> 16) & 0xf;
1672 gen_op_iwmmxt_movq_M0_wRn(rd0);
1673 gen_op_iwmmxt_andq_M0_wRn(rd1);
1674 gen_op_iwmmxt_setpsr_nz();
1675 gen_op_iwmmxt_movq_wRn_M0(wrd);
1676 gen_op_iwmmxt_set_mup();
1677 gen_op_iwmmxt_set_cup();
1678 break;
1679 case 0x810: case 0xa10: /* WMADD */
1680 wrd = (insn >> 12) & 0xf;
1681 rd0 = (insn >> 0) & 0xf;
1682 rd1 = (insn >> 16) & 0xf;
1683 gen_op_iwmmxt_movq_M0_wRn(rd0);
1684 if (insn & (1 << 21))
1685 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1686 else
1687 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1688 gen_op_iwmmxt_movq_wRn_M0(wrd);
1689 gen_op_iwmmxt_set_mup();
1690 break;
1691 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1692 wrd = (insn >> 12) & 0xf;
1693 rd0 = (insn >> 16) & 0xf;
1694 rd1 = (insn >> 0) & 0xf;
1695 gen_op_iwmmxt_movq_M0_wRn(rd0);
1696 switch ((insn >> 22) & 3) {
1697 case 0:
1698 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1699 break;
1700 case 1:
1701 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1702 break;
1703 case 2:
1704 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1705 break;
1706 case 3:
1707 return 1;
1709 gen_op_iwmmxt_movq_wRn_M0(wrd);
1710 gen_op_iwmmxt_set_mup();
1711 gen_op_iwmmxt_set_cup();
1712 break;
1713 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1714 wrd = (insn >> 12) & 0xf;
1715 rd0 = (insn >> 16) & 0xf;
1716 rd1 = (insn >> 0) & 0xf;
1717 gen_op_iwmmxt_movq_M0_wRn(rd0);
1718 switch ((insn >> 22) & 3) {
1719 case 0:
1720 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1721 break;
1722 case 1:
1723 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1724 break;
1725 case 2:
1726 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1727 break;
1728 case 3:
1729 return 1;
1731 gen_op_iwmmxt_movq_wRn_M0(wrd);
1732 gen_op_iwmmxt_set_mup();
1733 gen_op_iwmmxt_set_cup();
1734 break;
1735 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1736 wrd = (insn >> 12) & 0xf;
1737 rd0 = (insn >> 16) & 0xf;
1738 rd1 = (insn >> 0) & 0xf;
1739 gen_op_iwmmxt_movq_M0_wRn(rd0);
1740 if (insn & (1 << 22))
1741 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1742 else
1743 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1744 if (!(insn & (1 << 20)))
1745 gen_op_iwmmxt_addl_M0_wRn(wrd);
1746 gen_op_iwmmxt_movq_wRn_M0(wrd);
1747 gen_op_iwmmxt_set_mup();
1748 break;
1749 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1750 wrd = (insn >> 12) & 0xf;
1751 rd0 = (insn >> 16) & 0xf;
1752 rd1 = (insn >> 0) & 0xf;
1753 gen_op_iwmmxt_movq_M0_wRn(rd0);
1754 if (insn & (1 << 21)) {
1755 if (insn & (1 << 20))
1756 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1757 else
1758 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1759 } else {
1760 if (insn & (1 << 20))
1761 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1762 else
1763 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1765 gen_op_iwmmxt_movq_wRn_M0(wrd);
1766 gen_op_iwmmxt_set_mup();
1767 break;
1768 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1769 wrd = (insn >> 12) & 0xf;
1770 rd0 = (insn >> 16) & 0xf;
1771 rd1 = (insn >> 0) & 0xf;
1772 gen_op_iwmmxt_movq_M0_wRn(rd0);
1773 if (insn & (1 << 21))
1774 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1775 else
1776 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1777 if (!(insn & (1 << 20))) {
1778 iwmmxt_load_reg(cpu_V1, wrd);
1779 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1781 gen_op_iwmmxt_movq_wRn_M0(wrd);
1782 gen_op_iwmmxt_set_mup();
1783 break;
1784 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1785 wrd = (insn >> 12) & 0xf;
1786 rd0 = (insn >> 16) & 0xf;
1787 rd1 = (insn >> 0) & 0xf;
1788 gen_op_iwmmxt_movq_M0_wRn(rd0);
1789 switch ((insn >> 22) & 3) {
1790 case 0:
1791 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1792 break;
1793 case 1:
1794 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1795 break;
1796 case 2:
1797 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1798 break;
1799 case 3:
1800 return 1;
1802 gen_op_iwmmxt_movq_wRn_M0(wrd);
1803 gen_op_iwmmxt_set_mup();
1804 gen_op_iwmmxt_set_cup();
1805 break;
1806 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1807 wrd = (insn >> 12) & 0xf;
1808 rd0 = (insn >> 16) & 0xf;
1809 rd1 = (insn >> 0) & 0xf;
1810 gen_op_iwmmxt_movq_M0_wRn(rd0);
1811 if (insn & (1 << 22)) {
1812 if (insn & (1 << 20))
1813 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1814 else
1815 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1816 } else {
1817 if (insn & (1 << 20))
1818 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1819 else
1820 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1822 gen_op_iwmmxt_movq_wRn_M0(wrd);
1823 gen_op_iwmmxt_set_mup();
1824 gen_op_iwmmxt_set_cup();
1825 break;
1826 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1827 wrd = (insn >> 12) & 0xf;
1828 rd0 = (insn >> 16) & 0xf;
1829 rd1 = (insn >> 0) & 0xf;
1830 gen_op_iwmmxt_movq_M0_wRn(rd0);
1831 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1832 tcg_gen_andi_i32(tmp, tmp, 7);
1833 iwmmxt_load_reg(cpu_V1, rd1);
1834 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
1835 tcg_temp_free_i32(tmp);
1836 gen_op_iwmmxt_movq_wRn_M0(wrd);
1837 gen_op_iwmmxt_set_mup();
1838 break;
1839 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1840 if (((insn >> 6) & 3) == 3)
1841 return 1;
1842 rd = (insn >> 12) & 0xf;
1843 wrd = (insn >> 16) & 0xf;
1844 tmp = load_reg(s, rd);
1845 gen_op_iwmmxt_movq_M0_wRn(wrd);
1846 switch ((insn >> 6) & 3) {
1847 case 0:
1848 tmp2 = tcg_constant_i32(0xff);
1849 tmp3 = tcg_constant_i32((insn & 7) << 3);
1850 break;
1851 case 1:
1852 tmp2 = tcg_constant_i32(0xffff);
1853 tmp3 = tcg_constant_i32((insn & 3) << 4);
1854 break;
1855 case 2:
1856 tmp2 = tcg_constant_i32(0xffffffff);
1857 tmp3 = tcg_constant_i32((insn & 1) << 5);
1858 break;
1859 default:
1860 g_assert_not_reached();
1862 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
1863 tcg_temp_free_i32(tmp);
1864 gen_op_iwmmxt_movq_wRn_M0(wrd);
1865 gen_op_iwmmxt_set_mup();
1866 break;
1867 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1868 rd = (insn >> 12) & 0xf;
1869 wrd = (insn >> 16) & 0xf;
1870 if (rd == 15 || ((insn >> 22) & 3) == 3)
1871 return 1;
1872 gen_op_iwmmxt_movq_M0_wRn(wrd);
1873 tmp = tcg_temp_new_i32();
1874 switch ((insn >> 22) & 3) {
1875 case 0:
1876 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
1877 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1878 if (insn & 8) {
1879 tcg_gen_ext8s_i32(tmp, tmp);
1880 } else {
1881 tcg_gen_andi_i32(tmp, tmp, 0xff);
1883 break;
1884 case 1:
1885 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
1886 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1887 if (insn & 8) {
1888 tcg_gen_ext16s_i32(tmp, tmp);
1889 } else {
1890 tcg_gen_andi_i32(tmp, tmp, 0xffff);
1892 break;
1893 case 2:
1894 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
1895 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1896 break;
1898 store_reg(s, rd, tmp);
1899 break;
1900 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1901 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1902 return 1;
1903 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1904 switch ((insn >> 22) & 3) {
1905 case 0:
1906 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
1907 break;
1908 case 1:
1909 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
1910 break;
1911 case 2:
1912 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
1913 break;
1915 tcg_gen_shli_i32(tmp, tmp, 28);
1916 gen_set_nzcv(tmp);
1917 tcg_temp_free_i32(tmp);
1918 break;
1919 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1920 if (((insn >> 6) & 3) == 3)
1921 return 1;
1922 rd = (insn >> 12) & 0xf;
1923 wrd = (insn >> 16) & 0xf;
1924 tmp = load_reg(s, rd);
1925 switch ((insn >> 6) & 3) {
1926 case 0:
1927 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
1928 break;
1929 case 1:
1930 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
1931 break;
1932 case 2:
1933 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
1934 break;
1936 tcg_temp_free_i32(tmp);
1937 gen_op_iwmmxt_movq_wRn_M0(wrd);
1938 gen_op_iwmmxt_set_mup();
1939 break;
1940 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1941 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1942 return 1;
1943 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1944 tmp2 = tcg_temp_new_i32();
1945 tcg_gen_mov_i32(tmp2, tmp);
1946 switch ((insn >> 22) & 3) {
1947 case 0:
1948 for (i = 0; i < 7; i ++) {
1949 tcg_gen_shli_i32(tmp2, tmp2, 4);
1950 tcg_gen_and_i32(tmp, tmp, tmp2);
1952 break;
1953 case 1:
1954 for (i = 0; i < 3; i ++) {
1955 tcg_gen_shli_i32(tmp2, tmp2, 8);
1956 tcg_gen_and_i32(tmp, tmp, tmp2);
1958 break;
1959 case 2:
1960 tcg_gen_shli_i32(tmp2, tmp2, 16);
1961 tcg_gen_and_i32(tmp, tmp, tmp2);
1962 break;
1964 gen_set_nzcv(tmp);
1965 tcg_temp_free_i32(tmp2);
1966 tcg_temp_free_i32(tmp);
1967 break;
1968 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1969 wrd = (insn >> 12) & 0xf;
1970 rd0 = (insn >> 16) & 0xf;
1971 gen_op_iwmmxt_movq_M0_wRn(rd0);
1972 switch ((insn >> 22) & 3) {
1973 case 0:
1974 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1975 break;
1976 case 1:
1977 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1978 break;
1979 case 2:
1980 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1981 break;
1982 case 3:
1983 return 1;
1985 gen_op_iwmmxt_movq_wRn_M0(wrd);
1986 gen_op_iwmmxt_set_mup();
1987 break;
1988 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1989 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1990 return 1;
1991 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1992 tmp2 = tcg_temp_new_i32();
1993 tcg_gen_mov_i32(tmp2, tmp);
1994 switch ((insn >> 22) & 3) {
1995 case 0:
1996 for (i = 0; i < 7; i ++) {
1997 tcg_gen_shli_i32(tmp2, tmp2, 4);
1998 tcg_gen_or_i32(tmp, tmp, tmp2);
2000 break;
2001 case 1:
2002 for (i = 0; i < 3; i ++) {
2003 tcg_gen_shli_i32(tmp2, tmp2, 8);
2004 tcg_gen_or_i32(tmp, tmp, tmp2);
2006 break;
2007 case 2:
2008 tcg_gen_shli_i32(tmp2, tmp2, 16);
2009 tcg_gen_or_i32(tmp, tmp, tmp2);
2010 break;
2012 gen_set_nzcv(tmp);
2013 tcg_temp_free_i32(tmp2);
2014 tcg_temp_free_i32(tmp);
2015 break;
2016 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
2017 rd = (insn >> 12) & 0xf;
2018 rd0 = (insn >> 16) & 0xf;
2019 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
2020 return 1;
2021 gen_op_iwmmxt_movq_M0_wRn(rd0);
2022 tmp = tcg_temp_new_i32();
2023 switch ((insn >> 22) & 3) {
2024 case 0:
2025 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
2026 break;
2027 case 1:
2028 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
2029 break;
2030 case 2:
2031 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
2032 break;
2034 store_reg(s, rd, tmp);
2035 break;
2036 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
2037 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2038 wrd = (insn >> 12) & 0xf;
2039 rd0 = (insn >> 16) & 0xf;
2040 rd1 = (insn >> 0) & 0xf;
2041 gen_op_iwmmxt_movq_M0_wRn(rd0);
2042 switch ((insn >> 22) & 3) {
2043 case 0:
2044 if (insn & (1 << 21))
2045 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
2046 else
2047 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
2048 break;
2049 case 1:
2050 if (insn & (1 << 21))
2051 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
2052 else
2053 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2054 break;
2055 case 2:
2056 if (insn & (1 << 21))
2057 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2058 else
2059 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2060 break;
2061 case 3:
2062 return 1;
2064 gen_op_iwmmxt_movq_wRn_M0(wrd);
2065 gen_op_iwmmxt_set_mup();
2066 gen_op_iwmmxt_set_cup();
2067 break;
2068 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2069 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2070 wrd = (insn >> 12) & 0xf;
2071 rd0 = (insn >> 16) & 0xf;
2072 gen_op_iwmmxt_movq_M0_wRn(rd0);
2073 switch ((insn >> 22) & 3) {
2074 case 0:
2075 if (insn & (1 << 21))
2076 gen_op_iwmmxt_unpacklsb_M0();
2077 else
2078 gen_op_iwmmxt_unpacklub_M0();
2079 break;
2080 case 1:
2081 if (insn & (1 << 21))
2082 gen_op_iwmmxt_unpacklsw_M0();
2083 else
2084 gen_op_iwmmxt_unpackluw_M0();
2085 break;
2086 case 2:
2087 if (insn & (1 << 21))
2088 gen_op_iwmmxt_unpacklsl_M0();
2089 else
2090 gen_op_iwmmxt_unpacklul_M0();
2091 break;
2092 case 3:
2093 return 1;
2095 gen_op_iwmmxt_movq_wRn_M0(wrd);
2096 gen_op_iwmmxt_set_mup();
2097 gen_op_iwmmxt_set_cup();
2098 break;
2099 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2100 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2101 wrd = (insn >> 12) & 0xf;
2102 rd0 = (insn >> 16) & 0xf;
2103 gen_op_iwmmxt_movq_M0_wRn(rd0);
2104 switch ((insn >> 22) & 3) {
2105 case 0:
2106 if (insn & (1 << 21))
2107 gen_op_iwmmxt_unpackhsb_M0();
2108 else
2109 gen_op_iwmmxt_unpackhub_M0();
2110 break;
2111 case 1:
2112 if (insn & (1 << 21))
2113 gen_op_iwmmxt_unpackhsw_M0();
2114 else
2115 gen_op_iwmmxt_unpackhuw_M0();
2116 break;
2117 case 2:
2118 if (insn & (1 << 21))
2119 gen_op_iwmmxt_unpackhsl_M0();
2120 else
2121 gen_op_iwmmxt_unpackhul_M0();
2122 break;
2123 case 3:
2124 return 1;
2126 gen_op_iwmmxt_movq_wRn_M0(wrd);
2127 gen_op_iwmmxt_set_mup();
2128 gen_op_iwmmxt_set_cup();
2129 break;
2130 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2131 case 0x214: case 0x614: case 0xa14: case 0xe14:
2132 if (((insn >> 22) & 3) == 0)
2133 return 1;
2134 wrd = (insn >> 12) & 0xf;
2135 rd0 = (insn >> 16) & 0xf;
2136 gen_op_iwmmxt_movq_M0_wRn(rd0);
2137 tmp = tcg_temp_new_i32();
2138 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2139 tcg_temp_free_i32(tmp);
2140 return 1;
2142 switch ((insn >> 22) & 3) {
2143 case 1:
2144 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
2145 break;
2146 case 2:
2147 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
2148 break;
2149 case 3:
2150 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
2151 break;
2153 tcg_temp_free_i32(tmp);
2154 gen_op_iwmmxt_movq_wRn_M0(wrd);
2155 gen_op_iwmmxt_set_mup();
2156 gen_op_iwmmxt_set_cup();
2157 break;
2158 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2159 case 0x014: case 0x414: case 0x814: case 0xc14:
2160 if (((insn >> 22) & 3) == 0)
2161 return 1;
2162 wrd = (insn >> 12) & 0xf;
2163 rd0 = (insn >> 16) & 0xf;
2164 gen_op_iwmmxt_movq_M0_wRn(rd0);
2165 tmp = tcg_temp_new_i32();
2166 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2167 tcg_temp_free_i32(tmp);
2168 return 1;
2170 switch ((insn >> 22) & 3) {
2171 case 1:
2172 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
2173 break;
2174 case 2:
2175 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
2176 break;
2177 case 3:
2178 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
2179 break;
2181 tcg_temp_free_i32(tmp);
2182 gen_op_iwmmxt_movq_wRn_M0(wrd);
2183 gen_op_iwmmxt_set_mup();
2184 gen_op_iwmmxt_set_cup();
2185 break;
2186 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2187 case 0x114: case 0x514: case 0x914: case 0xd14:
2188 if (((insn >> 22) & 3) == 0)
2189 return 1;
2190 wrd = (insn >> 12) & 0xf;
2191 rd0 = (insn >> 16) & 0xf;
2192 gen_op_iwmmxt_movq_M0_wRn(rd0);
2193 tmp = tcg_temp_new_i32();
2194 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2195 tcg_temp_free_i32(tmp);
2196 return 1;
2198 switch ((insn >> 22) & 3) {
2199 case 1:
2200 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2201 break;
2202 case 2:
2203 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2204 break;
2205 case 3:
2206 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2207 break;
2209 tcg_temp_free_i32(tmp);
2210 gen_op_iwmmxt_movq_wRn_M0(wrd);
2211 gen_op_iwmmxt_set_mup();
2212 gen_op_iwmmxt_set_cup();
2213 break;
2214 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2215 case 0x314: case 0x714: case 0xb14: case 0xf14:
2216 if (((insn >> 22) & 3) == 0)
2217 return 1;
2218 wrd = (insn >> 12) & 0xf;
2219 rd0 = (insn >> 16) & 0xf;
2220 gen_op_iwmmxt_movq_M0_wRn(rd0);
2221 tmp = tcg_temp_new_i32();
2222 switch ((insn >> 22) & 3) {
2223 case 1:
2224 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2225 tcg_temp_free_i32(tmp);
2226 return 1;
2228 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2229 break;
2230 case 2:
2231 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2232 tcg_temp_free_i32(tmp);
2233 return 1;
2235 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2236 break;
2237 case 3:
2238 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2239 tcg_temp_free_i32(tmp);
2240 return 1;
2242 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2243 break;
2245 tcg_temp_free_i32(tmp);
2246 gen_op_iwmmxt_movq_wRn_M0(wrd);
2247 gen_op_iwmmxt_set_mup();
2248 gen_op_iwmmxt_set_cup();
2249 break;
2250 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2251 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2252 wrd = (insn >> 12) & 0xf;
2253 rd0 = (insn >> 16) & 0xf;
2254 rd1 = (insn >> 0) & 0xf;
2255 gen_op_iwmmxt_movq_M0_wRn(rd0);
2256 switch ((insn >> 22) & 3) {
2257 case 0:
2258 if (insn & (1 << 21))
2259 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2260 else
2261 gen_op_iwmmxt_minub_M0_wRn(rd1);
2262 break;
2263 case 1:
2264 if (insn & (1 << 21))
2265 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2266 else
2267 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2268 break;
2269 case 2:
2270 if (insn & (1 << 21))
2271 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2272 else
2273 gen_op_iwmmxt_minul_M0_wRn(rd1);
2274 break;
2275 case 3:
2276 return 1;
2278 gen_op_iwmmxt_movq_wRn_M0(wrd);
2279 gen_op_iwmmxt_set_mup();
2280 break;
2281 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2282 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2283 wrd = (insn >> 12) & 0xf;
2284 rd0 = (insn >> 16) & 0xf;
2285 rd1 = (insn >> 0) & 0xf;
2286 gen_op_iwmmxt_movq_M0_wRn(rd0);
2287 switch ((insn >> 22) & 3) {
2288 case 0:
2289 if (insn & (1 << 21))
2290 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2291 else
2292 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2293 break;
2294 case 1:
2295 if (insn & (1 << 21))
2296 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2297 else
2298 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2299 break;
2300 case 2:
2301 if (insn & (1 << 21))
2302 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2303 else
2304 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2305 break;
2306 case 3:
2307 return 1;
2309 gen_op_iwmmxt_movq_wRn_M0(wrd);
2310 gen_op_iwmmxt_set_mup();
2311 break;
2312 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2313 case 0x402: case 0x502: case 0x602: case 0x702:
2314 wrd = (insn >> 12) & 0xf;
2315 rd0 = (insn >> 16) & 0xf;
2316 rd1 = (insn >> 0) & 0xf;
2317 gen_op_iwmmxt_movq_M0_wRn(rd0);
2318 iwmmxt_load_reg(cpu_V1, rd1);
2319 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1,
2320 tcg_constant_i32((insn >> 20) & 3));
2321 gen_op_iwmmxt_movq_wRn_M0(wrd);
2322 gen_op_iwmmxt_set_mup();
2323 break;
2324 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2325 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2326 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2327 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2328 wrd = (insn >> 12) & 0xf;
2329 rd0 = (insn >> 16) & 0xf;
2330 rd1 = (insn >> 0) & 0xf;
2331 gen_op_iwmmxt_movq_M0_wRn(rd0);
2332 switch ((insn >> 20) & 0xf) {
2333 case 0x0:
2334 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2335 break;
2336 case 0x1:
2337 gen_op_iwmmxt_subub_M0_wRn(rd1);
2338 break;
2339 case 0x3:
2340 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2341 break;
2342 case 0x4:
2343 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2344 break;
2345 case 0x5:
2346 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2347 break;
2348 case 0x7:
2349 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2350 break;
2351 case 0x8:
2352 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2353 break;
2354 case 0x9:
2355 gen_op_iwmmxt_subul_M0_wRn(rd1);
2356 break;
2357 case 0xb:
2358 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2359 break;
2360 default:
2361 return 1;
2363 gen_op_iwmmxt_movq_wRn_M0(wrd);
2364 gen_op_iwmmxt_set_mup();
2365 gen_op_iwmmxt_set_cup();
2366 break;
2367 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2368 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2369 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2370 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2371 wrd = (insn >> 12) & 0xf;
2372 rd0 = (insn >> 16) & 0xf;
2373 gen_op_iwmmxt_movq_M0_wRn(rd0);
2374 tmp = tcg_constant_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2375 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2376 gen_op_iwmmxt_movq_wRn_M0(wrd);
2377 gen_op_iwmmxt_set_mup();
2378 gen_op_iwmmxt_set_cup();
2379 break;
2380 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2381 case 0x418: case 0x518: case 0x618: case 0x718:
2382 case 0x818: case 0x918: case 0xa18: case 0xb18:
2383 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2384 wrd = (insn >> 12) & 0xf;
2385 rd0 = (insn >> 16) & 0xf;
2386 rd1 = (insn >> 0) & 0xf;
2387 gen_op_iwmmxt_movq_M0_wRn(rd0);
2388 switch ((insn >> 20) & 0xf) {
2389 case 0x0:
2390 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2391 break;
2392 case 0x1:
2393 gen_op_iwmmxt_addub_M0_wRn(rd1);
2394 break;
2395 case 0x3:
2396 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2397 break;
2398 case 0x4:
2399 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2400 break;
2401 case 0x5:
2402 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2403 break;
2404 case 0x7:
2405 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2406 break;
2407 case 0x8:
2408 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2409 break;
2410 case 0x9:
2411 gen_op_iwmmxt_addul_M0_wRn(rd1);
2412 break;
2413 case 0xb:
2414 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2415 break;
2416 default:
2417 return 1;
2419 gen_op_iwmmxt_movq_wRn_M0(wrd);
2420 gen_op_iwmmxt_set_mup();
2421 gen_op_iwmmxt_set_cup();
2422 break;
2423 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2424 case 0x408: case 0x508: case 0x608: case 0x708:
2425 case 0x808: case 0x908: case 0xa08: case 0xb08:
2426 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2427 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2428 return 1;
2429 wrd = (insn >> 12) & 0xf;
2430 rd0 = (insn >> 16) & 0xf;
2431 rd1 = (insn >> 0) & 0xf;
2432 gen_op_iwmmxt_movq_M0_wRn(rd0);
2433 switch ((insn >> 22) & 3) {
2434 case 1:
2435 if (insn & (1 << 21))
2436 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2437 else
2438 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2439 break;
2440 case 2:
2441 if (insn & (1 << 21))
2442 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2443 else
2444 gen_op_iwmmxt_packul_M0_wRn(rd1);
2445 break;
2446 case 3:
2447 if (insn & (1 << 21))
2448 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2449 else
2450 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2451 break;
2453 gen_op_iwmmxt_movq_wRn_M0(wrd);
2454 gen_op_iwmmxt_set_mup();
2455 gen_op_iwmmxt_set_cup();
2456 break;
2457 case 0x201: case 0x203: case 0x205: case 0x207:
2458 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2459 case 0x211: case 0x213: case 0x215: case 0x217:
2460 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2461 wrd = (insn >> 5) & 0xf;
2462 rd0 = (insn >> 12) & 0xf;
2463 rd1 = (insn >> 0) & 0xf;
2464 if (rd0 == 0xf || rd1 == 0xf)
2465 return 1;
2466 gen_op_iwmmxt_movq_M0_wRn(wrd);
2467 tmp = load_reg(s, rd0);
2468 tmp2 = load_reg(s, rd1);
2469 switch ((insn >> 16) & 0xf) {
2470 case 0x0: /* TMIA */
2471 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2472 break;
2473 case 0x8: /* TMIAPH */
2474 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2475 break;
2476 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2477 if (insn & (1 << 16))
2478 tcg_gen_shri_i32(tmp, tmp, 16);
2479 if (insn & (1 << 17))
2480 tcg_gen_shri_i32(tmp2, tmp2, 16);
2481 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2482 break;
2483 default:
2484 tcg_temp_free_i32(tmp2);
2485 tcg_temp_free_i32(tmp);
2486 return 1;
2488 tcg_temp_free_i32(tmp2);
2489 tcg_temp_free_i32(tmp);
2490 gen_op_iwmmxt_movq_wRn_M0(wrd);
2491 gen_op_iwmmxt_set_mup();
2492 break;
2493 default:
2494 return 1;
2497 return 0;
2500 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
2501 (ie. an undefined instruction). */
2502 static int disas_dsp_insn(DisasContext *s, uint32_t insn)
2504 int acc, rd0, rd1, rdhi, rdlo;
2505 TCGv_i32 tmp, tmp2;
2507 if ((insn & 0x0ff00f10) == 0x0e200010) {
2508 /* Multiply with Internal Accumulate Format */
2509 rd0 = (insn >> 12) & 0xf;
2510 rd1 = insn & 0xf;
2511 acc = (insn >> 5) & 7;
2513 if (acc != 0)
2514 return 1;
2516 tmp = load_reg(s, rd0);
2517 tmp2 = load_reg(s, rd1);
2518 switch ((insn >> 16) & 0xf) {
2519 case 0x0: /* MIA */
2520 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2521 break;
2522 case 0x8: /* MIAPH */
2523 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2524 break;
2525 case 0xc: /* MIABB */
2526 case 0xd: /* MIABT */
2527 case 0xe: /* MIATB */
2528 case 0xf: /* MIATT */
2529 if (insn & (1 << 16))
2530 tcg_gen_shri_i32(tmp, tmp, 16);
2531 if (insn & (1 << 17))
2532 tcg_gen_shri_i32(tmp2, tmp2, 16);
2533 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2534 break;
2535 default:
2536 return 1;
2538 tcg_temp_free_i32(tmp2);
2539 tcg_temp_free_i32(tmp);
2541 gen_op_iwmmxt_movq_wRn_M0(acc);
2542 return 0;
2545 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2546 /* Internal Accumulator Access Format */
2547 rdhi = (insn >> 16) & 0xf;
2548 rdlo = (insn >> 12) & 0xf;
2549 acc = insn & 7;
2551 if (acc != 0)
2552 return 1;
2554 if (insn & ARM_CP_RW_BIT) { /* MRA */
2555 iwmmxt_load_reg(cpu_V0, acc);
2556 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
2557 tcg_gen_extrh_i64_i32(cpu_R[rdhi], cpu_V0);
2558 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
2559 } else { /* MAR */
2560 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2561 iwmmxt_store_reg(cpu_V0, acc);
2563 return 0;
2566 return 1;
2569 static void gen_goto_ptr(void)
2571 tcg_gen_lookup_and_goto_ptr();
2574 /* This will end the TB but doesn't guarantee we'll return to
2575 * cpu_loop_exec. Any live exit_requests will be processed as we
2576 * enter the next TB.
2578 static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
2580 if (translator_use_goto_tb(&s->base, dest)) {
2581 tcg_gen_goto_tb(n);
2582 gen_set_pc_im(s, dest);
2583 tcg_gen_exit_tb(s->base.tb, n);
2584 } else {
2585 gen_set_pc_im(s, dest);
2586 gen_goto_ptr();
2588 s->base.is_jmp = DISAS_NORETURN;
2591 /* Jump, specifying which TB number to use if we gen_goto_tb() */
2592 static inline void gen_jmp_tb(DisasContext *s, uint32_t dest, int tbno)
2594 if (unlikely(s->ss_active)) {
2595 /* An indirect jump so that we still trigger the debug exception. */
2596 gen_set_pc_im(s, dest);
2597 s->base.is_jmp = DISAS_JUMP;
2598 return;
2600 switch (s->base.is_jmp) {
2601 case DISAS_NEXT:
2602 case DISAS_TOO_MANY:
2603 case DISAS_NORETURN:
2605 * The normal case: just go to the destination TB.
2606 * NB: NORETURN happens if we generate code like
2607 * gen_brcondi(l);
2608 * gen_jmp();
2609 * gen_set_label(l);
2610 * gen_jmp();
2611 * on the second call to gen_jmp().
2613 gen_goto_tb(s, tbno, dest);
2614 break;
2615 case DISAS_UPDATE_NOCHAIN:
2616 case DISAS_UPDATE_EXIT:
2618 * We already decided we're leaving the TB for some other reason.
2619 * Avoid using goto_tb so we really do exit back to the main loop
2620 * and don't chain to another TB.
2622 gen_set_pc_im(s, dest);
2623 gen_goto_ptr();
2624 s->base.is_jmp = DISAS_NORETURN;
2625 break;
2626 default:
2628 * We shouldn't be emitting code for a jump and also have
2629 * is_jmp set to one of the special cases like DISAS_SWI.
2631 g_assert_not_reached();
2635 static inline void gen_jmp(DisasContext *s, uint32_t dest)
2637 gen_jmp_tb(s, dest, 0);
2640 static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
2642 if (x)
2643 tcg_gen_sari_i32(t0, t0, 16);
2644 else
2645 gen_sxth(t0);
2646 if (y)
2647 tcg_gen_sari_i32(t1, t1, 16);
2648 else
2649 gen_sxth(t1);
2650 tcg_gen_mul_i32(t0, t0, t1);
2653 /* Return the mask of PSR bits set by a MSR instruction. */
2654 static uint32_t msr_mask(DisasContext *s, int flags, int spsr)
2656 uint32_t mask = 0;
2658 if (flags & (1 << 0)) {
2659 mask |= 0xff;
2661 if (flags & (1 << 1)) {
2662 mask |= 0xff00;
2664 if (flags & (1 << 2)) {
2665 mask |= 0xff0000;
2667 if (flags & (1 << 3)) {
2668 mask |= 0xff000000;
2671 /* Mask out undefined and reserved bits. */
2672 mask &= aarch32_cpsr_valid_mask(s->features, s->isar);
2674 /* Mask out execution state. */
2675 if (!spsr) {
2676 mask &= ~CPSR_EXEC;
2679 /* Mask out privileged bits. */
2680 if (IS_USER(s)) {
2681 mask &= CPSR_USER;
2683 return mask;
2686 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
2687 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv_i32 t0)
2689 TCGv_i32 tmp;
2690 if (spsr) {
2691 /* ??? This is also undefined in system mode. */
2692 if (IS_USER(s))
2693 return 1;
2695 tmp = load_cpu_field(spsr);
2696 tcg_gen_andi_i32(tmp, tmp, ~mask);
2697 tcg_gen_andi_i32(t0, t0, mask);
2698 tcg_gen_or_i32(tmp, tmp, t0);
2699 store_cpu_field(tmp, spsr);
2700 } else {
2701 gen_set_cpsr(t0, mask);
2703 tcg_temp_free_i32(t0);
2704 gen_lookup_tb(s);
2705 return 0;
2708 /* Returns nonzero if access to the PSR is not permitted. */
2709 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
2711 TCGv_i32 tmp;
2712 tmp = tcg_temp_new_i32();
2713 tcg_gen_movi_i32(tmp, val);
2714 return gen_set_psr(s, mask, spsr, tmp);
2717 static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
2718 int *tgtmode, int *regno)
2720 /* Decode the r and sysm fields of MSR/MRS banked accesses into
2721 * the target mode and register number, and identify the various
2722 * unpredictable cases.
2723 * MSR (banked) and MRS (banked) are CONSTRAINED UNPREDICTABLE if:
2724 * + executed in user mode
2725 * + using R15 as the src/dest register
2726 * + accessing an unimplemented register
2727 * + accessing a register that's inaccessible at current PL/security state*
2728 * + accessing a register that you could access with a different insn
2729 * We choose to UNDEF in all these cases.
2730 * Since we don't know which of the various AArch32 modes we are in
2731 * we have to defer some checks to runtime.
2732 * Accesses to Monitor mode registers from Secure EL1 (which implies
2733 * that EL3 is AArch64) must trap to EL3.
2735 * If the access checks fail this function will emit code to take
2736 * an exception and return false. Otherwise it will return true,
2737 * and set *tgtmode and *regno appropriately.
2739 int exc_target = default_exception_el(s);
2741 /* These instructions are present only in ARMv8, or in ARMv7 with the
2742 * Virtualization Extensions.
2744 if (!arm_dc_feature(s, ARM_FEATURE_V8) &&
2745 !arm_dc_feature(s, ARM_FEATURE_EL2)) {
2746 goto undef;
2749 if (IS_USER(s) || rn == 15) {
2750 goto undef;
2753 /* The table in the v8 ARM ARM section F5.2.3 describes the encoding
2754 * of registers into (r, sysm).
2756 if (r) {
2757 /* SPSRs for other modes */
2758 switch (sysm) {
2759 case 0xe: /* SPSR_fiq */
2760 *tgtmode = ARM_CPU_MODE_FIQ;
2761 break;
2762 case 0x10: /* SPSR_irq */
2763 *tgtmode = ARM_CPU_MODE_IRQ;
2764 break;
2765 case 0x12: /* SPSR_svc */
2766 *tgtmode = ARM_CPU_MODE_SVC;
2767 break;
2768 case 0x14: /* SPSR_abt */
2769 *tgtmode = ARM_CPU_MODE_ABT;
2770 break;
2771 case 0x16: /* SPSR_und */
2772 *tgtmode = ARM_CPU_MODE_UND;
2773 break;
2774 case 0x1c: /* SPSR_mon */
2775 *tgtmode = ARM_CPU_MODE_MON;
2776 break;
2777 case 0x1e: /* SPSR_hyp */
2778 *tgtmode = ARM_CPU_MODE_HYP;
2779 break;
2780 default: /* unallocated */
2781 goto undef;
2783 /* We arbitrarily assign SPSR a register number of 16. */
2784 *regno = 16;
2785 } else {
2786 /* general purpose registers for other modes */
2787 switch (sysm) {
2788 case 0x0 ... 0x6: /* 0b00xxx : r8_usr ... r14_usr */
2789 *tgtmode = ARM_CPU_MODE_USR;
2790 *regno = sysm + 8;
2791 break;
2792 case 0x8 ... 0xe: /* 0b01xxx : r8_fiq ... r14_fiq */
2793 *tgtmode = ARM_CPU_MODE_FIQ;
2794 *regno = sysm;
2795 break;
2796 case 0x10 ... 0x11: /* 0b1000x : r14_irq, r13_irq */
2797 *tgtmode = ARM_CPU_MODE_IRQ;
2798 *regno = sysm & 1 ? 13 : 14;
2799 break;
2800 case 0x12 ... 0x13: /* 0b1001x : r14_svc, r13_svc */
2801 *tgtmode = ARM_CPU_MODE_SVC;
2802 *regno = sysm & 1 ? 13 : 14;
2803 break;
2804 case 0x14 ... 0x15: /* 0b1010x : r14_abt, r13_abt */
2805 *tgtmode = ARM_CPU_MODE_ABT;
2806 *regno = sysm & 1 ? 13 : 14;
2807 break;
2808 case 0x16 ... 0x17: /* 0b1011x : r14_und, r13_und */
2809 *tgtmode = ARM_CPU_MODE_UND;
2810 *regno = sysm & 1 ? 13 : 14;
2811 break;
2812 case 0x1c ... 0x1d: /* 0b1110x : r14_mon, r13_mon */
2813 *tgtmode = ARM_CPU_MODE_MON;
2814 *regno = sysm & 1 ? 13 : 14;
2815 break;
2816 case 0x1e ... 0x1f: /* 0b1111x : elr_hyp, r13_hyp */
2817 *tgtmode = ARM_CPU_MODE_HYP;
2818 /* Arbitrarily pick 17 for ELR_Hyp (which is not a banked LR!) */
2819 *regno = sysm & 1 ? 13 : 17;
2820 break;
2821 default: /* unallocated */
2822 goto undef;
2826 /* Catch the 'accessing inaccessible register' cases we can detect
2827 * at translate time.
2829 switch (*tgtmode) {
2830 case ARM_CPU_MODE_MON:
2831 if (!arm_dc_feature(s, ARM_FEATURE_EL3) || s->ns) {
2832 goto undef;
2834 if (s->current_el == 1) {
2835 /* If we're in Secure EL1 (which implies that EL3 is AArch64)
2836 * then accesses to Mon registers trap to Secure EL2, if it exists,
2837 * otherwise EL3.
2839 TCGv_i32 tcg_el;
2841 if (arm_dc_feature(s, ARM_FEATURE_AARCH64) &&
2842 dc_isar_feature(aa64_sel2, s)) {
2843 /* Target EL is EL<3 minus SCR_EL3.EEL2> */
2844 tcg_el = load_cpu_field(cp15.scr_el3);
2845 tcg_gen_sextract_i32(tcg_el, tcg_el, ctz32(SCR_EEL2), 1);
2846 tcg_gen_addi_i32(tcg_el, tcg_el, 3);
2847 } else {
2848 tcg_el = tcg_constant_i32(3);
2851 gen_exception_el(s, EXCP_UDEF, syn_uncategorized(), tcg_el);
2852 tcg_temp_free_i32(tcg_el);
2853 return false;
2855 break;
2856 case ARM_CPU_MODE_HYP:
2858 * SPSR_hyp and r13_hyp can only be accessed from Monitor mode
2859 * (and so we can forbid accesses from EL2 or below). elr_hyp
2860 * can be accessed also from Hyp mode, so forbid accesses from
2861 * EL0 or EL1.
2863 if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_el < 2 ||
2864 (s->current_el < 3 && *regno != 17)) {
2865 goto undef;
2867 break;
2868 default:
2869 break;
2872 return true;
2874 undef:
2875 /* If we get here then some access check did not pass */
2876 gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
2877 syn_uncategorized(), exc_target);
2878 return false;
2881 static void gen_msr_banked(DisasContext *s, int r, int sysm, int rn)
2883 TCGv_i32 tcg_reg;
2884 int tgtmode = 0, regno = 0;
2886 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
2887 return;
2890 /* Sync state because msr_banked() can raise exceptions */
2891 gen_set_condexec(s);
2892 gen_set_pc_im(s, s->pc_curr);
2893 tcg_reg = load_reg(s, rn);
2894 gen_helper_msr_banked(cpu_env, tcg_reg,
2895 tcg_constant_i32(tgtmode),
2896 tcg_constant_i32(regno));
2897 tcg_temp_free_i32(tcg_reg);
2898 s->base.is_jmp = DISAS_UPDATE_EXIT;
2901 static void gen_mrs_banked(DisasContext *s, int r, int sysm, int rn)
2903 TCGv_i32 tcg_reg;
2904 int tgtmode = 0, regno = 0;
2906 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
2907 return;
2910 /* Sync state because mrs_banked() can raise exceptions */
2911 gen_set_condexec(s);
2912 gen_set_pc_im(s, s->pc_curr);
2913 tcg_reg = tcg_temp_new_i32();
2914 gen_helper_mrs_banked(tcg_reg, cpu_env,
2915 tcg_constant_i32(tgtmode),
2916 tcg_constant_i32(regno));
2917 store_reg(s, rn, tcg_reg);
2918 s->base.is_jmp = DISAS_UPDATE_EXIT;
2921 /* Store value to PC as for an exception return (ie don't
2922 * mask bits). The subsequent call to gen_helper_cpsr_write_eret()
2923 * will do the masking based on the new value of the Thumb bit.
2925 static void store_pc_exc_ret(DisasContext *s, TCGv_i32 pc)
2927 tcg_gen_mov_i32(cpu_R[15], pc);
2928 tcg_temp_free_i32(pc);
2931 /* Generate a v6 exception return. Marks both values as dead. */
2932 static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
2934 store_pc_exc_ret(s, pc);
2935 /* The cpsr_write_eret helper will mask the low bits of PC
2936 * appropriately depending on the new Thumb bit, so it must
2937 * be called after storing the new PC.
2939 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
2940 gen_io_start();
2942 gen_helper_cpsr_write_eret(cpu_env, cpsr);
2943 tcg_temp_free_i32(cpsr);
2944 /* Must exit loop to check un-masked IRQs */
2945 s->base.is_jmp = DISAS_EXIT;
2948 /* Generate an old-style exception return. Marks pc as dead. */
2949 static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
2951 gen_rfe(s, pc, load_cpu_field(spsr));
2954 static void gen_gvec_fn3_qc(uint32_t rd_ofs, uint32_t rn_ofs, uint32_t rm_ofs,
2955 uint32_t opr_sz, uint32_t max_sz,
2956 gen_helper_gvec_3_ptr *fn)
2958 TCGv_ptr qc_ptr = tcg_temp_new_ptr();
2960 tcg_gen_addi_ptr(qc_ptr, cpu_env, offsetof(CPUARMState, vfp.qc));
2961 tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, qc_ptr,
2962 opr_sz, max_sz, 0, fn);
2963 tcg_temp_free_ptr(qc_ptr);
2966 void gen_gvec_sqrdmlah_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
2967 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
2969 static gen_helper_gvec_3_ptr * const fns[2] = {
2970 gen_helper_gvec_qrdmlah_s16, gen_helper_gvec_qrdmlah_s32
2972 tcg_debug_assert(vece >= 1 && vece <= 2);
2973 gen_gvec_fn3_qc(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, fns[vece - 1]);
2976 void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
2977 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
2979 static gen_helper_gvec_3_ptr * const fns[2] = {
2980 gen_helper_gvec_qrdmlsh_s16, gen_helper_gvec_qrdmlsh_s32
2982 tcg_debug_assert(vece >= 1 && vece <= 2);
2983 gen_gvec_fn3_qc(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, fns[vece - 1]);
2986 #define GEN_CMP0(NAME, COND) \
2987 static void gen_##NAME##0_i32(TCGv_i32 d, TCGv_i32 a) \
2989 tcg_gen_setcondi_i32(COND, d, a, 0); \
2990 tcg_gen_neg_i32(d, d); \
2992 static void gen_##NAME##0_i64(TCGv_i64 d, TCGv_i64 a) \
2994 tcg_gen_setcondi_i64(COND, d, a, 0); \
2995 tcg_gen_neg_i64(d, d); \
2997 static void gen_##NAME##0_vec(unsigned vece, TCGv_vec d, TCGv_vec a) \
2999 TCGv_vec zero = tcg_constant_vec_matching(d, vece, 0); \
3000 tcg_gen_cmp_vec(COND, vece, d, a, zero); \
3002 void gen_gvec_##NAME##0(unsigned vece, uint32_t d, uint32_t m, \
3003 uint32_t opr_sz, uint32_t max_sz) \
3005 const GVecGen2 op[4] = { \
3006 { .fno = gen_helper_gvec_##NAME##0_b, \
3007 .fniv = gen_##NAME##0_vec, \
3008 .opt_opc = vecop_list_cmp, \
3009 .vece = MO_8 }, \
3010 { .fno = gen_helper_gvec_##NAME##0_h, \
3011 .fniv = gen_##NAME##0_vec, \
3012 .opt_opc = vecop_list_cmp, \
3013 .vece = MO_16 }, \
3014 { .fni4 = gen_##NAME##0_i32, \
3015 .fniv = gen_##NAME##0_vec, \
3016 .opt_opc = vecop_list_cmp, \
3017 .vece = MO_32 }, \
3018 { .fni8 = gen_##NAME##0_i64, \
3019 .fniv = gen_##NAME##0_vec, \
3020 .opt_opc = vecop_list_cmp, \
3021 .prefer_i64 = TCG_TARGET_REG_BITS == 64, \
3022 .vece = MO_64 }, \
3023 }; \
3024 tcg_gen_gvec_2(d, m, opr_sz, max_sz, &op[vece]); \
3027 static const TCGOpcode vecop_list_cmp[] = {
3028 INDEX_op_cmp_vec, 0
3031 GEN_CMP0(ceq, TCG_COND_EQ)
3032 GEN_CMP0(cle, TCG_COND_LE)
3033 GEN_CMP0(cge, TCG_COND_GE)
3034 GEN_CMP0(clt, TCG_COND_LT)
3035 GEN_CMP0(cgt, TCG_COND_GT)
3037 #undef GEN_CMP0
3039 static void gen_ssra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3041 tcg_gen_vec_sar8i_i64(a, a, shift);
3042 tcg_gen_vec_add8_i64(d, d, a);
3045 static void gen_ssra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3047 tcg_gen_vec_sar16i_i64(a, a, shift);
3048 tcg_gen_vec_add16_i64(d, d, a);
3051 static void gen_ssra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
3053 tcg_gen_sari_i32(a, a, shift);
3054 tcg_gen_add_i32(d, d, a);
3057 static void gen_ssra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3059 tcg_gen_sari_i64(a, a, shift);
3060 tcg_gen_add_i64(d, d, a);
3063 static void gen_ssra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3065 tcg_gen_sari_vec(vece, a, a, sh);
3066 tcg_gen_add_vec(vece, d, d, a);
3069 void gen_gvec_ssra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3070 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3072 static const TCGOpcode vecop_list[] = {
3073 INDEX_op_sari_vec, INDEX_op_add_vec, 0
3075 static const GVecGen2i ops[4] = {
3076 { .fni8 = gen_ssra8_i64,
3077 .fniv = gen_ssra_vec,
3078 .fno = gen_helper_gvec_ssra_b,
3079 .load_dest = true,
3080 .opt_opc = vecop_list,
3081 .vece = MO_8 },
3082 { .fni8 = gen_ssra16_i64,
3083 .fniv = gen_ssra_vec,
3084 .fno = gen_helper_gvec_ssra_h,
3085 .load_dest = true,
3086 .opt_opc = vecop_list,
3087 .vece = MO_16 },
3088 { .fni4 = gen_ssra32_i32,
3089 .fniv = gen_ssra_vec,
3090 .fno = gen_helper_gvec_ssra_s,
3091 .load_dest = true,
3092 .opt_opc = vecop_list,
3093 .vece = MO_32 },
3094 { .fni8 = gen_ssra64_i64,
3095 .fniv = gen_ssra_vec,
3096 .fno = gen_helper_gvec_ssra_b,
3097 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3098 .opt_opc = vecop_list,
3099 .load_dest = true,
3100 .vece = MO_64 },
3103 /* tszimm encoding produces immediates in the range [1..esize]. */
3104 tcg_debug_assert(shift > 0);
3105 tcg_debug_assert(shift <= (8 << vece));
3108 * Shifts larger than the element size are architecturally valid.
3109 * Signed results in all sign bits.
3111 shift = MIN(shift, (8 << vece) - 1);
3112 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3115 static void gen_usra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3117 tcg_gen_vec_shr8i_i64(a, a, shift);
3118 tcg_gen_vec_add8_i64(d, d, a);
3121 static void gen_usra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3123 tcg_gen_vec_shr16i_i64(a, a, shift);
3124 tcg_gen_vec_add16_i64(d, d, a);
3127 static void gen_usra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
3129 tcg_gen_shri_i32(a, a, shift);
3130 tcg_gen_add_i32(d, d, a);
3133 static void gen_usra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3135 tcg_gen_shri_i64(a, a, shift);
3136 tcg_gen_add_i64(d, d, a);
3139 static void gen_usra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3141 tcg_gen_shri_vec(vece, a, a, sh);
3142 tcg_gen_add_vec(vece, d, d, a);
3145 void gen_gvec_usra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3146 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3148 static const TCGOpcode vecop_list[] = {
3149 INDEX_op_shri_vec, INDEX_op_add_vec, 0
3151 static const GVecGen2i ops[4] = {
3152 { .fni8 = gen_usra8_i64,
3153 .fniv = gen_usra_vec,
3154 .fno = gen_helper_gvec_usra_b,
3155 .load_dest = true,
3156 .opt_opc = vecop_list,
3157 .vece = MO_8, },
3158 { .fni8 = gen_usra16_i64,
3159 .fniv = gen_usra_vec,
3160 .fno = gen_helper_gvec_usra_h,
3161 .load_dest = true,
3162 .opt_opc = vecop_list,
3163 .vece = MO_16, },
3164 { .fni4 = gen_usra32_i32,
3165 .fniv = gen_usra_vec,
3166 .fno = gen_helper_gvec_usra_s,
3167 .load_dest = true,
3168 .opt_opc = vecop_list,
3169 .vece = MO_32, },
3170 { .fni8 = gen_usra64_i64,
3171 .fniv = gen_usra_vec,
3172 .fno = gen_helper_gvec_usra_d,
3173 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3174 .load_dest = true,
3175 .opt_opc = vecop_list,
3176 .vece = MO_64, },
3179 /* tszimm encoding produces immediates in the range [1..esize]. */
3180 tcg_debug_assert(shift > 0);
3181 tcg_debug_assert(shift <= (8 << vece));
3184 * Shifts larger than the element size are architecturally valid.
3185 * Unsigned results in all zeros as input to accumulate: nop.
3187 if (shift < (8 << vece)) {
3188 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3189 } else {
3190 /* Nop, but we do need to clear the tail. */
3191 tcg_gen_gvec_mov(vece, rd_ofs, rd_ofs, opr_sz, max_sz);
3196 * Shift one less than the requested amount, and the low bit is
3197 * the rounding bit. For the 8 and 16-bit operations, because we
3198 * mask the low bit, we can perform a normal integer shift instead
3199 * of a vector shift.
3201 static void gen_srshr8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3203 TCGv_i64 t = tcg_temp_new_i64();
3205 tcg_gen_shri_i64(t, a, sh - 1);
3206 tcg_gen_andi_i64(t, t, dup_const(MO_8, 1));
3207 tcg_gen_vec_sar8i_i64(d, a, sh);
3208 tcg_gen_vec_add8_i64(d, d, t);
3209 tcg_temp_free_i64(t);
3212 static void gen_srshr16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3214 TCGv_i64 t = tcg_temp_new_i64();
3216 tcg_gen_shri_i64(t, a, sh - 1);
3217 tcg_gen_andi_i64(t, t, dup_const(MO_16, 1));
3218 tcg_gen_vec_sar16i_i64(d, a, sh);
3219 tcg_gen_vec_add16_i64(d, d, t);
3220 tcg_temp_free_i64(t);
3223 static void gen_srshr32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
3225 TCGv_i32 t;
3227 /* Handle shift by the input size for the benefit of trans_SRSHR_ri */
3228 if (sh == 32) {
3229 tcg_gen_movi_i32(d, 0);
3230 return;
3232 t = tcg_temp_new_i32();
3233 tcg_gen_extract_i32(t, a, sh - 1, 1);
3234 tcg_gen_sari_i32(d, a, sh);
3235 tcg_gen_add_i32(d, d, t);
3236 tcg_temp_free_i32(t);
3239 static void gen_srshr64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3241 TCGv_i64 t = tcg_temp_new_i64();
3243 tcg_gen_extract_i64(t, a, sh - 1, 1);
3244 tcg_gen_sari_i64(d, a, sh);
3245 tcg_gen_add_i64(d, d, t);
3246 tcg_temp_free_i64(t);
3249 static void gen_srshr_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3251 TCGv_vec t = tcg_temp_new_vec_matching(d);
3252 TCGv_vec ones = tcg_temp_new_vec_matching(d);
3254 tcg_gen_shri_vec(vece, t, a, sh - 1);
3255 tcg_gen_dupi_vec(vece, ones, 1);
3256 tcg_gen_and_vec(vece, t, t, ones);
3257 tcg_gen_sari_vec(vece, d, a, sh);
3258 tcg_gen_add_vec(vece, d, d, t);
3260 tcg_temp_free_vec(t);
3261 tcg_temp_free_vec(ones);
3264 void gen_gvec_srshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3265 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3267 static const TCGOpcode vecop_list[] = {
3268 INDEX_op_shri_vec, INDEX_op_sari_vec, INDEX_op_add_vec, 0
3270 static const GVecGen2i ops[4] = {
3271 { .fni8 = gen_srshr8_i64,
3272 .fniv = gen_srshr_vec,
3273 .fno = gen_helper_gvec_srshr_b,
3274 .opt_opc = vecop_list,
3275 .vece = MO_8 },
3276 { .fni8 = gen_srshr16_i64,
3277 .fniv = gen_srshr_vec,
3278 .fno = gen_helper_gvec_srshr_h,
3279 .opt_opc = vecop_list,
3280 .vece = MO_16 },
3281 { .fni4 = gen_srshr32_i32,
3282 .fniv = gen_srshr_vec,
3283 .fno = gen_helper_gvec_srshr_s,
3284 .opt_opc = vecop_list,
3285 .vece = MO_32 },
3286 { .fni8 = gen_srshr64_i64,
3287 .fniv = gen_srshr_vec,
3288 .fno = gen_helper_gvec_srshr_d,
3289 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3290 .opt_opc = vecop_list,
3291 .vece = MO_64 },
3294 /* tszimm encoding produces immediates in the range [1..esize] */
3295 tcg_debug_assert(shift > 0);
3296 tcg_debug_assert(shift <= (8 << vece));
3298 if (shift == (8 << vece)) {
3300 * Shifts larger than the element size are architecturally valid.
3301 * Signed results in all sign bits. With rounding, this produces
3302 * (-1 + 1) >> 1 == 0, or (0 + 1) >> 1 == 0.
3303 * I.e. always zero.
3305 tcg_gen_gvec_dup_imm(vece, rd_ofs, opr_sz, max_sz, 0);
3306 } else {
3307 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3311 static void gen_srsra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3313 TCGv_i64 t = tcg_temp_new_i64();
3315 gen_srshr8_i64(t, a, sh);
3316 tcg_gen_vec_add8_i64(d, d, t);
3317 tcg_temp_free_i64(t);
3320 static void gen_srsra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3322 TCGv_i64 t = tcg_temp_new_i64();
3324 gen_srshr16_i64(t, a, sh);
3325 tcg_gen_vec_add16_i64(d, d, t);
3326 tcg_temp_free_i64(t);
3329 static void gen_srsra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
3331 TCGv_i32 t = tcg_temp_new_i32();
3333 gen_srshr32_i32(t, a, sh);
3334 tcg_gen_add_i32(d, d, t);
3335 tcg_temp_free_i32(t);
3338 static void gen_srsra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3340 TCGv_i64 t = tcg_temp_new_i64();
3342 gen_srshr64_i64(t, a, sh);
3343 tcg_gen_add_i64(d, d, t);
3344 tcg_temp_free_i64(t);
3347 static void gen_srsra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3349 TCGv_vec t = tcg_temp_new_vec_matching(d);
3351 gen_srshr_vec(vece, t, a, sh);
3352 tcg_gen_add_vec(vece, d, d, t);
3353 tcg_temp_free_vec(t);
3356 void gen_gvec_srsra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3357 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3359 static const TCGOpcode vecop_list[] = {
3360 INDEX_op_shri_vec, INDEX_op_sari_vec, INDEX_op_add_vec, 0
3362 static const GVecGen2i ops[4] = {
3363 { .fni8 = gen_srsra8_i64,
3364 .fniv = gen_srsra_vec,
3365 .fno = gen_helper_gvec_srsra_b,
3366 .opt_opc = vecop_list,
3367 .load_dest = true,
3368 .vece = MO_8 },
3369 { .fni8 = gen_srsra16_i64,
3370 .fniv = gen_srsra_vec,
3371 .fno = gen_helper_gvec_srsra_h,
3372 .opt_opc = vecop_list,
3373 .load_dest = true,
3374 .vece = MO_16 },
3375 { .fni4 = gen_srsra32_i32,
3376 .fniv = gen_srsra_vec,
3377 .fno = gen_helper_gvec_srsra_s,
3378 .opt_opc = vecop_list,
3379 .load_dest = true,
3380 .vece = MO_32 },
3381 { .fni8 = gen_srsra64_i64,
3382 .fniv = gen_srsra_vec,
3383 .fno = gen_helper_gvec_srsra_d,
3384 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3385 .opt_opc = vecop_list,
3386 .load_dest = true,
3387 .vece = MO_64 },
3390 /* tszimm encoding produces immediates in the range [1..esize] */
3391 tcg_debug_assert(shift > 0);
3392 tcg_debug_assert(shift <= (8 << vece));
3395 * Shifts larger than the element size are architecturally valid.
3396 * Signed results in all sign bits. With rounding, this produces
3397 * (-1 + 1) >> 1 == 0, or (0 + 1) >> 1 == 0.
3398 * I.e. always zero. With accumulation, this leaves D unchanged.
3400 if (shift == (8 << vece)) {
3401 /* Nop, but we do need to clear the tail. */
3402 tcg_gen_gvec_mov(vece, rd_ofs, rd_ofs, opr_sz, max_sz);
3403 } else {
3404 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3408 static void gen_urshr8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3410 TCGv_i64 t = tcg_temp_new_i64();
3412 tcg_gen_shri_i64(t, a, sh - 1);
3413 tcg_gen_andi_i64(t, t, dup_const(MO_8, 1));
3414 tcg_gen_vec_shr8i_i64(d, a, sh);
3415 tcg_gen_vec_add8_i64(d, d, t);
3416 tcg_temp_free_i64(t);
3419 static void gen_urshr16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3421 TCGv_i64 t = tcg_temp_new_i64();
3423 tcg_gen_shri_i64(t, a, sh - 1);
3424 tcg_gen_andi_i64(t, t, dup_const(MO_16, 1));
3425 tcg_gen_vec_shr16i_i64(d, a, sh);
3426 tcg_gen_vec_add16_i64(d, d, t);
3427 tcg_temp_free_i64(t);
3430 static void gen_urshr32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
3432 TCGv_i32 t;
3434 /* Handle shift by the input size for the benefit of trans_URSHR_ri */
3435 if (sh == 32) {
3436 tcg_gen_extract_i32(d, a, sh - 1, 1);
3437 return;
3439 t = tcg_temp_new_i32();
3440 tcg_gen_extract_i32(t, a, sh - 1, 1);
3441 tcg_gen_shri_i32(d, a, sh);
3442 tcg_gen_add_i32(d, d, t);
3443 tcg_temp_free_i32(t);
3446 static void gen_urshr64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3448 TCGv_i64 t = tcg_temp_new_i64();
3450 tcg_gen_extract_i64(t, a, sh - 1, 1);
3451 tcg_gen_shri_i64(d, a, sh);
3452 tcg_gen_add_i64(d, d, t);
3453 tcg_temp_free_i64(t);
3456 static void gen_urshr_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t shift)
3458 TCGv_vec t = tcg_temp_new_vec_matching(d);
3459 TCGv_vec ones = tcg_temp_new_vec_matching(d);
3461 tcg_gen_shri_vec(vece, t, a, shift - 1);
3462 tcg_gen_dupi_vec(vece, ones, 1);
3463 tcg_gen_and_vec(vece, t, t, ones);
3464 tcg_gen_shri_vec(vece, d, a, shift);
3465 tcg_gen_add_vec(vece, d, d, t);
3467 tcg_temp_free_vec(t);
3468 tcg_temp_free_vec(ones);
3471 void gen_gvec_urshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3472 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3474 static const TCGOpcode vecop_list[] = {
3475 INDEX_op_shri_vec, INDEX_op_add_vec, 0
3477 static const GVecGen2i ops[4] = {
3478 { .fni8 = gen_urshr8_i64,
3479 .fniv = gen_urshr_vec,
3480 .fno = gen_helper_gvec_urshr_b,
3481 .opt_opc = vecop_list,
3482 .vece = MO_8 },
3483 { .fni8 = gen_urshr16_i64,
3484 .fniv = gen_urshr_vec,
3485 .fno = gen_helper_gvec_urshr_h,
3486 .opt_opc = vecop_list,
3487 .vece = MO_16 },
3488 { .fni4 = gen_urshr32_i32,
3489 .fniv = gen_urshr_vec,
3490 .fno = gen_helper_gvec_urshr_s,
3491 .opt_opc = vecop_list,
3492 .vece = MO_32 },
3493 { .fni8 = gen_urshr64_i64,
3494 .fniv = gen_urshr_vec,
3495 .fno = gen_helper_gvec_urshr_d,
3496 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3497 .opt_opc = vecop_list,
3498 .vece = MO_64 },
3501 /* tszimm encoding produces immediates in the range [1..esize] */
3502 tcg_debug_assert(shift > 0);
3503 tcg_debug_assert(shift <= (8 << vece));
3505 if (shift == (8 << vece)) {
3507 * Shifts larger than the element size are architecturally valid.
3508 * Unsigned results in zero. With rounding, this produces a
3509 * copy of the most significant bit.
3511 tcg_gen_gvec_shri(vece, rd_ofs, rm_ofs, shift - 1, opr_sz, max_sz);
3512 } else {
3513 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3517 static void gen_ursra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3519 TCGv_i64 t = tcg_temp_new_i64();
3521 if (sh == 8) {
3522 tcg_gen_vec_shr8i_i64(t, a, 7);
3523 } else {
3524 gen_urshr8_i64(t, a, sh);
3526 tcg_gen_vec_add8_i64(d, d, t);
3527 tcg_temp_free_i64(t);
3530 static void gen_ursra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3532 TCGv_i64 t = tcg_temp_new_i64();
3534 if (sh == 16) {
3535 tcg_gen_vec_shr16i_i64(t, a, 15);
3536 } else {
3537 gen_urshr16_i64(t, a, sh);
3539 tcg_gen_vec_add16_i64(d, d, t);
3540 tcg_temp_free_i64(t);
3543 static void gen_ursra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
3545 TCGv_i32 t = tcg_temp_new_i32();
3547 if (sh == 32) {
3548 tcg_gen_shri_i32(t, a, 31);
3549 } else {
3550 gen_urshr32_i32(t, a, sh);
3552 tcg_gen_add_i32(d, d, t);
3553 tcg_temp_free_i32(t);
3556 static void gen_ursra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3558 TCGv_i64 t = tcg_temp_new_i64();
3560 if (sh == 64) {
3561 tcg_gen_shri_i64(t, a, 63);
3562 } else {
3563 gen_urshr64_i64(t, a, sh);
3565 tcg_gen_add_i64(d, d, t);
3566 tcg_temp_free_i64(t);
3569 static void gen_ursra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3571 TCGv_vec t = tcg_temp_new_vec_matching(d);
3573 if (sh == (8 << vece)) {
3574 tcg_gen_shri_vec(vece, t, a, sh - 1);
3575 } else {
3576 gen_urshr_vec(vece, t, a, sh);
3578 tcg_gen_add_vec(vece, d, d, t);
3579 tcg_temp_free_vec(t);
3582 void gen_gvec_ursra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3583 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3585 static const TCGOpcode vecop_list[] = {
3586 INDEX_op_shri_vec, INDEX_op_add_vec, 0
3588 static const GVecGen2i ops[4] = {
3589 { .fni8 = gen_ursra8_i64,
3590 .fniv = gen_ursra_vec,
3591 .fno = gen_helper_gvec_ursra_b,
3592 .opt_opc = vecop_list,
3593 .load_dest = true,
3594 .vece = MO_8 },
3595 { .fni8 = gen_ursra16_i64,
3596 .fniv = gen_ursra_vec,
3597 .fno = gen_helper_gvec_ursra_h,
3598 .opt_opc = vecop_list,
3599 .load_dest = true,
3600 .vece = MO_16 },
3601 { .fni4 = gen_ursra32_i32,
3602 .fniv = gen_ursra_vec,
3603 .fno = gen_helper_gvec_ursra_s,
3604 .opt_opc = vecop_list,
3605 .load_dest = true,
3606 .vece = MO_32 },
3607 { .fni8 = gen_ursra64_i64,
3608 .fniv = gen_ursra_vec,
3609 .fno = gen_helper_gvec_ursra_d,
3610 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3611 .opt_opc = vecop_list,
3612 .load_dest = true,
3613 .vece = MO_64 },
3616 /* tszimm encoding produces immediates in the range [1..esize] */
3617 tcg_debug_assert(shift > 0);
3618 tcg_debug_assert(shift <= (8 << vece));
3620 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3623 static void gen_shr8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3625 uint64_t mask = dup_const(MO_8, 0xff >> shift);
3626 TCGv_i64 t = tcg_temp_new_i64();
3628 tcg_gen_shri_i64(t, a, shift);
3629 tcg_gen_andi_i64(t, t, mask);
3630 tcg_gen_andi_i64(d, d, ~mask);
3631 tcg_gen_or_i64(d, d, t);
3632 tcg_temp_free_i64(t);
3635 static void gen_shr16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3637 uint64_t mask = dup_const(MO_16, 0xffff >> shift);
3638 TCGv_i64 t = tcg_temp_new_i64();
3640 tcg_gen_shri_i64(t, a, shift);
3641 tcg_gen_andi_i64(t, t, mask);
3642 tcg_gen_andi_i64(d, d, ~mask);
3643 tcg_gen_or_i64(d, d, t);
3644 tcg_temp_free_i64(t);
3647 static void gen_shr32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
3649 tcg_gen_shri_i32(a, a, shift);
3650 tcg_gen_deposit_i32(d, d, a, 0, 32 - shift);
3653 static void gen_shr64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3655 tcg_gen_shri_i64(a, a, shift);
3656 tcg_gen_deposit_i64(d, d, a, 0, 64 - shift);
3659 static void gen_shr_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3661 TCGv_vec t = tcg_temp_new_vec_matching(d);
3662 TCGv_vec m = tcg_temp_new_vec_matching(d);
3664 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK((8 << vece) - sh, sh));
3665 tcg_gen_shri_vec(vece, t, a, sh);
3666 tcg_gen_and_vec(vece, d, d, m);
3667 tcg_gen_or_vec(vece, d, d, t);
3669 tcg_temp_free_vec(t);
3670 tcg_temp_free_vec(m);
3673 void gen_gvec_sri(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3674 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3676 static const TCGOpcode vecop_list[] = { INDEX_op_shri_vec, 0 };
3677 const GVecGen2i ops[4] = {
3678 { .fni8 = gen_shr8_ins_i64,
3679 .fniv = gen_shr_ins_vec,
3680 .fno = gen_helper_gvec_sri_b,
3681 .load_dest = true,
3682 .opt_opc = vecop_list,
3683 .vece = MO_8 },
3684 { .fni8 = gen_shr16_ins_i64,
3685 .fniv = gen_shr_ins_vec,
3686 .fno = gen_helper_gvec_sri_h,
3687 .load_dest = true,
3688 .opt_opc = vecop_list,
3689 .vece = MO_16 },
3690 { .fni4 = gen_shr32_ins_i32,
3691 .fniv = gen_shr_ins_vec,
3692 .fno = gen_helper_gvec_sri_s,
3693 .load_dest = true,
3694 .opt_opc = vecop_list,
3695 .vece = MO_32 },
3696 { .fni8 = gen_shr64_ins_i64,
3697 .fniv = gen_shr_ins_vec,
3698 .fno = gen_helper_gvec_sri_d,
3699 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3700 .load_dest = true,
3701 .opt_opc = vecop_list,
3702 .vece = MO_64 },
3705 /* tszimm encoding produces immediates in the range [1..esize]. */
3706 tcg_debug_assert(shift > 0);
3707 tcg_debug_assert(shift <= (8 << vece));
3709 /* Shift of esize leaves destination unchanged. */
3710 if (shift < (8 << vece)) {
3711 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3712 } else {
3713 /* Nop, but we do need to clear the tail. */
3714 tcg_gen_gvec_mov(vece, rd_ofs, rd_ofs, opr_sz, max_sz);
3718 static void gen_shl8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3720 uint64_t mask = dup_const(MO_8, 0xff << shift);
3721 TCGv_i64 t = tcg_temp_new_i64();
3723 tcg_gen_shli_i64(t, a, shift);
3724 tcg_gen_andi_i64(t, t, mask);
3725 tcg_gen_andi_i64(d, d, ~mask);
3726 tcg_gen_or_i64(d, d, t);
3727 tcg_temp_free_i64(t);
3730 static void gen_shl16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3732 uint64_t mask = dup_const(MO_16, 0xffff << shift);
3733 TCGv_i64 t = tcg_temp_new_i64();
3735 tcg_gen_shli_i64(t, a, shift);
3736 tcg_gen_andi_i64(t, t, mask);
3737 tcg_gen_andi_i64(d, d, ~mask);
3738 tcg_gen_or_i64(d, d, t);
3739 tcg_temp_free_i64(t);
3742 static void gen_shl32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
3744 tcg_gen_deposit_i32(d, d, a, shift, 32 - shift);
3747 static void gen_shl64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3749 tcg_gen_deposit_i64(d, d, a, shift, 64 - shift);
3752 static void gen_shl_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3754 TCGv_vec t = tcg_temp_new_vec_matching(d);
3755 TCGv_vec m = tcg_temp_new_vec_matching(d);
3757 tcg_gen_shli_vec(vece, t, a, sh);
3758 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK(0, sh));
3759 tcg_gen_and_vec(vece, d, d, m);
3760 tcg_gen_or_vec(vece, d, d, t);
3762 tcg_temp_free_vec(t);
3763 tcg_temp_free_vec(m);
3766 void gen_gvec_sli(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3767 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3769 static const TCGOpcode vecop_list[] = { INDEX_op_shli_vec, 0 };
3770 const GVecGen2i ops[4] = {
3771 { .fni8 = gen_shl8_ins_i64,
3772 .fniv = gen_shl_ins_vec,
3773 .fno = gen_helper_gvec_sli_b,
3774 .load_dest = true,
3775 .opt_opc = vecop_list,
3776 .vece = MO_8 },
3777 { .fni8 = gen_shl16_ins_i64,
3778 .fniv = gen_shl_ins_vec,
3779 .fno = gen_helper_gvec_sli_h,
3780 .load_dest = true,
3781 .opt_opc = vecop_list,
3782 .vece = MO_16 },
3783 { .fni4 = gen_shl32_ins_i32,
3784 .fniv = gen_shl_ins_vec,
3785 .fno = gen_helper_gvec_sli_s,
3786 .load_dest = true,
3787 .opt_opc = vecop_list,
3788 .vece = MO_32 },
3789 { .fni8 = gen_shl64_ins_i64,
3790 .fniv = gen_shl_ins_vec,
3791 .fno = gen_helper_gvec_sli_d,
3792 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3793 .load_dest = true,
3794 .opt_opc = vecop_list,
3795 .vece = MO_64 },
3798 /* tszimm encoding produces immediates in the range [0..esize-1]. */
3799 tcg_debug_assert(shift >= 0);
3800 tcg_debug_assert(shift < (8 << vece));
3802 if (shift == 0) {
3803 tcg_gen_gvec_mov(vece, rd_ofs, rm_ofs, opr_sz, max_sz);
3804 } else {
3805 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3809 static void gen_mla8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3811 gen_helper_neon_mul_u8(a, a, b);
3812 gen_helper_neon_add_u8(d, d, a);
3815 static void gen_mls8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3817 gen_helper_neon_mul_u8(a, a, b);
3818 gen_helper_neon_sub_u8(d, d, a);
3821 static void gen_mla16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3823 gen_helper_neon_mul_u16(a, a, b);
3824 gen_helper_neon_add_u16(d, d, a);
3827 static void gen_mls16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3829 gen_helper_neon_mul_u16(a, a, b);
3830 gen_helper_neon_sub_u16(d, d, a);
3833 static void gen_mla32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3835 tcg_gen_mul_i32(a, a, b);
3836 tcg_gen_add_i32(d, d, a);
3839 static void gen_mls32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3841 tcg_gen_mul_i32(a, a, b);
3842 tcg_gen_sub_i32(d, d, a);
3845 static void gen_mla64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
3847 tcg_gen_mul_i64(a, a, b);
3848 tcg_gen_add_i64(d, d, a);
3851 static void gen_mls64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
3853 tcg_gen_mul_i64(a, a, b);
3854 tcg_gen_sub_i64(d, d, a);
3857 static void gen_mla_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
3859 tcg_gen_mul_vec(vece, a, a, b);
3860 tcg_gen_add_vec(vece, d, d, a);
3863 static void gen_mls_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
3865 tcg_gen_mul_vec(vece, a, a, b);
3866 tcg_gen_sub_vec(vece, d, d, a);
3869 /* Note that while NEON does not support VMLA and VMLS as 64-bit ops,
3870 * these tables are shared with AArch64 which does support them.
3872 void gen_gvec_mla(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
3873 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
3875 static const TCGOpcode vecop_list[] = {
3876 INDEX_op_mul_vec, INDEX_op_add_vec, 0
3878 static const GVecGen3 ops[4] = {
3879 { .fni4 = gen_mla8_i32,
3880 .fniv = gen_mla_vec,
3881 .load_dest = true,
3882 .opt_opc = vecop_list,
3883 .vece = MO_8 },
3884 { .fni4 = gen_mla16_i32,
3885 .fniv = gen_mla_vec,
3886 .load_dest = true,
3887 .opt_opc = vecop_list,
3888 .vece = MO_16 },
3889 { .fni4 = gen_mla32_i32,
3890 .fniv = gen_mla_vec,
3891 .load_dest = true,
3892 .opt_opc = vecop_list,
3893 .vece = MO_32 },
3894 { .fni8 = gen_mla64_i64,
3895 .fniv = gen_mla_vec,
3896 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3897 .load_dest = true,
3898 .opt_opc = vecop_list,
3899 .vece = MO_64 },
3901 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
3904 void gen_gvec_mls(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
3905 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
3907 static const TCGOpcode vecop_list[] = {
3908 INDEX_op_mul_vec, INDEX_op_sub_vec, 0
3910 static const GVecGen3 ops[4] = {
3911 { .fni4 = gen_mls8_i32,
3912 .fniv = gen_mls_vec,
3913 .load_dest = true,
3914 .opt_opc = vecop_list,
3915 .vece = MO_8 },
3916 { .fni4 = gen_mls16_i32,
3917 .fniv = gen_mls_vec,
3918 .load_dest = true,
3919 .opt_opc = vecop_list,
3920 .vece = MO_16 },
3921 { .fni4 = gen_mls32_i32,
3922 .fniv = gen_mls_vec,
3923 .load_dest = true,
3924 .opt_opc = vecop_list,
3925 .vece = MO_32 },
3926 { .fni8 = gen_mls64_i64,
3927 .fniv = gen_mls_vec,
3928 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3929 .load_dest = true,
3930 .opt_opc = vecop_list,
3931 .vece = MO_64 },
3933 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
3936 /* CMTST : test is "if (X & Y != 0)". */
3937 static void gen_cmtst_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3939 tcg_gen_and_i32(d, a, b);
3940 tcg_gen_setcondi_i32(TCG_COND_NE, d, d, 0);
3941 tcg_gen_neg_i32(d, d);
3944 void gen_cmtst_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
3946 tcg_gen_and_i64(d, a, b);
3947 tcg_gen_setcondi_i64(TCG_COND_NE, d, d, 0);
3948 tcg_gen_neg_i64(d, d);
3951 static void gen_cmtst_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
3953 tcg_gen_and_vec(vece, d, a, b);
3954 tcg_gen_dupi_vec(vece, a, 0);
3955 tcg_gen_cmp_vec(TCG_COND_NE, vece, d, d, a);
3958 void gen_gvec_cmtst(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
3959 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
3961 static const TCGOpcode vecop_list[] = { INDEX_op_cmp_vec, 0 };
3962 static const GVecGen3 ops[4] = {
3963 { .fni4 = gen_helper_neon_tst_u8,
3964 .fniv = gen_cmtst_vec,
3965 .opt_opc = vecop_list,
3966 .vece = MO_8 },
3967 { .fni4 = gen_helper_neon_tst_u16,
3968 .fniv = gen_cmtst_vec,
3969 .opt_opc = vecop_list,
3970 .vece = MO_16 },
3971 { .fni4 = gen_cmtst_i32,
3972 .fniv = gen_cmtst_vec,
3973 .opt_opc = vecop_list,
3974 .vece = MO_32 },
3975 { .fni8 = gen_cmtst_i64,
3976 .fniv = gen_cmtst_vec,
3977 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3978 .opt_opc = vecop_list,
3979 .vece = MO_64 },
3981 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
3984 void gen_ushl_i32(TCGv_i32 dst, TCGv_i32 src, TCGv_i32 shift)
3986 TCGv_i32 lval = tcg_temp_new_i32();
3987 TCGv_i32 rval = tcg_temp_new_i32();
3988 TCGv_i32 lsh = tcg_temp_new_i32();
3989 TCGv_i32 rsh = tcg_temp_new_i32();
3990 TCGv_i32 zero = tcg_constant_i32(0);
3991 TCGv_i32 max = tcg_constant_i32(32);
3994 * Rely on the TCG guarantee that out of range shifts produce
3995 * unspecified results, not undefined behaviour (i.e. no trap).
3996 * Discard out-of-range results after the fact.
3998 tcg_gen_ext8s_i32(lsh, shift);
3999 tcg_gen_neg_i32(rsh, lsh);
4000 tcg_gen_shl_i32(lval, src, lsh);
4001 tcg_gen_shr_i32(rval, src, rsh);
4002 tcg_gen_movcond_i32(TCG_COND_LTU, dst, lsh, max, lval, zero);
4003 tcg_gen_movcond_i32(TCG_COND_LTU, dst, rsh, max, rval, dst);
4005 tcg_temp_free_i32(lval);
4006 tcg_temp_free_i32(rval);
4007 tcg_temp_free_i32(lsh);
4008 tcg_temp_free_i32(rsh);
4011 void gen_ushl_i64(TCGv_i64 dst, TCGv_i64 src, TCGv_i64 shift)
4013 TCGv_i64 lval = tcg_temp_new_i64();
4014 TCGv_i64 rval = tcg_temp_new_i64();
4015 TCGv_i64 lsh = tcg_temp_new_i64();
4016 TCGv_i64 rsh = tcg_temp_new_i64();
4017 TCGv_i64 zero = tcg_constant_i64(0);
4018 TCGv_i64 max = tcg_constant_i64(64);
4021 * Rely on the TCG guarantee that out of range shifts produce
4022 * unspecified results, not undefined behaviour (i.e. no trap).
4023 * Discard out-of-range results after the fact.
4025 tcg_gen_ext8s_i64(lsh, shift);
4026 tcg_gen_neg_i64(rsh, lsh);
4027 tcg_gen_shl_i64(lval, src, lsh);
4028 tcg_gen_shr_i64(rval, src, rsh);
4029 tcg_gen_movcond_i64(TCG_COND_LTU, dst, lsh, max, lval, zero);
4030 tcg_gen_movcond_i64(TCG_COND_LTU, dst, rsh, max, rval, dst);
4032 tcg_temp_free_i64(lval);
4033 tcg_temp_free_i64(rval);
4034 tcg_temp_free_i64(lsh);
4035 tcg_temp_free_i64(rsh);
4038 static void gen_ushl_vec(unsigned vece, TCGv_vec dst,
4039 TCGv_vec src, TCGv_vec shift)
4041 TCGv_vec lval = tcg_temp_new_vec_matching(dst);
4042 TCGv_vec rval = tcg_temp_new_vec_matching(dst);
4043 TCGv_vec lsh = tcg_temp_new_vec_matching(dst);
4044 TCGv_vec rsh = tcg_temp_new_vec_matching(dst);
4045 TCGv_vec msk, max;
4047 tcg_gen_neg_vec(vece, rsh, shift);
4048 if (vece == MO_8) {
4049 tcg_gen_mov_vec(lsh, shift);
4050 } else {
4051 msk = tcg_temp_new_vec_matching(dst);
4052 tcg_gen_dupi_vec(vece, msk, 0xff);
4053 tcg_gen_and_vec(vece, lsh, shift, msk);
4054 tcg_gen_and_vec(vece, rsh, rsh, msk);
4055 tcg_temp_free_vec(msk);
4059 * Rely on the TCG guarantee that out of range shifts produce
4060 * unspecified results, not undefined behaviour (i.e. no trap).
4061 * Discard out-of-range results after the fact.
4063 tcg_gen_shlv_vec(vece, lval, src, lsh);
4064 tcg_gen_shrv_vec(vece, rval, src, rsh);
4066 max = tcg_temp_new_vec_matching(dst);
4067 tcg_gen_dupi_vec(vece, max, 8 << vece);
4070 * The choice of LT (signed) and GEU (unsigned) are biased toward
4071 * the instructions of the x86_64 host. For MO_8, the whole byte
4072 * is significant so we must use an unsigned compare; otherwise we
4073 * have already masked to a byte and so a signed compare works.
4074 * Other tcg hosts have a full set of comparisons and do not care.
4076 if (vece == MO_8) {
4077 tcg_gen_cmp_vec(TCG_COND_GEU, vece, lsh, lsh, max);
4078 tcg_gen_cmp_vec(TCG_COND_GEU, vece, rsh, rsh, max);
4079 tcg_gen_andc_vec(vece, lval, lval, lsh);
4080 tcg_gen_andc_vec(vece, rval, rval, rsh);
4081 } else {
4082 tcg_gen_cmp_vec(TCG_COND_LT, vece, lsh, lsh, max);
4083 tcg_gen_cmp_vec(TCG_COND_LT, vece, rsh, rsh, max);
4084 tcg_gen_and_vec(vece, lval, lval, lsh);
4085 tcg_gen_and_vec(vece, rval, rval, rsh);
4087 tcg_gen_or_vec(vece, dst, lval, rval);
4089 tcg_temp_free_vec(max);
4090 tcg_temp_free_vec(lval);
4091 tcg_temp_free_vec(rval);
4092 tcg_temp_free_vec(lsh);
4093 tcg_temp_free_vec(rsh);
4096 void gen_gvec_ushl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4097 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4099 static const TCGOpcode vecop_list[] = {
4100 INDEX_op_neg_vec, INDEX_op_shlv_vec,
4101 INDEX_op_shrv_vec, INDEX_op_cmp_vec, 0
4103 static const GVecGen3 ops[4] = {
4104 { .fniv = gen_ushl_vec,
4105 .fno = gen_helper_gvec_ushl_b,
4106 .opt_opc = vecop_list,
4107 .vece = MO_8 },
4108 { .fniv = gen_ushl_vec,
4109 .fno = gen_helper_gvec_ushl_h,
4110 .opt_opc = vecop_list,
4111 .vece = MO_16 },
4112 { .fni4 = gen_ushl_i32,
4113 .fniv = gen_ushl_vec,
4114 .opt_opc = vecop_list,
4115 .vece = MO_32 },
4116 { .fni8 = gen_ushl_i64,
4117 .fniv = gen_ushl_vec,
4118 .opt_opc = vecop_list,
4119 .vece = MO_64 },
4121 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4124 void gen_sshl_i32(TCGv_i32 dst, TCGv_i32 src, TCGv_i32 shift)
4126 TCGv_i32 lval = tcg_temp_new_i32();
4127 TCGv_i32 rval = tcg_temp_new_i32();
4128 TCGv_i32 lsh = tcg_temp_new_i32();
4129 TCGv_i32 rsh = tcg_temp_new_i32();
4130 TCGv_i32 zero = tcg_constant_i32(0);
4131 TCGv_i32 max = tcg_constant_i32(31);
4134 * Rely on the TCG guarantee that out of range shifts produce
4135 * unspecified results, not undefined behaviour (i.e. no trap).
4136 * Discard out-of-range results after the fact.
4138 tcg_gen_ext8s_i32(lsh, shift);
4139 tcg_gen_neg_i32(rsh, lsh);
4140 tcg_gen_shl_i32(lval, src, lsh);
4141 tcg_gen_umin_i32(rsh, rsh, max);
4142 tcg_gen_sar_i32(rval, src, rsh);
4143 tcg_gen_movcond_i32(TCG_COND_LEU, lval, lsh, max, lval, zero);
4144 tcg_gen_movcond_i32(TCG_COND_LT, dst, lsh, zero, rval, lval);
4146 tcg_temp_free_i32(lval);
4147 tcg_temp_free_i32(rval);
4148 tcg_temp_free_i32(lsh);
4149 tcg_temp_free_i32(rsh);
4152 void gen_sshl_i64(TCGv_i64 dst, TCGv_i64 src, TCGv_i64 shift)
4154 TCGv_i64 lval = tcg_temp_new_i64();
4155 TCGv_i64 rval = tcg_temp_new_i64();
4156 TCGv_i64 lsh = tcg_temp_new_i64();
4157 TCGv_i64 rsh = tcg_temp_new_i64();
4158 TCGv_i64 zero = tcg_constant_i64(0);
4159 TCGv_i64 max = tcg_constant_i64(63);
4162 * Rely on the TCG guarantee that out of range shifts produce
4163 * unspecified results, not undefined behaviour (i.e. no trap).
4164 * Discard out-of-range results after the fact.
4166 tcg_gen_ext8s_i64(lsh, shift);
4167 tcg_gen_neg_i64(rsh, lsh);
4168 tcg_gen_shl_i64(lval, src, lsh);
4169 tcg_gen_umin_i64(rsh, rsh, max);
4170 tcg_gen_sar_i64(rval, src, rsh);
4171 tcg_gen_movcond_i64(TCG_COND_LEU, lval, lsh, max, lval, zero);
4172 tcg_gen_movcond_i64(TCG_COND_LT, dst, lsh, zero, rval, lval);
4174 tcg_temp_free_i64(lval);
4175 tcg_temp_free_i64(rval);
4176 tcg_temp_free_i64(lsh);
4177 tcg_temp_free_i64(rsh);
4180 static void gen_sshl_vec(unsigned vece, TCGv_vec dst,
4181 TCGv_vec src, TCGv_vec shift)
4183 TCGv_vec lval = tcg_temp_new_vec_matching(dst);
4184 TCGv_vec rval = tcg_temp_new_vec_matching(dst);
4185 TCGv_vec lsh = tcg_temp_new_vec_matching(dst);
4186 TCGv_vec rsh = tcg_temp_new_vec_matching(dst);
4187 TCGv_vec tmp = tcg_temp_new_vec_matching(dst);
4190 * Rely on the TCG guarantee that out of range shifts produce
4191 * unspecified results, not undefined behaviour (i.e. no trap).
4192 * Discard out-of-range results after the fact.
4194 tcg_gen_neg_vec(vece, rsh, shift);
4195 if (vece == MO_8) {
4196 tcg_gen_mov_vec(lsh, shift);
4197 } else {
4198 tcg_gen_dupi_vec(vece, tmp, 0xff);
4199 tcg_gen_and_vec(vece, lsh, shift, tmp);
4200 tcg_gen_and_vec(vece, rsh, rsh, tmp);
4203 /* Bound rsh so out of bound right shift gets -1. */
4204 tcg_gen_dupi_vec(vece, tmp, (8 << vece) - 1);
4205 tcg_gen_umin_vec(vece, rsh, rsh, tmp);
4206 tcg_gen_cmp_vec(TCG_COND_GT, vece, tmp, lsh, tmp);
4208 tcg_gen_shlv_vec(vece, lval, src, lsh);
4209 tcg_gen_sarv_vec(vece, rval, src, rsh);
4211 /* Select in-bound left shift. */
4212 tcg_gen_andc_vec(vece, lval, lval, tmp);
4214 /* Select between left and right shift. */
4215 if (vece == MO_8) {
4216 tcg_gen_dupi_vec(vece, tmp, 0);
4217 tcg_gen_cmpsel_vec(TCG_COND_LT, vece, dst, lsh, tmp, rval, lval);
4218 } else {
4219 tcg_gen_dupi_vec(vece, tmp, 0x80);
4220 tcg_gen_cmpsel_vec(TCG_COND_LT, vece, dst, lsh, tmp, lval, rval);
4223 tcg_temp_free_vec(lval);
4224 tcg_temp_free_vec(rval);
4225 tcg_temp_free_vec(lsh);
4226 tcg_temp_free_vec(rsh);
4227 tcg_temp_free_vec(tmp);
4230 void gen_gvec_sshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4231 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4233 static const TCGOpcode vecop_list[] = {
4234 INDEX_op_neg_vec, INDEX_op_umin_vec, INDEX_op_shlv_vec,
4235 INDEX_op_sarv_vec, INDEX_op_cmp_vec, INDEX_op_cmpsel_vec, 0
4237 static const GVecGen3 ops[4] = {
4238 { .fniv = gen_sshl_vec,
4239 .fno = gen_helper_gvec_sshl_b,
4240 .opt_opc = vecop_list,
4241 .vece = MO_8 },
4242 { .fniv = gen_sshl_vec,
4243 .fno = gen_helper_gvec_sshl_h,
4244 .opt_opc = vecop_list,
4245 .vece = MO_16 },
4246 { .fni4 = gen_sshl_i32,
4247 .fniv = gen_sshl_vec,
4248 .opt_opc = vecop_list,
4249 .vece = MO_32 },
4250 { .fni8 = gen_sshl_i64,
4251 .fniv = gen_sshl_vec,
4252 .opt_opc = vecop_list,
4253 .vece = MO_64 },
4255 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4258 static void gen_uqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4259 TCGv_vec a, TCGv_vec b)
4261 TCGv_vec x = tcg_temp_new_vec_matching(t);
4262 tcg_gen_add_vec(vece, x, a, b);
4263 tcg_gen_usadd_vec(vece, t, a, b);
4264 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4265 tcg_gen_or_vec(vece, sat, sat, x);
4266 tcg_temp_free_vec(x);
4269 void gen_gvec_uqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4270 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4272 static const TCGOpcode vecop_list[] = {
4273 INDEX_op_usadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
4275 static const GVecGen4 ops[4] = {
4276 { .fniv = gen_uqadd_vec,
4277 .fno = gen_helper_gvec_uqadd_b,
4278 .write_aofs = true,
4279 .opt_opc = vecop_list,
4280 .vece = MO_8 },
4281 { .fniv = gen_uqadd_vec,
4282 .fno = gen_helper_gvec_uqadd_h,
4283 .write_aofs = true,
4284 .opt_opc = vecop_list,
4285 .vece = MO_16 },
4286 { .fniv = gen_uqadd_vec,
4287 .fno = gen_helper_gvec_uqadd_s,
4288 .write_aofs = true,
4289 .opt_opc = vecop_list,
4290 .vece = MO_32 },
4291 { .fniv = gen_uqadd_vec,
4292 .fno = gen_helper_gvec_uqadd_d,
4293 .write_aofs = true,
4294 .opt_opc = vecop_list,
4295 .vece = MO_64 },
4297 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
4298 rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4301 static void gen_sqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4302 TCGv_vec a, TCGv_vec b)
4304 TCGv_vec x = tcg_temp_new_vec_matching(t);
4305 tcg_gen_add_vec(vece, x, a, b);
4306 tcg_gen_ssadd_vec(vece, t, a, b);
4307 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4308 tcg_gen_or_vec(vece, sat, sat, x);
4309 tcg_temp_free_vec(x);
4312 void gen_gvec_sqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4313 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4315 static const TCGOpcode vecop_list[] = {
4316 INDEX_op_ssadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
4318 static const GVecGen4 ops[4] = {
4319 { .fniv = gen_sqadd_vec,
4320 .fno = gen_helper_gvec_sqadd_b,
4321 .opt_opc = vecop_list,
4322 .write_aofs = true,
4323 .vece = MO_8 },
4324 { .fniv = gen_sqadd_vec,
4325 .fno = gen_helper_gvec_sqadd_h,
4326 .opt_opc = vecop_list,
4327 .write_aofs = true,
4328 .vece = MO_16 },
4329 { .fniv = gen_sqadd_vec,
4330 .fno = gen_helper_gvec_sqadd_s,
4331 .opt_opc = vecop_list,
4332 .write_aofs = true,
4333 .vece = MO_32 },
4334 { .fniv = gen_sqadd_vec,
4335 .fno = gen_helper_gvec_sqadd_d,
4336 .opt_opc = vecop_list,
4337 .write_aofs = true,
4338 .vece = MO_64 },
4340 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
4341 rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4344 static void gen_uqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4345 TCGv_vec a, TCGv_vec b)
4347 TCGv_vec x = tcg_temp_new_vec_matching(t);
4348 tcg_gen_sub_vec(vece, x, a, b);
4349 tcg_gen_ussub_vec(vece, t, a, b);
4350 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4351 tcg_gen_or_vec(vece, sat, sat, x);
4352 tcg_temp_free_vec(x);
4355 void gen_gvec_uqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4356 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4358 static const TCGOpcode vecop_list[] = {
4359 INDEX_op_ussub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
4361 static const GVecGen4 ops[4] = {
4362 { .fniv = gen_uqsub_vec,
4363 .fno = gen_helper_gvec_uqsub_b,
4364 .opt_opc = vecop_list,
4365 .write_aofs = true,
4366 .vece = MO_8 },
4367 { .fniv = gen_uqsub_vec,
4368 .fno = gen_helper_gvec_uqsub_h,
4369 .opt_opc = vecop_list,
4370 .write_aofs = true,
4371 .vece = MO_16 },
4372 { .fniv = gen_uqsub_vec,
4373 .fno = gen_helper_gvec_uqsub_s,
4374 .opt_opc = vecop_list,
4375 .write_aofs = true,
4376 .vece = MO_32 },
4377 { .fniv = gen_uqsub_vec,
4378 .fno = gen_helper_gvec_uqsub_d,
4379 .opt_opc = vecop_list,
4380 .write_aofs = true,
4381 .vece = MO_64 },
4383 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
4384 rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4387 static void gen_sqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4388 TCGv_vec a, TCGv_vec b)
4390 TCGv_vec x = tcg_temp_new_vec_matching(t);
4391 tcg_gen_sub_vec(vece, x, a, b);
4392 tcg_gen_sssub_vec(vece, t, a, b);
4393 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4394 tcg_gen_or_vec(vece, sat, sat, x);
4395 tcg_temp_free_vec(x);
4398 void gen_gvec_sqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4399 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4401 static const TCGOpcode vecop_list[] = {
4402 INDEX_op_sssub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
4404 static const GVecGen4 ops[4] = {
4405 { .fniv = gen_sqsub_vec,
4406 .fno = gen_helper_gvec_sqsub_b,
4407 .opt_opc = vecop_list,
4408 .write_aofs = true,
4409 .vece = MO_8 },
4410 { .fniv = gen_sqsub_vec,
4411 .fno = gen_helper_gvec_sqsub_h,
4412 .opt_opc = vecop_list,
4413 .write_aofs = true,
4414 .vece = MO_16 },
4415 { .fniv = gen_sqsub_vec,
4416 .fno = gen_helper_gvec_sqsub_s,
4417 .opt_opc = vecop_list,
4418 .write_aofs = true,
4419 .vece = MO_32 },
4420 { .fniv = gen_sqsub_vec,
4421 .fno = gen_helper_gvec_sqsub_d,
4422 .opt_opc = vecop_list,
4423 .write_aofs = true,
4424 .vece = MO_64 },
4426 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
4427 rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4430 static void gen_sabd_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4432 TCGv_i32 t = tcg_temp_new_i32();
4434 tcg_gen_sub_i32(t, a, b);
4435 tcg_gen_sub_i32(d, b, a);
4436 tcg_gen_movcond_i32(TCG_COND_LT, d, a, b, d, t);
4437 tcg_temp_free_i32(t);
4440 static void gen_sabd_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4442 TCGv_i64 t = tcg_temp_new_i64();
4444 tcg_gen_sub_i64(t, a, b);
4445 tcg_gen_sub_i64(d, b, a);
4446 tcg_gen_movcond_i64(TCG_COND_LT, d, a, b, d, t);
4447 tcg_temp_free_i64(t);
4450 static void gen_sabd_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4452 TCGv_vec t = tcg_temp_new_vec_matching(d);
4454 tcg_gen_smin_vec(vece, t, a, b);
4455 tcg_gen_smax_vec(vece, d, a, b);
4456 tcg_gen_sub_vec(vece, d, d, t);
4457 tcg_temp_free_vec(t);
4460 void gen_gvec_sabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4461 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4463 static const TCGOpcode vecop_list[] = {
4464 INDEX_op_sub_vec, INDEX_op_smin_vec, INDEX_op_smax_vec, 0
4466 static const GVecGen3 ops[4] = {
4467 { .fniv = gen_sabd_vec,
4468 .fno = gen_helper_gvec_sabd_b,
4469 .opt_opc = vecop_list,
4470 .vece = MO_8 },
4471 { .fniv = gen_sabd_vec,
4472 .fno = gen_helper_gvec_sabd_h,
4473 .opt_opc = vecop_list,
4474 .vece = MO_16 },
4475 { .fni4 = gen_sabd_i32,
4476 .fniv = gen_sabd_vec,
4477 .fno = gen_helper_gvec_sabd_s,
4478 .opt_opc = vecop_list,
4479 .vece = MO_32 },
4480 { .fni8 = gen_sabd_i64,
4481 .fniv = gen_sabd_vec,
4482 .fno = gen_helper_gvec_sabd_d,
4483 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4484 .opt_opc = vecop_list,
4485 .vece = MO_64 },
4487 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4490 static void gen_uabd_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4492 TCGv_i32 t = tcg_temp_new_i32();
4494 tcg_gen_sub_i32(t, a, b);
4495 tcg_gen_sub_i32(d, b, a);
4496 tcg_gen_movcond_i32(TCG_COND_LTU, d, a, b, d, t);
4497 tcg_temp_free_i32(t);
4500 static void gen_uabd_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4502 TCGv_i64 t = tcg_temp_new_i64();
4504 tcg_gen_sub_i64(t, a, b);
4505 tcg_gen_sub_i64(d, b, a);
4506 tcg_gen_movcond_i64(TCG_COND_LTU, d, a, b, d, t);
4507 tcg_temp_free_i64(t);
4510 static void gen_uabd_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4512 TCGv_vec t = tcg_temp_new_vec_matching(d);
4514 tcg_gen_umin_vec(vece, t, a, b);
4515 tcg_gen_umax_vec(vece, d, a, b);
4516 tcg_gen_sub_vec(vece, d, d, t);
4517 tcg_temp_free_vec(t);
4520 void gen_gvec_uabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4521 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4523 static const TCGOpcode vecop_list[] = {
4524 INDEX_op_sub_vec, INDEX_op_umin_vec, INDEX_op_umax_vec, 0
4526 static const GVecGen3 ops[4] = {
4527 { .fniv = gen_uabd_vec,
4528 .fno = gen_helper_gvec_uabd_b,
4529 .opt_opc = vecop_list,
4530 .vece = MO_8 },
4531 { .fniv = gen_uabd_vec,
4532 .fno = gen_helper_gvec_uabd_h,
4533 .opt_opc = vecop_list,
4534 .vece = MO_16 },
4535 { .fni4 = gen_uabd_i32,
4536 .fniv = gen_uabd_vec,
4537 .fno = gen_helper_gvec_uabd_s,
4538 .opt_opc = vecop_list,
4539 .vece = MO_32 },
4540 { .fni8 = gen_uabd_i64,
4541 .fniv = gen_uabd_vec,
4542 .fno = gen_helper_gvec_uabd_d,
4543 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4544 .opt_opc = vecop_list,
4545 .vece = MO_64 },
4547 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4550 static void gen_saba_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4552 TCGv_i32 t = tcg_temp_new_i32();
4553 gen_sabd_i32(t, a, b);
4554 tcg_gen_add_i32(d, d, t);
4555 tcg_temp_free_i32(t);
4558 static void gen_saba_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4560 TCGv_i64 t = tcg_temp_new_i64();
4561 gen_sabd_i64(t, a, b);
4562 tcg_gen_add_i64(d, d, t);
4563 tcg_temp_free_i64(t);
4566 static void gen_saba_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4568 TCGv_vec t = tcg_temp_new_vec_matching(d);
4569 gen_sabd_vec(vece, t, a, b);
4570 tcg_gen_add_vec(vece, d, d, t);
4571 tcg_temp_free_vec(t);
4574 void gen_gvec_saba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4575 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4577 static const TCGOpcode vecop_list[] = {
4578 INDEX_op_sub_vec, INDEX_op_add_vec,
4579 INDEX_op_smin_vec, INDEX_op_smax_vec, 0
4581 static const GVecGen3 ops[4] = {
4582 { .fniv = gen_saba_vec,
4583 .fno = gen_helper_gvec_saba_b,
4584 .opt_opc = vecop_list,
4585 .load_dest = true,
4586 .vece = MO_8 },
4587 { .fniv = gen_saba_vec,
4588 .fno = gen_helper_gvec_saba_h,
4589 .opt_opc = vecop_list,
4590 .load_dest = true,
4591 .vece = MO_16 },
4592 { .fni4 = gen_saba_i32,
4593 .fniv = gen_saba_vec,
4594 .fno = gen_helper_gvec_saba_s,
4595 .opt_opc = vecop_list,
4596 .load_dest = true,
4597 .vece = MO_32 },
4598 { .fni8 = gen_saba_i64,
4599 .fniv = gen_saba_vec,
4600 .fno = gen_helper_gvec_saba_d,
4601 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4602 .opt_opc = vecop_list,
4603 .load_dest = true,
4604 .vece = MO_64 },
4606 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4609 static void gen_uaba_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4611 TCGv_i32 t = tcg_temp_new_i32();
4612 gen_uabd_i32(t, a, b);
4613 tcg_gen_add_i32(d, d, t);
4614 tcg_temp_free_i32(t);
4617 static void gen_uaba_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4619 TCGv_i64 t = tcg_temp_new_i64();
4620 gen_uabd_i64(t, a, b);
4621 tcg_gen_add_i64(d, d, t);
4622 tcg_temp_free_i64(t);
4625 static void gen_uaba_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4627 TCGv_vec t = tcg_temp_new_vec_matching(d);
4628 gen_uabd_vec(vece, t, a, b);
4629 tcg_gen_add_vec(vece, d, d, t);
4630 tcg_temp_free_vec(t);
4633 void gen_gvec_uaba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4634 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4636 static const TCGOpcode vecop_list[] = {
4637 INDEX_op_sub_vec, INDEX_op_add_vec,
4638 INDEX_op_umin_vec, INDEX_op_umax_vec, 0
4640 static const GVecGen3 ops[4] = {
4641 { .fniv = gen_uaba_vec,
4642 .fno = gen_helper_gvec_uaba_b,
4643 .opt_opc = vecop_list,
4644 .load_dest = true,
4645 .vece = MO_8 },
4646 { .fniv = gen_uaba_vec,
4647 .fno = gen_helper_gvec_uaba_h,
4648 .opt_opc = vecop_list,
4649 .load_dest = true,
4650 .vece = MO_16 },
4651 { .fni4 = gen_uaba_i32,
4652 .fniv = gen_uaba_vec,
4653 .fno = gen_helper_gvec_uaba_s,
4654 .opt_opc = vecop_list,
4655 .load_dest = true,
4656 .vece = MO_32 },
4657 { .fni8 = gen_uaba_i64,
4658 .fniv = gen_uaba_vec,
4659 .fno = gen_helper_gvec_uaba_d,
4660 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4661 .opt_opc = vecop_list,
4662 .load_dest = true,
4663 .vece = MO_64 },
4665 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4668 static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
4669 int opc1, int crn, int crm, int opc2,
4670 bool isread, int rt, int rt2)
4672 const ARMCPRegInfo *ri;
4674 ri = get_arm_cp_reginfo(s->cp_regs,
4675 ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2));
4676 if (ri) {
4677 bool need_exit_tb;
4679 /* Check access permissions */
4680 if (!cp_access_ok(s->current_el, ri, isread)) {
4681 unallocated_encoding(s);
4682 return;
4685 if (s->hstr_active || ri->accessfn ||
4686 (arm_dc_feature(s, ARM_FEATURE_XSCALE) && cpnum < 14)) {
4687 /* Emit code to perform further access permissions checks at
4688 * runtime; this may result in an exception.
4689 * Note that on XScale all cp0..c13 registers do an access check
4690 * call in order to handle c15_cpar.
4692 uint32_t syndrome;
4694 /* Note that since we are an implementation which takes an
4695 * exception on a trapped conditional instruction only if the
4696 * instruction passes its condition code check, we can take
4697 * advantage of the clause in the ARM ARM that allows us to set
4698 * the COND field in the instruction to 0xE in all cases.
4699 * We could fish the actual condition out of the insn (ARM)
4700 * or the condexec bits (Thumb) but it isn't necessary.
4702 switch (cpnum) {
4703 case 14:
4704 if (is64) {
4705 syndrome = syn_cp14_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
4706 isread, false);
4707 } else {
4708 syndrome = syn_cp14_rt_trap(1, 0xe, opc1, opc2, crn, crm,
4709 rt, isread, false);
4711 break;
4712 case 15:
4713 if (is64) {
4714 syndrome = syn_cp15_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
4715 isread, false);
4716 } else {
4717 syndrome = syn_cp15_rt_trap(1, 0xe, opc1, opc2, crn, crm,
4718 rt, isread, false);
4720 break;
4721 default:
4722 /* ARMv8 defines that only coprocessors 14 and 15 exist,
4723 * so this can only happen if this is an ARMv7 or earlier CPU,
4724 * in which case the syndrome information won't actually be
4725 * guest visible.
4727 assert(!arm_dc_feature(s, ARM_FEATURE_V8));
4728 syndrome = syn_uncategorized();
4729 break;
4732 gen_set_condexec(s);
4733 gen_set_pc_im(s, s->pc_curr);
4734 gen_helper_access_check_cp_reg(cpu_env,
4735 tcg_constant_ptr(ri),
4736 tcg_constant_i32(syndrome),
4737 tcg_constant_i32(isread));
4738 } else if (ri->type & ARM_CP_RAISES_EXC) {
4740 * The readfn or writefn might raise an exception;
4741 * synchronize the CPU state in case it does.
4743 gen_set_condexec(s);
4744 gen_set_pc_im(s, s->pc_curr);
4747 /* Handle special cases first */
4748 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
4749 case ARM_CP_NOP:
4750 return;
4751 case ARM_CP_WFI:
4752 if (isread) {
4753 unallocated_encoding(s);
4754 return;
4756 gen_set_pc_im(s, s->base.pc_next);
4757 s->base.is_jmp = DISAS_WFI;
4758 return;
4759 default:
4760 break;
4763 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
4764 gen_io_start();
4767 if (isread) {
4768 /* Read */
4769 if (is64) {
4770 TCGv_i64 tmp64;
4771 TCGv_i32 tmp;
4772 if (ri->type & ARM_CP_CONST) {
4773 tmp64 = tcg_constant_i64(ri->resetvalue);
4774 } else if (ri->readfn) {
4775 tmp64 = tcg_temp_new_i64();
4776 gen_helper_get_cp_reg64(tmp64, cpu_env,
4777 tcg_constant_ptr(ri));
4778 } else {
4779 tmp64 = tcg_temp_new_i64();
4780 tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
4782 tmp = tcg_temp_new_i32();
4783 tcg_gen_extrl_i64_i32(tmp, tmp64);
4784 store_reg(s, rt, tmp);
4785 tmp = tcg_temp_new_i32();
4786 tcg_gen_extrh_i64_i32(tmp, tmp64);
4787 tcg_temp_free_i64(tmp64);
4788 store_reg(s, rt2, tmp);
4789 } else {
4790 TCGv_i32 tmp;
4791 if (ri->type & ARM_CP_CONST) {
4792 tmp = tcg_constant_i32(ri->resetvalue);
4793 } else if (ri->readfn) {
4794 tmp = tcg_temp_new_i32();
4795 gen_helper_get_cp_reg(tmp, cpu_env, tcg_constant_ptr(ri));
4796 } else {
4797 tmp = load_cpu_offset(ri->fieldoffset);
4799 if (rt == 15) {
4800 /* Destination register of r15 for 32 bit loads sets
4801 * the condition codes from the high 4 bits of the value
4803 gen_set_nzcv(tmp);
4804 tcg_temp_free_i32(tmp);
4805 } else {
4806 store_reg(s, rt, tmp);
4809 } else {
4810 /* Write */
4811 if (ri->type & ARM_CP_CONST) {
4812 /* If not forbidden by access permissions, treat as WI */
4813 return;
4816 if (is64) {
4817 TCGv_i32 tmplo, tmphi;
4818 TCGv_i64 tmp64 = tcg_temp_new_i64();
4819 tmplo = load_reg(s, rt);
4820 tmphi = load_reg(s, rt2);
4821 tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
4822 tcg_temp_free_i32(tmplo);
4823 tcg_temp_free_i32(tmphi);
4824 if (ri->writefn) {
4825 gen_helper_set_cp_reg64(cpu_env, tcg_constant_ptr(ri),
4826 tmp64);
4827 } else {
4828 tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
4830 tcg_temp_free_i64(tmp64);
4831 } else {
4832 TCGv_i32 tmp = load_reg(s, rt);
4833 if (ri->writefn) {
4834 gen_helper_set_cp_reg(cpu_env, tcg_constant_ptr(ri), tmp);
4835 tcg_temp_free_i32(tmp);
4836 } else {
4837 store_cpu_offset(tmp, ri->fieldoffset, 4);
4842 /* I/O operations must end the TB here (whether read or write) */
4843 need_exit_tb = ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) &&
4844 (ri->type & ARM_CP_IO));
4846 if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
4848 * A write to any coprocessor register that ends a TB
4849 * must rebuild the hflags for the next TB.
4851 gen_rebuild_hflags(s, ri->type & ARM_CP_NEWEL);
4853 * We default to ending the TB on a coprocessor register write,
4854 * but allow this to be suppressed by the register definition
4855 * (usually only necessary to work around guest bugs).
4857 need_exit_tb = true;
4859 if (need_exit_tb) {
4860 gen_lookup_tb(s);
4863 return;
4866 /* Unknown register; this might be a guest error or a QEMU
4867 * unimplemented feature.
4869 if (is64) {
4870 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
4871 "64 bit system register cp:%d opc1: %d crm:%d "
4872 "(%s)\n",
4873 isread ? "read" : "write", cpnum, opc1, crm,
4874 s->ns ? "non-secure" : "secure");
4875 } else {
4876 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
4877 "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d "
4878 "(%s)\n",
4879 isread ? "read" : "write", cpnum, opc1, crn, crm, opc2,
4880 s->ns ? "non-secure" : "secure");
4883 unallocated_encoding(s);
4884 return;
4887 /* Decode XScale DSP or iWMMXt insn (in the copro space, cp=0 or 1) */
4888 static void disas_xscale_insn(DisasContext *s, uint32_t insn)
4890 int cpnum = (insn >> 8) & 0xf;
4892 if (extract32(s->c15_cpar, cpnum, 1) == 0) {
4893 unallocated_encoding(s);
4894 } else if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
4895 if (disas_iwmmxt_insn(s, insn)) {
4896 unallocated_encoding(s);
4898 } else if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) {
4899 if (disas_dsp_insn(s, insn)) {
4900 unallocated_encoding(s);
4905 /* Store a 64-bit value to a register pair. Clobbers val. */
4906 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
4908 TCGv_i32 tmp;
4909 tmp = tcg_temp_new_i32();
4910 tcg_gen_extrl_i64_i32(tmp, val);
4911 store_reg(s, rlow, tmp);
4912 tmp = tcg_temp_new_i32();
4913 tcg_gen_extrh_i64_i32(tmp, val);
4914 store_reg(s, rhigh, tmp);
4917 /* load and add a 64-bit value from a register pair. */
4918 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
4920 TCGv_i64 tmp;
4921 TCGv_i32 tmpl;
4922 TCGv_i32 tmph;
4924 /* Load 64-bit value rd:rn. */
4925 tmpl = load_reg(s, rlow);
4926 tmph = load_reg(s, rhigh);
4927 tmp = tcg_temp_new_i64();
4928 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
4929 tcg_temp_free_i32(tmpl);
4930 tcg_temp_free_i32(tmph);
4931 tcg_gen_add_i64(val, val, tmp);
4932 tcg_temp_free_i64(tmp);
4935 /* Set N and Z flags from hi|lo. */
4936 static void gen_logicq_cc(TCGv_i32 lo, TCGv_i32 hi)
4938 tcg_gen_mov_i32(cpu_NF, hi);
4939 tcg_gen_or_i32(cpu_ZF, lo, hi);
4942 /* Load/Store exclusive instructions are implemented by remembering
4943 the value/address loaded, and seeing if these are the same
4944 when the store is performed. This should be sufficient to implement
4945 the architecturally mandated semantics, and avoids having to monitor
4946 regular stores. The compare vs the remembered value is done during
4947 the cmpxchg operation, but we must compare the addresses manually. */
4948 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
4949 TCGv_i32 addr, int size)
4951 TCGv_i32 tmp = tcg_temp_new_i32();
4952 MemOp opc = size | MO_ALIGN | s->be_data;
4954 s->is_ldex = true;
4956 if (size == 3) {
4957 TCGv_i32 tmp2 = tcg_temp_new_i32();
4958 TCGv_i64 t64 = tcg_temp_new_i64();
4961 * For AArch32, architecturally the 32-bit word at the lowest
4962 * address is always Rt and the one at addr+4 is Rt2, even if
4963 * the CPU is big-endian. That means we don't want to do a
4964 * gen_aa32_ld_i64(), which checks SCTLR_B as if for an
4965 * architecturally 64-bit access, but instead do a 64-bit access
4966 * using MO_BE if appropriate and then split the two halves.
4968 TCGv taddr = gen_aa32_addr(s, addr, opc);
4970 tcg_gen_qemu_ld_i64(t64, taddr, get_mem_index(s), opc);
4971 tcg_temp_free(taddr);
4972 tcg_gen_mov_i64(cpu_exclusive_val, t64);
4973 if (s->be_data == MO_BE) {
4974 tcg_gen_extr_i64_i32(tmp2, tmp, t64);
4975 } else {
4976 tcg_gen_extr_i64_i32(tmp, tmp2, t64);
4978 tcg_temp_free_i64(t64);
4980 store_reg(s, rt2, tmp2);
4981 } else {
4982 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), opc);
4983 tcg_gen_extu_i32_i64(cpu_exclusive_val, tmp);
4986 store_reg(s, rt, tmp);
4987 tcg_gen_extu_i32_i64(cpu_exclusive_addr, addr);
4990 static void gen_clrex(DisasContext *s)
4992 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
4995 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
4996 TCGv_i32 addr, int size)
4998 TCGv_i32 t0, t1, t2;
4999 TCGv_i64 extaddr;
5000 TCGv taddr;
5001 TCGLabel *done_label;
5002 TCGLabel *fail_label;
5003 MemOp opc = size | MO_ALIGN | s->be_data;
5005 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
5006 [addr] = {Rt};
5007 {Rd} = 0;
5008 } else {
5009 {Rd} = 1;
5010 } */
5011 fail_label = gen_new_label();
5012 done_label = gen_new_label();
5013 extaddr = tcg_temp_new_i64();
5014 tcg_gen_extu_i32_i64(extaddr, addr);
5015 tcg_gen_brcond_i64(TCG_COND_NE, extaddr, cpu_exclusive_addr, fail_label);
5016 tcg_temp_free_i64(extaddr);
5018 taddr = gen_aa32_addr(s, addr, opc);
5019 t0 = tcg_temp_new_i32();
5020 t1 = load_reg(s, rt);
5021 if (size == 3) {
5022 TCGv_i64 o64 = tcg_temp_new_i64();
5023 TCGv_i64 n64 = tcg_temp_new_i64();
5025 t2 = load_reg(s, rt2);
5028 * For AArch32, architecturally the 32-bit word at the lowest
5029 * address is always Rt and the one at addr+4 is Rt2, even if
5030 * the CPU is big-endian. Since we're going to treat this as a
5031 * single 64-bit BE store, we need to put the two halves in the
5032 * opposite order for BE to LE, so that they end up in the right
5033 * places. We don't want gen_aa32_st_i64, because that checks
5034 * SCTLR_B as if for an architectural 64-bit access.
5036 if (s->be_data == MO_BE) {
5037 tcg_gen_concat_i32_i64(n64, t2, t1);
5038 } else {
5039 tcg_gen_concat_i32_i64(n64, t1, t2);
5041 tcg_temp_free_i32(t2);
5043 tcg_gen_atomic_cmpxchg_i64(o64, taddr, cpu_exclusive_val, n64,
5044 get_mem_index(s), opc);
5045 tcg_temp_free_i64(n64);
5047 tcg_gen_setcond_i64(TCG_COND_NE, o64, o64, cpu_exclusive_val);
5048 tcg_gen_extrl_i64_i32(t0, o64);
5050 tcg_temp_free_i64(o64);
5051 } else {
5052 t2 = tcg_temp_new_i32();
5053 tcg_gen_extrl_i64_i32(t2, cpu_exclusive_val);
5054 tcg_gen_atomic_cmpxchg_i32(t0, taddr, t2, t1, get_mem_index(s), opc);
5055 tcg_gen_setcond_i32(TCG_COND_NE, t0, t0, t2);
5056 tcg_temp_free_i32(t2);
5058 tcg_temp_free_i32(t1);
5059 tcg_temp_free(taddr);
5060 tcg_gen_mov_i32(cpu_R[rd], t0);
5061 tcg_temp_free_i32(t0);
5062 tcg_gen_br(done_label);
5064 gen_set_label(fail_label);
5065 tcg_gen_movi_i32(cpu_R[rd], 1);
5066 gen_set_label(done_label);
5067 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
5070 /* gen_srs:
5071 * @env: CPUARMState
5072 * @s: DisasContext
5073 * @mode: mode field from insn (which stack to store to)
5074 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
5075 * @writeback: true if writeback bit set
5077 * Generate code for the SRS (Store Return State) insn.
5079 static void gen_srs(DisasContext *s,
5080 uint32_t mode, uint32_t amode, bool writeback)
5082 int32_t offset;
5083 TCGv_i32 addr, tmp;
5084 bool undef = false;
5086 /* SRS is:
5087 * - trapped to EL3 if EL3 is AArch64 and we are at Secure EL1
5088 * and specified mode is monitor mode
5089 * - UNDEFINED in Hyp mode
5090 * - UNPREDICTABLE in User or System mode
5091 * - UNPREDICTABLE if the specified mode is:
5092 * -- not implemented
5093 * -- not a valid mode number
5094 * -- a mode that's at a higher exception level
5095 * -- Monitor, if we are Non-secure
5096 * For the UNPREDICTABLE cases we choose to UNDEF.
5098 if (s->current_el == 1 && !s->ns && mode == ARM_CPU_MODE_MON) {
5099 gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(), 3);
5100 return;
5103 if (s->current_el == 0 || s->current_el == 2) {
5104 undef = true;
5107 switch (mode) {
5108 case ARM_CPU_MODE_USR:
5109 case ARM_CPU_MODE_FIQ:
5110 case ARM_CPU_MODE_IRQ:
5111 case ARM_CPU_MODE_SVC:
5112 case ARM_CPU_MODE_ABT:
5113 case ARM_CPU_MODE_UND:
5114 case ARM_CPU_MODE_SYS:
5115 break;
5116 case ARM_CPU_MODE_HYP:
5117 if (s->current_el == 1 || !arm_dc_feature(s, ARM_FEATURE_EL2)) {
5118 undef = true;
5120 break;
5121 case ARM_CPU_MODE_MON:
5122 /* No need to check specifically for "are we non-secure" because
5123 * we've already made EL0 UNDEF and handled the trap for S-EL1;
5124 * so if this isn't EL3 then we must be non-secure.
5126 if (s->current_el != 3) {
5127 undef = true;
5129 break;
5130 default:
5131 undef = true;
5134 if (undef) {
5135 unallocated_encoding(s);
5136 return;
5139 addr = tcg_temp_new_i32();
5140 /* get_r13_banked() will raise an exception if called from System mode */
5141 gen_set_condexec(s);
5142 gen_set_pc_im(s, s->pc_curr);
5143 gen_helper_get_r13_banked(addr, cpu_env, tcg_constant_i32(mode));
5144 switch (amode) {
5145 case 0: /* DA */
5146 offset = -4;
5147 break;
5148 case 1: /* IA */
5149 offset = 0;
5150 break;
5151 case 2: /* DB */
5152 offset = -8;
5153 break;
5154 case 3: /* IB */
5155 offset = 4;
5156 break;
5157 default:
5158 abort();
5160 tcg_gen_addi_i32(addr, addr, offset);
5161 tmp = load_reg(s, 14);
5162 gen_aa32_st_i32(s, tmp, addr, get_mem_index(s), MO_UL | MO_ALIGN);
5163 tcg_temp_free_i32(tmp);
5164 tmp = load_cpu_field(spsr);
5165 tcg_gen_addi_i32(addr, addr, 4);
5166 gen_aa32_st_i32(s, tmp, addr, get_mem_index(s), MO_UL | MO_ALIGN);
5167 tcg_temp_free_i32(tmp);
5168 if (writeback) {
5169 switch (amode) {
5170 case 0:
5171 offset = -8;
5172 break;
5173 case 1:
5174 offset = 4;
5175 break;
5176 case 2:
5177 offset = -4;
5178 break;
5179 case 3:
5180 offset = 0;
5181 break;
5182 default:
5183 abort();
5185 tcg_gen_addi_i32(addr, addr, offset);
5186 gen_helper_set_r13_banked(cpu_env, tcg_constant_i32(mode), addr);
5188 tcg_temp_free_i32(addr);
5189 s->base.is_jmp = DISAS_UPDATE_EXIT;
5192 /* Skip this instruction if the ARM condition is false */
5193 static void arm_skip_unless(DisasContext *s, uint32_t cond)
5195 arm_gen_condlabel(s);
5196 arm_gen_test_cc(cond ^ 1, s->condlabel);
5201 * Constant expanders used by T16/T32 decode
5204 /* Return only the rotation part of T32ExpandImm. */
5205 static int t32_expandimm_rot(DisasContext *s, int x)
5207 return x & 0xc00 ? extract32(x, 7, 5) : 0;
5210 /* Return the unrotated immediate from T32ExpandImm. */
5211 static int t32_expandimm_imm(DisasContext *s, int x)
5213 int imm = extract32(x, 0, 8);
5215 switch (extract32(x, 8, 4)) {
5216 case 0: /* XY */
5217 /* Nothing to do. */
5218 break;
5219 case 1: /* 00XY00XY */
5220 imm *= 0x00010001;
5221 break;
5222 case 2: /* XY00XY00 */
5223 imm *= 0x01000100;
5224 break;
5225 case 3: /* XYXYXYXY */
5226 imm *= 0x01010101;
5227 break;
5228 default:
5229 /* Rotated constant. */
5230 imm |= 0x80;
5231 break;
5233 return imm;
5236 static int t32_branch24(DisasContext *s, int x)
5238 /* Convert J1:J2 at x[22:21] to I2:I1, which involves I=J^~S. */
5239 x ^= !(x < 0) * (3 << 21);
5240 /* Append the final zero. */
5241 return x << 1;
5244 static int t16_setflags(DisasContext *s)
5246 return s->condexec_mask == 0;
5249 static int t16_push_list(DisasContext *s, int x)
5251 return (x & 0xff) | (x & 0x100) << (14 - 8);
5254 static int t16_pop_list(DisasContext *s, int x)
5256 return (x & 0xff) | (x & 0x100) << (15 - 8);
5260 * Include the generated decoders.
5263 #include "decode-a32.c.inc"
5264 #include "decode-a32-uncond.c.inc"
5265 #include "decode-t32.c.inc"
5266 #include "decode-t16.c.inc"
5268 static bool valid_cp(DisasContext *s, int cp)
5271 * Return true if this coprocessor field indicates something
5272 * that's really a possible coprocessor.
5273 * For v7 and earlier, coprocessors 8..15 were reserved for Arm use,
5274 * and of those only cp14 and cp15 were used for registers.
5275 * cp10 and cp11 were used for VFP and Neon, whose decode is
5276 * dealt with elsewhere. With the advent of fp16, cp9 is also
5277 * now part of VFP.
5278 * For v8A and later, the encoding has been tightened so that
5279 * only cp14 and cp15 are valid, and other values aren't considered
5280 * to be in the coprocessor-instruction space at all. v8M still
5281 * permits coprocessors 0..7.
5282 * For XScale, we must not decode the XScale cp0, cp1 space as
5283 * a standard coprocessor insn, because we want to fall through to
5284 * the legacy disas_xscale_insn() decoder after decodetree is done.
5286 if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cp == 0 || cp == 1)) {
5287 return false;
5290 if (arm_dc_feature(s, ARM_FEATURE_V8) &&
5291 !arm_dc_feature(s, ARM_FEATURE_M)) {
5292 return cp >= 14;
5294 return cp < 8 || cp >= 14;
5297 static bool trans_MCR(DisasContext *s, arg_MCR *a)
5299 if (!valid_cp(s, a->cp)) {
5300 return false;
5302 do_coproc_insn(s, a->cp, false, a->opc1, a->crn, a->crm, a->opc2,
5303 false, a->rt, 0);
5304 return true;
5307 static bool trans_MRC(DisasContext *s, arg_MRC *a)
5309 if (!valid_cp(s, a->cp)) {
5310 return false;
5312 do_coproc_insn(s, a->cp, false, a->opc1, a->crn, a->crm, a->opc2,
5313 true, a->rt, 0);
5314 return true;
5317 static bool trans_MCRR(DisasContext *s, arg_MCRR *a)
5319 if (!valid_cp(s, a->cp)) {
5320 return false;
5322 do_coproc_insn(s, a->cp, true, a->opc1, 0, a->crm, 0,
5323 false, a->rt, a->rt2);
5324 return true;
5327 static bool trans_MRRC(DisasContext *s, arg_MRRC *a)
5329 if (!valid_cp(s, a->cp)) {
5330 return false;
5332 do_coproc_insn(s, a->cp, true, a->opc1, 0, a->crm, 0,
5333 true, a->rt, a->rt2);
5334 return true;
5337 /* Helpers to swap operands for reverse-subtract. */
5338 static void gen_rsb(TCGv_i32 dst, TCGv_i32 a, TCGv_i32 b)
5340 tcg_gen_sub_i32(dst, b, a);
5343 static void gen_rsb_CC(TCGv_i32 dst, TCGv_i32 a, TCGv_i32 b)
5345 gen_sub_CC(dst, b, a);
5348 static void gen_rsc(TCGv_i32 dest, TCGv_i32 a, TCGv_i32 b)
5350 gen_sub_carry(dest, b, a);
5353 static void gen_rsc_CC(TCGv_i32 dest, TCGv_i32 a, TCGv_i32 b)
5355 gen_sbc_CC(dest, b, a);
5359 * Helpers for the data processing routines.
5361 * After the computation store the results back.
5362 * This may be suppressed altogether (STREG_NONE), require a runtime
5363 * check against the stack limits (STREG_SP_CHECK), or generate an
5364 * exception return. Oh, or store into a register.
5366 * Always return true, indicating success for a trans_* function.
5368 typedef enum {
5369 STREG_NONE,
5370 STREG_NORMAL,
5371 STREG_SP_CHECK,
5372 STREG_EXC_RET,
5373 } StoreRegKind;
5375 static bool store_reg_kind(DisasContext *s, int rd,
5376 TCGv_i32 val, StoreRegKind kind)
5378 switch (kind) {
5379 case STREG_NONE:
5380 tcg_temp_free_i32(val);
5381 return true;
5382 case STREG_NORMAL:
5383 /* See ALUWritePC: Interworking only from a32 mode. */
5384 if (s->thumb) {
5385 store_reg(s, rd, val);
5386 } else {
5387 store_reg_bx(s, rd, val);
5389 return true;
5390 case STREG_SP_CHECK:
5391 store_sp_checked(s, val);
5392 return true;
5393 case STREG_EXC_RET:
5394 gen_exception_return(s, val);
5395 return true;
5397 g_assert_not_reached();
5401 * Data Processing (register)
5403 * Operate, with set flags, one register source,
5404 * one immediate shifted register source, and a destination.
5406 static bool op_s_rrr_shi(DisasContext *s, arg_s_rrr_shi *a,
5407 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32),
5408 int logic_cc, StoreRegKind kind)
5410 TCGv_i32 tmp1, tmp2;
5412 tmp2 = load_reg(s, a->rm);
5413 gen_arm_shift_im(tmp2, a->shty, a->shim, logic_cc);
5414 tmp1 = load_reg(s, a->rn);
5416 gen(tmp1, tmp1, tmp2);
5417 tcg_temp_free_i32(tmp2);
5419 if (logic_cc) {
5420 gen_logic_CC(tmp1);
5422 return store_reg_kind(s, a->rd, tmp1, kind);
5425 static bool op_s_rxr_shi(DisasContext *s, arg_s_rrr_shi *a,
5426 void (*gen)(TCGv_i32, TCGv_i32),
5427 int logic_cc, StoreRegKind kind)
5429 TCGv_i32 tmp;
5431 tmp = load_reg(s, a->rm);
5432 gen_arm_shift_im(tmp, a->shty, a->shim, logic_cc);
5434 gen(tmp, tmp);
5435 if (logic_cc) {
5436 gen_logic_CC(tmp);
5438 return store_reg_kind(s, a->rd, tmp, kind);
5442 * Data-processing (register-shifted register)
5444 * Operate, with set flags, one register source,
5445 * one register shifted register source, and a destination.
5447 static bool op_s_rrr_shr(DisasContext *s, arg_s_rrr_shr *a,
5448 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32),
5449 int logic_cc, StoreRegKind kind)
5451 TCGv_i32 tmp1, tmp2;
5453 tmp1 = load_reg(s, a->rs);
5454 tmp2 = load_reg(s, a->rm);
5455 gen_arm_shift_reg(tmp2, a->shty, tmp1, logic_cc);
5456 tmp1 = load_reg(s, a->rn);
5458 gen(tmp1, tmp1, tmp2);
5459 tcg_temp_free_i32(tmp2);
5461 if (logic_cc) {
5462 gen_logic_CC(tmp1);
5464 return store_reg_kind(s, a->rd, tmp1, kind);
5467 static bool op_s_rxr_shr(DisasContext *s, arg_s_rrr_shr *a,
5468 void (*gen)(TCGv_i32, TCGv_i32),
5469 int logic_cc, StoreRegKind kind)
5471 TCGv_i32 tmp1, tmp2;
5473 tmp1 = load_reg(s, a->rs);
5474 tmp2 = load_reg(s, a->rm);
5475 gen_arm_shift_reg(tmp2, a->shty, tmp1, logic_cc);
5477 gen(tmp2, tmp2);
5478 if (logic_cc) {
5479 gen_logic_CC(tmp2);
5481 return store_reg_kind(s, a->rd, tmp2, kind);
5485 * Data-processing (immediate)
5487 * Operate, with set flags, one register source,
5488 * one rotated immediate, and a destination.
5490 * Note that logic_cc && a->rot setting CF based on the msb of the
5491 * immediate is the reason why we must pass in the unrotated form
5492 * of the immediate.
5494 static bool op_s_rri_rot(DisasContext *s, arg_s_rri_rot *a,
5495 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32),
5496 int logic_cc, StoreRegKind kind)
5498 TCGv_i32 tmp1;
5499 uint32_t imm;
5501 imm = ror32(a->imm, a->rot);
5502 if (logic_cc && a->rot) {
5503 tcg_gen_movi_i32(cpu_CF, imm >> 31);
5505 tmp1 = load_reg(s, a->rn);
5507 gen(tmp1, tmp1, tcg_constant_i32(imm));
5509 if (logic_cc) {
5510 gen_logic_CC(tmp1);
5512 return store_reg_kind(s, a->rd, tmp1, kind);
5515 static bool op_s_rxi_rot(DisasContext *s, arg_s_rri_rot *a,
5516 void (*gen)(TCGv_i32, TCGv_i32),
5517 int logic_cc, StoreRegKind kind)
5519 TCGv_i32 tmp;
5520 uint32_t imm;
5522 imm = ror32(a->imm, a->rot);
5523 if (logic_cc && a->rot) {
5524 tcg_gen_movi_i32(cpu_CF, imm >> 31);
5527 tmp = tcg_temp_new_i32();
5528 gen(tmp, tcg_constant_i32(imm));
5530 if (logic_cc) {
5531 gen_logic_CC(tmp);
5533 return store_reg_kind(s, a->rd, tmp, kind);
5536 #define DO_ANY3(NAME, OP, L, K) \
5537 static bool trans_##NAME##_rrri(DisasContext *s, arg_s_rrr_shi *a) \
5538 { StoreRegKind k = (K); return op_s_rrr_shi(s, a, OP, L, k); } \
5539 static bool trans_##NAME##_rrrr(DisasContext *s, arg_s_rrr_shr *a) \
5540 { StoreRegKind k = (K); return op_s_rrr_shr(s, a, OP, L, k); } \
5541 static bool trans_##NAME##_rri(DisasContext *s, arg_s_rri_rot *a) \
5542 { StoreRegKind k = (K); return op_s_rri_rot(s, a, OP, L, k); }
5544 #define DO_ANY2(NAME, OP, L, K) \
5545 static bool trans_##NAME##_rxri(DisasContext *s, arg_s_rrr_shi *a) \
5546 { StoreRegKind k = (K); return op_s_rxr_shi(s, a, OP, L, k); } \
5547 static bool trans_##NAME##_rxrr(DisasContext *s, arg_s_rrr_shr *a) \
5548 { StoreRegKind k = (K); return op_s_rxr_shr(s, a, OP, L, k); } \
5549 static bool trans_##NAME##_rxi(DisasContext *s, arg_s_rri_rot *a) \
5550 { StoreRegKind k = (K); return op_s_rxi_rot(s, a, OP, L, k); }
5552 #define DO_CMP2(NAME, OP, L) \
5553 static bool trans_##NAME##_xrri(DisasContext *s, arg_s_rrr_shi *a) \
5554 { return op_s_rrr_shi(s, a, OP, L, STREG_NONE); } \
5555 static bool trans_##NAME##_xrrr(DisasContext *s, arg_s_rrr_shr *a) \
5556 { return op_s_rrr_shr(s, a, OP, L, STREG_NONE); } \
5557 static bool trans_##NAME##_xri(DisasContext *s, arg_s_rri_rot *a) \
5558 { return op_s_rri_rot(s, a, OP, L, STREG_NONE); }
5560 DO_ANY3(AND, tcg_gen_and_i32, a->s, STREG_NORMAL)
5561 DO_ANY3(EOR, tcg_gen_xor_i32, a->s, STREG_NORMAL)
5562 DO_ANY3(ORR, tcg_gen_or_i32, a->s, STREG_NORMAL)
5563 DO_ANY3(BIC, tcg_gen_andc_i32, a->s, STREG_NORMAL)
5565 DO_ANY3(RSB, a->s ? gen_rsb_CC : gen_rsb, false, STREG_NORMAL)
5566 DO_ANY3(ADC, a->s ? gen_adc_CC : gen_add_carry, false, STREG_NORMAL)
5567 DO_ANY3(SBC, a->s ? gen_sbc_CC : gen_sub_carry, false, STREG_NORMAL)
5568 DO_ANY3(RSC, a->s ? gen_rsc_CC : gen_rsc, false, STREG_NORMAL)
5570 DO_CMP2(TST, tcg_gen_and_i32, true)
5571 DO_CMP2(TEQ, tcg_gen_xor_i32, true)
5572 DO_CMP2(CMN, gen_add_CC, false)
5573 DO_CMP2(CMP, gen_sub_CC, false)
5575 DO_ANY3(ADD, a->s ? gen_add_CC : tcg_gen_add_i32, false,
5576 a->rd == 13 && a->rn == 13 ? STREG_SP_CHECK : STREG_NORMAL)
5579 * Note for the computation of StoreRegKind we return out of the
5580 * middle of the functions that are expanded by DO_ANY3, and that
5581 * we modify a->s via that parameter before it is used by OP.
5583 DO_ANY3(SUB, a->s ? gen_sub_CC : tcg_gen_sub_i32, false,
5585 StoreRegKind ret = STREG_NORMAL;
5586 if (a->rd == 15 && a->s) {
5588 * See ALUExceptionReturn:
5589 * In User mode, UNPREDICTABLE; we choose UNDEF.
5590 * In Hyp mode, UNDEFINED.
5592 if (IS_USER(s) || s->current_el == 2) {
5593 unallocated_encoding(s);
5594 return true;
5596 /* There is no writeback of nzcv to PSTATE. */
5597 a->s = 0;
5598 ret = STREG_EXC_RET;
5599 } else if (a->rd == 13 && a->rn == 13) {
5600 ret = STREG_SP_CHECK;
5602 ret;
5605 DO_ANY2(MOV, tcg_gen_mov_i32, a->s,
5607 StoreRegKind ret = STREG_NORMAL;
5608 if (a->rd == 15 && a->s) {
5610 * See ALUExceptionReturn:
5611 * In User mode, UNPREDICTABLE; we choose UNDEF.
5612 * In Hyp mode, UNDEFINED.
5614 if (IS_USER(s) || s->current_el == 2) {
5615 unallocated_encoding(s);
5616 return true;
5618 /* There is no writeback of nzcv to PSTATE. */
5619 a->s = 0;
5620 ret = STREG_EXC_RET;
5621 } else if (a->rd == 13) {
5622 ret = STREG_SP_CHECK;
5624 ret;
5627 DO_ANY2(MVN, tcg_gen_not_i32, a->s, STREG_NORMAL)
5630 * ORN is only available with T32, so there is no register-shifted-register
5631 * form of the insn. Using the DO_ANY3 macro would create an unused function.
5633 static bool trans_ORN_rrri(DisasContext *s, arg_s_rrr_shi *a)
5635 return op_s_rrr_shi(s, a, tcg_gen_orc_i32, a->s, STREG_NORMAL);
5638 static bool trans_ORN_rri(DisasContext *s, arg_s_rri_rot *a)
5640 return op_s_rri_rot(s, a, tcg_gen_orc_i32, a->s, STREG_NORMAL);
5643 #undef DO_ANY3
5644 #undef DO_ANY2
5645 #undef DO_CMP2
5647 static bool trans_ADR(DisasContext *s, arg_ri *a)
5649 store_reg_bx(s, a->rd, add_reg_for_lit(s, 15, a->imm));
5650 return true;
5653 static bool trans_MOVW(DisasContext *s, arg_MOVW *a)
5655 if (!ENABLE_ARCH_6T2) {
5656 return false;
5659 store_reg(s, a->rd, tcg_constant_i32(a->imm));
5660 return true;
5663 static bool trans_MOVT(DisasContext *s, arg_MOVW *a)
5665 TCGv_i32 tmp;
5667 if (!ENABLE_ARCH_6T2) {
5668 return false;
5671 tmp = load_reg(s, a->rd);
5672 tcg_gen_ext16u_i32(tmp, tmp);
5673 tcg_gen_ori_i32(tmp, tmp, a->imm << 16);
5674 store_reg(s, a->rd, tmp);
5675 return true;
5679 * v8.1M MVE wide-shifts
5681 static bool do_mve_shl_ri(DisasContext *s, arg_mve_shl_ri *a,
5682 WideShiftImmFn *fn)
5684 TCGv_i64 rda;
5685 TCGv_i32 rdalo, rdahi;
5687 if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
5688 /* Decode falls through to ORR/MOV UNPREDICTABLE handling */
5689 return false;
5691 if (a->rdahi == 15) {
5692 /* These are a different encoding (SQSHL/SRSHR/UQSHL/URSHR) */
5693 return false;
5695 if (!dc_isar_feature(aa32_mve, s) ||
5696 !arm_dc_feature(s, ARM_FEATURE_M_MAIN) ||
5697 a->rdahi == 13) {
5698 /* RdaHi == 13 is UNPREDICTABLE; we choose to UNDEF */
5699 unallocated_encoding(s);
5700 return true;
5703 if (a->shim == 0) {
5704 a->shim = 32;
5707 rda = tcg_temp_new_i64();
5708 rdalo = load_reg(s, a->rdalo);
5709 rdahi = load_reg(s, a->rdahi);
5710 tcg_gen_concat_i32_i64(rda, rdalo, rdahi);
5712 fn(rda, rda, a->shim);
5714 tcg_gen_extrl_i64_i32(rdalo, rda);
5715 tcg_gen_extrh_i64_i32(rdahi, rda);
5716 store_reg(s, a->rdalo, rdalo);
5717 store_reg(s, a->rdahi, rdahi);
5718 tcg_temp_free_i64(rda);
5720 return true;
5723 static bool trans_ASRL_ri(DisasContext *s, arg_mve_shl_ri *a)
5725 return do_mve_shl_ri(s, a, tcg_gen_sari_i64);
5728 static bool trans_LSLL_ri(DisasContext *s, arg_mve_shl_ri *a)
5730 return do_mve_shl_ri(s, a, tcg_gen_shli_i64);
5733 static bool trans_LSRL_ri(DisasContext *s, arg_mve_shl_ri *a)
5735 return do_mve_shl_ri(s, a, tcg_gen_shri_i64);
5738 static void gen_mve_sqshll(TCGv_i64 r, TCGv_i64 n, int64_t shift)
5740 gen_helper_mve_sqshll(r, cpu_env, n, tcg_constant_i32(shift));
5743 static bool trans_SQSHLL_ri(DisasContext *s, arg_mve_shl_ri *a)
5745 return do_mve_shl_ri(s, a, gen_mve_sqshll);
5748 static void gen_mve_uqshll(TCGv_i64 r, TCGv_i64 n, int64_t shift)
5750 gen_helper_mve_uqshll(r, cpu_env, n, tcg_constant_i32(shift));
5753 static bool trans_UQSHLL_ri(DisasContext *s, arg_mve_shl_ri *a)
5755 return do_mve_shl_ri(s, a, gen_mve_uqshll);
5758 static bool trans_SRSHRL_ri(DisasContext *s, arg_mve_shl_ri *a)
5760 return do_mve_shl_ri(s, a, gen_srshr64_i64);
5763 static bool trans_URSHRL_ri(DisasContext *s, arg_mve_shl_ri *a)
5765 return do_mve_shl_ri(s, a, gen_urshr64_i64);
5768 static bool do_mve_shl_rr(DisasContext *s, arg_mve_shl_rr *a, WideShiftFn *fn)
5770 TCGv_i64 rda;
5771 TCGv_i32 rdalo, rdahi;
5773 if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
5774 /* Decode falls through to ORR/MOV UNPREDICTABLE handling */
5775 return false;
5777 if (a->rdahi == 15) {
5778 /* These are a different encoding (SQSHL/SRSHR/UQSHL/URSHR) */
5779 return false;
5781 if (!dc_isar_feature(aa32_mve, s) ||
5782 !arm_dc_feature(s, ARM_FEATURE_M_MAIN) ||
5783 a->rdahi == 13 || a->rm == 13 || a->rm == 15 ||
5784 a->rm == a->rdahi || a->rm == a->rdalo) {
5785 /* These rdahi/rdalo/rm cases are UNPREDICTABLE; we choose to UNDEF */
5786 unallocated_encoding(s);
5787 return true;
5790 rda = tcg_temp_new_i64();
5791 rdalo = load_reg(s, a->rdalo);
5792 rdahi = load_reg(s, a->rdahi);
5793 tcg_gen_concat_i32_i64(rda, rdalo, rdahi);
5795 /* The helper takes care of the sign-extension of the low 8 bits of Rm */
5796 fn(rda, cpu_env, rda, cpu_R[a->rm]);
5798 tcg_gen_extrl_i64_i32(rdalo, rda);
5799 tcg_gen_extrh_i64_i32(rdahi, rda);
5800 store_reg(s, a->rdalo, rdalo);
5801 store_reg(s, a->rdahi, rdahi);
5802 tcg_temp_free_i64(rda);
5804 return true;
5807 static bool trans_LSLL_rr(DisasContext *s, arg_mve_shl_rr *a)
5809 return do_mve_shl_rr(s, a, gen_helper_mve_ushll);
5812 static bool trans_ASRL_rr(DisasContext *s, arg_mve_shl_rr *a)
5814 return do_mve_shl_rr(s, a, gen_helper_mve_sshrl);
5817 static bool trans_UQRSHLL64_rr(DisasContext *s, arg_mve_shl_rr *a)
5819 return do_mve_shl_rr(s, a, gen_helper_mve_uqrshll);
5822 static bool trans_SQRSHRL64_rr(DisasContext *s, arg_mve_shl_rr *a)
5824 return do_mve_shl_rr(s, a, gen_helper_mve_sqrshrl);
5827 static bool trans_UQRSHLL48_rr(DisasContext *s, arg_mve_shl_rr *a)
5829 return do_mve_shl_rr(s, a, gen_helper_mve_uqrshll48);
5832 static bool trans_SQRSHRL48_rr(DisasContext *s, arg_mve_shl_rr *a)
5834 return do_mve_shl_rr(s, a, gen_helper_mve_sqrshrl48);
5837 static bool do_mve_sh_ri(DisasContext *s, arg_mve_sh_ri *a, ShiftImmFn *fn)
5839 if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
5840 /* Decode falls through to ORR/MOV UNPREDICTABLE handling */
5841 return false;
5843 if (!dc_isar_feature(aa32_mve, s) ||
5844 !arm_dc_feature(s, ARM_FEATURE_M_MAIN) ||
5845 a->rda == 13 || a->rda == 15) {
5846 /* These rda cases are UNPREDICTABLE; we choose to UNDEF */
5847 unallocated_encoding(s);
5848 return true;
5851 if (a->shim == 0) {
5852 a->shim = 32;
5854 fn(cpu_R[a->rda], cpu_R[a->rda], a->shim);
5856 return true;
5859 static bool trans_URSHR_ri(DisasContext *s, arg_mve_sh_ri *a)
5861 return do_mve_sh_ri(s, a, gen_urshr32_i32);
5864 static bool trans_SRSHR_ri(DisasContext *s, arg_mve_sh_ri *a)
5866 return do_mve_sh_ri(s, a, gen_srshr32_i32);
5869 static void gen_mve_sqshl(TCGv_i32 r, TCGv_i32 n, int32_t shift)
5871 gen_helper_mve_sqshl(r, cpu_env, n, tcg_constant_i32(shift));
5874 static bool trans_SQSHL_ri(DisasContext *s, arg_mve_sh_ri *a)
5876 return do_mve_sh_ri(s, a, gen_mve_sqshl);
5879 static void gen_mve_uqshl(TCGv_i32 r, TCGv_i32 n, int32_t shift)
5881 gen_helper_mve_uqshl(r, cpu_env, n, tcg_constant_i32(shift));
5884 static bool trans_UQSHL_ri(DisasContext *s, arg_mve_sh_ri *a)
5886 return do_mve_sh_ri(s, a, gen_mve_uqshl);
5889 static bool do_mve_sh_rr(DisasContext *s, arg_mve_sh_rr *a, ShiftFn *fn)
5891 if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
5892 /* Decode falls through to ORR/MOV UNPREDICTABLE handling */
5893 return false;
5895 if (!dc_isar_feature(aa32_mve, s) ||
5896 !arm_dc_feature(s, ARM_FEATURE_M_MAIN) ||
5897 a->rda == 13 || a->rda == 15 || a->rm == 13 || a->rm == 15 ||
5898 a->rm == a->rda) {
5899 /* These rda/rm cases are UNPREDICTABLE; we choose to UNDEF */
5900 unallocated_encoding(s);
5901 return true;
5904 /* The helper takes care of the sign-extension of the low 8 bits of Rm */
5905 fn(cpu_R[a->rda], cpu_env, cpu_R[a->rda], cpu_R[a->rm]);
5906 return true;
5909 static bool trans_SQRSHR_rr(DisasContext *s, arg_mve_sh_rr *a)
5911 return do_mve_sh_rr(s, a, gen_helper_mve_sqrshr);
5914 static bool trans_UQRSHL_rr(DisasContext *s, arg_mve_sh_rr *a)
5916 return do_mve_sh_rr(s, a, gen_helper_mve_uqrshl);
5920 * Multiply and multiply accumulate
5923 static bool op_mla(DisasContext *s, arg_s_rrrr *a, bool add)
5925 TCGv_i32 t1, t2;
5927 t1 = load_reg(s, a->rn);
5928 t2 = load_reg(s, a->rm);
5929 tcg_gen_mul_i32(t1, t1, t2);
5930 tcg_temp_free_i32(t2);
5931 if (add) {
5932 t2 = load_reg(s, a->ra);
5933 tcg_gen_add_i32(t1, t1, t2);
5934 tcg_temp_free_i32(t2);
5936 if (a->s) {
5937 gen_logic_CC(t1);
5939 store_reg(s, a->rd, t1);
5940 return true;
5943 static bool trans_MUL(DisasContext *s, arg_MUL *a)
5945 return op_mla(s, a, false);
5948 static bool trans_MLA(DisasContext *s, arg_MLA *a)
5950 return op_mla(s, a, true);
5953 static bool trans_MLS(DisasContext *s, arg_MLS *a)
5955 TCGv_i32 t1, t2;
5957 if (!ENABLE_ARCH_6T2) {
5958 return false;
5960 t1 = load_reg(s, a->rn);
5961 t2 = load_reg(s, a->rm);
5962 tcg_gen_mul_i32(t1, t1, t2);
5963 tcg_temp_free_i32(t2);
5964 t2 = load_reg(s, a->ra);
5965 tcg_gen_sub_i32(t1, t2, t1);
5966 tcg_temp_free_i32(t2);
5967 store_reg(s, a->rd, t1);
5968 return true;
5971 static bool op_mlal(DisasContext *s, arg_s_rrrr *a, bool uns, bool add)
5973 TCGv_i32 t0, t1, t2, t3;
5975 t0 = load_reg(s, a->rm);
5976 t1 = load_reg(s, a->rn);
5977 if (uns) {
5978 tcg_gen_mulu2_i32(t0, t1, t0, t1);
5979 } else {
5980 tcg_gen_muls2_i32(t0, t1, t0, t1);
5982 if (add) {
5983 t2 = load_reg(s, a->ra);
5984 t3 = load_reg(s, a->rd);
5985 tcg_gen_add2_i32(t0, t1, t0, t1, t2, t3);
5986 tcg_temp_free_i32(t2);
5987 tcg_temp_free_i32(t3);
5989 if (a->s) {
5990 gen_logicq_cc(t0, t1);
5992 store_reg(s, a->ra, t0);
5993 store_reg(s, a->rd, t1);
5994 return true;
5997 static bool trans_UMULL(DisasContext *s, arg_UMULL *a)
5999 return op_mlal(s, a, true, false);
6002 static bool trans_SMULL(DisasContext *s, arg_SMULL *a)
6004 return op_mlal(s, a, false, false);
6007 static bool trans_UMLAL(DisasContext *s, arg_UMLAL *a)
6009 return op_mlal(s, a, true, true);
6012 static bool trans_SMLAL(DisasContext *s, arg_SMLAL *a)
6014 return op_mlal(s, a, false, true);
6017 static bool trans_UMAAL(DisasContext *s, arg_UMAAL *a)
6019 TCGv_i32 t0, t1, t2, zero;
6021 if (s->thumb
6022 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
6023 : !ENABLE_ARCH_6) {
6024 return false;
6027 t0 = load_reg(s, a->rm);
6028 t1 = load_reg(s, a->rn);
6029 tcg_gen_mulu2_i32(t0, t1, t0, t1);
6030 zero = tcg_constant_i32(0);
6031 t2 = load_reg(s, a->ra);
6032 tcg_gen_add2_i32(t0, t1, t0, t1, t2, zero);
6033 tcg_temp_free_i32(t2);
6034 t2 = load_reg(s, a->rd);
6035 tcg_gen_add2_i32(t0, t1, t0, t1, t2, zero);
6036 tcg_temp_free_i32(t2);
6037 store_reg(s, a->ra, t0);
6038 store_reg(s, a->rd, t1);
6039 return true;
6043 * Saturating addition and subtraction
6046 static bool op_qaddsub(DisasContext *s, arg_rrr *a, bool add, bool doub)
6048 TCGv_i32 t0, t1;
6050 if (s->thumb
6051 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
6052 : !ENABLE_ARCH_5TE) {
6053 return false;
6056 t0 = load_reg(s, a->rm);
6057 t1 = load_reg(s, a->rn);
6058 if (doub) {
6059 gen_helper_add_saturate(t1, cpu_env, t1, t1);
6061 if (add) {
6062 gen_helper_add_saturate(t0, cpu_env, t0, t1);
6063 } else {
6064 gen_helper_sub_saturate(t0, cpu_env, t0, t1);
6066 tcg_temp_free_i32(t1);
6067 store_reg(s, a->rd, t0);
6068 return true;
6071 #define DO_QADDSUB(NAME, ADD, DOUB) \
6072 static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
6074 return op_qaddsub(s, a, ADD, DOUB); \
6077 DO_QADDSUB(QADD, true, false)
6078 DO_QADDSUB(QSUB, false, false)
6079 DO_QADDSUB(QDADD, true, true)
6080 DO_QADDSUB(QDSUB, false, true)
6082 #undef DO_QADDSUB
6085 * Halfword multiply and multiply accumulate
6088 static bool op_smlaxxx(DisasContext *s, arg_rrrr *a,
6089 int add_long, bool nt, bool mt)
6091 TCGv_i32 t0, t1, tl, th;
6093 if (s->thumb
6094 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
6095 : !ENABLE_ARCH_5TE) {
6096 return false;
6099 t0 = load_reg(s, a->rn);
6100 t1 = load_reg(s, a->rm);
6101 gen_mulxy(t0, t1, nt, mt);
6102 tcg_temp_free_i32(t1);
6104 switch (add_long) {
6105 case 0:
6106 store_reg(s, a->rd, t0);
6107 break;
6108 case 1:
6109 t1 = load_reg(s, a->ra);
6110 gen_helper_add_setq(t0, cpu_env, t0, t1);
6111 tcg_temp_free_i32(t1);
6112 store_reg(s, a->rd, t0);
6113 break;
6114 case 2:
6115 tl = load_reg(s, a->ra);
6116 th = load_reg(s, a->rd);
6117 /* Sign-extend the 32-bit product to 64 bits. */
6118 t1 = tcg_temp_new_i32();
6119 tcg_gen_sari_i32(t1, t0, 31);
6120 tcg_gen_add2_i32(tl, th, tl, th, t0, t1);
6121 tcg_temp_free_i32(t0);
6122 tcg_temp_free_i32(t1);
6123 store_reg(s, a->ra, tl);
6124 store_reg(s, a->rd, th);
6125 break;
6126 default:
6127 g_assert_not_reached();
6129 return true;
6132 #define DO_SMLAX(NAME, add, nt, mt) \
6133 static bool trans_##NAME(DisasContext *s, arg_rrrr *a) \
6135 return op_smlaxxx(s, a, add, nt, mt); \
6138 DO_SMLAX(SMULBB, 0, 0, 0)
6139 DO_SMLAX(SMULBT, 0, 0, 1)
6140 DO_SMLAX(SMULTB, 0, 1, 0)
6141 DO_SMLAX(SMULTT, 0, 1, 1)
6143 DO_SMLAX(SMLABB, 1, 0, 0)
6144 DO_SMLAX(SMLABT, 1, 0, 1)
6145 DO_SMLAX(SMLATB, 1, 1, 0)
6146 DO_SMLAX(SMLATT, 1, 1, 1)
6148 DO_SMLAX(SMLALBB, 2, 0, 0)
6149 DO_SMLAX(SMLALBT, 2, 0, 1)
6150 DO_SMLAX(SMLALTB, 2, 1, 0)
6151 DO_SMLAX(SMLALTT, 2, 1, 1)
6153 #undef DO_SMLAX
6155 static bool op_smlawx(DisasContext *s, arg_rrrr *a, bool add, bool mt)
6157 TCGv_i32 t0, t1;
6159 if (!ENABLE_ARCH_5TE) {
6160 return false;
6163 t0 = load_reg(s, a->rn);
6164 t1 = load_reg(s, a->rm);
6166 * Since the nominal result is product<47:16>, shift the 16-bit
6167 * input up by 16 bits, so that the result is at product<63:32>.
6169 if (mt) {
6170 tcg_gen_andi_i32(t1, t1, 0xffff0000);
6171 } else {
6172 tcg_gen_shli_i32(t1, t1, 16);
6174 tcg_gen_muls2_i32(t0, t1, t0, t1);
6175 tcg_temp_free_i32(t0);
6176 if (add) {
6177 t0 = load_reg(s, a->ra);
6178 gen_helper_add_setq(t1, cpu_env, t1, t0);
6179 tcg_temp_free_i32(t0);
6181 store_reg(s, a->rd, t1);
6182 return true;
6185 #define DO_SMLAWX(NAME, add, mt) \
6186 static bool trans_##NAME(DisasContext *s, arg_rrrr *a) \
6188 return op_smlawx(s, a, add, mt); \
6191 DO_SMLAWX(SMULWB, 0, 0)
6192 DO_SMLAWX(SMULWT, 0, 1)
6193 DO_SMLAWX(SMLAWB, 1, 0)
6194 DO_SMLAWX(SMLAWT, 1, 1)
6196 #undef DO_SMLAWX
6199 * MSR (immediate) and hints
6202 static bool trans_YIELD(DisasContext *s, arg_YIELD *a)
6205 * When running single-threaded TCG code, use the helper to ensure that
6206 * the next round-robin scheduled vCPU gets a crack. When running in
6207 * MTTCG we don't generate jumps to the helper as it won't affect the
6208 * scheduling of other vCPUs.
6210 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
6211 gen_set_pc_im(s, s->base.pc_next);
6212 s->base.is_jmp = DISAS_YIELD;
6214 return true;
6217 static bool trans_WFE(DisasContext *s, arg_WFE *a)
6220 * When running single-threaded TCG code, use the helper to ensure that
6221 * the next round-robin scheduled vCPU gets a crack. In MTTCG mode we
6222 * just skip this instruction. Currently the SEV/SEVL instructions,
6223 * which are *one* of many ways to wake the CPU from WFE, are not
6224 * implemented so we can't sleep like WFI does.
6226 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
6227 gen_set_pc_im(s, s->base.pc_next);
6228 s->base.is_jmp = DISAS_WFE;
6230 return true;
6233 static bool trans_WFI(DisasContext *s, arg_WFI *a)
6235 /* For WFI, halt the vCPU until an IRQ. */
6236 gen_set_pc_im(s, s->base.pc_next);
6237 s->base.is_jmp = DISAS_WFI;
6238 return true;
6241 static bool trans_NOP(DisasContext *s, arg_NOP *a)
6243 return true;
6246 static bool trans_MSR_imm(DisasContext *s, arg_MSR_imm *a)
6248 uint32_t val = ror32(a->imm, a->rot * 2);
6249 uint32_t mask = msr_mask(s, a->mask, a->r);
6251 if (gen_set_psr_im(s, mask, a->r, val)) {
6252 unallocated_encoding(s);
6254 return true;
6258 * Cyclic Redundancy Check
6261 static bool op_crc32(DisasContext *s, arg_rrr *a, bool c, MemOp sz)
6263 TCGv_i32 t1, t2, t3;
6265 if (!dc_isar_feature(aa32_crc32, s)) {
6266 return false;
6269 t1 = load_reg(s, a->rn);
6270 t2 = load_reg(s, a->rm);
6271 switch (sz) {
6272 case MO_8:
6273 gen_uxtb(t2);
6274 break;
6275 case MO_16:
6276 gen_uxth(t2);
6277 break;
6278 case MO_32:
6279 break;
6280 default:
6281 g_assert_not_reached();
6283 t3 = tcg_constant_i32(1 << sz);
6284 if (c) {
6285 gen_helper_crc32c(t1, t1, t2, t3);
6286 } else {
6287 gen_helper_crc32(t1, t1, t2, t3);
6289 tcg_temp_free_i32(t2);
6290 store_reg(s, a->rd, t1);
6291 return true;
6294 #define DO_CRC32(NAME, c, sz) \
6295 static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
6296 { return op_crc32(s, a, c, sz); }
6298 DO_CRC32(CRC32B, false, MO_8)
6299 DO_CRC32(CRC32H, false, MO_16)
6300 DO_CRC32(CRC32W, false, MO_32)
6301 DO_CRC32(CRC32CB, true, MO_8)
6302 DO_CRC32(CRC32CH, true, MO_16)
6303 DO_CRC32(CRC32CW, true, MO_32)
6305 #undef DO_CRC32
6308 * Miscellaneous instructions
6311 static bool trans_MRS_bank(DisasContext *s, arg_MRS_bank *a)
6313 if (arm_dc_feature(s, ARM_FEATURE_M)) {
6314 return false;
6316 gen_mrs_banked(s, a->r, a->sysm, a->rd);
6317 return true;
6320 static bool trans_MSR_bank(DisasContext *s, arg_MSR_bank *a)
6322 if (arm_dc_feature(s, ARM_FEATURE_M)) {
6323 return false;
6325 gen_msr_banked(s, a->r, a->sysm, a->rn);
6326 return true;
6329 static bool trans_MRS_reg(DisasContext *s, arg_MRS_reg *a)
6331 TCGv_i32 tmp;
6333 if (arm_dc_feature(s, ARM_FEATURE_M)) {
6334 return false;
6336 if (a->r) {
6337 if (IS_USER(s)) {
6338 unallocated_encoding(s);
6339 return true;
6341 tmp = load_cpu_field(spsr);
6342 } else {
6343 tmp = tcg_temp_new_i32();
6344 gen_helper_cpsr_read(tmp, cpu_env);
6346 store_reg(s, a->rd, tmp);
6347 return true;
6350 static bool trans_MSR_reg(DisasContext *s, arg_MSR_reg *a)
6352 TCGv_i32 tmp;
6353 uint32_t mask = msr_mask(s, a->mask, a->r);
6355 if (arm_dc_feature(s, ARM_FEATURE_M)) {
6356 return false;
6358 tmp = load_reg(s, a->rn);
6359 if (gen_set_psr(s, mask, a->r, tmp)) {
6360 unallocated_encoding(s);
6362 return true;
6365 static bool trans_MRS_v7m(DisasContext *s, arg_MRS_v7m *a)
6367 TCGv_i32 tmp;
6369 if (!arm_dc_feature(s, ARM_FEATURE_M)) {
6370 return false;
6372 tmp = tcg_temp_new_i32();
6373 gen_helper_v7m_mrs(tmp, cpu_env, tcg_constant_i32(a->sysm));
6374 store_reg(s, a->rd, tmp);
6375 return true;
6378 static bool trans_MSR_v7m(DisasContext *s, arg_MSR_v7m *a)
6380 TCGv_i32 addr, reg;
6382 if (!arm_dc_feature(s, ARM_FEATURE_M)) {
6383 return false;
6385 addr = tcg_constant_i32((a->mask << 10) | a->sysm);
6386 reg = load_reg(s, a->rn);
6387 gen_helper_v7m_msr(cpu_env, addr, reg);
6388 tcg_temp_free_i32(reg);
6389 /* If we wrote to CONTROL, the EL might have changed */
6390 gen_rebuild_hflags(s, true);
6391 gen_lookup_tb(s);
6392 return true;
6395 static bool trans_BX(DisasContext *s, arg_BX *a)
6397 if (!ENABLE_ARCH_4T) {
6398 return false;
6400 gen_bx_excret(s, load_reg(s, a->rm));
6401 return true;
6404 static bool trans_BXJ(DisasContext *s, arg_BXJ *a)
6406 if (!ENABLE_ARCH_5J || arm_dc_feature(s, ARM_FEATURE_M)) {
6407 return false;
6410 * v7A allows BXJ to be trapped via HSTR.TJDBX. We don't waste a
6411 * TBFLAGS bit on a basically-never-happens case, so call a helper
6412 * function to check for the trap and raise the exception if needed
6413 * (passing it the register number for the syndrome value).
6414 * v8A doesn't have this HSTR bit.
6416 if (!arm_dc_feature(s, ARM_FEATURE_V8) &&
6417 arm_dc_feature(s, ARM_FEATURE_EL2) &&
6418 s->current_el < 2 && s->ns) {
6419 gen_helper_check_bxj_trap(cpu_env, tcg_constant_i32(a->rm));
6421 /* Trivial implementation equivalent to bx. */
6422 gen_bx(s, load_reg(s, a->rm));
6423 return true;
6426 static bool trans_BLX_r(DisasContext *s, arg_BLX_r *a)
6428 TCGv_i32 tmp;
6430 if (!ENABLE_ARCH_5) {
6431 return false;
6433 tmp = load_reg(s, a->rm);
6434 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
6435 gen_bx(s, tmp);
6436 return true;
6440 * BXNS/BLXNS: only exist for v8M with the security extensions,
6441 * and always UNDEF if NonSecure. We don't implement these in
6442 * the user-only mode either (in theory you can use them from
6443 * Secure User mode but they are too tied in to system emulation).
6445 static bool trans_BXNS(DisasContext *s, arg_BXNS *a)
6447 if (!s->v8m_secure || IS_USER_ONLY) {
6448 unallocated_encoding(s);
6449 } else {
6450 gen_bxns(s, a->rm);
6452 return true;
6455 static bool trans_BLXNS(DisasContext *s, arg_BLXNS *a)
6457 if (!s->v8m_secure || IS_USER_ONLY) {
6458 unallocated_encoding(s);
6459 } else {
6460 gen_blxns(s, a->rm);
6462 return true;
6465 static bool trans_CLZ(DisasContext *s, arg_CLZ *a)
6467 TCGv_i32 tmp;
6469 if (!ENABLE_ARCH_5) {
6470 return false;
6472 tmp = load_reg(s, a->rm);
6473 tcg_gen_clzi_i32(tmp, tmp, 32);
6474 store_reg(s, a->rd, tmp);
6475 return true;
6478 static bool trans_ERET(DisasContext *s, arg_ERET *a)
6480 TCGv_i32 tmp;
6482 if (!arm_dc_feature(s, ARM_FEATURE_V7VE)) {
6483 return false;
6485 if (IS_USER(s)) {
6486 unallocated_encoding(s);
6487 return true;
6489 if (s->current_el == 2) {
6490 /* ERET from Hyp uses ELR_Hyp, not LR */
6491 tmp = load_cpu_field(elr_el[2]);
6492 } else {
6493 tmp = load_reg(s, 14);
6495 gen_exception_return(s, tmp);
6496 return true;
6499 static bool trans_HLT(DisasContext *s, arg_HLT *a)
6501 gen_hlt(s, a->imm);
6502 return true;
6505 static bool trans_BKPT(DisasContext *s, arg_BKPT *a)
6507 if (!ENABLE_ARCH_5) {
6508 return false;
6510 /* BKPT is OK with ECI set and leaves it untouched */
6511 s->eci_handled = true;
6512 if (arm_dc_feature(s, ARM_FEATURE_M) &&
6513 semihosting_enabled() &&
6514 #ifndef CONFIG_USER_ONLY
6515 !IS_USER(s) &&
6516 #endif
6517 (a->imm == 0xab)) {
6518 gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
6519 } else {
6520 gen_exception_bkpt_insn(s, syn_aa32_bkpt(a->imm, false));
6522 return true;
6525 static bool trans_HVC(DisasContext *s, arg_HVC *a)
6527 if (!ENABLE_ARCH_7 || arm_dc_feature(s, ARM_FEATURE_M)) {
6528 return false;
6530 if (IS_USER(s)) {
6531 unallocated_encoding(s);
6532 } else {
6533 gen_hvc(s, a->imm);
6535 return true;
6538 static bool trans_SMC(DisasContext *s, arg_SMC *a)
6540 if (!ENABLE_ARCH_6K || arm_dc_feature(s, ARM_FEATURE_M)) {
6541 return false;
6543 if (IS_USER(s)) {
6544 unallocated_encoding(s);
6545 } else {
6546 gen_smc(s);
6548 return true;
6551 static bool trans_SG(DisasContext *s, arg_SG *a)
6553 if (!arm_dc_feature(s, ARM_FEATURE_M) ||
6554 !arm_dc_feature(s, ARM_FEATURE_V8)) {
6555 return false;
6558 * SG (v8M only)
6559 * The bulk of the behaviour for this instruction is implemented
6560 * in v7m_handle_execute_nsc(), which deals with the insn when
6561 * it is executed by a CPU in non-secure state from memory
6562 * which is Secure & NonSecure-Callable.
6563 * Here we only need to handle the remaining cases:
6564 * * in NS memory (including the "security extension not
6565 * implemented" case) : NOP
6566 * * in S memory but CPU already secure (clear IT bits)
6567 * We know that the attribute for the memory this insn is
6568 * in must match the current CPU state, because otherwise
6569 * get_phys_addr_pmsav8 would have generated an exception.
6571 if (s->v8m_secure) {
6572 /* Like the IT insn, we don't need to generate any code */
6573 s->condexec_cond = 0;
6574 s->condexec_mask = 0;
6576 return true;
6579 static bool trans_TT(DisasContext *s, arg_TT *a)
6581 TCGv_i32 addr, tmp;
6583 if (!arm_dc_feature(s, ARM_FEATURE_M) ||
6584 !arm_dc_feature(s, ARM_FEATURE_V8)) {
6585 return false;
6587 if (a->rd == 13 || a->rd == 15 || a->rn == 15) {
6588 /* We UNDEF for these UNPREDICTABLE cases */
6589 unallocated_encoding(s);
6590 return true;
6592 if (a->A && !s->v8m_secure) {
6593 /* This case is UNDEFINED. */
6594 unallocated_encoding(s);
6595 return true;
6598 addr = load_reg(s, a->rn);
6599 tmp = tcg_temp_new_i32();
6600 gen_helper_v7m_tt(tmp, cpu_env, addr, tcg_constant_i32((a->A << 1) | a->T));
6601 tcg_temp_free_i32(addr);
6602 store_reg(s, a->rd, tmp);
6603 return true;
6607 * Load/store register index
6610 static ISSInfo make_issinfo(DisasContext *s, int rd, bool p, bool w)
6612 ISSInfo ret;
6614 /* ISS not valid if writeback */
6615 if (p && !w) {
6616 ret = rd;
6617 if (s->base.pc_next - s->pc_curr == 2) {
6618 ret |= ISSIs16Bit;
6620 } else {
6621 ret = ISSInvalid;
6623 return ret;
6626 static TCGv_i32 op_addr_rr_pre(DisasContext *s, arg_ldst_rr *a)
6628 TCGv_i32 addr = load_reg(s, a->rn);
6630 if (s->v8m_stackcheck && a->rn == 13 && a->w) {
6631 gen_helper_v8m_stackcheck(cpu_env, addr);
6634 if (a->p) {
6635 TCGv_i32 ofs = load_reg(s, a->rm);
6636 gen_arm_shift_im(ofs, a->shtype, a->shimm, 0);
6637 if (a->u) {
6638 tcg_gen_add_i32(addr, addr, ofs);
6639 } else {
6640 tcg_gen_sub_i32(addr, addr, ofs);
6642 tcg_temp_free_i32(ofs);
6644 return addr;
6647 static void op_addr_rr_post(DisasContext *s, arg_ldst_rr *a,
6648 TCGv_i32 addr, int address_offset)
6650 if (!a->p) {
6651 TCGv_i32 ofs = load_reg(s, a->rm);
6652 gen_arm_shift_im(ofs, a->shtype, a->shimm, 0);
6653 if (a->u) {
6654 tcg_gen_add_i32(addr, addr, ofs);
6655 } else {
6656 tcg_gen_sub_i32(addr, addr, ofs);
6658 tcg_temp_free_i32(ofs);
6659 } else if (!a->w) {
6660 tcg_temp_free_i32(addr);
6661 return;
6663 tcg_gen_addi_i32(addr, addr, address_offset);
6664 store_reg(s, a->rn, addr);
6667 static bool op_load_rr(DisasContext *s, arg_ldst_rr *a,
6668 MemOp mop, int mem_idx)
6670 ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w);
6671 TCGv_i32 addr, tmp;
6673 addr = op_addr_rr_pre(s, a);
6675 tmp = tcg_temp_new_i32();
6676 gen_aa32_ld_i32(s, tmp, addr, mem_idx, mop);
6677 disas_set_da_iss(s, mop, issinfo);
6680 * Perform base writeback before the loaded value to
6681 * ensure correct behavior with overlapping index registers.
6683 op_addr_rr_post(s, a, addr, 0);
6684 store_reg_from_load(s, a->rt, tmp);
6685 return true;
6688 static bool op_store_rr(DisasContext *s, arg_ldst_rr *a,
6689 MemOp mop, int mem_idx)
6691 ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w) | ISSIsWrite;
6692 TCGv_i32 addr, tmp;
6695 * In Thumb encodings of stores Rn=1111 is UNDEF; for Arm it
6696 * is either UNPREDICTABLE or has defined behaviour
6698 if (s->thumb && a->rn == 15) {
6699 return false;
6702 addr = op_addr_rr_pre(s, a);
6704 tmp = load_reg(s, a->rt);
6705 gen_aa32_st_i32(s, tmp, addr, mem_idx, mop);
6706 disas_set_da_iss(s, mop, issinfo);
6707 tcg_temp_free_i32(tmp);
6709 op_addr_rr_post(s, a, addr, 0);
6710 return true;
6713 static bool trans_LDRD_rr(DisasContext *s, arg_ldst_rr *a)
6715 int mem_idx = get_mem_index(s);
6716 TCGv_i32 addr, tmp;
6718 if (!ENABLE_ARCH_5TE) {
6719 return false;
6721 if (a->rt & 1) {
6722 unallocated_encoding(s);
6723 return true;
6725 addr = op_addr_rr_pre(s, a);
6727 tmp = tcg_temp_new_i32();
6728 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
6729 store_reg(s, a->rt, tmp);
6731 tcg_gen_addi_i32(addr, addr, 4);
6733 tmp = tcg_temp_new_i32();
6734 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
6735 store_reg(s, a->rt + 1, tmp);
6737 /* LDRD w/ base writeback is undefined if the registers overlap. */
6738 op_addr_rr_post(s, a, addr, -4);
6739 return true;
6742 static bool trans_STRD_rr(DisasContext *s, arg_ldst_rr *a)
6744 int mem_idx = get_mem_index(s);
6745 TCGv_i32 addr, tmp;
6747 if (!ENABLE_ARCH_5TE) {
6748 return false;
6750 if (a->rt & 1) {
6751 unallocated_encoding(s);
6752 return true;
6754 addr = op_addr_rr_pre(s, a);
6756 tmp = load_reg(s, a->rt);
6757 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
6758 tcg_temp_free_i32(tmp);
6760 tcg_gen_addi_i32(addr, addr, 4);
6762 tmp = load_reg(s, a->rt + 1);
6763 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
6764 tcg_temp_free_i32(tmp);
6766 op_addr_rr_post(s, a, addr, -4);
6767 return true;
6771 * Load/store immediate index
6774 static TCGv_i32 op_addr_ri_pre(DisasContext *s, arg_ldst_ri *a)
6776 int ofs = a->imm;
6778 if (!a->u) {
6779 ofs = -ofs;
6782 if (s->v8m_stackcheck && a->rn == 13 && a->w) {
6784 * Stackcheck. Here we know 'addr' is the current SP;
6785 * U is set if we're moving SP up, else down. It is
6786 * UNKNOWN whether the limit check triggers when SP starts
6787 * below the limit and ends up above it; we chose to do so.
6789 if (!a->u) {
6790 TCGv_i32 newsp = tcg_temp_new_i32();
6791 tcg_gen_addi_i32(newsp, cpu_R[13], ofs);
6792 gen_helper_v8m_stackcheck(cpu_env, newsp);
6793 tcg_temp_free_i32(newsp);
6794 } else {
6795 gen_helper_v8m_stackcheck(cpu_env, cpu_R[13]);
6799 return add_reg_for_lit(s, a->rn, a->p ? ofs : 0);
6802 static void op_addr_ri_post(DisasContext *s, arg_ldst_ri *a,
6803 TCGv_i32 addr, int address_offset)
6805 if (!a->p) {
6806 if (a->u) {
6807 address_offset += a->imm;
6808 } else {
6809 address_offset -= a->imm;
6811 } else if (!a->w) {
6812 tcg_temp_free_i32(addr);
6813 return;
6815 tcg_gen_addi_i32(addr, addr, address_offset);
6816 store_reg(s, a->rn, addr);
6819 static bool op_load_ri(DisasContext *s, arg_ldst_ri *a,
6820 MemOp mop, int mem_idx)
6822 ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w);
6823 TCGv_i32 addr, tmp;
6825 addr = op_addr_ri_pre(s, a);
6827 tmp = tcg_temp_new_i32();
6828 gen_aa32_ld_i32(s, tmp, addr, mem_idx, mop);
6829 disas_set_da_iss(s, mop, issinfo);
6832 * Perform base writeback before the loaded value to
6833 * ensure correct behavior with overlapping index registers.
6835 op_addr_ri_post(s, a, addr, 0);
6836 store_reg_from_load(s, a->rt, tmp);
6837 return true;
6840 static bool op_store_ri(DisasContext *s, arg_ldst_ri *a,
6841 MemOp mop, int mem_idx)
6843 ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w) | ISSIsWrite;
6844 TCGv_i32 addr, tmp;
6847 * In Thumb encodings of stores Rn=1111 is UNDEF; for Arm it
6848 * is either UNPREDICTABLE or has defined behaviour
6850 if (s->thumb && a->rn == 15) {
6851 return false;
6854 addr = op_addr_ri_pre(s, a);
6856 tmp = load_reg(s, a->rt);
6857 gen_aa32_st_i32(s, tmp, addr, mem_idx, mop);
6858 disas_set_da_iss(s, mop, issinfo);
6859 tcg_temp_free_i32(tmp);
6861 op_addr_ri_post(s, a, addr, 0);
6862 return true;
6865 static bool op_ldrd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
6867 int mem_idx = get_mem_index(s);
6868 TCGv_i32 addr, tmp;
6870 addr = op_addr_ri_pre(s, a);
6872 tmp = tcg_temp_new_i32();
6873 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
6874 store_reg(s, a->rt, tmp);
6876 tcg_gen_addi_i32(addr, addr, 4);
6878 tmp = tcg_temp_new_i32();
6879 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
6880 store_reg(s, rt2, tmp);
6882 /* LDRD w/ base writeback is undefined if the registers overlap. */
6883 op_addr_ri_post(s, a, addr, -4);
6884 return true;
6887 static bool trans_LDRD_ri_a32(DisasContext *s, arg_ldst_ri *a)
6889 if (!ENABLE_ARCH_5TE || (a->rt & 1)) {
6890 return false;
6892 return op_ldrd_ri(s, a, a->rt + 1);
6895 static bool trans_LDRD_ri_t32(DisasContext *s, arg_ldst_ri2 *a)
6897 arg_ldst_ri b = {
6898 .u = a->u, .w = a->w, .p = a->p,
6899 .rn = a->rn, .rt = a->rt, .imm = a->imm
6901 return op_ldrd_ri(s, &b, a->rt2);
6904 static bool op_strd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
6906 int mem_idx = get_mem_index(s);
6907 TCGv_i32 addr, tmp;
6909 addr = op_addr_ri_pre(s, a);
6911 tmp = load_reg(s, a->rt);
6912 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
6913 tcg_temp_free_i32(tmp);
6915 tcg_gen_addi_i32(addr, addr, 4);
6917 tmp = load_reg(s, rt2);
6918 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
6919 tcg_temp_free_i32(tmp);
6921 op_addr_ri_post(s, a, addr, -4);
6922 return true;
6925 static bool trans_STRD_ri_a32(DisasContext *s, arg_ldst_ri *a)
6927 if (!ENABLE_ARCH_5TE || (a->rt & 1)) {
6928 return false;
6930 return op_strd_ri(s, a, a->rt + 1);
6933 static bool trans_STRD_ri_t32(DisasContext *s, arg_ldst_ri2 *a)
6935 arg_ldst_ri b = {
6936 .u = a->u, .w = a->w, .p = a->p,
6937 .rn = a->rn, .rt = a->rt, .imm = a->imm
6939 return op_strd_ri(s, &b, a->rt2);
6942 #define DO_LDST(NAME, WHICH, MEMOP) \
6943 static bool trans_##NAME##_ri(DisasContext *s, arg_ldst_ri *a) \
6945 return op_##WHICH##_ri(s, a, MEMOP, get_mem_index(s)); \
6947 static bool trans_##NAME##T_ri(DisasContext *s, arg_ldst_ri *a) \
6949 return op_##WHICH##_ri(s, a, MEMOP, get_a32_user_mem_index(s)); \
6951 static bool trans_##NAME##_rr(DisasContext *s, arg_ldst_rr *a) \
6953 return op_##WHICH##_rr(s, a, MEMOP, get_mem_index(s)); \
6955 static bool trans_##NAME##T_rr(DisasContext *s, arg_ldst_rr *a) \
6957 return op_##WHICH##_rr(s, a, MEMOP, get_a32_user_mem_index(s)); \
6960 DO_LDST(LDR, load, MO_UL)
6961 DO_LDST(LDRB, load, MO_UB)
6962 DO_LDST(LDRH, load, MO_UW)
6963 DO_LDST(LDRSB, load, MO_SB)
6964 DO_LDST(LDRSH, load, MO_SW)
6966 DO_LDST(STR, store, MO_UL)
6967 DO_LDST(STRB, store, MO_UB)
6968 DO_LDST(STRH, store, MO_UW)
6970 #undef DO_LDST
6973 * Synchronization primitives
6976 static bool op_swp(DisasContext *s, arg_SWP *a, MemOp opc)
6978 TCGv_i32 addr, tmp;
6979 TCGv taddr;
6981 opc |= s->be_data;
6982 addr = load_reg(s, a->rn);
6983 taddr = gen_aa32_addr(s, addr, opc);
6984 tcg_temp_free_i32(addr);
6986 tmp = load_reg(s, a->rt2);
6987 tcg_gen_atomic_xchg_i32(tmp, taddr, tmp, get_mem_index(s), opc);
6988 tcg_temp_free(taddr);
6990 store_reg(s, a->rt, tmp);
6991 return true;
6994 static bool trans_SWP(DisasContext *s, arg_SWP *a)
6996 return op_swp(s, a, MO_UL | MO_ALIGN);
6999 static bool trans_SWPB(DisasContext *s, arg_SWP *a)
7001 return op_swp(s, a, MO_UB);
7005 * Load/Store Exclusive and Load-Acquire/Store-Release
7008 static bool op_strex(DisasContext *s, arg_STREX *a, MemOp mop, bool rel)
7010 TCGv_i32 addr;
7011 /* Some cases stopped being UNPREDICTABLE in v8A (but not v8M) */
7012 bool v8a = ENABLE_ARCH_8 && !arm_dc_feature(s, ARM_FEATURE_M);
7014 /* We UNDEF for these UNPREDICTABLE cases. */
7015 if (a->rd == 15 || a->rn == 15 || a->rt == 15
7016 || a->rd == a->rn || a->rd == a->rt
7017 || (!v8a && s->thumb && (a->rd == 13 || a->rt == 13))
7018 || (mop == MO_64
7019 && (a->rt2 == 15
7020 || a->rd == a->rt2
7021 || (!v8a && s->thumb && a->rt2 == 13)))) {
7022 unallocated_encoding(s);
7023 return true;
7026 if (rel) {
7027 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
7030 addr = tcg_temp_local_new_i32();
7031 load_reg_var(s, addr, a->rn);
7032 tcg_gen_addi_i32(addr, addr, a->imm);
7034 gen_store_exclusive(s, a->rd, a->rt, a->rt2, addr, mop);
7035 tcg_temp_free_i32(addr);
7036 return true;
7039 static bool trans_STREX(DisasContext *s, arg_STREX *a)
7041 if (!ENABLE_ARCH_6) {
7042 return false;
7044 return op_strex(s, a, MO_32, false);
7047 static bool trans_STREXD_a32(DisasContext *s, arg_STREX *a)
7049 if (!ENABLE_ARCH_6K) {
7050 return false;
7052 /* We UNDEF for these UNPREDICTABLE cases. */
7053 if (a->rt & 1) {
7054 unallocated_encoding(s);
7055 return true;
7057 a->rt2 = a->rt + 1;
7058 return op_strex(s, a, MO_64, false);
7061 static bool trans_STREXD_t32(DisasContext *s, arg_STREX *a)
7063 return op_strex(s, a, MO_64, false);
7066 static bool trans_STREXB(DisasContext *s, arg_STREX *a)
7068 if (s->thumb ? !ENABLE_ARCH_7 : !ENABLE_ARCH_6K) {
7069 return false;
7071 return op_strex(s, a, MO_8, false);
7074 static bool trans_STREXH(DisasContext *s, arg_STREX *a)
7076 if (s->thumb ? !ENABLE_ARCH_7 : !ENABLE_ARCH_6K) {
7077 return false;
7079 return op_strex(s, a, MO_16, false);
7082 static bool trans_STLEX(DisasContext *s, arg_STREX *a)
7084 if (!ENABLE_ARCH_8) {
7085 return false;
7087 return op_strex(s, a, MO_32, true);
7090 static bool trans_STLEXD_a32(DisasContext *s, arg_STREX *a)
7092 if (!ENABLE_ARCH_8) {
7093 return false;
7095 /* We UNDEF for these UNPREDICTABLE cases. */
7096 if (a->rt & 1) {
7097 unallocated_encoding(s);
7098 return true;
7100 a->rt2 = a->rt + 1;
7101 return op_strex(s, a, MO_64, true);
7104 static bool trans_STLEXD_t32(DisasContext *s, arg_STREX *a)
7106 if (!ENABLE_ARCH_8) {
7107 return false;
7109 return op_strex(s, a, MO_64, true);
7112 static bool trans_STLEXB(DisasContext *s, arg_STREX *a)
7114 if (!ENABLE_ARCH_8) {
7115 return false;
7117 return op_strex(s, a, MO_8, true);
7120 static bool trans_STLEXH(DisasContext *s, arg_STREX *a)
7122 if (!ENABLE_ARCH_8) {
7123 return false;
7125 return op_strex(s, a, MO_16, true);
7128 static bool op_stl(DisasContext *s, arg_STL *a, MemOp mop)
7130 TCGv_i32 addr, tmp;
7132 if (!ENABLE_ARCH_8) {
7133 return false;
7135 /* We UNDEF for these UNPREDICTABLE cases. */
7136 if (a->rn == 15 || a->rt == 15) {
7137 unallocated_encoding(s);
7138 return true;
7141 addr = load_reg(s, a->rn);
7142 tmp = load_reg(s, a->rt);
7143 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
7144 gen_aa32_st_i32(s, tmp, addr, get_mem_index(s), mop | MO_ALIGN);
7145 disas_set_da_iss(s, mop, a->rt | ISSIsAcqRel | ISSIsWrite);
7147 tcg_temp_free_i32(tmp);
7148 tcg_temp_free_i32(addr);
7149 return true;
7152 static bool trans_STL(DisasContext *s, arg_STL *a)
7154 return op_stl(s, a, MO_UL);
7157 static bool trans_STLB(DisasContext *s, arg_STL *a)
7159 return op_stl(s, a, MO_UB);
7162 static bool trans_STLH(DisasContext *s, arg_STL *a)
7164 return op_stl(s, a, MO_UW);
7167 static bool op_ldrex(DisasContext *s, arg_LDREX *a, MemOp mop, bool acq)
7169 TCGv_i32 addr;
7170 /* Some cases stopped being UNPREDICTABLE in v8A (but not v8M) */
7171 bool v8a = ENABLE_ARCH_8 && !arm_dc_feature(s, ARM_FEATURE_M);
7173 /* We UNDEF for these UNPREDICTABLE cases. */
7174 if (a->rn == 15 || a->rt == 15
7175 || (!v8a && s->thumb && a->rt == 13)
7176 || (mop == MO_64
7177 && (a->rt2 == 15 || a->rt == a->rt2
7178 || (!v8a && s->thumb && a->rt2 == 13)))) {
7179 unallocated_encoding(s);
7180 return true;
7183 addr = tcg_temp_local_new_i32();
7184 load_reg_var(s, addr, a->rn);
7185 tcg_gen_addi_i32(addr, addr, a->imm);
7187 gen_load_exclusive(s, a->rt, a->rt2, addr, mop);
7188 tcg_temp_free_i32(addr);
7190 if (acq) {
7191 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
7193 return true;
7196 static bool trans_LDREX(DisasContext *s, arg_LDREX *a)
7198 if (!ENABLE_ARCH_6) {
7199 return false;
7201 return op_ldrex(s, a, MO_32, false);
7204 static bool trans_LDREXD_a32(DisasContext *s, arg_LDREX *a)
7206 if (!ENABLE_ARCH_6K) {
7207 return false;
7209 /* We UNDEF for these UNPREDICTABLE cases. */
7210 if (a->rt & 1) {
7211 unallocated_encoding(s);
7212 return true;
7214 a->rt2 = a->rt + 1;
7215 return op_ldrex(s, a, MO_64, false);
7218 static bool trans_LDREXD_t32(DisasContext *s, arg_LDREX *a)
7220 return op_ldrex(s, a, MO_64, false);
7223 static bool trans_LDREXB(DisasContext *s, arg_LDREX *a)
7225 if (s->thumb ? !ENABLE_ARCH_7 : !ENABLE_ARCH_6K) {
7226 return false;
7228 return op_ldrex(s, a, MO_8, false);
7231 static bool trans_LDREXH(DisasContext *s, arg_LDREX *a)
7233 if (s->thumb ? !ENABLE_ARCH_7 : !ENABLE_ARCH_6K) {
7234 return false;
7236 return op_ldrex(s, a, MO_16, false);
7239 static bool trans_LDAEX(DisasContext *s, arg_LDREX *a)
7241 if (!ENABLE_ARCH_8) {
7242 return false;
7244 return op_ldrex(s, a, MO_32, true);
7247 static bool trans_LDAEXD_a32(DisasContext *s, arg_LDREX *a)
7249 if (!ENABLE_ARCH_8) {
7250 return false;
7252 /* We UNDEF for these UNPREDICTABLE cases. */
7253 if (a->rt & 1) {
7254 unallocated_encoding(s);
7255 return true;
7257 a->rt2 = a->rt + 1;
7258 return op_ldrex(s, a, MO_64, true);
7261 static bool trans_LDAEXD_t32(DisasContext *s, arg_LDREX *a)
7263 if (!ENABLE_ARCH_8) {
7264 return false;
7266 return op_ldrex(s, a, MO_64, true);
7269 static bool trans_LDAEXB(DisasContext *s, arg_LDREX *a)
7271 if (!ENABLE_ARCH_8) {
7272 return false;
7274 return op_ldrex(s, a, MO_8, true);
7277 static bool trans_LDAEXH(DisasContext *s, arg_LDREX *a)
7279 if (!ENABLE_ARCH_8) {
7280 return false;
7282 return op_ldrex(s, a, MO_16, true);
7285 static bool op_lda(DisasContext *s, arg_LDA *a, MemOp mop)
7287 TCGv_i32 addr, tmp;
7289 if (!ENABLE_ARCH_8) {
7290 return false;
7292 /* We UNDEF for these UNPREDICTABLE cases. */
7293 if (a->rn == 15 || a->rt == 15) {
7294 unallocated_encoding(s);
7295 return true;
7298 addr = load_reg(s, a->rn);
7299 tmp = tcg_temp_new_i32();
7300 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), mop | MO_ALIGN);
7301 disas_set_da_iss(s, mop, a->rt | ISSIsAcqRel);
7302 tcg_temp_free_i32(addr);
7304 store_reg(s, a->rt, tmp);
7305 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
7306 return true;
7309 static bool trans_LDA(DisasContext *s, arg_LDA *a)
7311 return op_lda(s, a, MO_UL);
7314 static bool trans_LDAB(DisasContext *s, arg_LDA *a)
7316 return op_lda(s, a, MO_UB);
7319 static bool trans_LDAH(DisasContext *s, arg_LDA *a)
7321 return op_lda(s, a, MO_UW);
7325 * Media instructions
7328 static bool trans_USADA8(DisasContext *s, arg_USADA8 *a)
7330 TCGv_i32 t1, t2;
7332 if (!ENABLE_ARCH_6) {
7333 return false;
7336 t1 = load_reg(s, a->rn);
7337 t2 = load_reg(s, a->rm);
7338 gen_helper_usad8(t1, t1, t2);
7339 tcg_temp_free_i32(t2);
7340 if (a->ra != 15) {
7341 t2 = load_reg(s, a->ra);
7342 tcg_gen_add_i32(t1, t1, t2);
7343 tcg_temp_free_i32(t2);
7345 store_reg(s, a->rd, t1);
7346 return true;
7349 static bool op_bfx(DisasContext *s, arg_UBFX *a, bool u)
7351 TCGv_i32 tmp;
7352 int width = a->widthm1 + 1;
7353 int shift = a->lsb;
7355 if (!ENABLE_ARCH_6T2) {
7356 return false;
7358 if (shift + width > 32) {
7359 /* UNPREDICTABLE; we choose to UNDEF */
7360 unallocated_encoding(s);
7361 return true;
7364 tmp = load_reg(s, a->rn);
7365 if (u) {
7366 tcg_gen_extract_i32(tmp, tmp, shift, width);
7367 } else {
7368 tcg_gen_sextract_i32(tmp, tmp, shift, width);
7370 store_reg(s, a->rd, tmp);
7371 return true;
7374 static bool trans_SBFX(DisasContext *s, arg_SBFX *a)
7376 return op_bfx(s, a, false);
7379 static bool trans_UBFX(DisasContext *s, arg_UBFX *a)
7381 return op_bfx(s, a, true);
7384 static bool trans_BFCI(DisasContext *s, arg_BFCI *a)
7386 TCGv_i32 tmp;
7387 int msb = a->msb, lsb = a->lsb;
7388 int width;
7390 if (!ENABLE_ARCH_6T2) {
7391 return false;
7393 if (msb < lsb) {
7394 /* UNPREDICTABLE; we choose to UNDEF */
7395 unallocated_encoding(s);
7396 return true;
7399 width = msb + 1 - lsb;
7400 if (a->rn == 15) {
7401 /* BFC */
7402 tmp = tcg_const_i32(0);
7403 } else {
7404 /* BFI */
7405 tmp = load_reg(s, a->rn);
7407 if (width != 32) {
7408 TCGv_i32 tmp2 = load_reg(s, a->rd);
7409 tcg_gen_deposit_i32(tmp, tmp2, tmp, lsb, width);
7410 tcg_temp_free_i32(tmp2);
7412 store_reg(s, a->rd, tmp);
7413 return true;
7416 static bool trans_UDF(DisasContext *s, arg_UDF *a)
7418 unallocated_encoding(s);
7419 return true;
7423 * Parallel addition and subtraction
7426 static bool op_par_addsub(DisasContext *s, arg_rrr *a,
7427 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32))
7429 TCGv_i32 t0, t1;
7431 if (s->thumb
7432 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
7433 : !ENABLE_ARCH_6) {
7434 return false;
7437 t0 = load_reg(s, a->rn);
7438 t1 = load_reg(s, a->rm);
7440 gen(t0, t0, t1);
7442 tcg_temp_free_i32(t1);
7443 store_reg(s, a->rd, t0);
7444 return true;
7447 static bool op_par_addsub_ge(DisasContext *s, arg_rrr *a,
7448 void (*gen)(TCGv_i32, TCGv_i32,
7449 TCGv_i32, TCGv_ptr))
7451 TCGv_i32 t0, t1;
7452 TCGv_ptr ge;
7454 if (s->thumb
7455 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
7456 : !ENABLE_ARCH_6) {
7457 return false;
7460 t0 = load_reg(s, a->rn);
7461 t1 = load_reg(s, a->rm);
7463 ge = tcg_temp_new_ptr();
7464 tcg_gen_addi_ptr(ge, cpu_env, offsetof(CPUARMState, GE));
7465 gen(t0, t0, t1, ge);
7467 tcg_temp_free_ptr(ge);
7468 tcg_temp_free_i32(t1);
7469 store_reg(s, a->rd, t0);
7470 return true;
7473 #define DO_PAR_ADDSUB(NAME, helper) \
7474 static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
7476 return op_par_addsub(s, a, helper); \
7479 #define DO_PAR_ADDSUB_GE(NAME, helper) \
7480 static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
7482 return op_par_addsub_ge(s, a, helper); \
7485 DO_PAR_ADDSUB_GE(SADD16, gen_helper_sadd16)
7486 DO_PAR_ADDSUB_GE(SASX, gen_helper_saddsubx)
7487 DO_PAR_ADDSUB_GE(SSAX, gen_helper_ssubaddx)
7488 DO_PAR_ADDSUB_GE(SSUB16, gen_helper_ssub16)
7489 DO_PAR_ADDSUB_GE(SADD8, gen_helper_sadd8)
7490 DO_PAR_ADDSUB_GE(SSUB8, gen_helper_ssub8)
7492 DO_PAR_ADDSUB_GE(UADD16, gen_helper_uadd16)
7493 DO_PAR_ADDSUB_GE(UASX, gen_helper_uaddsubx)
7494 DO_PAR_ADDSUB_GE(USAX, gen_helper_usubaddx)
7495 DO_PAR_ADDSUB_GE(USUB16, gen_helper_usub16)
7496 DO_PAR_ADDSUB_GE(UADD8, gen_helper_uadd8)
7497 DO_PAR_ADDSUB_GE(USUB8, gen_helper_usub8)
7499 DO_PAR_ADDSUB(QADD16, gen_helper_qadd16)
7500 DO_PAR_ADDSUB(QASX, gen_helper_qaddsubx)
7501 DO_PAR_ADDSUB(QSAX, gen_helper_qsubaddx)
7502 DO_PAR_ADDSUB(QSUB16, gen_helper_qsub16)
7503 DO_PAR_ADDSUB(QADD8, gen_helper_qadd8)
7504 DO_PAR_ADDSUB(QSUB8, gen_helper_qsub8)
7506 DO_PAR_ADDSUB(UQADD16, gen_helper_uqadd16)
7507 DO_PAR_ADDSUB(UQASX, gen_helper_uqaddsubx)
7508 DO_PAR_ADDSUB(UQSAX, gen_helper_uqsubaddx)
7509 DO_PAR_ADDSUB(UQSUB16, gen_helper_uqsub16)
7510 DO_PAR_ADDSUB(UQADD8, gen_helper_uqadd8)
7511 DO_PAR_ADDSUB(UQSUB8, gen_helper_uqsub8)
7513 DO_PAR_ADDSUB(SHADD16, gen_helper_shadd16)
7514 DO_PAR_ADDSUB(SHASX, gen_helper_shaddsubx)
7515 DO_PAR_ADDSUB(SHSAX, gen_helper_shsubaddx)
7516 DO_PAR_ADDSUB(SHSUB16, gen_helper_shsub16)
7517 DO_PAR_ADDSUB(SHADD8, gen_helper_shadd8)
7518 DO_PAR_ADDSUB(SHSUB8, gen_helper_shsub8)
7520 DO_PAR_ADDSUB(UHADD16, gen_helper_uhadd16)
7521 DO_PAR_ADDSUB(UHASX, gen_helper_uhaddsubx)
7522 DO_PAR_ADDSUB(UHSAX, gen_helper_uhsubaddx)
7523 DO_PAR_ADDSUB(UHSUB16, gen_helper_uhsub16)
7524 DO_PAR_ADDSUB(UHADD8, gen_helper_uhadd8)
7525 DO_PAR_ADDSUB(UHSUB8, gen_helper_uhsub8)
7527 #undef DO_PAR_ADDSUB
7528 #undef DO_PAR_ADDSUB_GE
7531 * Packing, unpacking, saturation, and reversal
7534 static bool trans_PKH(DisasContext *s, arg_PKH *a)
7536 TCGv_i32 tn, tm;
7537 int shift = a->imm;
7539 if (s->thumb
7540 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
7541 : !ENABLE_ARCH_6) {
7542 return false;
7545 tn = load_reg(s, a->rn);
7546 tm = load_reg(s, a->rm);
7547 if (a->tb) {
7548 /* PKHTB */
7549 if (shift == 0) {
7550 shift = 31;
7552 tcg_gen_sari_i32(tm, tm, shift);
7553 tcg_gen_deposit_i32(tn, tn, tm, 0, 16);
7554 } else {
7555 /* PKHBT */
7556 tcg_gen_shli_i32(tm, tm, shift);
7557 tcg_gen_deposit_i32(tn, tm, tn, 0, 16);
7559 tcg_temp_free_i32(tm);
7560 store_reg(s, a->rd, tn);
7561 return true;
7564 static bool op_sat(DisasContext *s, arg_sat *a,
7565 void (*gen)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32))
7567 TCGv_i32 tmp;
7568 int shift = a->imm;
7570 if (!ENABLE_ARCH_6) {
7571 return false;
7574 tmp = load_reg(s, a->rn);
7575 if (a->sh) {
7576 tcg_gen_sari_i32(tmp, tmp, shift ? shift : 31);
7577 } else {
7578 tcg_gen_shli_i32(tmp, tmp, shift);
7581 gen(tmp, cpu_env, tmp, tcg_constant_i32(a->satimm));
7583 store_reg(s, a->rd, tmp);
7584 return true;
7587 static bool trans_SSAT(DisasContext *s, arg_sat *a)
7589 return op_sat(s, a, gen_helper_ssat);
7592 static bool trans_USAT(DisasContext *s, arg_sat *a)
7594 return op_sat(s, a, gen_helper_usat);
7597 static bool trans_SSAT16(DisasContext *s, arg_sat *a)
7599 if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
7600 return false;
7602 return op_sat(s, a, gen_helper_ssat16);
7605 static bool trans_USAT16(DisasContext *s, arg_sat *a)
7607 if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
7608 return false;
7610 return op_sat(s, a, gen_helper_usat16);
7613 static bool op_xta(DisasContext *s, arg_rrr_rot *a,
7614 void (*gen_extract)(TCGv_i32, TCGv_i32),
7615 void (*gen_add)(TCGv_i32, TCGv_i32, TCGv_i32))
7617 TCGv_i32 tmp;
7619 if (!ENABLE_ARCH_6) {
7620 return false;
7623 tmp = load_reg(s, a->rm);
7625 * TODO: In many cases we could do a shift instead of a rotate.
7626 * Combined with a simple extend, that becomes an extract.
7628 tcg_gen_rotri_i32(tmp, tmp, a->rot * 8);
7629 gen_extract(tmp, tmp);
7631 if (a->rn != 15) {
7632 TCGv_i32 tmp2 = load_reg(s, a->rn);
7633 gen_add(tmp, tmp, tmp2);
7634 tcg_temp_free_i32(tmp2);
7636 store_reg(s, a->rd, tmp);
7637 return true;
7640 static bool trans_SXTAB(DisasContext *s, arg_rrr_rot *a)
7642 return op_xta(s, a, tcg_gen_ext8s_i32, tcg_gen_add_i32);
7645 static bool trans_SXTAH(DisasContext *s, arg_rrr_rot *a)
7647 return op_xta(s, a, tcg_gen_ext16s_i32, tcg_gen_add_i32);
7650 static bool trans_SXTAB16(DisasContext *s, arg_rrr_rot *a)
7652 if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
7653 return false;
7655 return op_xta(s, a, gen_helper_sxtb16, gen_add16);
7658 static bool trans_UXTAB(DisasContext *s, arg_rrr_rot *a)
7660 return op_xta(s, a, tcg_gen_ext8u_i32, tcg_gen_add_i32);
7663 static bool trans_UXTAH(DisasContext *s, arg_rrr_rot *a)
7665 return op_xta(s, a, tcg_gen_ext16u_i32, tcg_gen_add_i32);
7668 static bool trans_UXTAB16(DisasContext *s, arg_rrr_rot *a)
7670 if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
7671 return false;
7673 return op_xta(s, a, gen_helper_uxtb16, gen_add16);
7676 static bool trans_SEL(DisasContext *s, arg_rrr *a)
7678 TCGv_i32 t1, t2, t3;
7680 if (s->thumb
7681 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
7682 : !ENABLE_ARCH_6) {
7683 return false;
7686 t1 = load_reg(s, a->rn);
7687 t2 = load_reg(s, a->rm);
7688 t3 = tcg_temp_new_i32();
7689 tcg_gen_ld_i32(t3, cpu_env, offsetof(CPUARMState, GE));
7690 gen_helper_sel_flags(t1, t3, t1, t2);
7691 tcg_temp_free_i32(t3);
7692 tcg_temp_free_i32(t2);
7693 store_reg(s, a->rd, t1);
7694 return true;
7697 static bool op_rr(DisasContext *s, arg_rr *a,
7698 void (*gen)(TCGv_i32, TCGv_i32))
7700 TCGv_i32 tmp;
7702 tmp = load_reg(s, a->rm);
7703 gen(tmp, tmp);
7704 store_reg(s, a->rd, tmp);
7705 return true;
7708 static bool trans_REV(DisasContext *s, arg_rr *a)
7710 if (!ENABLE_ARCH_6) {
7711 return false;
7713 return op_rr(s, a, tcg_gen_bswap32_i32);
7716 static bool trans_REV16(DisasContext *s, arg_rr *a)
7718 if (!ENABLE_ARCH_6) {
7719 return false;
7721 return op_rr(s, a, gen_rev16);
7724 static bool trans_REVSH(DisasContext *s, arg_rr *a)
7726 if (!ENABLE_ARCH_6) {
7727 return false;
7729 return op_rr(s, a, gen_revsh);
7732 static bool trans_RBIT(DisasContext *s, arg_rr *a)
7734 if (!ENABLE_ARCH_6T2) {
7735 return false;
7737 return op_rr(s, a, gen_helper_rbit);
7741 * Signed multiply, signed and unsigned divide
7744 static bool op_smlad(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub)
7746 TCGv_i32 t1, t2;
7748 if (!ENABLE_ARCH_6) {
7749 return false;
7752 t1 = load_reg(s, a->rn);
7753 t2 = load_reg(s, a->rm);
7754 if (m_swap) {
7755 gen_swap_half(t2, t2);
7757 gen_smul_dual(t1, t2);
7759 if (sub) {
7761 * This subtraction cannot overflow, so we can do a simple
7762 * 32-bit subtraction and then a possible 32-bit saturating
7763 * addition of Ra.
7765 tcg_gen_sub_i32(t1, t1, t2);
7766 tcg_temp_free_i32(t2);
7768 if (a->ra != 15) {
7769 t2 = load_reg(s, a->ra);
7770 gen_helper_add_setq(t1, cpu_env, t1, t2);
7771 tcg_temp_free_i32(t2);
7773 } else if (a->ra == 15) {
7774 /* Single saturation-checking addition */
7775 gen_helper_add_setq(t1, cpu_env, t1, t2);
7776 tcg_temp_free_i32(t2);
7777 } else {
7779 * We need to add the products and Ra together and then
7780 * determine whether the final result overflowed. Doing
7781 * this as two separate add-and-check-overflow steps incorrectly
7782 * sets Q for cases like (-32768 * -32768) + (-32768 * -32768) + -1.
7783 * Do all the arithmetic at 64-bits and then check for overflow.
7785 TCGv_i64 p64, q64;
7786 TCGv_i32 t3, qf, one;
7788 p64 = tcg_temp_new_i64();
7789 q64 = tcg_temp_new_i64();
7790 tcg_gen_ext_i32_i64(p64, t1);
7791 tcg_gen_ext_i32_i64(q64, t2);
7792 tcg_gen_add_i64(p64, p64, q64);
7793 load_reg_var(s, t2, a->ra);
7794 tcg_gen_ext_i32_i64(q64, t2);
7795 tcg_gen_add_i64(p64, p64, q64);
7796 tcg_temp_free_i64(q64);
7798 tcg_gen_extr_i64_i32(t1, t2, p64);
7799 tcg_temp_free_i64(p64);
7801 * t1 is the low half of the result which goes into Rd.
7802 * We have overflow and must set Q if the high half (t2)
7803 * is different from the sign-extension of t1.
7805 t3 = tcg_temp_new_i32();
7806 tcg_gen_sari_i32(t3, t1, 31);
7807 qf = load_cpu_field(QF);
7808 one = tcg_constant_i32(1);
7809 tcg_gen_movcond_i32(TCG_COND_NE, qf, t2, t3, one, qf);
7810 store_cpu_field(qf, QF);
7811 tcg_temp_free_i32(t3);
7812 tcg_temp_free_i32(t2);
7814 store_reg(s, a->rd, t1);
7815 return true;
7818 static bool trans_SMLAD(DisasContext *s, arg_rrrr *a)
7820 return op_smlad(s, a, false, false);
7823 static bool trans_SMLADX(DisasContext *s, arg_rrrr *a)
7825 return op_smlad(s, a, true, false);
7828 static bool trans_SMLSD(DisasContext *s, arg_rrrr *a)
7830 return op_smlad(s, a, false, true);
7833 static bool trans_SMLSDX(DisasContext *s, arg_rrrr *a)
7835 return op_smlad(s, a, true, true);
7838 static bool op_smlald(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub)
7840 TCGv_i32 t1, t2;
7841 TCGv_i64 l1, l2;
7843 if (!ENABLE_ARCH_6) {
7844 return false;
7847 t1 = load_reg(s, a->rn);
7848 t2 = load_reg(s, a->rm);
7849 if (m_swap) {
7850 gen_swap_half(t2, t2);
7852 gen_smul_dual(t1, t2);
7854 l1 = tcg_temp_new_i64();
7855 l2 = tcg_temp_new_i64();
7856 tcg_gen_ext_i32_i64(l1, t1);
7857 tcg_gen_ext_i32_i64(l2, t2);
7858 tcg_temp_free_i32(t1);
7859 tcg_temp_free_i32(t2);
7861 if (sub) {
7862 tcg_gen_sub_i64(l1, l1, l2);
7863 } else {
7864 tcg_gen_add_i64(l1, l1, l2);
7866 tcg_temp_free_i64(l2);
7868 gen_addq(s, l1, a->ra, a->rd);
7869 gen_storeq_reg(s, a->ra, a->rd, l1);
7870 tcg_temp_free_i64(l1);
7871 return true;
7874 static bool trans_SMLALD(DisasContext *s, arg_rrrr *a)
7876 return op_smlald(s, a, false, false);
7879 static bool trans_SMLALDX(DisasContext *s, arg_rrrr *a)
7881 return op_smlald(s, a, true, false);
7884 static bool trans_SMLSLD(DisasContext *s, arg_rrrr *a)
7886 return op_smlald(s, a, false, true);
7889 static bool trans_SMLSLDX(DisasContext *s, arg_rrrr *a)
7891 return op_smlald(s, a, true, true);
7894 static bool op_smmla(DisasContext *s, arg_rrrr *a, bool round, bool sub)
7896 TCGv_i32 t1, t2;
7898 if (s->thumb
7899 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
7900 : !ENABLE_ARCH_6) {
7901 return false;
7904 t1 = load_reg(s, a->rn);
7905 t2 = load_reg(s, a->rm);
7906 tcg_gen_muls2_i32(t2, t1, t1, t2);
7908 if (a->ra != 15) {
7909 TCGv_i32 t3 = load_reg(s, a->ra);
7910 if (sub) {
7912 * For SMMLS, we need a 64-bit subtract. Borrow caused by
7913 * a non-zero multiplicand lowpart, and the correct result
7914 * lowpart for rounding.
7916 tcg_gen_sub2_i32(t2, t1, tcg_constant_i32(0), t3, t2, t1);
7917 } else {
7918 tcg_gen_add_i32(t1, t1, t3);
7920 tcg_temp_free_i32(t3);
7922 if (round) {
7924 * Adding 0x80000000 to the 64-bit quantity means that we have
7925 * carry in to the high word when the low word has the msb set.
7927 tcg_gen_shri_i32(t2, t2, 31);
7928 tcg_gen_add_i32(t1, t1, t2);
7930 tcg_temp_free_i32(t2);
7931 store_reg(s, a->rd, t1);
7932 return true;
7935 static bool trans_SMMLA(DisasContext *s, arg_rrrr *a)
7937 return op_smmla(s, a, false, false);
7940 static bool trans_SMMLAR(DisasContext *s, arg_rrrr *a)
7942 return op_smmla(s, a, true, false);
7945 static bool trans_SMMLS(DisasContext *s, arg_rrrr *a)
7947 return op_smmla(s, a, false, true);
7950 static bool trans_SMMLSR(DisasContext *s, arg_rrrr *a)
7952 return op_smmla(s, a, true, true);
7955 static bool op_div(DisasContext *s, arg_rrr *a, bool u)
7957 TCGv_i32 t1, t2;
7959 if (s->thumb
7960 ? !dc_isar_feature(aa32_thumb_div, s)
7961 : !dc_isar_feature(aa32_arm_div, s)) {
7962 return false;
7965 t1 = load_reg(s, a->rn);
7966 t2 = load_reg(s, a->rm);
7967 if (u) {
7968 gen_helper_udiv(t1, cpu_env, t1, t2);
7969 } else {
7970 gen_helper_sdiv(t1, cpu_env, t1, t2);
7972 tcg_temp_free_i32(t2);
7973 store_reg(s, a->rd, t1);
7974 return true;
7977 static bool trans_SDIV(DisasContext *s, arg_rrr *a)
7979 return op_div(s, a, false);
7982 static bool trans_UDIV(DisasContext *s, arg_rrr *a)
7984 return op_div(s, a, true);
7988 * Block data transfer
7991 static TCGv_i32 op_addr_block_pre(DisasContext *s, arg_ldst_block *a, int n)
7993 TCGv_i32 addr = load_reg(s, a->rn);
7995 if (a->b) {
7996 if (a->i) {
7997 /* pre increment */
7998 tcg_gen_addi_i32(addr, addr, 4);
7999 } else {
8000 /* pre decrement */
8001 tcg_gen_addi_i32(addr, addr, -(n * 4));
8003 } else if (!a->i && n != 1) {
8004 /* post decrement */
8005 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
8008 if (s->v8m_stackcheck && a->rn == 13 && a->w) {
8010 * If the writeback is incrementing SP rather than
8011 * decrementing it, and the initial SP is below the
8012 * stack limit but the final written-back SP would
8013 * be above, then then we must not perform any memory
8014 * accesses, but it is IMPDEF whether we generate
8015 * an exception. We choose to do so in this case.
8016 * At this point 'addr' is the lowest address, so
8017 * either the original SP (if incrementing) or our
8018 * final SP (if decrementing), so that's what we check.
8020 gen_helper_v8m_stackcheck(cpu_env, addr);
8023 return addr;
8026 static void op_addr_block_post(DisasContext *s, arg_ldst_block *a,
8027 TCGv_i32 addr, int n)
8029 if (a->w) {
8030 /* write back */
8031 if (!a->b) {
8032 if (a->i) {
8033 /* post increment */
8034 tcg_gen_addi_i32(addr, addr, 4);
8035 } else {
8036 /* post decrement */
8037 tcg_gen_addi_i32(addr, addr, -(n * 4));
8039 } else if (!a->i && n != 1) {
8040 /* pre decrement */
8041 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
8043 store_reg(s, a->rn, addr);
8044 } else {
8045 tcg_temp_free_i32(addr);
8049 static bool op_stm(DisasContext *s, arg_ldst_block *a, int min_n)
8051 int i, j, n, list, mem_idx;
8052 bool user = a->u;
8053 TCGv_i32 addr, tmp;
8055 if (user) {
8056 /* STM (user) */
8057 if (IS_USER(s)) {
8058 /* Only usable in supervisor mode. */
8059 unallocated_encoding(s);
8060 return true;
8064 list = a->list;
8065 n = ctpop16(list);
8066 if (n < min_n || a->rn == 15) {
8067 unallocated_encoding(s);
8068 return true;
8071 s->eci_handled = true;
8073 addr = op_addr_block_pre(s, a, n);
8074 mem_idx = get_mem_index(s);
8076 for (i = j = 0; i < 16; i++) {
8077 if (!(list & (1 << i))) {
8078 continue;
8081 if (user && i != 15) {
8082 tmp = tcg_temp_new_i32();
8083 gen_helper_get_user_reg(tmp, cpu_env, tcg_constant_i32(i));
8084 } else {
8085 tmp = load_reg(s, i);
8087 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
8088 tcg_temp_free_i32(tmp);
8090 /* No need to add after the last transfer. */
8091 if (++j != n) {
8092 tcg_gen_addi_i32(addr, addr, 4);
8096 op_addr_block_post(s, a, addr, n);
8097 clear_eci_state(s);
8098 return true;
8101 static bool trans_STM(DisasContext *s, arg_ldst_block *a)
8103 /* BitCount(list) < 1 is UNPREDICTABLE */
8104 return op_stm(s, a, 1);
8107 static bool trans_STM_t32(DisasContext *s, arg_ldst_block *a)
8109 /* Writeback register in register list is UNPREDICTABLE for T32. */
8110 if (a->w && (a->list & (1 << a->rn))) {
8111 unallocated_encoding(s);
8112 return true;
8114 /* BitCount(list) < 2 is UNPREDICTABLE */
8115 return op_stm(s, a, 2);
8118 static bool do_ldm(DisasContext *s, arg_ldst_block *a, int min_n)
8120 int i, j, n, list, mem_idx;
8121 bool loaded_base;
8122 bool user = a->u;
8123 bool exc_return = false;
8124 TCGv_i32 addr, tmp, loaded_var;
8126 if (user) {
8127 /* LDM (user), LDM (exception return) */
8128 if (IS_USER(s)) {
8129 /* Only usable in supervisor mode. */
8130 unallocated_encoding(s);
8131 return true;
8133 if (extract32(a->list, 15, 1)) {
8134 exc_return = true;
8135 user = false;
8136 } else {
8137 /* LDM (user) does not allow writeback. */
8138 if (a->w) {
8139 unallocated_encoding(s);
8140 return true;
8145 list = a->list;
8146 n = ctpop16(list);
8147 if (n < min_n || a->rn == 15) {
8148 unallocated_encoding(s);
8149 return true;
8152 s->eci_handled = true;
8154 addr = op_addr_block_pre(s, a, n);
8155 mem_idx = get_mem_index(s);
8156 loaded_base = false;
8157 loaded_var = NULL;
8159 for (i = j = 0; i < 16; i++) {
8160 if (!(list & (1 << i))) {
8161 continue;
8164 tmp = tcg_temp_new_i32();
8165 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
8166 if (user) {
8167 gen_helper_set_user_reg(cpu_env, tcg_constant_i32(i), tmp);
8168 tcg_temp_free_i32(tmp);
8169 } else if (i == a->rn) {
8170 loaded_var = tmp;
8171 loaded_base = true;
8172 } else if (i == 15 && exc_return) {
8173 store_pc_exc_ret(s, tmp);
8174 } else {
8175 store_reg_from_load(s, i, tmp);
8178 /* No need to add after the last transfer. */
8179 if (++j != n) {
8180 tcg_gen_addi_i32(addr, addr, 4);
8184 op_addr_block_post(s, a, addr, n);
8186 if (loaded_base) {
8187 /* Note that we reject base == pc above. */
8188 store_reg(s, a->rn, loaded_var);
8191 if (exc_return) {
8192 /* Restore CPSR from SPSR. */
8193 tmp = load_cpu_field(spsr);
8194 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
8195 gen_io_start();
8197 gen_helper_cpsr_write_eret(cpu_env, tmp);
8198 tcg_temp_free_i32(tmp);
8199 /* Must exit loop to check un-masked IRQs */
8200 s->base.is_jmp = DISAS_EXIT;
8202 clear_eci_state(s);
8203 return true;
8206 static bool trans_LDM_a32(DisasContext *s, arg_ldst_block *a)
8209 * Writeback register in register list is UNPREDICTABLE
8210 * for ArchVersion() >= 7. Prior to v7, A32 would write
8211 * an UNKNOWN value to the base register.
8213 if (ENABLE_ARCH_7 && a->w && (a->list & (1 << a->rn))) {
8214 unallocated_encoding(s);
8215 return true;
8217 /* BitCount(list) < 1 is UNPREDICTABLE */
8218 return do_ldm(s, a, 1);
8221 static bool trans_LDM_t32(DisasContext *s, arg_ldst_block *a)
8223 /* Writeback register in register list is UNPREDICTABLE for T32. */
8224 if (a->w && (a->list & (1 << a->rn))) {
8225 unallocated_encoding(s);
8226 return true;
8228 /* BitCount(list) < 2 is UNPREDICTABLE */
8229 return do_ldm(s, a, 2);
8232 static bool trans_LDM_t16(DisasContext *s, arg_ldst_block *a)
8234 /* Writeback is conditional on the base register not being loaded. */
8235 a->w = !(a->list & (1 << a->rn));
8236 /* BitCount(list) < 1 is UNPREDICTABLE */
8237 return do_ldm(s, a, 1);
8240 static bool trans_CLRM(DisasContext *s, arg_CLRM *a)
8242 int i;
8243 TCGv_i32 zero;
8245 if (!dc_isar_feature(aa32_m_sec_state, s)) {
8246 return false;
8249 if (extract32(a->list, 13, 1)) {
8250 return false;
8253 if (!a->list) {
8254 /* UNPREDICTABLE; we choose to UNDEF */
8255 return false;
8258 s->eci_handled = true;
8260 zero = tcg_const_i32(0);
8261 for (i = 0; i < 15; i++) {
8262 if (extract32(a->list, i, 1)) {
8263 /* Clear R[i] */
8264 tcg_gen_mov_i32(cpu_R[i], zero);
8267 if (extract32(a->list, 15, 1)) {
8269 * Clear APSR (by calling the MSR helper with the same argument
8270 * as for "MSR APSR_nzcvqg, Rn": mask = 0b1100, SYSM=0)
8272 TCGv_i32 maskreg = tcg_const_i32(0xc << 8);
8273 gen_helper_v7m_msr(cpu_env, maskreg, zero);
8274 tcg_temp_free_i32(maskreg);
8276 tcg_temp_free_i32(zero);
8277 clear_eci_state(s);
8278 return true;
8282 * Branch, branch with link
8285 static bool trans_B(DisasContext *s, arg_i *a)
8287 gen_jmp(s, read_pc(s) + a->imm);
8288 return true;
8291 static bool trans_B_cond_thumb(DisasContext *s, arg_ci *a)
8293 /* This has cond from encoding, required to be outside IT block. */
8294 if (a->cond >= 0xe) {
8295 return false;
8297 if (s->condexec_mask) {
8298 unallocated_encoding(s);
8299 return true;
8301 arm_skip_unless(s, a->cond);
8302 gen_jmp(s, read_pc(s) + a->imm);
8303 return true;
8306 static bool trans_BL(DisasContext *s, arg_i *a)
8308 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
8309 gen_jmp(s, read_pc(s) + a->imm);
8310 return true;
8313 static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
8316 * BLX <imm> would be useless on M-profile; the encoding space
8317 * is used for other insns from v8.1M onward, and UNDEFs before that.
8319 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8320 return false;
8323 /* For A32, ARM_FEATURE_V5 is checked near the start of the uncond block. */
8324 if (s->thumb && (a->imm & 2)) {
8325 return false;
8327 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
8328 store_cpu_field_constant(!s->thumb, thumb);
8329 gen_jmp(s, (read_pc(s) & ~3) + a->imm);
8330 return true;
8333 static bool trans_BL_BLX_prefix(DisasContext *s, arg_BL_BLX_prefix *a)
8335 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
8336 tcg_gen_movi_i32(cpu_R[14], read_pc(s) + (a->imm << 12));
8337 return true;
8340 static bool trans_BL_suffix(DisasContext *s, arg_BL_suffix *a)
8342 TCGv_i32 tmp = tcg_temp_new_i32();
8344 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
8345 tcg_gen_addi_i32(tmp, cpu_R[14], (a->imm << 1) | 1);
8346 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | 1);
8347 gen_bx(s, tmp);
8348 return true;
8351 static bool trans_BLX_suffix(DisasContext *s, arg_BLX_suffix *a)
8353 TCGv_i32 tmp;
8355 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
8356 if (!ENABLE_ARCH_5) {
8357 return false;
8359 tmp = tcg_temp_new_i32();
8360 tcg_gen_addi_i32(tmp, cpu_R[14], a->imm << 1);
8361 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
8362 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | 1);
8363 gen_bx(s, tmp);
8364 return true;
8367 static bool trans_BF(DisasContext *s, arg_BF *a)
8370 * M-profile branch future insns. The architecture permits an
8371 * implementation to implement these as NOPs (equivalent to
8372 * discarding the LO_BRANCH_INFO cache immediately), and we
8373 * take that IMPDEF option because for QEMU a "real" implementation
8374 * would be complicated and wouldn't execute any faster.
8376 if (!dc_isar_feature(aa32_lob, s)) {
8377 return false;
8379 if (a->boff == 0) {
8380 /* SEE "Related encodings" (loop insns) */
8381 return false;
8383 /* Handle as NOP */
8384 return true;
8387 static bool trans_DLS(DisasContext *s, arg_DLS *a)
8389 /* M-profile low-overhead loop start */
8390 TCGv_i32 tmp;
8392 if (!dc_isar_feature(aa32_lob, s)) {
8393 return false;
8395 if (a->rn == 13 || a->rn == 15) {
8397 * For DLSTP rn == 15 is a related encoding (LCTP); the
8398 * other cases caught by this condition are all
8399 * CONSTRAINED UNPREDICTABLE: we choose to UNDEF
8401 return false;
8404 if (a->size != 4) {
8405 /* DLSTP */
8406 if (!dc_isar_feature(aa32_mve, s)) {
8407 return false;
8409 if (!vfp_access_check(s)) {
8410 return true;
8414 /* Not a while loop: set LR to the count, and set LTPSIZE for DLSTP */
8415 tmp = load_reg(s, a->rn);
8416 store_reg(s, 14, tmp);
8417 if (a->size != 4) {
8418 /* DLSTP: set FPSCR.LTPSIZE */
8419 tmp = tcg_const_i32(a->size);
8420 store_cpu_field(tmp, v7m.ltpsize);
8421 s->base.is_jmp = DISAS_UPDATE_NOCHAIN;
8423 return true;
8426 static bool trans_WLS(DisasContext *s, arg_WLS *a)
8428 /* M-profile low-overhead while-loop start */
8429 TCGv_i32 tmp;
8430 TCGLabel *nextlabel;
8432 if (!dc_isar_feature(aa32_lob, s)) {
8433 return false;
8435 if (a->rn == 13 || a->rn == 15) {
8437 * For WLSTP rn == 15 is a related encoding (LE); the
8438 * other cases caught by this condition are all
8439 * CONSTRAINED UNPREDICTABLE: we choose to UNDEF
8441 return false;
8443 if (s->condexec_mask) {
8445 * WLS in an IT block is CONSTRAINED UNPREDICTABLE;
8446 * we choose to UNDEF, because otherwise our use of
8447 * gen_goto_tb(1) would clash with the use of TB exit 1
8448 * in the dc->condjmp condition-failed codepath in
8449 * arm_tr_tb_stop() and we'd get an assertion.
8451 return false;
8453 if (a->size != 4) {
8454 /* WLSTP */
8455 if (!dc_isar_feature(aa32_mve, s)) {
8456 return false;
8459 * We need to check that the FPU is enabled here, but mustn't
8460 * call vfp_access_check() to do that because we don't want to
8461 * do the lazy state preservation in the "loop count is zero" case.
8462 * Do the check-and-raise-exception by hand.
8464 if (s->fp_excp_el) {
8465 gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
8466 syn_uncategorized(), s->fp_excp_el);
8467 return true;
8471 nextlabel = gen_new_label();
8472 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_R[a->rn], 0, nextlabel);
8473 tmp = load_reg(s, a->rn);
8474 store_reg(s, 14, tmp);
8475 if (a->size != 4) {
8477 * WLSTP: set FPSCR.LTPSIZE. This requires that we do the
8478 * lazy state preservation, new FP context creation, etc,
8479 * that vfp_access_check() does. We know that the actual
8480 * access check will succeed (ie it won't generate code that
8481 * throws an exception) because we did that check by hand earlier.
8483 bool ok = vfp_access_check(s);
8484 assert(ok);
8485 tmp = tcg_const_i32(a->size);
8486 store_cpu_field(tmp, v7m.ltpsize);
8488 * LTPSIZE updated, but MVE_NO_PRED will always be the same thing (0)
8489 * when we take this upcoming exit from this TB, so gen_jmp_tb() is OK.
8492 gen_jmp_tb(s, s->base.pc_next, 1);
8494 gen_set_label(nextlabel);
8495 gen_jmp(s, read_pc(s) + a->imm);
8496 return true;
8499 static bool trans_LE(DisasContext *s, arg_LE *a)
8502 * M-profile low-overhead loop end. The architecture permits an
8503 * implementation to discard the LO_BRANCH_INFO cache at any time,
8504 * and we take the IMPDEF option to never set it in the first place
8505 * (equivalent to always discarding it immediately), because for QEMU
8506 * a "real" implementation would be complicated and wouldn't execute
8507 * any faster.
8509 TCGv_i32 tmp;
8510 TCGLabel *loopend;
8511 bool fpu_active;
8513 if (!dc_isar_feature(aa32_lob, s)) {
8514 return false;
8516 if (a->f && a->tp) {
8517 return false;
8519 if (s->condexec_mask) {
8521 * LE in an IT block is CONSTRAINED UNPREDICTABLE;
8522 * we choose to UNDEF, because otherwise our use of
8523 * gen_goto_tb(1) would clash with the use of TB exit 1
8524 * in the dc->condjmp condition-failed codepath in
8525 * arm_tr_tb_stop() and we'd get an assertion.
8527 return false;
8529 if (a->tp) {
8530 /* LETP */
8531 if (!dc_isar_feature(aa32_mve, s)) {
8532 return false;
8534 if (!vfp_access_check(s)) {
8535 s->eci_handled = true;
8536 return true;
8540 /* LE/LETP is OK with ECI set and leaves it untouched */
8541 s->eci_handled = true;
8544 * With MVE, LTPSIZE might not be 4, and we must emit an INVSTATE
8545 * UsageFault exception for the LE insn in that case. Note that we
8546 * are not directly checking FPSCR.LTPSIZE but instead check the
8547 * pseudocode LTPSIZE() function, which returns 4 if the FPU is
8548 * not currently active (ie ActiveFPState() returns false). We
8549 * can identify not-active purely from our TB state flags, as the
8550 * FPU is active only if:
8551 * the FPU is enabled
8552 * AND lazy state preservation is not active
8553 * AND we do not need a new fp context (this is the ASPEN/FPCA check)
8555 * Usually we don't need to care about this distinction between
8556 * LTPSIZE and FPSCR.LTPSIZE, because the code in vfp_access_check()
8557 * will either take an exception or clear the conditions that make
8558 * the FPU not active. But LE is an unusual case of a non-FP insn
8559 * that looks at LTPSIZE.
8561 fpu_active = !s->fp_excp_el && !s->v7m_lspact && !s->v7m_new_fp_ctxt_needed;
8563 if (!a->tp && dc_isar_feature(aa32_mve, s) && fpu_active) {
8564 /* Need to do a runtime check for LTPSIZE != 4 */
8565 TCGLabel *skipexc = gen_new_label();
8566 tmp = load_cpu_field(v7m.ltpsize);
8567 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 4, skipexc);
8568 tcg_temp_free_i32(tmp);
8569 gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
8570 default_exception_el(s));
8571 gen_set_label(skipexc);
8574 if (a->f) {
8575 /* Loop-forever: just jump back to the loop start */
8576 gen_jmp(s, read_pc(s) - a->imm);
8577 return true;
8581 * Not loop-forever. If LR <= loop-decrement-value this is the last loop.
8582 * For LE, we know at this point that LTPSIZE must be 4 and the
8583 * loop decrement value is 1. For LETP we need to calculate the decrement
8584 * value from LTPSIZE.
8586 loopend = gen_new_label();
8587 if (!a->tp) {
8588 tcg_gen_brcondi_i32(TCG_COND_LEU, cpu_R[14], 1, loopend);
8589 tcg_gen_addi_i32(cpu_R[14], cpu_R[14], -1);
8590 } else {
8592 * Decrement by 1 << (4 - LTPSIZE). We need to use a TCG local
8593 * so that decr stays live after the brcondi.
8595 TCGv_i32 decr = tcg_temp_local_new_i32();
8596 TCGv_i32 ltpsize = load_cpu_field(v7m.ltpsize);
8597 tcg_gen_sub_i32(decr, tcg_constant_i32(4), ltpsize);
8598 tcg_gen_shl_i32(decr, tcg_constant_i32(1), decr);
8599 tcg_temp_free_i32(ltpsize);
8601 tcg_gen_brcond_i32(TCG_COND_LEU, cpu_R[14], decr, loopend);
8603 tcg_gen_sub_i32(cpu_R[14], cpu_R[14], decr);
8604 tcg_temp_free_i32(decr);
8606 /* Jump back to the loop start */
8607 gen_jmp(s, read_pc(s) - a->imm);
8609 gen_set_label(loopend);
8610 if (a->tp) {
8611 /* Exits from tail-pred loops must reset LTPSIZE to 4 */
8612 tmp = tcg_const_i32(4);
8613 store_cpu_field(tmp, v7m.ltpsize);
8615 /* End TB, continuing to following insn */
8616 gen_jmp_tb(s, s->base.pc_next, 1);
8617 return true;
8620 static bool trans_LCTP(DisasContext *s, arg_LCTP *a)
8623 * M-profile Loop Clear with Tail Predication. Since our implementation
8624 * doesn't cache branch information, all we need to do is reset
8625 * FPSCR.LTPSIZE to 4.
8628 if (!dc_isar_feature(aa32_lob, s) ||
8629 !dc_isar_feature(aa32_mve, s)) {
8630 return false;
8633 if (!vfp_access_check(s)) {
8634 return true;
8637 store_cpu_field_constant(4, v7m.ltpsize);
8638 return true;
8641 static bool trans_VCTP(DisasContext *s, arg_VCTP *a)
8644 * M-profile Create Vector Tail Predicate. This insn is itself
8645 * predicated and is subject to beatwise execution.
8647 TCGv_i32 rn_shifted, masklen;
8649 if (!dc_isar_feature(aa32_mve, s) || a->rn == 13 || a->rn == 15) {
8650 return false;
8653 if (!mve_eci_check(s) || !vfp_access_check(s)) {
8654 return true;
8658 * We pre-calculate the mask length here to avoid having
8659 * to have multiple helpers specialized for size.
8660 * We pass the helper "rn <= (1 << (4 - size)) ? (rn << size) : 16".
8662 rn_shifted = tcg_temp_new_i32();
8663 masklen = load_reg(s, a->rn);
8664 tcg_gen_shli_i32(rn_shifted, masklen, a->size);
8665 tcg_gen_movcond_i32(TCG_COND_LEU, masklen,
8666 masklen, tcg_constant_i32(1 << (4 - a->size)),
8667 rn_shifted, tcg_constant_i32(16));
8668 gen_helper_mve_vctp(cpu_env, masklen);
8669 tcg_temp_free_i32(masklen);
8670 tcg_temp_free_i32(rn_shifted);
8671 /* This insn updates predication bits */
8672 s->base.is_jmp = DISAS_UPDATE_NOCHAIN;
8673 mve_update_eci(s);
8674 return true;
8677 static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
8679 TCGv_i32 addr, tmp;
8681 tmp = load_reg(s, a->rm);
8682 if (half) {
8683 tcg_gen_add_i32(tmp, tmp, tmp);
8685 addr = load_reg(s, a->rn);
8686 tcg_gen_add_i32(addr, addr, tmp);
8688 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), half ? MO_UW : MO_UB);
8689 tcg_temp_free_i32(addr);
8691 tcg_gen_add_i32(tmp, tmp, tmp);
8692 tcg_gen_addi_i32(tmp, tmp, read_pc(s));
8693 store_reg(s, 15, tmp);
8694 return true;
8697 static bool trans_TBB(DisasContext *s, arg_tbranch *a)
8699 return op_tbranch(s, a, false);
8702 static bool trans_TBH(DisasContext *s, arg_tbranch *a)
8704 return op_tbranch(s, a, true);
8707 static bool trans_CBZ(DisasContext *s, arg_CBZ *a)
8709 TCGv_i32 tmp = load_reg(s, a->rn);
8711 arm_gen_condlabel(s);
8712 tcg_gen_brcondi_i32(a->nz ? TCG_COND_EQ : TCG_COND_NE,
8713 tmp, 0, s->condlabel);
8714 tcg_temp_free_i32(tmp);
8715 gen_jmp(s, read_pc(s) + a->imm);
8716 return true;
8720 * Supervisor call - both T32 & A32 come here so we need to check
8721 * which mode we are in when checking for semihosting.
8724 static bool trans_SVC(DisasContext *s, arg_SVC *a)
8726 const uint32_t semihost_imm = s->thumb ? 0xab : 0x123456;
8728 if (!arm_dc_feature(s, ARM_FEATURE_M) && semihosting_enabled() &&
8729 #ifndef CONFIG_USER_ONLY
8730 !IS_USER(s) &&
8731 #endif
8732 (a->imm == semihost_imm)) {
8733 gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
8734 } else {
8735 gen_set_pc_im(s, s->base.pc_next);
8736 s->svc_imm = a->imm;
8737 s->base.is_jmp = DISAS_SWI;
8739 return true;
8743 * Unconditional system instructions
8746 static bool trans_RFE(DisasContext *s, arg_RFE *a)
8748 static const int8_t pre_offset[4] = {
8749 /* DA */ -4, /* IA */ 0, /* DB */ -8, /* IB */ 4
8751 static const int8_t post_offset[4] = {
8752 /* DA */ -8, /* IA */ 4, /* DB */ -4, /* IB */ 0
8754 TCGv_i32 addr, t1, t2;
8756 if (!ENABLE_ARCH_6 || arm_dc_feature(s, ARM_FEATURE_M)) {
8757 return false;
8759 if (IS_USER(s)) {
8760 unallocated_encoding(s);
8761 return true;
8764 addr = load_reg(s, a->rn);
8765 tcg_gen_addi_i32(addr, addr, pre_offset[a->pu]);
8767 /* Load PC into tmp and CPSR into tmp2. */
8768 t1 = tcg_temp_new_i32();
8769 gen_aa32_ld_i32(s, t1, addr, get_mem_index(s), MO_UL | MO_ALIGN);
8770 tcg_gen_addi_i32(addr, addr, 4);
8771 t2 = tcg_temp_new_i32();
8772 gen_aa32_ld_i32(s, t2, addr, get_mem_index(s), MO_UL | MO_ALIGN);
8774 if (a->w) {
8775 /* Base writeback. */
8776 tcg_gen_addi_i32(addr, addr, post_offset[a->pu]);
8777 store_reg(s, a->rn, addr);
8778 } else {
8779 tcg_temp_free_i32(addr);
8781 gen_rfe(s, t1, t2);
8782 return true;
8785 static bool trans_SRS(DisasContext *s, arg_SRS *a)
8787 if (!ENABLE_ARCH_6 || arm_dc_feature(s, ARM_FEATURE_M)) {
8788 return false;
8790 gen_srs(s, a->mode, a->pu, a->w);
8791 return true;
8794 static bool trans_CPS(DisasContext *s, arg_CPS *a)
8796 uint32_t mask, val;
8798 if (!ENABLE_ARCH_6 || arm_dc_feature(s, ARM_FEATURE_M)) {
8799 return false;
8801 if (IS_USER(s)) {
8802 /* Implemented as NOP in user mode. */
8803 return true;
8805 /* TODO: There are quite a lot of UNPREDICTABLE argument combinations. */
8807 mask = val = 0;
8808 if (a->imod & 2) {
8809 if (a->A) {
8810 mask |= CPSR_A;
8812 if (a->I) {
8813 mask |= CPSR_I;
8815 if (a->F) {
8816 mask |= CPSR_F;
8818 if (a->imod & 1) {
8819 val |= mask;
8822 if (a->M) {
8823 mask |= CPSR_M;
8824 val |= a->mode;
8826 if (mask) {
8827 gen_set_psr_im(s, mask, 0, val);
8829 return true;
8832 static bool trans_CPS_v7m(DisasContext *s, arg_CPS_v7m *a)
8834 TCGv_i32 tmp, addr;
8836 if (!arm_dc_feature(s, ARM_FEATURE_M)) {
8837 return false;
8839 if (IS_USER(s)) {
8840 /* Implemented as NOP in user mode. */
8841 return true;
8844 tmp = tcg_const_i32(a->im);
8845 /* FAULTMASK */
8846 if (a->F) {
8847 addr = tcg_const_i32(19);
8848 gen_helper_v7m_msr(cpu_env, addr, tmp);
8849 tcg_temp_free_i32(addr);
8851 /* PRIMASK */
8852 if (a->I) {
8853 addr = tcg_const_i32(16);
8854 gen_helper_v7m_msr(cpu_env, addr, tmp);
8855 tcg_temp_free_i32(addr);
8857 gen_rebuild_hflags(s, false);
8858 tcg_temp_free_i32(tmp);
8859 gen_lookup_tb(s);
8860 return true;
8864 * Clear-Exclusive, Barriers
8867 static bool trans_CLREX(DisasContext *s, arg_CLREX *a)
8869 if (s->thumb
8870 ? !ENABLE_ARCH_7 && !arm_dc_feature(s, ARM_FEATURE_M)
8871 : !ENABLE_ARCH_6K) {
8872 return false;
8874 gen_clrex(s);
8875 return true;
8878 static bool trans_DSB(DisasContext *s, arg_DSB *a)
8880 if (!ENABLE_ARCH_7 && !arm_dc_feature(s, ARM_FEATURE_M)) {
8881 return false;
8883 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
8884 return true;
8887 static bool trans_DMB(DisasContext *s, arg_DMB *a)
8889 return trans_DSB(s, NULL);
8892 static bool trans_ISB(DisasContext *s, arg_ISB *a)
8894 if (!ENABLE_ARCH_7 && !arm_dc_feature(s, ARM_FEATURE_M)) {
8895 return false;
8898 * We need to break the TB after this insn to execute
8899 * self-modifying code correctly and also to take
8900 * any pending interrupts immediately.
8902 s->base.is_jmp = DISAS_TOO_MANY;
8903 return true;
8906 static bool trans_SB(DisasContext *s, arg_SB *a)
8908 if (!dc_isar_feature(aa32_sb, s)) {
8909 return false;
8912 * TODO: There is no speculation barrier opcode
8913 * for TCG; MB and end the TB instead.
8915 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
8916 s->base.is_jmp = DISAS_TOO_MANY;
8917 return true;
8920 static bool trans_SETEND(DisasContext *s, arg_SETEND *a)
8922 if (!ENABLE_ARCH_6) {
8923 return false;
8925 if (a->E != (s->be_data == MO_BE)) {
8926 gen_helper_setend(cpu_env);
8927 s->base.is_jmp = DISAS_UPDATE_EXIT;
8929 return true;
8933 * Preload instructions
8934 * All are nops, contingent on the appropriate arch level.
8937 static bool trans_PLD(DisasContext *s, arg_PLD *a)
8939 return ENABLE_ARCH_5TE;
8942 static bool trans_PLDW(DisasContext *s, arg_PLD *a)
8944 return arm_dc_feature(s, ARM_FEATURE_V7MP);
8947 static bool trans_PLI(DisasContext *s, arg_PLD *a)
8949 return ENABLE_ARCH_7;
8953 * If-then
8956 static bool trans_IT(DisasContext *s, arg_IT *a)
8958 int cond_mask = a->cond_mask;
8961 * No actual code generated for this insn, just setup state.
8963 * Combinations of firstcond and mask which set up an 0b1111
8964 * condition are UNPREDICTABLE; we take the CONSTRAINED
8965 * UNPREDICTABLE choice to treat 0b1111 the same as 0b1110,
8966 * i.e. both meaning "execute always".
8968 s->condexec_cond = (cond_mask >> 4) & 0xe;
8969 s->condexec_mask = cond_mask & 0x1f;
8970 return true;
8973 /* v8.1M CSEL/CSINC/CSNEG/CSINV */
8974 static bool trans_CSEL(DisasContext *s, arg_CSEL *a)
8976 TCGv_i32 rn, rm, zero;
8977 DisasCompare c;
8979 if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
8980 return false;
8983 if (a->rm == 13) {
8984 /* SEE "Related encodings" (MVE shifts) */
8985 return false;
8988 if (a->rd == 13 || a->rd == 15 || a->rn == 13 || a->fcond >= 14) {
8989 /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
8990 return false;
8993 /* In this insn input reg fields of 0b1111 mean "zero", not "PC" */
8994 if (a->rn == 15) {
8995 rn = tcg_const_i32(0);
8996 } else {
8997 rn = load_reg(s, a->rn);
8999 if (a->rm == 15) {
9000 rm = tcg_const_i32(0);
9001 } else {
9002 rm = load_reg(s, a->rm);
9005 switch (a->op) {
9006 case 0: /* CSEL */
9007 break;
9008 case 1: /* CSINC */
9009 tcg_gen_addi_i32(rm, rm, 1);
9010 break;
9011 case 2: /* CSINV */
9012 tcg_gen_not_i32(rm, rm);
9013 break;
9014 case 3: /* CSNEG */
9015 tcg_gen_neg_i32(rm, rm);
9016 break;
9017 default:
9018 g_assert_not_reached();
9021 arm_test_cc(&c, a->fcond);
9022 zero = tcg_const_i32(0);
9023 tcg_gen_movcond_i32(c.cond, rn, c.value, zero, rn, rm);
9024 arm_free_cc(&c);
9025 tcg_temp_free_i32(zero);
9027 store_reg(s, a->rd, rn);
9028 tcg_temp_free_i32(rm);
9030 return true;
9034 * Legacy decoder.
9037 static void disas_arm_insn(DisasContext *s, unsigned int insn)
9039 unsigned int cond = insn >> 28;
9041 /* M variants do not implement ARM mode; this must raise the INVSTATE
9042 * UsageFault exception.
9044 if (arm_dc_feature(s, ARM_FEATURE_M)) {
9045 gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
9046 default_exception_el(s));
9047 return;
9050 if (s->pstate_il) {
9052 * Illegal execution state. This has priority over BTI
9053 * exceptions, but comes after instruction abort exceptions.
9055 gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
9056 syn_illegalstate(), default_exception_el(s));
9057 return;
9060 if (cond == 0xf) {
9061 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
9062 * choose to UNDEF. In ARMv5 and above the space is used
9063 * for miscellaneous unconditional instructions.
9065 if (!arm_dc_feature(s, ARM_FEATURE_V5)) {
9066 unallocated_encoding(s);
9067 return;
9070 /* Unconditional instructions. */
9071 /* TODO: Perhaps merge these into one decodetree output file. */
9072 if (disas_a32_uncond(s, insn) ||
9073 disas_vfp_uncond(s, insn) ||
9074 disas_neon_dp(s, insn) ||
9075 disas_neon_ls(s, insn) ||
9076 disas_neon_shared(s, insn)) {
9077 return;
9079 /* fall back to legacy decoder */
9081 if ((insn & 0x0e000f00) == 0x0c000100) {
9082 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
9083 /* iWMMXt register transfer. */
9084 if (extract32(s->c15_cpar, 1, 1)) {
9085 if (!disas_iwmmxt_insn(s, insn)) {
9086 return;
9091 goto illegal_op;
9093 if (cond != 0xe) {
9094 /* if not always execute, we generate a conditional jump to
9095 next instruction */
9096 arm_skip_unless(s, cond);
9099 /* TODO: Perhaps merge these into one decodetree output file. */
9100 if (disas_a32(s, insn) ||
9101 disas_vfp(s, insn)) {
9102 return;
9104 /* fall back to legacy decoder */
9105 /* TODO: convert xscale/iwmmxt decoder to decodetree ?? */
9106 if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) {
9107 if (((insn & 0x0c000e00) == 0x0c000000)
9108 && ((insn & 0x03000000) != 0x03000000)) {
9109 /* Coprocessor insn, coprocessor 0 or 1 */
9110 disas_xscale_insn(s, insn);
9111 return;
9115 illegal_op:
9116 unallocated_encoding(s);
9119 static bool thumb_insn_is_16bit(DisasContext *s, uint32_t pc, uint32_t insn)
9122 * Return true if this is a 16 bit instruction. We must be precise
9123 * about this (matching the decode).
9125 if ((insn >> 11) < 0x1d) {
9126 /* Definitely a 16-bit instruction */
9127 return true;
9130 /* Top five bits 0b11101 / 0b11110 / 0b11111 : this is the
9131 * first half of a 32-bit Thumb insn. Thumb-1 cores might
9132 * end up actually treating this as two 16-bit insns, though,
9133 * if it's half of a bl/blx pair that might span a page boundary.
9135 if (arm_dc_feature(s, ARM_FEATURE_THUMB2) ||
9136 arm_dc_feature(s, ARM_FEATURE_M)) {
9137 /* Thumb2 cores (including all M profile ones) always treat
9138 * 32-bit insns as 32-bit.
9140 return false;
9143 if ((insn >> 11) == 0x1e && pc - s->page_start < TARGET_PAGE_SIZE - 3) {
9144 /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix, and the suffix
9145 * is not on the next page; we merge this into a 32-bit
9146 * insn.
9148 return false;
9150 /* 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF);
9151 * 0b1111_1xxx_xxxx_xxxx : BL suffix;
9152 * 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix on the end of a page
9153 * -- handle as single 16 bit insn
9155 return true;
9158 /* Translate a 32-bit thumb instruction. */
9159 static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
9162 * ARMv6-M supports a limited subset of Thumb2 instructions.
9163 * Other Thumb1 architectures allow only 32-bit
9164 * combined BL/BLX prefix and suffix.
9166 if (arm_dc_feature(s, ARM_FEATURE_M) &&
9167 !arm_dc_feature(s, ARM_FEATURE_V7)) {
9168 int i;
9169 bool found = false;
9170 static const uint32_t armv6m_insn[] = {0xf3808000 /* msr */,
9171 0xf3b08040 /* dsb */,
9172 0xf3b08050 /* dmb */,
9173 0xf3b08060 /* isb */,
9174 0xf3e08000 /* mrs */,
9175 0xf000d000 /* bl */};
9176 static const uint32_t armv6m_mask[] = {0xffe0d000,
9177 0xfff0d0f0,
9178 0xfff0d0f0,
9179 0xfff0d0f0,
9180 0xffe0d000,
9181 0xf800d000};
9183 for (i = 0; i < ARRAY_SIZE(armv6m_insn); i++) {
9184 if ((insn & armv6m_mask[i]) == armv6m_insn[i]) {
9185 found = true;
9186 break;
9189 if (!found) {
9190 goto illegal_op;
9192 } else if ((insn & 0xf800e800) != 0xf000e800) {
9193 if (!arm_dc_feature(s, ARM_FEATURE_THUMB2)) {
9194 unallocated_encoding(s);
9195 return;
9199 if (arm_dc_feature(s, ARM_FEATURE_M)) {
9201 * NOCP takes precedence over any UNDEF for (almost) the
9202 * entire wide range of coprocessor-space encodings, so check
9203 * for it first before proceeding to actually decode eg VFP
9204 * insns. This decode also handles the few insns which are
9205 * in copro space but do not have NOCP checks (eg VLLDM, VLSTM).
9207 if (disas_m_nocp(s, insn)) {
9208 return;
9212 if ((insn & 0xef000000) == 0xef000000) {
9214 * T32 encodings 0b111p_1111_qqqq_qqqq_qqqq_qqqq_qqqq_qqqq
9215 * transform into
9216 * A32 encodings 0b1111_001p_qqqq_qqqq_qqqq_qqqq_qqqq_qqqq
9218 uint32_t a32_insn = (insn & 0xe2ffffff) |
9219 ((insn & (1 << 28)) >> 4) | (1 << 28);
9221 if (disas_neon_dp(s, a32_insn)) {
9222 return;
9226 if ((insn & 0xff100000) == 0xf9000000) {
9228 * T32 encodings 0b1111_1001_ppp0_qqqq_qqqq_qqqq_qqqq_qqqq
9229 * transform into
9230 * A32 encodings 0b1111_0100_ppp0_qqqq_qqqq_qqqq_qqqq_qqqq
9232 uint32_t a32_insn = (insn & 0x00ffffff) | 0xf4000000;
9234 if (disas_neon_ls(s, a32_insn)) {
9235 return;
9240 * TODO: Perhaps merge these into one decodetree output file.
9241 * Note disas_vfp is written for a32 with cond field in the
9242 * top nibble. The t32 encoding requires 0xe in the top nibble.
9244 if (disas_t32(s, insn) ||
9245 disas_vfp_uncond(s, insn) ||
9246 disas_neon_shared(s, insn) ||
9247 disas_mve(s, insn) ||
9248 ((insn >> 28) == 0xe && disas_vfp(s, insn))) {
9249 return;
9252 illegal_op:
9253 unallocated_encoding(s);
9256 static void disas_thumb_insn(DisasContext *s, uint32_t insn)
9258 if (!disas_t16(s, insn)) {
9259 unallocated_encoding(s);
9263 static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
9265 /* Return true if the insn at dc->base.pc_next might cross a page boundary.
9266 * (False positives are OK, false negatives are not.)
9267 * We know this is a Thumb insn, and our caller ensures we are
9268 * only called if dc->base.pc_next is less than 4 bytes from the page
9269 * boundary, so we cross the page if the first 16 bits indicate
9270 * that this is a 32 bit insn.
9272 uint16_t insn = arm_lduw_code(env, &s->base, s->base.pc_next, s->sctlr_b);
9274 return !thumb_insn_is_16bit(s, s->base.pc_next, insn);
9277 static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
9279 DisasContext *dc = container_of(dcbase, DisasContext, base);
9280 CPUARMState *env = cs->env_ptr;
9281 ARMCPU *cpu = env_archcpu(env);
9282 CPUARMTBFlags tb_flags = arm_tbflags_from_tb(dc->base.tb);
9283 uint32_t condexec, core_mmu_idx;
9285 dc->isar = &cpu->isar;
9286 dc->condjmp = 0;
9288 dc->aarch64 = false;
9289 /* If we are coming from secure EL0 in a system with a 32-bit EL3, then
9290 * there is no secure EL1, so we route exceptions to EL3.
9292 dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
9293 !arm_el_is_aa64(env, 3);
9294 dc->thumb = EX_TBFLAG_AM32(tb_flags, THUMB);
9295 dc->be_data = EX_TBFLAG_ANY(tb_flags, BE_DATA) ? MO_BE : MO_LE;
9296 condexec = EX_TBFLAG_AM32(tb_flags, CONDEXEC);
9298 * the CONDEXEC TB flags are CPSR bits [15:10][26:25]. On A-profile this
9299 * is always the IT bits. On M-profile, some of the reserved encodings
9300 * of IT are used instead to indicate either ICI or ECI, which
9301 * indicate partial progress of a restartable insn that was interrupted
9302 * partway through by an exception:
9303 * * if CONDEXEC[3:0] != 0b0000 : CONDEXEC is IT bits
9304 * * if CONDEXEC[3:0] == 0b0000 : CONDEXEC is ICI or ECI bits
9305 * In all cases CONDEXEC == 0 means "not in IT block or restartable
9306 * insn, behave normally".
9308 dc->eci = dc->condexec_mask = dc->condexec_cond = 0;
9309 dc->eci_handled = false;
9310 dc->insn_eci_rewind = NULL;
9311 if (condexec & 0xf) {
9312 dc->condexec_mask = (condexec & 0xf) << 1;
9313 dc->condexec_cond = condexec >> 4;
9314 } else {
9315 if (arm_feature(env, ARM_FEATURE_M)) {
9316 dc->eci = condexec >> 4;
9320 core_mmu_idx = EX_TBFLAG_ANY(tb_flags, MMUIDX);
9321 dc->mmu_idx = core_to_arm_mmu_idx(env, core_mmu_idx);
9322 dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
9323 #if !defined(CONFIG_USER_ONLY)
9324 dc->user = (dc->current_el == 0);
9325 #endif
9326 dc->fp_excp_el = EX_TBFLAG_ANY(tb_flags, FPEXC_EL);
9327 dc->align_mem = EX_TBFLAG_ANY(tb_flags, ALIGN_MEM);
9328 dc->pstate_il = EX_TBFLAG_ANY(tb_flags, PSTATE__IL);
9330 if (arm_feature(env, ARM_FEATURE_M)) {
9331 dc->vfp_enabled = 1;
9332 dc->be_data = MO_TE;
9333 dc->v7m_handler_mode = EX_TBFLAG_M32(tb_flags, HANDLER);
9334 dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
9335 regime_is_secure(env, dc->mmu_idx);
9336 dc->v8m_stackcheck = EX_TBFLAG_M32(tb_flags, STACKCHECK);
9337 dc->v8m_fpccr_s_wrong = EX_TBFLAG_M32(tb_flags, FPCCR_S_WRONG);
9338 dc->v7m_new_fp_ctxt_needed =
9339 EX_TBFLAG_M32(tb_flags, NEW_FP_CTXT_NEEDED);
9340 dc->v7m_lspact = EX_TBFLAG_M32(tb_flags, LSPACT);
9341 dc->mve_no_pred = EX_TBFLAG_M32(tb_flags, MVE_NO_PRED);
9342 } else {
9343 dc->debug_target_el = EX_TBFLAG_ANY(tb_flags, DEBUG_TARGET_EL);
9344 dc->sctlr_b = EX_TBFLAG_A32(tb_flags, SCTLR__B);
9345 dc->hstr_active = EX_TBFLAG_A32(tb_flags, HSTR_ACTIVE);
9346 dc->ns = EX_TBFLAG_A32(tb_flags, NS);
9347 dc->vfp_enabled = EX_TBFLAG_A32(tb_flags, VFPEN);
9348 if (arm_feature(env, ARM_FEATURE_XSCALE)) {
9349 dc->c15_cpar = EX_TBFLAG_A32(tb_flags, XSCALE_CPAR);
9350 } else {
9351 dc->vec_len = EX_TBFLAG_A32(tb_flags, VECLEN);
9352 dc->vec_stride = EX_TBFLAG_A32(tb_flags, VECSTRIDE);
9355 dc->cp_regs = cpu->cp_regs;
9356 dc->features = env->features;
9358 /* Single step state. The code-generation logic here is:
9359 * SS_ACTIVE == 0:
9360 * generate code with no special handling for single-stepping (except
9361 * that anything that can make us go to SS_ACTIVE == 1 must end the TB;
9362 * this happens anyway because those changes are all system register or
9363 * PSTATE writes).
9364 * SS_ACTIVE == 1, PSTATE.SS == 1: (active-not-pending)
9365 * emit code for one insn
9366 * emit code to clear PSTATE.SS
9367 * emit code to generate software step exception for completed step
9368 * end TB (as usual for having generated an exception)
9369 * SS_ACTIVE == 1, PSTATE.SS == 0: (active-pending)
9370 * emit code to generate a software step exception
9371 * end the TB
9373 dc->ss_active = EX_TBFLAG_ANY(tb_flags, SS_ACTIVE);
9374 dc->pstate_ss = EX_TBFLAG_ANY(tb_flags, PSTATE__SS);
9375 dc->is_ldex = false;
9377 dc->page_start = dc->base.pc_first & TARGET_PAGE_MASK;
9379 /* If architectural single step active, limit to 1. */
9380 if (dc->ss_active) {
9381 dc->base.max_insns = 1;
9384 /* ARM is a fixed-length ISA. Bound the number of insns to execute
9385 to those left on the page. */
9386 if (!dc->thumb) {
9387 int bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
9388 dc->base.max_insns = MIN(dc->base.max_insns, bound);
9391 cpu_V0 = tcg_temp_new_i64();
9392 cpu_V1 = tcg_temp_new_i64();
9393 cpu_M0 = tcg_temp_new_i64();
9396 static void arm_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
9398 DisasContext *dc = container_of(dcbase, DisasContext, base);
9400 /* A note on handling of the condexec (IT) bits:
9402 * We want to avoid the overhead of having to write the updated condexec
9403 * bits back to the CPUARMState for every instruction in an IT block. So:
9404 * (1) if the condexec bits are not already zero then we write
9405 * zero back into the CPUARMState now. This avoids complications trying
9406 * to do it at the end of the block. (For example if we don't do this
9407 * it's hard to identify whether we can safely skip writing condexec
9408 * at the end of the TB, which we definitely want to do for the case
9409 * where a TB doesn't do anything with the IT state at all.)
9410 * (2) if we are going to leave the TB then we call gen_set_condexec()
9411 * which will write the correct value into CPUARMState if zero is wrong.
9412 * This is done both for leaving the TB at the end, and for leaving
9413 * it because of an exception we know will happen, which is done in
9414 * gen_exception_insn(). The latter is necessary because we need to
9415 * leave the TB with the PC/IT state just prior to execution of the
9416 * instruction which caused the exception.
9417 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
9418 * then the CPUARMState will be wrong and we need to reset it.
9419 * This is handled in the same way as restoration of the
9420 * PC in these situations; we save the value of the condexec bits
9421 * for each PC via tcg_gen_insn_start(), and restore_state_to_opc()
9422 * then uses this to restore them after an exception.
9424 * Note that there are no instructions which can read the condexec
9425 * bits, and none which can write non-static values to them, so
9426 * we don't need to care about whether CPUARMState is correct in the
9427 * middle of a TB.
9430 /* Reset the conditional execution bits immediately. This avoids
9431 complications trying to do it at the end of the block. */
9432 if (dc->condexec_mask || dc->condexec_cond) {
9433 store_cpu_field_constant(0, condexec_bits);
9437 static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
9439 DisasContext *dc = container_of(dcbase, DisasContext, base);
9441 * The ECI/ICI bits share PSR bits with the IT bits, so we
9442 * need to reconstitute the bits from the split-out DisasContext
9443 * fields here.
9445 uint32_t condexec_bits;
9447 if (dc->eci) {
9448 condexec_bits = dc->eci << 4;
9449 } else {
9450 condexec_bits = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
9452 tcg_gen_insn_start(dc->base.pc_next, condexec_bits, 0);
9453 dc->insn_start = tcg_last_op();
9456 static bool arm_check_kernelpage(DisasContext *dc)
9458 #ifdef CONFIG_USER_ONLY
9459 /* Intercept jump to the magic kernel page. */
9460 if (dc->base.pc_next >= 0xffff0000) {
9461 /* We always get here via a jump, so know we are not in a
9462 conditional execution block. */
9463 gen_exception_internal(EXCP_KERNEL_TRAP);
9464 dc->base.is_jmp = DISAS_NORETURN;
9465 return true;
9467 #endif
9468 return false;
9471 static bool arm_check_ss_active(DisasContext *dc)
9473 if (dc->ss_active && !dc->pstate_ss) {
9474 /* Singlestep state is Active-pending.
9475 * If we're in this state at the start of a TB then either
9476 * a) we just took an exception to an EL which is being debugged
9477 * and this is the first insn in the exception handler
9478 * b) debug exceptions were masked and we just unmasked them
9479 * without changing EL (eg by clearing PSTATE.D)
9480 * In either case we're going to take a swstep exception in the
9481 * "did not step an insn" case, and so the syndrome ISV and EX
9482 * bits should be zero.
9484 assert(dc->base.num_insns == 1);
9485 gen_swstep_exception(dc, 0, 0);
9486 dc->base.is_jmp = DISAS_NORETURN;
9487 return true;
9490 return false;
9493 static void arm_post_translate_insn(DisasContext *dc)
9495 if (dc->condjmp && !dc->base.is_jmp) {
9496 gen_set_label(dc->condlabel);
9497 dc->condjmp = 0;
9499 translator_loop_temp_check(&dc->base);
9502 static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
9504 DisasContext *dc = container_of(dcbase, DisasContext, base);
9505 CPUARMState *env = cpu->env_ptr;
9506 uint32_t pc = dc->base.pc_next;
9507 unsigned int insn;
9509 /* Singlestep exceptions have the highest priority. */
9510 if (arm_check_ss_active(dc)) {
9511 dc->base.pc_next = pc + 4;
9512 return;
9515 if (pc & 3) {
9517 * PC alignment fault. This has priority over the instruction abort
9518 * that we would receive from a translation fault via arm_ldl_code
9519 * (or the execution of the kernelpage entrypoint). This should only
9520 * be possible after an indirect branch, at the start of the TB.
9522 assert(dc->base.num_insns == 1);
9523 gen_helper_exception_pc_alignment(cpu_env, tcg_constant_tl(pc));
9524 dc->base.is_jmp = DISAS_NORETURN;
9525 dc->base.pc_next = QEMU_ALIGN_UP(pc, 4);
9526 return;
9529 if (arm_check_kernelpage(dc)) {
9530 dc->base.pc_next = pc + 4;
9531 return;
9534 dc->pc_curr = pc;
9535 insn = arm_ldl_code(env, &dc->base, pc, dc->sctlr_b);
9536 dc->insn = insn;
9537 dc->base.pc_next = pc + 4;
9538 disas_arm_insn(dc, insn);
9540 arm_post_translate_insn(dc);
9542 /* ARM is a fixed-length ISA. We performed the cross-page check
9543 in init_disas_context by adjusting max_insns. */
9546 static bool thumb_insn_is_unconditional(DisasContext *s, uint32_t insn)
9548 /* Return true if this Thumb insn is always unconditional,
9549 * even inside an IT block. This is true of only a very few
9550 * instructions: BKPT, HLT, and SG.
9552 * A larger class of instructions are UNPREDICTABLE if used
9553 * inside an IT block; we do not need to detect those here, because
9554 * what we do by default (perform the cc check and update the IT
9555 * bits state machine) is a permitted CONSTRAINED UNPREDICTABLE
9556 * choice for those situations.
9558 * insn is either a 16-bit or a 32-bit instruction; the two are
9559 * distinguishable because for the 16-bit case the top 16 bits
9560 * are zeroes, and that isn't a valid 32-bit encoding.
9562 if ((insn & 0xffffff00) == 0xbe00) {
9563 /* BKPT */
9564 return true;
9567 if ((insn & 0xffffffc0) == 0xba80 && arm_dc_feature(s, ARM_FEATURE_V8) &&
9568 !arm_dc_feature(s, ARM_FEATURE_M)) {
9569 /* HLT: v8A only. This is unconditional even when it is going to
9570 * UNDEF; see the v8A ARM ARM DDI0487B.a H3.3.
9571 * For v7 cores this was a plain old undefined encoding and so
9572 * honours its cc check. (We might be using the encoding as
9573 * a semihosting trap, but we don't change the cc check behaviour
9574 * on that account, because a debugger connected to a real v7A
9575 * core and emulating semihosting traps by catching the UNDEF
9576 * exception would also only see cases where the cc check passed.
9577 * No guest code should be trying to do a HLT semihosting trap
9578 * in an IT block anyway.
9580 return true;
9583 if (insn == 0xe97fe97f && arm_dc_feature(s, ARM_FEATURE_V8) &&
9584 arm_dc_feature(s, ARM_FEATURE_M)) {
9585 /* SG: v8M only */
9586 return true;
9589 return false;
9592 static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
9594 DisasContext *dc = container_of(dcbase, DisasContext, base);
9595 CPUARMState *env = cpu->env_ptr;
9596 uint32_t pc = dc->base.pc_next;
9597 uint32_t insn;
9598 bool is_16bit;
9600 /* Misaligned thumb PC is architecturally impossible. */
9601 assert((dc->base.pc_next & 1) == 0);
9603 if (arm_check_ss_active(dc) || arm_check_kernelpage(dc)) {
9604 dc->base.pc_next = pc + 2;
9605 return;
9608 dc->pc_curr = pc;
9609 insn = arm_lduw_code(env, &dc->base, pc, dc->sctlr_b);
9610 is_16bit = thumb_insn_is_16bit(dc, dc->base.pc_next, insn);
9611 pc += 2;
9612 if (!is_16bit) {
9613 uint32_t insn2 = arm_lduw_code(env, &dc->base, pc, dc->sctlr_b);
9614 insn = insn << 16 | insn2;
9615 pc += 2;
9617 dc->base.pc_next = pc;
9618 dc->insn = insn;
9620 if (dc->pstate_il) {
9622 * Illegal execution state. This has priority over BTI
9623 * exceptions, but comes after instruction abort exceptions.
9625 gen_exception_insn(dc, dc->pc_curr, EXCP_UDEF,
9626 syn_illegalstate(), default_exception_el(dc));
9627 return;
9630 if (dc->eci) {
9632 * For M-profile continuable instructions, ECI/ICI handling
9633 * falls into these cases:
9634 * - interrupt-continuable instructions
9635 * These are the various load/store multiple insns (both
9636 * integer and fp). The ICI bits indicate the register
9637 * where the load/store can resume. We make the IMPDEF
9638 * choice to always do "instruction restart", ie ignore
9639 * the ICI value and always execute the ldm/stm from the
9640 * start. So all we need to do is zero PSR.ICI if the
9641 * insn executes.
9642 * - MVE instructions subject to beat-wise execution
9643 * Here the ECI bits indicate which beats have already been
9644 * executed, and we must honour this. Each insn of this
9645 * type will handle it correctly. We will update PSR.ECI
9646 * in the helper function for the insn (some ECI values
9647 * mean that the following insn also has been partially
9648 * executed).
9649 * - Special cases which don't advance ECI
9650 * The insns LE, LETP and BKPT leave the ECI/ICI state
9651 * bits untouched.
9652 * - all other insns (the common case)
9653 * Non-zero ECI/ICI means an INVSTATE UsageFault.
9654 * We place a rewind-marker here. Insns in the previous
9655 * three categories will set a flag in the DisasContext.
9656 * If the flag isn't set after we call disas_thumb_insn()
9657 * or disas_thumb2_insn() then we know we have a "some other
9658 * insn" case. We will rewind to the marker (ie throwing away
9659 * all the generated code) and instead emit "take exception".
9661 dc->insn_eci_rewind = tcg_last_op();
9664 if (dc->condexec_mask && !thumb_insn_is_unconditional(dc, insn)) {
9665 uint32_t cond = dc->condexec_cond;
9668 * Conditionally skip the insn. Note that both 0xe and 0xf mean
9669 * "always"; 0xf is not "never".
9671 if (cond < 0x0e) {
9672 arm_skip_unless(dc, cond);
9676 if (is_16bit) {
9677 disas_thumb_insn(dc, insn);
9678 } else {
9679 disas_thumb2_insn(dc, insn);
9682 /* Advance the Thumb condexec condition. */
9683 if (dc->condexec_mask) {
9684 dc->condexec_cond = ((dc->condexec_cond & 0xe) |
9685 ((dc->condexec_mask >> 4) & 1));
9686 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
9687 if (dc->condexec_mask == 0) {
9688 dc->condexec_cond = 0;
9692 if (dc->eci && !dc->eci_handled) {
9694 * Insn wasn't valid for ECI/ICI at all: undo what we
9695 * just generated and instead emit an exception
9697 tcg_remove_ops_after(dc->insn_eci_rewind);
9698 dc->condjmp = 0;
9699 gen_exception_insn(dc, dc->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
9700 default_exception_el(dc));
9703 arm_post_translate_insn(dc);
9705 /* Thumb is a variable-length ISA. Stop translation when the next insn
9706 * will touch a new page. This ensures that prefetch aborts occur at
9707 * the right place.
9709 * We want to stop the TB if the next insn starts in a new page,
9710 * or if it spans between this page and the next. This means that
9711 * if we're looking at the last halfword in the page we need to
9712 * see if it's a 16-bit Thumb insn (which will fit in this TB)
9713 * or a 32-bit Thumb insn (which won't).
9714 * This is to avoid generating a silly TB with a single 16-bit insn
9715 * in it at the end of this page (which would execute correctly
9716 * but isn't very efficient).
9718 if (dc->base.is_jmp == DISAS_NEXT
9719 && (dc->base.pc_next - dc->page_start >= TARGET_PAGE_SIZE
9720 || (dc->base.pc_next - dc->page_start >= TARGET_PAGE_SIZE - 3
9721 && insn_crosses_page(env, dc)))) {
9722 dc->base.is_jmp = DISAS_TOO_MANY;
9726 static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
9728 DisasContext *dc = container_of(dcbase, DisasContext, base);
9730 /* At this stage dc->condjmp will only be set when the skipped
9731 instruction was a conditional branch or trap, and the PC has
9732 already been written. */
9733 gen_set_condexec(dc);
9734 if (dc->base.is_jmp == DISAS_BX_EXCRET) {
9735 /* Exception return branches need some special case code at the
9736 * end of the TB, which is complex enough that it has to
9737 * handle the single-step vs not and the condition-failed
9738 * insn codepath itself.
9740 gen_bx_excret_final_code(dc);
9741 } else if (unlikely(dc->ss_active)) {
9742 /* Unconditional and "condition passed" instruction codepath. */
9743 switch (dc->base.is_jmp) {
9744 case DISAS_SWI:
9745 gen_ss_advance(dc);
9746 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
9747 default_exception_el(dc));
9748 break;
9749 case DISAS_HVC:
9750 gen_ss_advance(dc);
9751 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
9752 break;
9753 case DISAS_SMC:
9754 gen_ss_advance(dc);
9755 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
9756 break;
9757 case DISAS_NEXT:
9758 case DISAS_TOO_MANY:
9759 case DISAS_UPDATE_EXIT:
9760 case DISAS_UPDATE_NOCHAIN:
9761 gen_set_pc_im(dc, dc->base.pc_next);
9762 /* fall through */
9763 default:
9764 /* FIXME: Single stepping a WFI insn will not halt the CPU. */
9765 gen_singlestep_exception(dc);
9766 break;
9767 case DISAS_NORETURN:
9768 break;
9770 } else {
9771 /* While branches must always occur at the end of an IT block,
9772 there are a few other things that can cause us to terminate
9773 the TB in the middle of an IT block:
9774 - Exception generating instructions (bkpt, swi, undefined).
9775 - Page boundaries.
9776 - Hardware watchpoints.
9777 Hardware breakpoints have already been handled and skip this code.
9779 switch (dc->base.is_jmp) {
9780 case DISAS_NEXT:
9781 case DISAS_TOO_MANY:
9782 gen_goto_tb(dc, 1, dc->base.pc_next);
9783 break;
9784 case DISAS_UPDATE_NOCHAIN:
9785 gen_set_pc_im(dc, dc->base.pc_next);
9786 /* fall through */
9787 case DISAS_JUMP:
9788 gen_goto_ptr();
9789 break;
9790 case DISAS_UPDATE_EXIT:
9791 gen_set_pc_im(dc, dc->base.pc_next);
9792 /* fall through */
9793 default:
9794 /* indicate that the hash table must be used to find the next TB */
9795 tcg_gen_exit_tb(NULL, 0);
9796 break;
9797 case DISAS_NORETURN:
9798 /* nothing more to generate */
9799 break;
9800 case DISAS_WFI:
9801 gen_helper_wfi(cpu_env,
9802 tcg_constant_i32(dc->base.pc_next - dc->pc_curr));
9804 * The helper doesn't necessarily throw an exception, but we
9805 * must go back to the main loop to check for interrupts anyway.
9807 tcg_gen_exit_tb(NULL, 0);
9808 break;
9809 case DISAS_WFE:
9810 gen_helper_wfe(cpu_env);
9811 break;
9812 case DISAS_YIELD:
9813 gen_helper_yield(cpu_env);
9814 break;
9815 case DISAS_SWI:
9816 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
9817 default_exception_el(dc));
9818 break;
9819 case DISAS_HVC:
9820 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
9821 break;
9822 case DISAS_SMC:
9823 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
9824 break;
9828 if (dc->condjmp) {
9829 /* "Condition failed" instruction codepath for the branch/trap insn */
9830 gen_set_label(dc->condlabel);
9831 gen_set_condexec(dc);
9832 if (unlikely(dc->ss_active)) {
9833 gen_set_pc_im(dc, dc->base.pc_next);
9834 gen_singlestep_exception(dc);
9835 } else {
9836 gen_goto_tb(dc, 1, dc->base.pc_next);
9841 static void arm_tr_disas_log(const DisasContextBase *dcbase,
9842 CPUState *cpu, FILE *logfile)
9844 DisasContext *dc = container_of(dcbase, DisasContext, base);
9846 fprintf(logfile, "IN: %s\n", lookup_symbol(dc->base.pc_first));
9847 target_disas(logfile, cpu, dc->base.pc_first, dc->base.tb->size);
9850 static const TranslatorOps arm_translator_ops = {
9851 .init_disas_context = arm_tr_init_disas_context,
9852 .tb_start = arm_tr_tb_start,
9853 .insn_start = arm_tr_insn_start,
9854 .translate_insn = arm_tr_translate_insn,
9855 .tb_stop = arm_tr_tb_stop,
9856 .disas_log = arm_tr_disas_log,
9859 static const TranslatorOps thumb_translator_ops = {
9860 .init_disas_context = arm_tr_init_disas_context,
9861 .tb_start = arm_tr_tb_start,
9862 .insn_start = arm_tr_insn_start,
9863 .translate_insn = thumb_tr_translate_insn,
9864 .tb_stop = arm_tr_tb_stop,
9865 .disas_log = arm_tr_disas_log,
9868 /* generate intermediate code for basic block 'tb'. */
9869 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
9871 DisasContext dc = { };
9872 const TranslatorOps *ops = &arm_translator_ops;
9873 CPUARMTBFlags tb_flags = arm_tbflags_from_tb(tb);
9875 if (EX_TBFLAG_AM32(tb_flags, THUMB)) {
9876 ops = &thumb_translator_ops;
9878 #ifdef TARGET_AARCH64
9879 if (EX_TBFLAG_ANY(tb_flags, AARCH64_STATE)) {
9880 ops = &aarch64_translator_ops;
9882 #endif
9884 translator_loop(ops, &dc.base, cpu, tb, max_insns);
9887 void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb,
9888 target_ulong *data)
9890 if (is_a64(env)) {
9891 env->pc = data[0];
9892 env->condexec_bits = 0;
9893 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
9894 } else {
9895 env->regs[15] = data[0];
9896 env->condexec_bits = data[1];
9897 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;