target/arm: Move general-use constant expanders up in translate.c
[qemu/ar7.git] / target / arm / translate.c
blobf5acd32e76adea33b6ed58a57d98f2d48556ccf9
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 "hw/semihosting/semihost.h"
34 #include "exec/helper-proto.h"
35 #include "exec/helper-gen.h"
37 #include "trace-tcg.h"
38 #include "exec/log.h"
41 #define ENABLE_ARCH_4T arm_dc_feature(s, ARM_FEATURE_V4T)
42 #define ENABLE_ARCH_5 arm_dc_feature(s, ARM_FEATURE_V5)
43 /* currently all emulated v5 cores are also v5TE, so don't bother */
44 #define ENABLE_ARCH_5TE arm_dc_feature(s, ARM_FEATURE_V5)
45 #define ENABLE_ARCH_5J dc_isar_feature(aa32_jazelle, s)
46 #define ENABLE_ARCH_6 arm_dc_feature(s, ARM_FEATURE_V6)
47 #define ENABLE_ARCH_6K arm_dc_feature(s, ARM_FEATURE_V6K)
48 #define ENABLE_ARCH_6T2 arm_dc_feature(s, ARM_FEATURE_THUMB2)
49 #define ENABLE_ARCH_7 arm_dc_feature(s, ARM_FEATURE_V7)
50 #define ENABLE_ARCH_8 arm_dc_feature(s, ARM_FEATURE_V8)
52 #include "translate.h"
54 #if defined(CONFIG_USER_ONLY)
55 #define IS_USER(s) 1
56 #else
57 #define IS_USER(s) (s->user)
58 #endif
60 /* These are TCG temporaries used only by the legacy iwMMXt decoder */
61 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
62 /* These are TCG globals which alias CPUARMState fields */
63 static TCGv_i32 cpu_R[16];
64 TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
65 TCGv_i64 cpu_exclusive_addr;
66 TCGv_i64 cpu_exclusive_val;
68 #include "exec/gen-icount.h"
70 static const char * const regnames[] =
71 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
72 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
74 /* Function prototypes for gen_ functions calling Neon helpers. */
75 typedef void NeonGenThreeOpEnvFn(TCGv_i32, TCGv_env, TCGv_i32,
76 TCGv_i32, TCGv_i32);
77 /* Function prototypes for gen_ functions for fix point conversions */
78 typedef void VFPGenFixPointFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
80 /* initialize TCG globals. */
81 void arm_translate_init(void)
83 int i;
85 for (i = 0; i < 16; i++) {
86 cpu_R[i] = tcg_global_mem_new_i32(cpu_env,
87 offsetof(CPUARMState, regs[i]),
88 regnames[i]);
90 cpu_CF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, CF), "CF");
91 cpu_NF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, NF), "NF");
92 cpu_VF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, VF), "VF");
93 cpu_ZF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, ZF), "ZF");
95 cpu_exclusive_addr = tcg_global_mem_new_i64(cpu_env,
96 offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
97 cpu_exclusive_val = tcg_global_mem_new_i64(cpu_env,
98 offsetof(CPUARMState, exclusive_val), "exclusive_val");
100 a64_translate_init();
103 /* Generate a label used for skipping this instruction */
104 static void arm_gen_condlabel(DisasContext *s)
106 if (!s->condjmp) {
107 s->condlabel = gen_new_label();
108 s->condjmp = 1;
113 * Constant expanders for the decoders.
116 static int negate(DisasContext *s, int x)
118 return -x;
121 static int plus_2(DisasContext *s, int x)
123 return x + 2;
126 static int times_2(DisasContext *s, int x)
128 return x * 2;
131 static int times_4(DisasContext *s, int x)
133 return x * 4;
136 /* Flags for the disas_set_da_iss info argument:
137 * lower bits hold the Rt register number, higher bits are flags.
139 typedef enum ISSInfo {
140 ISSNone = 0,
141 ISSRegMask = 0x1f,
142 ISSInvalid = (1 << 5),
143 ISSIsAcqRel = (1 << 6),
144 ISSIsWrite = (1 << 7),
145 ISSIs16Bit = (1 << 8),
146 } ISSInfo;
148 /* Save the syndrome information for a Data Abort */
149 static void disas_set_da_iss(DisasContext *s, MemOp memop, ISSInfo issinfo)
151 uint32_t syn;
152 int sas = memop & MO_SIZE;
153 bool sse = memop & MO_SIGN;
154 bool is_acqrel = issinfo & ISSIsAcqRel;
155 bool is_write = issinfo & ISSIsWrite;
156 bool is_16bit = issinfo & ISSIs16Bit;
157 int srt = issinfo & ISSRegMask;
159 if (issinfo & ISSInvalid) {
160 /* Some callsites want to conditionally provide ISS info,
161 * eg "only if this was not a writeback"
163 return;
166 if (srt == 15) {
167 /* For AArch32, insns where the src/dest is R15 never generate
168 * ISS information. Catching that here saves checking at all
169 * the call sites.
171 return;
174 syn = syn_data_abort_with_iss(0, sas, sse, srt, 0, is_acqrel,
175 0, 0, 0, is_write, 0, is_16bit);
176 disas_set_insn_syndrome(s, syn);
179 static inline int get_a32_user_mem_index(DisasContext *s)
181 /* Return the core mmu_idx to use for A32/T32 "unprivileged load/store"
182 * insns:
183 * if PL2, UNPREDICTABLE (we choose to implement as if PL0)
184 * otherwise, access as if at PL0.
186 switch (s->mmu_idx) {
187 case ARMMMUIdx_E2: /* this one is UNPREDICTABLE */
188 case ARMMMUIdx_E10_0:
189 case ARMMMUIdx_E10_1:
190 case ARMMMUIdx_E10_1_PAN:
191 return arm_to_core_mmu_idx(ARMMMUIdx_E10_0);
192 case ARMMMUIdx_SE3:
193 case ARMMMUIdx_SE10_0:
194 case ARMMMUIdx_SE10_1:
195 case ARMMMUIdx_SE10_1_PAN:
196 return arm_to_core_mmu_idx(ARMMMUIdx_SE10_0);
197 case ARMMMUIdx_MUser:
198 case ARMMMUIdx_MPriv:
199 return arm_to_core_mmu_idx(ARMMMUIdx_MUser);
200 case ARMMMUIdx_MUserNegPri:
201 case ARMMMUIdx_MPrivNegPri:
202 return arm_to_core_mmu_idx(ARMMMUIdx_MUserNegPri);
203 case ARMMMUIdx_MSUser:
204 case ARMMMUIdx_MSPriv:
205 return arm_to_core_mmu_idx(ARMMMUIdx_MSUser);
206 case ARMMMUIdx_MSUserNegPri:
207 case ARMMMUIdx_MSPrivNegPri:
208 return arm_to_core_mmu_idx(ARMMMUIdx_MSUserNegPri);
209 default:
210 g_assert_not_reached();
214 static inline TCGv_i32 load_cpu_offset(int offset)
216 TCGv_i32 tmp = tcg_temp_new_i32();
217 tcg_gen_ld_i32(tmp, cpu_env, offset);
218 return tmp;
221 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
223 static inline void store_cpu_offset(TCGv_i32 var, int offset)
225 tcg_gen_st_i32(var, cpu_env, offset);
226 tcg_temp_free_i32(var);
229 #define store_cpu_field(var, name) \
230 store_cpu_offset(var, offsetof(CPUARMState, name))
232 /* The architectural value of PC. */
233 static uint32_t read_pc(DisasContext *s)
235 return s->pc_curr + (s->thumb ? 4 : 8);
238 /* Set a variable to the value of a CPU register. */
239 static void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
241 if (reg == 15) {
242 tcg_gen_movi_i32(var, read_pc(s));
243 } else {
244 tcg_gen_mov_i32(var, cpu_R[reg]);
248 /* Create a new temporary and set it to the value of a CPU register. */
249 static inline TCGv_i32 load_reg(DisasContext *s, int reg)
251 TCGv_i32 tmp = tcg_temp_new_i32();
252 load_reg_var(s, tmp, reg);
253 return tmp;
257 * Create a new temp, REG + OFS, except PC is ALIGN(PC, 4).
258 * This is used for load/store for which use of PC implies (literal),
259 * or ADD that implies ADR.
261 static TCGv_i32 add_reg_for_lit(DisasContext *s, int reg, int ofs)
263 TCGv_i32 tmp = tcg_temp_new_i32();
265 if (reg == 15) {
266 tcg_gen_movi_i32(tmp, (read_pc(s) & ~3) + ofs);
267 } else {
268 tcg_gen_addi_i32(tmp, cpu_R[reg], ofs);
270 return tmp;
273 /* Set a CPU register. The source must be a temporary and will be
274 marked as dead. */
275 static void store_reg(DisasContext *s, int reg, TCGv_i32 var)
277 if (reg == 15) {
278 /* In Thumb mode, we must ignore bit 0.
279 * In ARM mode, for ARMv4 and ARMv5, it is UNPREDICTABLE if bits [1:0]
280 * are not 0b00, but for ARMv6 and above, we must ignore bits [1:0].
281 * We choose to ignore [1:0] in ARM mode for all architecture versions.
283 tcg_gen_andi_i32(var, var, s->thumb ? ~1 : ~3);
284 s->base.is_jmp = DISAS_JUMP;
286 tcg_gen_mov_i32(cpu_R[reg], var);
287 tcg_temp_free_i32(var);
291 * Variant of store_reg which applies v8M stack-limit checks before updating
292 * SP. If the check fails this will result in an exception being taken.
293 * We disable the stack checks for CONFIG_USER_ONLY because we have
294 * no idea what the stack limits should be in that case.
295 * If stack checking is not being done this just acts like store_reg().
297 static void store_sp_checked(DisasContext *s, TCGv_i32 var)
299 #ifndef CONFIG_USER_ONLY
300 if (s->v8m_stackcheck) {
301 gen_helper_v8m_stackcheck(cpu_env, var);
303 #endif
304 store_reg(s, 13, var);
307 /* Value extensions. */
308 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
309 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
310 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
311 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
313 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
314 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
317 static inline void gen_set_cpsr(TCGv_i32 var, uint32_t mask)
319 TCGv_i32 tmp_mask = tcg_const_i32(mask);
320 gen_helper_cpsr_write(cpu_env, var, tmp_mask);
321 tcg_temp_free_i32(tmp_mask);
323 /* Set NZCV flags from the high 4 bits of var. */
324 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
326 static void gen_exception_internal(int excp)
328 TCGv_i32 tcg_excp = tcg_const_i32(excp);
330 assert(excp_is_internal(excp));
331 gen_helper_exception_internal(cpu_env, tcg_excp);
332 tcg_temp_free_i32(tcg_excp);
335 static void gen_step_complete_exception(DisasContext *s)
337 /* We just completed step of an insn. Move from Active-not-pending
338 * to Active-pending, and then also take the swstep exception.
339 * This corresponds to making the (IMPDEF) choice to prioritize
340 * swstep exceptions over asynchronous exceptions taken to an exception
341 * level where debug is disabled. This choice has the advantage that
342 * we do not need to maintain internal state corresponding to the
343 * ISV/EX syndrome bits between completion of the step and generation
344 * of the exception, and our syndrome information is always correct.
346 gen_ss_advance(s);
347 gen_swstep_exception(s, 1, s->is_ldex);
348 s->base.is_jmp = DISAS_NORETURN;
351 static void gen_singlestep_exception(DisasContext *s)
353 /* Generate the right kind of exception for singlestep, which is
354 * either the architectural singlestep or EXCP_DEBUG for QEMU's
355 * gdb singlestepping.
357 if (s->ss_active) {
358 gen_step_complete_exception(s);
359 } else {
360 gen_exception_internal(EXCP_DEBUG);
364 static inline bool is_singlestepping(DisasContext *s)
366 /* Return true if we are singlestepping either because of
367 * architectural singlestep or QEMU gdbstub singlestep. This does
368 * not include the command line '-singlestep' mode which is rather
369 * misnamed as it only means "one instruction per TB" and doesn't
370 * affect the code we generate.
372 return s->base.singlestep_enabled || s->ss_active;
375 static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
377 TCGv_i32 tmp1 = tcg_temp_new_i32();
378 TCGv_i32 tmp2 = tcg_temp_new_i32();
379 tcg_gen_ext16s_i32(tmp1, a);
380 tcg_gen_ext16s_i32(tmp2, b);
381 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
382 tcg_temp_free_i32(tmp2);
383 tcg_gen_sari_i32(a, a, 16);
384 tcg_gen_sari_i32(b, b, 16);
385 tcg_gen_mul_i32(b, b, a);
386 tcg_gen_mov_i32(a, tmp1);
387 tcg_temp_free_i32(tmp1);
390 /* Byteswap each halfword. */
391 static void gen_rev16(TCGv_i32 dest, TCGv_i32 var)
393 TCGv_i32 tmp = tcg_temp_new_i32();
394 TCGv_i32 mask = tcg_const_i32(0x00ff00ff);
395 tcg_gen_shri_i32(tmp, var, 8);
396 tcg_gen_and_i32(tmp, tmp, mask);
397 tcg_gen_and_i32(var, var, mask);
398 tcg_gen_shli_i32(var, var, 8);
399 tcg_gen_or_i32(dest, var, tmp);
400 tcg_temp_free_i32(mask);
401 tcg_temp_free_i32(tmp);
404 /* Byteswap low halfword and sign extend. */
405 static void gen_revsh(TCGv_i32 dest, TCGv_i32 var)
407 tcg_gen_ext16u_i32(var, var);
408 tcg_gen_bswap16_i32(var, var);
409 tcg_gen_ext16s_i32(dest, var);
412 /* Swap low and high halfwords. */
413 static void gen_swap_half(TCGv_i32 dest, TCGv_i32 var)
415 tcg_gen_rotri_i32(dest, var, 16);
418 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
419 tmp = (t0 ^ t1) & 0x8000;
420 t0 &= ~0x8000;
421 t1 &= ~0x8000;
422 t0 = (t0 + t1) ^ tmp;
425 static void gen_add16(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
427 TCGv_i32 tmp = tcg_temp_new_i32();
428 tcg_gen_xor_i32(tmp, t0, t1);
429 tcg_gen_andi_i32(tmp, tmp, 0x8000);
430 tcg_gen_andi_i32(t0, t0, ~0x8000);
431 tcg_gen_andi_i32(t1, t1, ~0x8000);
432 tcg_gen_add_i32(t0, t0, t1);
433 tcg_gen_xor_i32(dest, t0, tmp);
434 tcg_temp_free_i32(tmp);
437 /* Set N and Z flags from var. */
438 static inline void gen_logic_CC(TCGv_i32 var)
440 tcg_gen_mov_i32(cpu_NF, var);
441 tcg_gen_mov_i32(cpu_ZF, var);
444 /* dest = T0 + T1 + CF. */
445 static void gen_add_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
447 tcg_gen_add_i32(dest, t0, t1);
448 tcg_gen_add_i32(dest, dest, cpu_CF);
451 /* dest = T0 - T1 + CF - 1. */
452 static void gen_sub_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
454 tcg_gen_sub_i32(dest, t0, t1);
455 tcg_gen_add_i32(dest, dest, cpu_CF);
456 tcg_gen_subi_i32(dest, dest, 1);
459 /* dest = T0 + T1. Compute C, N, V and Z flags */
460 static void gen_add_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
462 TCGv_i32 tmp = tcg_temp_new_i32();
463 tcg_gen_movi_i32(tmp, 0);
464 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, t1, tmp);
465 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
466 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
467 tcg_gen_xor_i32(tmp, t0, t1);
468 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
469 tcg_temp_free_i32(tmp);
470 tcg_gen_mov_i32(dest, cpu_NF);
473 /* dest = T0 + T1 + CF. Compute C, N, V and Z flags */
474 static void gen_adc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
476 TCGv_i32 tmp = tcg_temp_new_i32();
477 if (TCG_TARGET_HAS_add2_i32) {
478 tcg_gen_movi_i32(tmp, 0);
479 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, cpu_CF, tmp);
480 tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1, tmp);
481 } else {
482 TCGv_i64 q0 = tcg_temp_new_i64();
483 TCGv_i64 q1 = tcg_temp_new_i64();
484 tcg_gen_extu_i32_i64(q0, t0);
485 tcg_gen_extu_i32_i64(q1, t1);
486 tcg_gen_add_i64(q0, q0, q1);
487 tcg_gen_extu_i32_i64(q1, cpu_CF);
488 tcg_gen_add_i64(q0, q0, q1);
489 tcg_gen_extr_i64_i32(cpu_NF, cpu_CF, q0);
490 tcg_temp_free_i64(q0);
491 tcg_temp_free_i64(q1);
493 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
494 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
495 tcg_gen_xor_i32(tmp, t0, t1);
496 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
497 tcg_temp_free_i32(tmp);
498 tcg_gen_mov_i32(dest, cpu_NF);
501 /* dest = T0 - T1. Compute C, N, V and Z flags */
502 static void gen_sub_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
504 TCGv_i32 tmp;
505 tcg_gen_sub_i32(cpu_NF, t0, t1);
506 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
507 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0, t1);
508 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
509 tmp = tcg_temp_new_i32();
510 tcg_gen_xor_i32(tmp, t0, t1);
511 tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
512 tcg_temp_free_i32(tmp);
513 tcg_gen_mov_i32(dest, cpu_NF);
516 /* dest = T0 + ~T1 + CF. Compute C, N, V and Z flags */
517 static void gen_sbc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
519 TCGv_i32 tmp = tcg_temp_new_i32();
520 tcg_gen_not_i32(tmp, t1);
521 gen_adc_CC(dest, t0, tmp);
522 tcg_temp_free_i32(tmp);
525 #define GEN_SHIFT(name) \
526 static void gen_##name(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) \
528 TCGv_i32 tmp1, tmp2, tmp3; \
529 tmp1 = tcg_temp_new_i32(); \
530 tcg_gen_andi_i32(tmp1, t1, 0xff); \
531 tmp2 = tcg_const_i32(0); \
532 tmp3 = tcg_const_i32(0x1f); \
533 tcg_gen_movcond_i32(TCG_COND_GTU, tmp2, tmp1, tmp3, tmp2, t0); \
534 tcg_temp_free_i32(tmp3); \
535 tcg_gen_andi_i32(tmp1, tmp1, 0x1f); \
536 tcg_gen_##name##_i32(dest, tmp2, tmp1); \
537 tcg_temp_free_i32(tmp2); \
538 tcg_temp_free_i32(tmp1); \
540 GEN_SHIFT(shl)
541 GEN_SHIFT(shr)
542 #undef GEN_SHIFT
544 static void gen_sar(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
546 TCGv_i32 tmp1, tmp2;
547 tmp1 = tcg_temp_new_i32();
548 tcg_gen_andi_i32(tmp1, t1, 0xff);
549 tmp2 = tcg_const_i32(0x1f);
550 tcg_gen_movcond_i32(TCG_COND_GTU, tmp1, tmp1, tmp2, tmp2, tmp1);
551 tcg_temp_free_i32(tmp2);
552 tcg_gen_sar_i32(dest, t0, tmp1);
553 tcg_temp_free_i32(tmp1);
556 static void shifter_out_im(TCGv_i32 var, int shift)
558 tcg_gen_extract_i32(cpu_CF, var, shift, 1);
561 /* Shift by immediate. Includes special handling for shift == 0. */
562 static inline void gen_arm_shift_im(TCGv_i32 var, int shiftop,
563 int shift, int flags)
565 switch (shiftop) {
566 case 0: /* LSL */
567 if (shift != 0) {
568 if (flags)
569 shifter_out_im(var, 32 - shift);
570 tcg_gen_shli_i32(var, var, shift);
572 break;
573 case 1: /* LSR */
574 if (shift == 0) {
575 if (flags) {
576 tcg_gen_shri_i32(cpu_CF, var, 31);
578 tcg_gen_movi_i32(var, 0);
579 } else {
580 if (flags)
581 shifter_out_im(var, shift - 1);
582 tcg_gen_shri_i32(var, var, shift);
584 break;
585 case 2: /* ASR */
586 if (shift == 0)
587 shift = 32;
588 if (flags)
589 shifter_out_im(var, shift - 1);
590 if (shift == 32)
591 shift = 31;
592 tcg_gen_sari_i32(var, var, shift);
593 break;
594 case 3: /* ROR/RRX */
595 if (shift != 0) {
596 if (flags)
597 shifter_out_im(var, shift - 1);
598 tcg_gen_rotri_i32(var, var, shift); break;
599 } else {
600 TCGv_i32 tmp = tcg_temp_new_i32();
601 tcg_gen_shli_i32(tmp, cpu_CF, 31);
602 if (flags)
603 shifter_out_im(var, 0);
604 tcg_gen_shri_i32(var, var, 1);
605 tcg_gen_or_i32(var, var, tmp);
606 tcg_temp_free_i32(tmp);
611 static inline void gen_arm_shift_reg(TCGv_i32 var, int shiftop,
612 TCGv_i32 shift, int flags)
614 if (flags) {
615 switch (shiftop) {
616 case 0: gen_helper_shl_cc(var, cpu_env, var, shift); break;
617 case 1: gen_helper_shr_cc(var, cpu_env, var, shift); break;
618 case 2: gen_helper_sar_cc(var, cpu_env, var, shift); break;
619 case 3: gen_helper_ror_cc(var, cpu_env, var, shift); break;
621 } else {
622 switch (shiftop) {
623 case 0:
624 gen_shl(var, var, shift);
625 break;
626 case 1:
627 gen_shr(var, var, shift);
628 break;
629 case 2:
630 gen_sar(var, var, shift);
631 break;
632 case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
633 tcg_gen_rotr_i32(var, var, shift); break;
636 tcg_temp_free_i32(shift);
640 * Generate a conditional based on ARM condition code cc.
641 * This is common between ARM and Aarch64 targets.
643 void arm_test_cc(DisasCompare *cmp, int cc)
645 TCGv_i32 value;
646 TCGCond cond;
647 bool global = true;
649 switch (cc) {
650 case 0: /* eq: Z */
651 case 1: /* ne: !Z */
652 cond = TCG_COND_EQ;
653 value = cpu_ZF;
654 break;
656 case 2: /* cs: C */
657 case 3: /* cc: !C */
658 cond = TCG_COND_NE;
659 value = cpu_CF;
660 break;
662 case 4: /* mi: N */
663 case 5: /* pl: !N */
664 cond = TCG_COND_LT;
665 value = cpu_NF;
666 break;
668 case 6: /* vs: V */
669 case 7: /* vc: !V */
670 cond = TCG_COND_LT;
671 value = cpu_VF;
672 break;
674 case 8: /* hi: C && !Z */
675 case 9: /* ls: !C || Z -> !(C && !Z) */
676 cond = TCG_COND_NE;
677 value = tcg_temp_new_i32();
678 global = false;
679 /* CF is 1 for C, so -CF is an all-bits-set mask for C;
680 ZF is non-zero for !Z; so AND the two subexpressions. */
681 tcg_gen_neg_i32(value, cpu_CF);
682 tcg_gen_and_i32(value, value, cpu_ZF);
683 break;
685 case 10: /* ge: N == V -> N ^ V == 0 */
686 case 11: /* lt: N != V -> N ^ V != 0 */
687 /* Since we're only interested in the sign bit, == 0 is >= 0. */
688 cond = TCG_COND_GE;
689 value = tcg_temp_new_i32();
690 global = false;
691 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
692 break;
694 case 12: /* gt: !Z && N == V */
695 case 13: /* le: Z || N != V */
696 cond = TCG_COND_NE;
697 value = tcg_temp_new_i32();
698 global = false;
699 /* (N == V) is equal to the sign bit of ~(NF ^ VF). Propagate
700 * the sign bit then AND with ZF to yield the result. */
701 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
702 tcg_gen_sari_i32(value, value, 31);
703 tcg_gen_andc_i32(value, cpu_ZF, value);
704 break;
706 case 14: /* always */
707 case 15: /* always */
708 /* Use the ALWAYS condition, which will fold early.
709 * It doesn't matter what we use for the value. */
710 cond = TCG_COND_ALWAYS;
711 value = cpu_ZF;
712 goto no_invert;
714 default:
715 fprintf(stderr, "Bad condition code 0x%x\n", cc);
716 abort();
719 if (cc & 1) {
720 cond = tcg_invert_cond(cond);
723 no_invert:
724 cmp->cond = cond;
725 cmp->value = value;
726 cmp->value_global = global;
729 void arm_free_cc(DisasCompare *cmp)
731 if (!cmp->value_global) {
732 tcg_temp_free_i32(cmp->value);
736 void arm_jump_cc(DisasCompare *cmp, TCGLabel *label)
738 tcg_gen_brcondi_i32(cmp->cond, cmp->value, 0, label);
741 void arm_gen_test_cc(int cc, TCGLabel *label)
743 DisasCompare cmp;
744 arm_test_cc(&cmp, cc);
745 arm_jump_cc(&cmp, label);
746 arm_free_cc(&cmp);
749 static inline void gen_set_condexec(DisasContext *s)
751 if (s->condexec_mask) {
752 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
753 TCGv_i32 tmp = tcg_temp_new_i32();
754 tcg_gen_movi_i32(tmp, val);
755 store_cpu_field(tmp, condexec_bits);
759 static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
761 tcg_gen_movi_i32(cpu_R[15], val);
764 /* Set PC and Thumb state from var. var is marked as dead. */
765 static inline void gen_bx(DisasContext *s, TCGv_i32 var)
767 s->base.is_jmp = DISAS_JUMP;
768 tcg_gen_andi_i32(cpu_R[15], var, ~1);
769 tcg_gen_andi_i32(var, var, 1);
770 store_cpu_field(var, thumb);
774 * Set PC and Thumb state from var. var is marked as dead.
775 * For M-profile CPUs, include logic to detect exception-return
776 * branches and handle them. This is needed for Thumb POP/LDM to PC, LDR to PC,
777 * and BX reg, and no others, and happens only for code in Handler mode.
778 * The Security Extension also requires us to check for the FNC_RETURN
779 * which signals a function return from non-secure state; this can happen
780 * in both Handler and Thread mode.
781 * To avoid having to do multiple comparisons in inline generated code,
782 * we make the check we do here loose, so it will match for EXC_RETURN
783 * in Thread mode. For system emulation do_v7m_exception_exit() checks
784 * for these spurious cases and returns without doing anything (giving
785 * the same behaviour as for a branch to a non-magic address).
787 * In linux-user mode it is unclear what the right behaviour for an
788 * attempted FNC_RETURN should be, because in real hardware this will go
789 * directly to Secure code (ie not the Linux kernel) which will then treat
790 * the error in any way it chooses. For QEMU we opt to make the FNC_RETURN
791 * attempt behave the way it would on a CPU without the security extension,
792 * which is to say "like a normal branch". That means we can simply treat
793 * all branches as normal with no magic address behaviour.
795 static inline void gen_bx_excret(DisasContext *s, TCGv_i32 var)
797 /* Generate the same code here as for a simple bx, but flag via
798 * s->base.is_jmp that we need to do the rest of the work later.
800 gen_bx(s, var);
801 #ifndef CONFIG_USER_ONLY
802 if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY) ||
803 (s->v7m_handler_mode && arm_dc_feature(s, ARM_FEATURE_M))) {
804 s->base.is_jmp = DISAS_BX_EXCRET;
806 #endif
809 static inline void gen_bx_excret_final_code(DisasContext *s)
811 /* Generate the code to finish possible exception return and end the TB */
812 TCGLabel *excret_label = gen_new_label();
813 uint32_t min_magic;
815 if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY)) {
816 /* Covers FNC_RETURN and EXC_RETURN magic */
817 min_magic = FNC_RETURN_MIN_MAGIC;
818 } else {
819 /* EXC_RETURN magic only */
820 min_magic = EXC_RETURN_MIN_MAGIC;
823 /* Is the new PC value in the magic range indicating exception return? */
824 tcg_gen_brcondi_i32(TCG_COND_GEU, cpu_R[15], min_magic, excret_label);
825 /* No: end the TB as we would for a DISAS_JMP */
826 if (is_singlestepping(s)) {
827 gen_singlestep_exception(s);
828 } else {
829 tcg_gen_exit_tb(NULL, 0);
831 gen_set_label(excret_label);
832 /* Yes: this is an exception return.
833 * At this point in runtime env->regs[15] and env->thumb will hold
834 * the exception-return magic number, which do_v7m_exception_exit()
835 * will read. Nothing else will be able to see those values because
836 * the cpu-exec main loop guarantees that we will always go straight
837 * from raising the exception to the exception-handling code.
839 * gen_ss_advance(s) does nothing on M profile currently but
840 * calling it is conceptually the right thing as we have executed
841 * this instruction (compare SWI, HVC, SMC handling).
843 gen_ss_advance(s);
844 gen_exception_internal(EXCP_EXCEPTION_EXIT);
847 static inline void gen_bxns(DisasContext *s, int rm)
849 TCGv_i32 var = load_reg(s, rm);
851 /* The bxns helper may raise an EXCEPTION_EXIT exception, so in theory
852 * we need to sync state before calling it, but:
853 * - we don't need to do gen_set_pc_im() because the bxns helper will
854 * always set the PC itself
855 * - we don't need to do gen_set_condexec() because BXNS is UNPREDICTABLE
856 * unless it's outside an IT block or the last insn in an IT block,
857 * so we know that condexec == 0 (already set at the top of the TB)
858 * is correct in the non-UNPREDICTABLE cases, and we can choose
859 * "zeroes the IT bits" as our UNPREDICTABLE behaviour otherwise.
861 gen_helper_v7m_bxns(cpu_env, var);
862 tcg_temp_free_i32(var);
863 s->base.is_jmp = DISAS_EXIT;
866 static inline void gen_blxns(DisasContext *s, int rm)
868 TCGv_i32 var = load_reg(s, rm);
870 /* We don't need to sync condexec state, for the same reason as bxns.
871 * We do however need to set the PC, because the blxns helper reads it.
872 * The blxns helper may throw an exception.
874 gen_set_pc_im(s, s->base.pc_next);
875 gen_helper_v7m_blxns(cpu_env, var);
876 tcg_temp_free_i32(var);
877 s->base.is_jmp = DISAS_EXIT;
880 /* Variant of store_reg which uses branch&exchange logic when storing
881 to r15 in ARM architecture v7 and above. The source must be a temporary
882 and will be marked as dead. */
883 static inline void store_reg_bx(DisasContext *s, int reg, TCGv_i32 var)
885 if (reg == 15 && ENABLE_ARCH_7) {
886 gen_bx(s, var);
887 } else {
888 store_reg(s, reg, var);
892 /* Variant of store_reg which uses branch&exchange logic when storing
893 * to r15 in ARM architecture v5T and above. This is used for storing
894 * the results of a LDR/LDM/POP into r15, and corresponds to the cases
895 * in the ARM ARM which use the LoadWritePC() pseudocode function. */
896 static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
898 if (reg == 15 && ENABLE_ARCH_5) {
899 gen_bx_excret(s, var);
900 } else {
901 store_reg(s, reg, var);
905 #ifdef CONFIG_USER_ONLY
906 #define IS_USER_ONLY 1
907 #else
908 #define IS_USER_ONLY 0
909 #endif
911 /* Abstractions of "generate code to do a guest load/store for
912 * AArch32", where a vaddr is always 32 bits (and is zero
913 * extended if we're a 64 bit core) and data is also
914 * 32 bits unless specifically doing a 64 bit access.
915 * These functions work like tcg_gen_qemu_{ld,st}* except
916 * that the address argument is TCGv_i32 rather than TCGv.
919 static inline TCGv gen_aa32_addr(DisasContext *s, TCGv_i32 a32, MemOp op)
921 TCGv addr = tcg_temp_new();
922 tcg_gen_extu_i32_tl(addr, a32);
924 /* Not needed for user-mode BE32, where we use MO_BE instead. */
925 if (!IS_USER_ONLY && s->sctlr_b && (op & MO_SIZE) < MO_32) {
926 tcg_gen_xori_tl(addr, addr, 4 - (1 << (op & MO_SIZE)));
928 return addr;
931 static void gen_aa32_ld_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
932 int index, MemOp opc)
934 TCGv addr;
936 if (arm_dc_feature(s, ARM_FEATURE_M) &&
937 !arm_dc_feature(s, ARM_FEATURE_M_MAIN)) {
938 opc |= MO_ALIGN;
941 addr = gen_aa32_addr(s, a32, opc);
942 tcg_gen_qemu_ld_i32(val, addr, index, opc);
943 tcg_temp_free(addr);
946 static void gen_aa32_st_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
947 int index, MemOp opc)
949 TCGv addr;
951 if (arm_dc_feature(s, ARM_FEATURE_M) &&
952 !arm_dc_feature(s, ARM_FEATURE_M_MAIN)) {
953 opc |= MO_ALIGN;
956 addr = gen_aa32_addr(s, a32, opc);
957 tcg_gen_qemu_st_i32(val, addr, index, opc);
958 tcg_temp_free(addr);
961 #define DO_GEN_LD(SUFF, OPC) \
962 static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \
963 TCGv_i32 a32, int index) \
965 gen_aa32_ld_i32(s, val, a32, index, OPC | s->be_data); \
968 #define DO_GEN_ST(SUFF, OPC) \
969 static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, \
970 TCGv_i32 a32, int index) \
972 gen_aa32_st_i32(s, val, a32, index, OPC | s->be_data); \
975 static inline void gen_aa32_frob64(DisasContext *s, TCGv_i64 val)
977 /* Not needed for user-mode BE32, where we use MO_BE instead. */
978 if (!IS_USER_ONLY && s->sctlr_b) {
979 tcg_gen_rotri_i64(val, val, 32);
983 static void gen_aa32_ld_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
984 int index, MemOp opc)
986 TCGv addr = gen_aa32_addr(s, a32, opc);
987 tcg_gen_qemu_ld_i64(val, addr, index, opc);
988 gen_aa32_frob64(s, val);
989 tcg_temp_free(addr);
992 static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
993 TCGv_i32 a32, int index)
995 gen_aa32_ld_i64(s, val, a32, index, MO_Q | s->be_data);
998 static void gen_aa32_st_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
999 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) {
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 static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
1016 TCGv_i32 a32, int index)
1018 gen_aa32_st_i64(s, val, a32, index, MO_Q | s->be_data);
1021 DO_GEN_LD(8u, MO_UB)
1022 DO_GEN_LD(16u, MO_UW)
1023 DO_GEN_LD(32u, MO_UL)
1024 DO_GEN_ST(8, MO_UB)
1025 DO_GEN_ST(16, MO_UW)
1026 DO_GEN_ST(32, MO_UL)
1028 static inline void gen_hvc(DisasContext *s, int imm16)
1030 /* The pre HVC helper handles cases when HVC gets trapped
1031 * as an undefined insn by runtime configuration (ie before
1032 * the insn really executes).
1034 gen_set_pc_im(s, s->pc_curr);
1035 gen_helper_pre_hvc(cpu_env);
1036 /* Otherwise we will treat this as a real exception which
1037 * happens after execution of the insn. (The distinction matters
1038 * for the PC value reported to the exception handler and also
1039 * for single stepping.)
1041 s->svc_imm = imm16;
1042 gen_set_pc_im(s, s->base.pc_next);
1043 s->base.is_jmp = DISAS_HVC;
1046 static inline void gen_smc(DisasContext *s)
1048 /* As with HVC, we may take an exception either before or after
1049 * the insn executes.
1051 TCGv_i32 tmp;
1053 gen_set_pc_im(s, s->pc_curr);
1054 tmp = tcg_const_i32(syn_aa32_smc());
1055 gen_helper_pre_smc(cpu_env, tmp);
1056 tcg_temp_free_i32(tmp);
1057 gen_set_pc_im(s, s->base.pc_next);
1058 s->base.is_jmp = DISAS_SMC;
1061 static void gen_exception_internal_insn(DisasContext *s, uint32_t pc, int excp)
1063 gen_set_condexec(s);
1064 gen_set_pc_im(s, pc);
1065 gen_exception_internal(excp);
1066 s->base.is_jmp = DISAS_NORETURN;
1069 static void gen_exception_insn(DisasContext *s, uint32_t pc, int excp,
1070 int syn, uint32_t target_el)
1072 gen_set_condexec(s);
1073 gen_set_pc_im(s, pc);
1074 gen_exception(excp, syn, target_el);
1075 s->base.is_jmp = DISAS_NORETURN;
1078 static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn)
1080 TCGv_i32 tcg_syn;
1082 gen_set_condexec(s);
1083 gen_set_pc_im(s, s->pc_curr);
1084 tcg_syn = tcg_const_i32(syn);
1085 gen_helper_exception_bkpt_insn(cpu_env, tcg_syn);
1086 tcg_temp_free_i32(tcg_syn);
1087 s->base.is_jmp = DISAS_NORETURN;
1090 static void unallocated_encoding(DisasContext *s)
1092 /* Unallocated and reserved encodings are uncategorized */
1093 gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(),
1094 default_exception_el(s));
1097 /* Force a TB lookup after an instruction that changes the CPU state. */
1098 static inline void gen_lookup_tb(DisasContext *s)
1100 tcg_gen_movi_i32(cpu_R[15], s->base.pc_next);
1101 s->base.is_jmp = DISAS_EXIT;
1104 static inline void gen_hlt(DisasContext *s, int imm)
1106 /* HLT. This has two purposes.
1107 * Architecturally, it is an external halting debug instruction.
1108 * Since QEMU doesn't implement external debug, we treat this as
1109 * it is required for halting debug disabled: it will UNDEF.
1110 * Secondly, "HLT 0x3C" is a T32 semihosting trap instruction,
1111 * and "HLT 0xF000" is an A32 semihosting syscall. These traps
1112 * must trigger semihosting even for ARMv7 and earlier, where
1113 * HLT was an undefined encoding.
1114 * In system mode, we don't allow userspace access to
1115 * semihosting, to provide some semblance of security
1116 * (and for consistency with our 32-bit semihosting).
1118 if (semihosting_enabled() &&
1119 #ifndef CONFIG_USER_ONLY
1120 s->current_el != 0 &&
1121 #endif
1122 (imm == (s->thumb ? 0x3c : 0xf000))) {
1123 gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
1124 return;
1127 unallocated_encoding(s);
1131 * Return the offset of a "full" NEON Dreg.
1133 static long neon_full_reg_offset(unsigned reg)
1135 return offsetof(CPUARMState, vfp.zregs[reg >> 1].d[reg & 1]);
1139 * Return the offset of a 2**SIZE piece of a NEON register, at index ELE,
1140 * where 0 is the least significant end of the register.
1142 static long neon_element_offset(int reg, int element, MemOp memop)
1144 int element_size = 1 << (memop & MO_SIZE);
1145 int ofs = element * element_size;
1146 #ifdef HOST_WORDS_BIGENDIAN
1148 * Calculate the offset assuming fully little-endian,
1149 * then XOR to account for the order of the 8-byte units.
1151 if (element_size < 8) {
1152 ofs ^= 8 - element_size;
1154 #endif
1155 return neon_full_reg_offset(reg) + ofs;
1158 /* Return the offset of a VFP Dreg (dp = true) or VFP Sreg (dp = false). */
1159 static long vfp_reg_offset(bool dp, unsigned reg)
1161 if (dp) {
1162 return neon_element_offset(reg, 0, MO_64);
1163 } else {
1164 return neon_element_offset(reg >> 1, reg & 1, MO_32);
1168 static inline void vfp_load_reg64(TCGv_i64 var, int reg)
1170 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(true, reg));
1173 static inline void vfp_store_reg64(TCGv_i64 var, int reg)
1175 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(true, reg));
1178 static inline void vfp_load_reg32(TCGv_i32 var, int reg)
1180 tcg_gen_ld_i32(var, cpu_env, vfp_reg_offset(false, reg));
1183 static inline void vfp_store_reg32(TCGv_i32 var, int reg)
1185 tcg_gen_st_i32(var, cpu_env, vfp_reg_offset(false, reg));
1188 static void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp memop)
1190 long off = neon_element_offset(reg, ele, memop);
1192 switch (memop) {
1193 case MO_SB:
1194 tcg_gen_ld8s_i32(dest, cpu_env, off);
1195 break;
1196 case MO_UB:
1197 tcg_gen_ld8u_i32(dest, cpu_env, off);
1198 break;
1199 case MO_SW:
1200 tcg_gen_ld16s_i32(dest, cpu_env, off);
1201 break;
1202 case MO_UW:
1203 tcg_gen_ld16u_i32(dest, cpu_env, off);
1204 break;
1205 case MO_UL:
1206 case MO_SL:
1207 tcg_gen_ld_i32(dest, cpu_env, off);
1208 break;
1209 default:
1210 g_assert_not_reached();
1214 static void read_neon_element64(TCGv_i64 dest, int reg, int ele, MemOp memop)
1216 long off = neon_element_offset(reg, ele, memop);
1218 switch (memop) {
1219 case MO_SL:
1220 tcg_gen_ld32s_i64(dest, cpu_env, off);
1221 break;
1222 case MO_UL:
1223 tcg_gen_ld32u_i64(dest, cpu_env, off);
1224 break;
1225 case MO_Q:
1226 tcg_gen_ld_i64(dest, cpu_env, off);
1227 break;
1228 default:
1229 g_assert_not_reached();
1233 static void write_neon_element32(TCGv_i32 src, int reg, int ele, MemOp memop)
1235 long off = neon_element_offset(reg, ele, memop);
1237 switch (memop) {
1238 case MO_8:
1239 tcg_gen_st8_i32(src, cpu_env, off);
1240 break;
1241 case MO_16:
1242 tcg_gen_st16_i32(src, cpu_env, off);
1243 break;
1244 case MO_32:
1245 tcg_gen_st_i32(src, cpu_env, off);
1246 break;
1247 default:
1248 g_assert_not_reached();
1252 static void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop)
1254 long off = neon_element_offset(reg, ele, memop);
1256 switch (memop) {
1257 case MO_32:
1258 tcg_gen_st32_i64(src, cpu_env, off);
1259 break;
1260 case MO_64:
1261 tcg_gen_st_i64(src, cpu_env, off);
1262 break;
1263 default:
1264 g_assert_not_reached();
1268 static TCGv_ptr vfp_reg_ptr(bool dp, int reg)
1270 TCGv_ptr ret = tcg_temp_new_ptr();
1271 tcg_gen_addi_ptr(ret, cpu_env, vfp_reg_offset(dp, reg));
1272 return ret;
1275 #define ARM_CP_RW_BIT (1 << 20)
1277 /* Include the VFP and Neon decoders */
1278 #include "decode-m-nocp.c.inc"
1279 #include "translate-vfp.c.inc"
1280 #include "translate-neon.c.inc"
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_const_i32(0xff);
1849 tmp3 = tcg_const_i32((insn & 7) << 3);
1850 break;
1851 case 1:
1852 tmp2 = tcg_const_i32(0xffff);
1853 tmp3 = tcg_const_i32((insn & 3) << 4);
1854 break;
1855 case 2:
1856 tmp2 = tcg_const_i32(0xffffffff);
1857 tmp3 = tcg_const_i32((insn & 1) << 5);
1858 break;
1859 default:
1860 tmp2 = NULL;
1861 tmp3 = NULL;
1863 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
1864 tcg_temp_free_i32(tmp3);
1865 tcg_temp_free_i32(tmp2);
1866 tcg_temp_free_i32(tmp);
1867 gen_op_iwmmxt_movq_wRn_M0(wrd);
1868 gen_op_iwmmxt_set_mup();
1869 break;
1870 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1871 rd = (insn >> 12) & 0xf;
1872 wrd = (insn >> 16) & 0xf;
1873 if (rd == 15 || ((insn >> 22) & 3) == 3)
1874 return 1;
1875 gen_op_iwmmxt_movq_M0_wRn(wrd);
1876 tmp = tcg_temp_new_i32();
1877 switch ((insn >> 22) & 3) {
1878 case 0:
1879 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
1880 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1881 if (insn & 8) {
1882 tcg_gen_ext8s_i32(tmp, tmp);
1883 } else {
1884 tcg_gen_andi_i32(tmp, tmp, 0xff);
1886 break;
1887 case 1:
1888 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
1889 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1890 if (insn & 8) {
1891 tcg_gen_ext16s_i32(tmp, tmp);
1892 } else {
1893 tcg_gen_andi_i32(tmp, tmp, 0xffff);
1895 break;
1896 case 2:
1897 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
1898 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1899 break;
1901 store_reg(s, rd, tmp);
1902 break;
1903 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1904 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1905 return 1;
1906 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1907 switch ((insn >> 22) & 3) {
1908 case 0:
1909 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
1910 break;
1911 case 1:
1912 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
1913 break;
1914 case 2:
1915 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
1916 break;
1918 tcg_gen_shli_i32(tmp, tmp, 28);
1919 gen_set_nzcv(tmp);
1920 tcg_temp_free_i32(tmp);
1921 break;
1922 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1923 if (((insn >> 6) & 3) == 3)
1924 return 1;
1925 rd = (insn >> 12) & 0xf;
1926 wrd = (insn >> 16) & 0xf;
1927 tmp = load_reg(s, rd);
1928 switch ((insn >> 6) & 3) {
1929 case 0:
1930 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
1931 break;
1932 case 1:
1933 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
1934 break;
1935 case 2:
1936 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
1937 break;
1939 tcg_temp_free_i32(tmp);
1940 gen_op_iwmmxt_movq_wRn_M0(wrd);
1941 gen_op_iwmmxt_set_mup();
1942 break;
1943 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1944 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1945 return 1;
1946 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1947 tmp2 = tcg_temp_new_i32();
1948 tcg_gen_mov_i32(tmp2, tmp);
1949 switch ((insn >> 22) & 3) {
1950 case 0:
1951 for (i = 0; i < 7; i ++) {
1952 tcg_gen_shli_i32(tmp2, tmp2, 4);
1953 tcg_gen_and_i32(tmp, tmp, tmp2);
1955 break;
1956 case 1:
1957 for (i = 0; i < 3; i ++) {
1958 tcg_gen_shli_i32(tmp2, tmp2, 8);
1959 tcg_gen_and_i32(tmp, tmp, tmp2);
1961 break;
1962 case 2:
1963 tcg_gen_shli_i32(tmp2, tmp2, 16);
1964 tcg_gen_and_i32(tmp, tmp, tmp2);
1965 break;
1967 gen_set_nzcv(tmp);
1968 tcg_temp_free_i32(tmp2);
1969 tcg_temp_free_i32(tmp);
1970 break;
1971 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1972 wrd = (insn >> 12) & 0xf;
1973 rd0 = (insn >> 16) & 0xf;
1974 gen_op_iwmmxt_movq_M0_wRn(rd0);
1975 switch ((insn >> 22) & 3) {
1976 case 0:
1977 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1978 break;
1979 case 1:
1980 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1981 break;
1982 case 2:
1983 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1984 break;
1985 case 3:
1986 return 1;
1988 gen_op_iwmmxt_movq_wRn_M0(wrd);
1989 gen_op_iwmmxt_set_mup();
1990 break;
1991 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1992 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1993 return 1;
1994 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1995 tmp2 = tcg_temp_new_i32();
1996 tcg_gen_mov_i32(tmp2, tmp);
1997 switch ((insn >> 22) & 3) {
1998 case 0:
1999 for (i = 0; i < 7; i ++) {
2000 tcg_gen_shli_i32(tmp2, tmp2, 4);
2001 tcg_gen_or_i32(tmp, tmp, tmp2);
2003 break;
2004 case 1:
2005 for (i = 0; i < 3; i ++) {
2006 tcg_gen_shli_i32(tmp2, tmp2, 8);
2007 tcg_gen_or_i32(tmp, tmp, tmp2);
2009 break;
2010 case 2:
2011 tcg_gen_shli_i32(tmp2, tmp2, 16);
2012 tcg_gen_or_i32(tmp, tmp, tmp2);
2013 break;
2015 gen_set_nzcv(tmp);
2016 tcg_temp_free_i32(tmp2);
2017 tcg_temp_free_i32(tmp);
2018 break;
2019 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
2020 rd = (insn >> 12) & 0xf;
2021 rd0 = (insn >> 16) & 0xf;
2022 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
2023 return 1;
2024 gen_op_iwmmxt_movq_M0_wRn(rd0);
2025 tmp = tcg_temp_new_i32();
2026 switch ((insn >> 22) & 3) {
2027 case 0:
2028 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
2029 break;
2030 case 1:
2031 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
2032 break;
2033 case 2:
2034 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
2035 break;
2037 store_reg(s, rd, tmp);
2038 break;
2039 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
2040 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2041 wrd = (insn >> 12) & 0xf;
2042 rd0 = (insn >> 16) & 0xf;
2043 rd1 = (insn >> 0) & 0xf;
2044 gen_op_iwmmxt_movq_M0_wRn(rd0);
2045 switch ((insn >> 22) & 3) {
2046 case 0:
2047 if (insn & (1 << 21))
2048 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
2049 else
2050 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
2051 break;
2052 case 1:
2053 if (insn & (1 << 21))
2054 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
2055 else
2056 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2057 break;
2058 case 2:
2059 if (insn & (1 << 21))
2060 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2061 else
2062 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2063 break;
2064 case 3:
2065 return 1;
2067 gen_op_iwmmxt_movq_wRn_M0(wrd);
2068 gen_op_iwmmxt_set_mup();
2069 gen_op_iwmmxt_set_cup();
2070 break;
2071 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2072 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2073 wrd = (insn >> 12) & 0xf;
2074 rd0 = (insn >> 16) & 0xf;
2075 gen_op_iwmmxt_movq_M0_wRn(rd0);
2076 switch ((insn >> 22) & 3) {
2077 case 0:
2078 if (insn & (1 << 21))
2079 gen_op_iwmmxt_unpacklsb_M0();
2080 else
2081 gen_op_iwmmxt_unpacklub_M0();
2082 break;
2083 case 1:
2084 if (insn & (1 << 21))
2085 gen_op_iwmmxt_unpacklsw_M0();
2086 else
2087 gen_op_iwmmxt_unpackluw_M0();
2088 break;
2089 case 2:
2090 if (insn & (1 << 21))
2091 gen_op_iwmmxt_unpacklsl_M0();
2092 else
2093 gen_op_iwmmxt_unpacklul_M0();
2094 break;
2095 case 3:
2096 return 1;
2098 gen_op_iwmmxt_movq_wRn_M0(wrd);
2099 gen_op_iwmmxt_set_mup();
2100 gen_op_iwmmxt_set_cup();
2101 break;
2102 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2103 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2104 wrd = (insn >> 12) & 0xf;
2105 rd0 = (insn >> 16) & 0xf;
2106 gen_op_iwmmxt_movq_M0_wRn(rd0);
2107 switch ((insn >> 22) & 3) {
2108 case 0:
2109 if (insn & (1 << 21))
2110 gen_op_iwmmxt_unpackhsb_M0();
2111 else
2112 gen_op_iwmmxt_unpackhub_M0();
2113 break;
2114 case 1:
2115 if (insn & (1 << 21))
2116 gen_op_iwmmxt_unpackhsw_M0();
2117 else
2118 gen_op_iwmmxt_unpackhuw_M0();
2119 break;
2120 case 2:
2121 if (insn & (1 << 21))
2122 gen_op_iwmmxt_unpackhsl_M0();
2123 else
2124 gen_op_iwmmxt_unpackhul_M0();
2125 break;
2126 case 3:
2127 return 1;
2129 gen_op_iwmmxt_movq_wRn_M0(wrd);
2130 gen_op_iwmmxt_set_mup();
2131 gen_op_iwmmxt_set_cup();
2132 break;
2133 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2134 case 0x214: case 0x614: case 0xa14: case 0xe14:
2135 if (((insn >> 22) & 3) == 0)
2136 return 1;
2137 wrd = (insn >> 12) & 0xf;
2138 rd0 = (insn >> 16) & 0xf;
2139 gen_op_iwmmxt_movq_M0_wRn(rd0);
2140 tmp = tcg_temp_new_i32();
2141 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2142 tcg_temp_free_i32(tmp);
2143 return 1;
2145 switch ((insn >> 22) & 3) {
2146 case 1:
2147 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
2148 break;
2149 case 2:
2150 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
2151 break;
2152 case 3:
2153 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
2154 break;
2156 tcg_temp_free_i32(tmp);
2157 gen_op_iwmmxt_movq_wRn_M0(wrd);
2158 gen_op_iwmmxt_set_mup();
2159 gen_op_iwmmxt_set_cup();
2160 break;
2161 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2162 case 0x014: case 0x414: case 0x814: case 0xc14:
2163 if (((insn >> 22) & 3) == 0)
2164 return 1;
2165 wrd = (insn >> 12) & 0xf;
2166 rd0 = (insn >> 16) & 0xf;
2167 gen_op_iwmmxt_movq_M0_wRn(rd0);
2168 tmp = tcg_temp_new_i32();
2169 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2170 tcg_temp_free_i32(tmp);
2171 return 1;
2173 switch ((insn >> 22) & 3) {
2174 case 1:
2175 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
2176 break;
2177 case 2:
2178 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
2179 break;
2180 case 3:
2181 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
2182 break;
2184 tcg_temp_free_i32(tmp);
2185 gen_op_iwmmxt_movq_wRn_M0(wrd);
2186 gen_op_iwmmxt_set_mup();
2187 gen_op_iwmmxt_set_cup();
2188 break;
2189 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2190 case 0x114: case 0x514: case 0x914: case 0xd14:
2191 if (((insn >> 22) & 3) == 0)
2192 return 1;
2193 wrd = (insn >> 12) & 0xf;
2194 rd0 = (insn >> 16) & 0xf;
2195 gen_op_iwmmxt_movq_M0_wRn(rd0);
2196 tmp = tcg_temp_new_i32();
2197 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2198 tcg_temp_free_i32(tmp);
2199 return 1;
2201 switch ((insn >> 22) & 3) {
2202 case 1:
2203 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2204 break;
2205 case 2:
2206 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2207 break;
2208 case 3:
2209 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2210 break;
2212 tcg_temp_free_i32(tmp);
2213 gen_op_iwmmxt_movq_wRn_M0(wrd);
2214 gen_op_iwmmxt_set_mup();
2215 gen_op_iwmmxt_set_cup();
2216 break;
2217 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2218 case 0x314: case 0x714: case 0xb14: case 0xf14:
2219 if (((insn >> 22) & 3) == 0)
2220 return 1;
2221 wrd = (insn >> 12) & 0xf;
2222 rd0 = (insn >> 16) & 0xf;
2223 gen_op_iwmmxt_movq_M0_wRn(rd0);
2224 tmp = tcg_temp_new_i32();
2225 switch ((insn >> 22) & 3) {
2226 case 1:
2227 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2228 tcg_temp_free_i32(tmp);
2229 return 1;
2231 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2232 break;
2233 case 2:
2234 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2235 tcg_temp_free_i32(tmp);
2236 return 1;
2238 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2239 break;
2240 case 3:
2241 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2242 tcg_temp_free_i32(tmp);
2243 return 1;
2245 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2246 break;
2248 tcg_temp_free_i32(tmp);
2249 gen_op_iwmmxt_movq_wRn_M0(wrd);
2250 gen_op_iwmmxt_set_mup();
2251 gen_op_iwmmxt_set_cup();
2252 break;
2253 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2254 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2255 wrd = (insn >> 12) & 0xf;
2256 rd0 = (insn >> 16) & 0xf;
2257 rd1 = (insn >> 0) & 0xf;
2258 gen_op_iwmmxt_movq_M0_wRn(rd0);
2259 switch ((insn >> 22) & 3) {
2260 case 0:
2261 if (insn & (1 << 21))
2262 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2263 else
2264 gen_op_iwmmxt_minub_M0_wRn(rd1);
2265 break;
2266 case 1:
2267 if (insn & (1 << 21))
2268 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2269 else
2270 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2271 break;
2272 case 2:
2273 if (insn & (1 << 21))
2274 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2275 else
2276 gen_op_iwmmxt_minul_M0_wRn(rd1);
2277 break;
2278 case 3:
2279 return 1;
2281 gen_op_iwmmxt_movq_wRn_M0(wrd);
2282 gen_op_iwmmxt_set_mup();
2283 break;
2284 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2285 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2286 wrd = (insn >> 12) & 0xf;
2287 rd0 = (insn >> 16) & 0xf;
2288 rd1 = (insn >> 0) & 0xf;
2289 gen_op_iwmmxt_movq_M0_wRn(rd0);
2290 switch ((insn >> 22) & 3) {
2291 case 0:
2292 if (insn & (1 << 21))
2293 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2294 else
2295 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2296 break;
2297 case 1:
2298 if (insn & (1 << 21))
2299 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2300 else
2301 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2302 break;
2303 case 2:
2304 if (insn & (1 << 21))
2305 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2306 else
2307 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2308 break;
2309 case 3:
2310 return 1;
2312 gen_op_iwmmxt_movq_wRn_M0(wrd);
2313 gen_op_iwmmxt_set_mup();
2314 break;
2315 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2316 case 0x402: case 0x502: case 0x602: case 0x702:
2317 wrd = (insn >> 12) & 0xf;
2318 rd0 = (insn >> 16) & 0xf;
2319 rd1 = (insn >> 0) & 0xf;
2320 gen_op_iwmmxt_movq_M0_wRn(rd0);
2321 tmp = tcg_const_i32((insn >> 20) & 3);
2322 iwmmxt_load_reg(cpu_V1, rd1);
2323 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2324 tcg_temp_free_i32(tmp);
2325 gen_op_iwmmxt_movq_wRn_M0(wrd);
2326 gen_op_iwmmxt_set_mup();
2327 break;
2328 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2329 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2330 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2331 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2332 wrd = (insn >> 12) & 0xf;
2333 rd0 = (insn >> 16) & 0xf;
2334 rd1 = (insn >> 0) & 0xf;
2335 gen_op_iwmmxt_movq_M0_wRn(rd0);
2336 switch ((insn >> 20) & 0xf) {
2337 case 0x0:
2338 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2339 break;
2340 case 0x1:
2341 gen_op_iwmmxt_subub_M0_wRn(rd1);
2342 break;
2343 case 0x3:
2344 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2345 break;
2346 case 0x4:
2347 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2348 break;
2349 case 0x5:
2350 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2351 break;
2352 case 0x7:
2353 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2354 break;
2355 case 0x8:
2356 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2357 break;
2358 case 0x9:
2359 gen_op_iwmmxt_subul_M0_wRn(rd1);
2360 break;
2361 case 0xb:
2362 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2363 break;
2364 default:
2365 return 1;
2367 gen_op_iwmmxt_movq_wRn_M0(wrd);
2368 gen_op_iwmmxt_set_mup();
2369 gen_op_iwmmxt_set_cup();
2370 break;
2371 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2372 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2373 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2374 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2375 wrd = (insn >> 12) & 0xf;
2376 rd0 = (insn >> 16) & 0xf;
2377 gen_op_iwmmxt_movq_M0_wRn(rd0);
2378 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2379 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2380 tcg_temp_free_i32(tmp);
2381 gen_op_iwmmxt_movq_wRn_M0(wrd);
2382 gen_op_iwmmxt_set_mup();
2383 gen_op_iwmmxt_set_cup();
2384 break;
2385 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2386 case 0x418: case 0x518: case 0x618: case 0x718:
2387 case 0x818: case 0x918: case 0xa18: case 0xb18:
2388 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2389 wrd = (insn >> 12) & 0xf;
2390 rd0 = (insn >> 16) & 0xf;
2391 rd1 = (insn >> 0) & 0xf;
2392 gen_op_iwmmxt_movq_M0_wRn(rd0);
2393 switch ((insn >> 20) & 0xf) {
2394 case 0x0:
2395 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2396 break;
2397 case 0x1:
2398 gen_op_iwmmxt_addub_M0_wRn(rd1);
2399 break;
2400 case 0x3:
2401 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2402 break;
2403 case 0x4:
2404 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2405 break;
2406 case 0x5:
2407 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2408 break;
2409 case 0x7:
2410 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2411 break;
2412 case 0x8:
2413 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2414 break;
2415 case 0x9:
2416 gen_op_iwmmxt_addul_M0_wRn(rd1);
2417 break;
2418 case 0xb:
2419 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2420 break;
2421 default:
2422 return 1;
2424 gen_op_iwmmxt_movq_wRn_M0(wrd);
2425 gen_op_iwmmxt_set_mup();
2426 gen_op_iwmmxt_set_cup();
2427 break;
2428 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2429 case 0x408: case 0x508: case 0x608: case 0x708:
2430 case 0x808: case 0x908: case 0xa08: case 0xb08:
2431 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2432 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2433 return 1;
2434 wrd = (insn >> 12) & 0xf;
2435 rd0 = (insn >> 16) & 0xf;
2436 rd1 = (insn >> 0) & 0xf;
2437 gen_op_iwmmxt_movq_M0_wRn(rd0);
2438 switch ((insn >> 22) & 3) {
2439 case 1:
2440 if (insn & (1 << 21))
2441 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2442 else
2443 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2444 break;
2445 case 2:
2446 if (insn & (1 << 21))
2447 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2448 else
2449 gen_op_iwmmxt_packul_M0_wRn(rd1);
2450 break;
2451 case 3:
2452 if (insn & (1 << 21))
2453 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2454 else
2455 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2456 break;
2458 gen_op_iwmmxt_movq_wRn_M0(wrd);
2459 gen_op_iwmmxt_set_mup();
2460 gen_op_iwmmxt_set_cup();
2461 break;
2462 case 0x201: case 0x203: case 0x205: case 0x207:
2463 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2464 case 0x211: case 0x213: case 0x215: case 0x217:
2465 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2466 wrd = (insn >> 5) & 0xf;
2467 rd0 = (insn >> 12) & 0xf;
2468 rd1 = (insn >> 0) & 0xf;
2469 if (rd0 == 0xf || rd1 == 0xf)
2470 return 1;
2471 gen_op_iwmmxt_movq_M0_wRn(wrd);
2472 tmp = load_reg(s, rd0);
2473 tmp2 = load_reg(s, rd1);
2474 switch ((insn >> 16) & 0xf) {
2475 case 0x0: /* TMIA */
2476 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2477 break;
2478 case 0x8: /* TMIAPH */
2479 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2480 break;
2481 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2482 if (insn & (1 << 16))
2483 tcg_gen_shri_i32(tmp, tmp, 16);
2484 if (insn & (1 << 17))
2485 tcg_gen_shri_i32(tmp2, tmp2, 16);
2486 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2487 break;
2488 default:
2489 tcg_temp_free_i32(tmp2);
2490 tcg_temp_free_i32(tmp);
2491 return 1;
2493 tcg_temp_free_i32(tmp2);
2494 tcg_temp_free_i32(tmp);
2495 gen_op_iwmmxt_movq_wRn_M0(wrd);
2496 gen_op_iwmmxt_set_mup();
2497 break;
2498 default:
2499 return 1;
2502 return 0;
2505 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
2506 (ie. an undefined instruction). */
2507 static int disas_dsp_insn(DisasContext *s, uint32_t insn)
2509 int acc, rd0, rd1, rdhi, rdlo;
2510 TCGv_i32 tmp, tmp2;
2512 if ((insn & 0x0ff00f10) == 0x0e200010) {
2513 /* Multiply with Internal Accumulate Format */
2514 rd0 = (insn >> 12) & 0xf;
2515 rd1 = insn & 0xf;
2516 acc = (insn >> 5) & 7;
2518 if (acc != 0)
2519 return 1;
2521 tmp = load_reg(s, rd0);
2522 tmp2 = load_reg(s, rd1);
2523 switch ((insn >> 16) & 0xf) {
2524 case 0x0: /* MIA */
2525 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2526 break;
2527 case 0x8: /* MIAPH */
2528 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2529 break;
2530 case 0xc: /* MIABB */
2531 case 0xd: /* MIABT */
2532 case 0xe: /* MIATB */
2533 case 0xf: /* MIATT */
2534 if (insn & (1 << 16))
2535 tcg_gen_shri_i32(tmp, tmp, 16);
2536 if (insn & (1 << 17))
2537 tcg_gen_shri_i32(tmp2, tmp2, 16);
2538 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2539 break;
2540 default:
2541 return 1;
2543 tcg_temp_free_i32(tmp2);
2544 tcg_temp_free_i32(tmp);
2546 gen_op_iwmmxt_movq_wRn_M0(acc);
2547 return 0;
2550 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2551 /* Internal Accumulator Access Format */
2552 rdhi = (insn >> 16) & 0xf;
2553 rdlo = (insn >> 12) & 0xf;
2554 acc = insn & 7;
2556 if (acc != 0)
2557 return 1;
2559 if (insn & ARM_CP_RW_BIT) { /* MRA */
2560 iwmmxt_load_reg(cpu_V0, acc);
2561 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
2562 tcg_gen_extrh_i64_i32(cpu_R[rdhi], cpu_V0);
2563 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
2564 } else { /* MAR */
2565 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2566 iwmmxt_store_reg(cpu_V0, acc);
2568 return 0;
2571 return 1;
2574 static inline bool use_goto_tb(DisasContext *s, target_ulong dest)
2576 #ifndef CONFIG_USER_ONLY
2577 return (s->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
2578 ((s->base.pc_next - 1) & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
2579 #else
2580 return true;
2581 #endif
2584 static void gen_goto_ptr(void)
2586 tcg_gen_lookup_and_goto_ptr();
2589 /* This will end the TB but doesn't guarantee we'll return to
2590 * cpu_loop_exec. Any live exit_requests will be processed as we
2591 * enter the next TB.
2593 static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
2595 if (use_goto_tb(s, dest)) {
2596 tcg_gen_goto_tb(n);
2597 gen_set_pc_im(s, dest);
2598 tcg_gen_exit_tb(s->base.tb, n);
2599 } else {
2600 gen_set_pc_im(s, dest);
2601 gen_goto_ptr();
2603 s->base.is_jmp = DISAS_NORETURN;
2606 /* Jump, specifying which TB number to use if we gen_goto_tb() */
2607 static inline void gen_jmp_tb(DisasContext *s, uint32_t dest, int tbno)
2609 if (unlikely(is_singlestepping(s))) {
2610 /* An indirect jump so that we still trigger the debug exception. */
2611 gen_set_pc_im(s, dest);
2612 s->base.is_jmp = DISAS_JUMP;
2613 } else {
2614 gen_goto_tb(s, tbno, dest);
2618 static inline void gen_jmp(DisasContext *s, uint32_t dest)
2620 gen_jmp_tb(s, dest, 0);
2623 static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
2625 if (x)
2626 tcg_gen_sari_i32(t0, t0, 16);
2627 else
2628 gen_sxth(t0);
2629 if (y)
2630 tcg_gen_sari_i32(t1, t1, 16);
2631 else
2632 gen_sxth(t1);
2633 tcg_gen_mul_i32(t0, t0, t1);
2636 /* Return the mask of PSR bits set by a MSR instruction. */
2637 static uint32_t msr_mask(DisasContext *s, int flags, int spsr)
2639 uint32_t mask = 0;
2641 if (flags & (1 << 0)) {
2642 mask |= 0xff;
2644 if (flags & (1 << 1)) {
2645 mask |= 0xff00;
2647 if (flags & (1 << 2)) {
2648 mask |= 0xff0000;
2650 if (flags & (1 << 3)) {
2651 mask |= 0xff000000;
2654 /* Mask out undefined and reserved bits. */
2655 mask &= aarch32_cpsr_valid_mask(s->features, s->isar);
2657 /* Mask out execution state. */
2658 if (!spsr) {
2659 mask &= ~CPSR_EXEC;
2662 /* Mask out privileged bits. */
2663 if (IS_USER(s)) {
2664 mask &= CPSR_USER;
2666 return mask;
2669 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
2670 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv_i32 t0)
2672 TCGv_i32 tmp;
2673 if (spsr) {
2674 /* ??? This is also undefined in system mode. */
2675 if (IS_USER(s))
2676 return 1;
2678 tmp = load_cpu_field(spsr);
2679 tcg_gen_andi_i32(tmp, tmp, ~mask);
2680 tcg_gen_andi_i32(t0, t0, mask);
2681 tcg_gen_or_i32(tmp, tmp, t0);
2682 store_cpu_field(tmp, spsr);
2683 } else {
2684 gen_set_cpsr(t0, mask);
2686 tcg_temp_free_i32(t0);
2687 gen_lookup_tb(s);
2688 return 0;
2691 /* Returns nonzero if access to the PSR is not permitted. */
2692 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
2694 TCGv_i32 tmp;
2695 tmp = tcg_temp_new_i32();
2696 tcg_gen_movi_i32(tmp, val);
2697 return gen_set_psr(s, mask, spsr, tmp);
2700 static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
2701 int *tgtmode, int *regno)
2703 /* Decode the r and sysm fields of MSR/MRS banked accesses into
2704 * the target mode and register number, and identify the various
2705 * unpredictable cases.
2706 * MSR (banked) and MRS (banked) are CONSTRAINED UNPREDICTABLE if:
2707 * + executed in user mode
2708 * + using R15 as the src/dest register
2709 * + accessing an unimplemented register
2710 * + accessing a register that's inaccessible at current PL/security state*
2711 * + accessing a register that you could access with a different insn
2712 * We choose to UNDEF in all these cases.
2713 * Since we don't know which of the various AArch32 modes we are in
2714 * we have to defer some checks to runtime.
2715 * Accesses to Monitor mode registers from Secure EL1 (which implies
2716 * that EL3 is AArch64) must trap to EL3.
2718 * If the access checks fail this function will emit code to take
2719 * an exception and return false. Otherwise it will return true,
2720 * and set *tgtmode and *regno appropriately.
2722 int exc_target = default_exception_el(s);
2724 /* These instructions are present only in ARMv8, or in ARMv7 with the
2725 * Virtualization Extensions.
2727 if (!arm_dc_feature(s, ARM_FEATURE_V8) &&
2728 !arm_dc_feature(s, ARM_FEATURE_EL2)) {
2729 goto undef;
2732 if (IS_USER(s) || rn == 15) {
2733 goto undef;
2736 /* The table in the v8 ARM ARM section F5.2.3 describes the encoding
2737 * of registers into (r, sysm).
2739 if (r) {
2740 /* SPSRs for other modes */
2741 switch (sysm) {
2742 case 0xe: /* SPSR_fiq */
2743 *tgtmode = ARM_CPU_MODE_FIQ;
2744 break;
2745 case 0x10: /* SPSR_irq */
2746 *tgtmode = ARM_CPU_MODE_IRQ;
2747 break;
2748 case 0x12: /* SPSR_svc */
2749 *tgtmode = ARM_CPU_MODE_SVC;
2750 break;
2751 case 0x14: /* SPSR_abt */
2752 *tgtmode = ARM_CPU_MODE_ABT;
2753 break;
2754 case 0x16: /* SPSR_und */
2755 *tgtmode = ARM_CPU_MODE_UND;
2756 break;
2757 case 0x1c: /* SPSR_mon */
2758 *tgtmode = ARM_CPU_MODE_MON;
2759 break;
2760 case 0x1e: /* SPSR_hyp */
2761 *tgtmode = ARM_CPU_MODE_HYP;
2762 break;
2763 default: /* unallocated */
2764 goto undef;
2766 /* We arbitrarily assign SPSR a register number of 16. */
2767 *regno = 16;
2768 } else {
2769 /* general purpose registers for other modes */
2770 switch (sysm) {
2771 case 0x0 ... 0x6: /* 0b00xxx : r8_usr ... r14_usr */
2772 *tgtmode = ARM_CPU_MODE_USR;
2773 *regno = sysm + 8;
2774 break;
2775 case 0x8 ... 0xe: /* 0b01xxx : r8_fiq ... r14_fiq */
2776 *tgtmode = ARM_CPU_MODE_FIQ;
2777 *regno = sysm;
2778 break;
2779 case 0x10 ... 0x11: /* 0b1000x : r14_irq, r13_irq */
2780 *tgtmode = ARM_CPU_MODE_IRQ;
2781 *regno = sysm & 1 ? 13 : 14;
2782 break;
2783 case 0x12 ... 0x13: /* 0b1001x : r14_svc, r13_svc */
2784 *tgtmode = ARM_CPU_MODE_SVC;
2785 *regno = sysm & 1 ? 13 : 14;
2786 break;
2787 case 0x14 ... 0x15: /* 0b1010x : r14_abt, r13_abt */
2788 *tgtmode = ARM_CPU_MODE_ABT;
2789 *regno = sysm & 1 ? 13 : 14;
2790 break;
2791 case 0x16 ... 0x17: /* 0b1011x : r14_und, r13_und */
2792 *tgtmode = ARM_CPU_MODE_UND;
2793 *regno = sysm & 1 ? 13 : 14;
2794 break;
2795 case 0x1c ... 0x1d: /* 0b1110x : r14_mon, r13_mon */
2796 *tgtmode = ARM_CPU_MODE_MON;
2797 *regno = sysm & 1 ? 13 : 14;
2798 break;
2799 case 0x1e ... 0x1f: /* 0b1111x : elr_hyp, r13_hyp */
2800 *tgtmode = ARM_CPU_MODE_HYP;
2801 /* Arbitrarily pick 17 for ELR_Hyp (which is not a banked LR!) */
2802 *regno = sysm & 1 ? 13 : 17;
2803 break;
2804 default: /* unallocated */
2805 goto undef;
2809 /* Catch the 'accessing inaccessible register' cases we can detect
2810 * at translate time.
2812 switch (*tgtmode) {
2813 case ARM_CPU_MODE_MON:
2814 if (!arm_dc_feature(s, ARM_FEATURE_EL3) || s->ns) {
2815 goto undef;
2817 if (s->current_el == 1) {
2818 /* If we're in Secure EL1 (which implies that EL3 is AArch64)
2819 * then accesses to Mon registers trap to EL3
2821 exc_target = 3;
2822 goto undef;
2824 break;
2825 case ARM_CPU_MODE_HYP:
2827 * SPSR_hyp and r13_hyp can only be accessed from Monitor mode
2828 * (and so we can forbid accesses from EL2 or below). elr_hyp
2829 * can be accessed also from Hyp mode, so forbid accesses from
2830 * EL0 or EL1.
2832 if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_el < 2 ||
2833 (s->current_el < 3 && *regno != 17)) {
2834 goto undef;
2836 break;
2837 default:
2838 break;
2841 return true;
2843 undef:
2844 /* If we get here then some access check did not pass */
2845 gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
2846 syn_uncategorized(), exc_target);
2847 return false;
2850 static void gen_msr_banked(DisasContext *s, int r, int sysm, int rn)
2852 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
2853 int tgtmode = 0, regno = 0;
2855 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
2856 return;
2859 /* Sync state because msr_banked() can raise exceptions */
2860 gen_set_condexec(s);
2861 gen_set_pc_im(s, s->pc_curr);
2862 tcg_reg = load_reg(s, rn);
2863 tcg_tgtmode = tcg_const_i32(tgtmode);
2864 tcg_regno = tcg_const_i32(regno);
2865 gen_helper_msr_banked(cpu_env, tcg_reg, tcg_tgtmode, tcg_regno);
2866 tcg_temp_free_i32(tcg_tgtmode);
2867 tcg_temp_free_i32(tcg_regno);
2868 tcg_temp_free_i32(tcg_reg);
2869 s->base.is_jmp = DISAS_UPDATE_EXIT;
2872 static void gen_mrs_banked(DisasContext *s, int r, int sysm, int rn)
2874 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
2875 int tgtmode = 0, regno = 0;
2877 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
2878 return;
2881 /* Sync state because mrs_banked() can raise exceptions */
2882 gen_set_condexec(s);
2883 gen_set_pc_im(s, s->pc_curr);
2884 tcg_reg = tcg_temp_new_i32();
2885 tcg_tgtmode = tcg_const_i32(tgtmode);
2886 tcg_regno = tcg_const_i32(regno);
2887 gen_helper_mrs_banked(tcg_reg, cpu_env, tcg_tgtmode, tcg_regno);
2888 tcg_temp_free_i32(tcg_tgtmode);
2889 tcg_temp_free_i32(tcg_regno);
2890 store_reg(s, rn, tcg_reg);
2891 s->base.is_jmp = DISAS_UPDATE_EXIT;
2894 /* Store value to PC as for an exception return (ie don't
2895 * mask bits). The subsequent call to gen_helper_cpsr_write_eret()
2896 * will do the masking based on the new value of the Thumb bit.
2898 static void store_pc_exc_ret(DisasContext *s, TCGv_i32 pc)
2900 tcg_gen_mov_i32(cpu_R[15], pc);
2901 tcg_temp_free_i32(pc);
2904 /* Generate a v6 exception return. Marks both values as dead. */
2905 static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
2907 store_pc_exc_ret(s, pc);
2908 /* The cpsr_write_eret helper will mask the low bits of PC
2909 * appropriately depending on the new Thumb bit, so it must
2910 * be called after storing the new PC.
2912 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
2913 gen_io_start();
2915 gen_helper_cpsr_write_eret(cpu_env, cpsr);
2916 tcg_temp_free_i32(cpsr);
2917 /* Must exit loop to check un-masked IRQs */
2918 s->base.is_jmp = DISAS_EXIT;
2921 /* Generate an old-style exception return. Marks pc as dead. */
2922 static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
2924 gen_rfe(s, pc, load_cpu_field(spsr));
2927 static void gen_gvec_fn3_qc(uint32_t rd_ofs, uint32_t rn_ofs, uint32_t rm_ofs,
2928 uint32_t opr_sz, uint32_t max_sz,
2929 gen_helper_gvec_3_ptr *fn)
2931 TCGv_ptr qc_ptr = tcg_temp_new_ptr();
2933 tcg_gen_addi_ptr(qc_ptr, cpu_env, offsetof(CPUARMState, vfp.qc));
2934 tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, qc_ptr,
2935 opr_sz, max_sz, 0, fn);
2936 tcg_temp_free_ptr(qc_ptr);
2939 void gen_gvec_sqrdmlah_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
2940 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
2942 static gen_helper_gvec_3_ptr * const fns[2] = {
2943 gen_helper_gvec_qrdmlah_s16, gen_helper_gvec_qrdmlah_s32
2945 tcg_debug_assert(vece >= 1 && vece <= 2);
2946 gen_gvec_fn3_qc(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, fns[vece - 1]);
2949 void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
2950 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
2952 static gen_helper_gvec_3_ptr * const fns[2] = {
2953 gen_helper_gvec_qrdmlsh_s16, gen_helper_gvec_qrdmlsh_s32
2955 tcg_debug_assert(vece >= 1 && vece <= 2);
2956 gen_gvec_fn3_qc(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, fns[vece - 1]);
2959 #define GEN_CMP0(NAME, COND) \
2960 static void gen_##NAME##0_i32(TCGv_i32 d, TCGv_i32 a) \
2962 tcg_gen_setcondi_i32(COND, d, a, 0); \
2963 tcg_gen_neg_i32(d, d); \
2965 static void gen_##NAME##0_i64(TCGv_i64 d, TCGv_i64 a) \
2967 tcg_gen_setcondi_i64(COND, d, a, 0); \
2968 tcg_gen_neg_i64(d, d); \
2970 static void gen_##NAME##0_vec(unsigned vece, TCGv_vec d, TCGv_vec a) \
2972 TCGv_vec zero = tcg_const_zeros_vec_matching(d); \
2973 tcg_gen_cmp_vec(COND, vece, d, a, zero); \
2974 tcg_temp_free_vec(zero); \
2976 void gen_gvec_##NAME##0(unsigned vece, uint32_t d, uint32_t m, \
2977 uint32_t opr_sz, uint32_t max_sz) \
2979 const GVecGen2 op[4] = { \
2980 { .fno = gen_helper_gvec_##NAME##0_b, \
2981 .fniv = gen_##NAME##0_vec, \
2982 .opt_opc = vecop_list_cmp, \
2983 .vece = MO_8 }, \
2984 { .fno = gen_helper_gvec_##NAME##0_h, \
2985 .fniv = gen_##NAME##0_vec, \
2986 .opt_opc = vecop_list_cmp, \
2987 .vece = MO_16 }, \
2988 { .fni4 = gen_##NAME##0_i32, \
2989 .fniv = gen_##NAME##0_vec, \
2990 .opt_opc = vecop_list_cmp, \
2991 .vece = MO_32 }, \
2992 { .fni8 = gen_##NAME##0_i64, \
2993 .fniv = gen_##NAME##0_vec, \
2994 .opt_opc = vecop_list_cmp, \
2995 .prefer_i64 = TCG_TARGET_REG_BITS == 64, \
2996 .vece = MO_64 }, \
2997 }; \
2998 tcg_gen_gvec_2(d, m, opr_sz, max_sz, &op[vece]); \
3001 static const TCGOpcode vecop_list_cmp[] = {
3002 INDEX_op_cmp_vec, 0
3005 GEN_CMP0(ceq, TCG_COND_EQ)
3006 GEN_CMP0(cle, TCG_COND_LE)
3007 GEN_CMP0(cge, TCG_COND_GE)
3008 GEN_CMP0(clt, TCG_COND_LT)
3009 GEN_CMP0(cgt, TCG_COND_GT)
3011 #undef GEN_CMP0
3013 static void gen_ssra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3015 tcg_gen_vec_sar8i_i64(a, a, shift);
3016 tcg_gen_vec_add8_i64(d, d, a);
3019 static void gen_ssra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3021 tcg_gen_vec_sar16i_i64(a, a, shift);
3022 tcg_gen_vec_add16_i64(d, d, a);
3025 static void gen_ssra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
3027 tcg_gen_sari_i32(a, a, shift);
3028 tcg_gen_add_i32(d, d, a);
3031 static void gen_ssra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3033 tcg_gen_sari_i64(a, a, shift);
3034 tcg_gen_add_i64(d, d, a);
3037 static void gen_ssra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3039 tcg_gen_sari_vec(vece, a, a, sh);
3040 tcg_gen_add_vec(vece, d, d, a);
3043 void gen_gvec_ssra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3044 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3046 static const TCGOpcode vecop_list[] = {
3047 INDEX_op_sari_vec, INDEX_op_add_vec, 0
3049 static const GVecGen2i ops[4] = {
3050 { .fni8 = gen_ssra8_i64,
3051 .fniv = gen_ssra_vec,
3052 .fno = gen_helper_gvec_ssra_b,
3053 .load_dest = true,
3054 .opt_opc = vecop_list,
3055 .vece = MO_8 },
3056 { .fni8 = gen_ssra16_i64,
3057 .fniv = gen_ssra_vec,
3058 .fno = gen_helper_gvec_ssra_h,
3059 .load_dest = true,
3060 .opt_opc = vecop_list,
3061 .vece = MO_16 },
3062 { .fni4 = gen_ssra32_i32,
3063 .fniv = gen_ssra_vec,
3064 .fno = gen_helper_gvec_ssra_s,
3065 .load_dest = true,
3066 .opt_opc = vecop_list,
3067 .vece = MO_32 },
3068 { .fni8 = gen_ssra64_i64,
3069 .fniv = gen_ssra_vec,
3070 .fno = gen_helper_gvec_ssra_b,
3071 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3072 .opt_opc = vecop_list,
3073 .load_dest = true,
3074 .vece = MO_64 },
3077 /* tszimm encoding produces immediates in the range [1..esize]. */
3078 tcg_debug_assert(shift > 0);
3079 tcg_debug_assert(shift <= (8 << vece));
3082 * Shifts larger than the element size are architecturally valid.
3083 * Signed results in all sign bits.
3085 shift = MIN(shift, (8 << vece) - 1);
3086 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3089 static void gen_usra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3091 tcg_gen_vec_shr8i_i64(a, a, shift);
3092 tcg_gen_vec_add8_i64(d, d, a);
3095 static void gen_usra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3097 tcg_gen_vec_shr16i_i64(a, a, shift);
3098 tcg_gen_vec_add16_i64(d, d, a);
3101 static void gen_usra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
3103 tcg_gen_shri_i32(a, a, shift);
3104 tcg_gen_add_i32(d, d, a);
3107 static void gen_usra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3109 tcg_gen_shri_i64(a, a, shift);
3110 tcg_gen_add_i64(d, d, a);
3113 static void gen_usra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3115 tcg_gen_shri_vec(vece, a, a, sh);
3116 tcg_gen_add_vec(vece, d, d, a);
3119 void gen_gvec_usra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3120 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3122 static const TCGOpcode vecop_list[] = {
3123 INDEX_op_shri_vec, INDEX_op_add_vec, 0
3125 static const GVecGen2i ops[4] = {
3126 { .fni8 = gen_usra8_i64,
3127 .fniv = gen_usra_vec,
3128 .fno = gen_helper_gvec_usra_b,
3129 .load_dest = true,
3130 .opt_opc = vecop_list,
3131 .vece = MO_8, },
3132 { .fni8 = gen_usra16_i64,
3133 .fniv = gen_usra_vec,
3134 .fno = gen_helper_gvec_usra_h,
3135 .load_dest = true,
3136 .opt_opc = vecop_list,
3137 .vece = MO_16, },
3138 { .fni4 = gen_usra32_i32,
3139 .fniv = gen_usra_vec,
3140 .fno = gen_helper_gvec_usra_s,
3141 .load_dest = true,
3142 .opt_opc = vecop_list,
3143 .vece = MO_32, },
3144 { .fni8 = gen_usra64_i64,
3145 .fniv = gen_usra_vec,
3146 .fno = gen_helper_gvec_usra_d,
3147 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3148 .load_dest = true,
3149 .opt_opc = vecop_list,
3150 .vece = MO_64, },
3153 /* tszimm encoding produces immediates in the range [1..esize]. */
3154 tcg_debug_assert(shift > 0);
3155 tcg_debug_assert(shift <= (8 << vece));
3158 * Shifts larger than the element size are architecturally valid.
3159 * Unsigned results in all zeros as input to accumulate: nop.
3161 if (shift < (8 << vece)) {
3162 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3163 } else {
3164 /* Nop, but we do need to clear the tail. */
3165 tcg_gen_gvec_mov(vece, rd_ofs, rd_ofs, opr_sz, max_sz);
3170 * Shift one less than the requested amount, and the low bit is
3171 * the rounding bit. For the 8 and 16-bit operations, because we
3172 * mask the low bit, we can perform a normal integer shift instead
3173 * of a vector shift.
3175 static void gen_srshr8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3177 TCGv_i64 t = tcg_temp_new_i64();
3179 tcg_gen_shri_i64(t, a, sh - 1);
3180 tcg_gen_andi_i64(t, t, dup_const(MO_8, 1));
3181 tcg_gen_vec_sar8i_i64(d, a, sh);
3182 tcg_gen_vec_add8_i64(d, d, t);
3183 tcg_temp_free_i64(t);
3186 static void gen_srshr16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3188 TCGv_i64 t = tcg_temp_new_i64();
3190 tcg_gen_shri_i64(t, a, sh - 1);
3191 tcg_gen_andi_i64(t, t, dup_const(MO_16, 1));
3192 tcg_gen_vec_sar16i_i64(d, a, sh);
3193 tcg_gen_vec_add16_i64(d, d, t);
3194 tcg_temp_free_i64(t);
3197 static void gen_srshr32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
3199 TCGv_i32 t = tcg_temp_new_i32();
3201 tcg_gen_extract_i32(t, a, sh - 1, 1);
3202 tcg_gen_sari_i32(d, a, sh);
3203 tcg_gen_add_i32(d, d, t);
3204 tcg_temp_free_i32(t);
3207 static void gen_srshr64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3209 TCGv_i64 t = tcg_temp_new_i64();
3211 tcg_gen_extract_i64(t, a, sh - 1, 1);
3212 tcg_gen_sari_i64(d, a, sh);
3213 tcg_gen_add_i64(d, d, t);
3214 tcg_temp_free_i64(t);
3217 static void gen_srshr_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3219 TCGv_vec t = tcg_temp_new_vec_matching(d);
3220 TCGv_vec ones = tcg_temp_new_vec_matching(d);
3222 tcg_gen_shri_vec(vece, t, a, sh - 1);
3223 tcg_gen_dupi_vec(vece, ones, 1);
3224 tcg_gen_and_vec(vece, t, t, ones);
3225 tcg_gen_sari_vec(vece, d, a, sh);
3226 tcg_gen_add_vec(vece, d, d, t);
3228 tcg_temp_free_vec(t);
3229 tcg_temp_free_vec(ones);
3232 void gen_gvec_srshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3233 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3235 static const TCGOpcode vecop_list[] = {
3236 INDEX_op_shri_vec, INDEX_op_sari_vec, INDEX_op_add_vec, 0
3238 static const GVecGen2i ops[4] = {
3239 { .fni8 = gen_srshr8_i64,
3240 .fniv = gen_srshr_vec,
3241 .fno = gen_helper_gvec_srshr_b,
3242 .opt_opc = vecop_list,
3243 .vece = MO_8 },
3244 { .fni8 = gen_srshr16_i64,
3245 .fniv = gen_srshr_vec,
3246 .fno = gen_helper_gvec_srshr_h,
3247 .opt_opc = vecop_list,
3248 .vece = MO_16 },
3249 { .fni4 = gen_srshr32_i32,
3250 .fniv = gen_srshr_vec,
3251 .fno = gen_helper_gvec_srshr_s,
3252 .opt_opc = vecop_list,
3253 .vece = MO_32 },
3254 { .fni8 = gen_srshr64_i64,
3255 .fniv = gen_srshr_vec,
3256 .fno = gen_helper_gvec_srshr_d,
3257 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3258 .opt_opc = vecop_list,
3259 .vece = MO_64 },
3262 /* tszimm encoding produces immediates in the range [1..esize] */
3263 tcg_debug_assert(shift > 0);
3264 tcg_debug_assert(shift <= (8 << vece));
3266 if (shift == (8 << vece)) {
3268 * Shifts larger than the element size are architecturally valid.
3269 * Signed results in all sign bits. With rounding, this produces
3270 * (-1 + 1) >> 1 == 0, or (0 + 1) >> 1 == 0.
3271 * I.e. always zero.
3273 tcg_gen_gvec_dup_imm(vece, rd_ofs, opr_sz, max_sz, 0);
3274 } else {
3275 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3279 static void gen_srsra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3281 TCGv_i64 t = tcg_temp_new_i64();
3283 gen_srshr8_i64(t, a, sh);
3284 tcg_gen_vec_add8_i64(d, d, t);
3285 tcg_temp_free_i64(t);
3288 static void gen_srsra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3290 TCGv_i64 t = tcg_temp_new_i64();
3292 gen_srshr16_i64(t, a, sh);
3293 tcg_gen_vec_add16_i64(d, d, t);
3294 tcg_temp_free_i64(t);
3297 static void gen_srsra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
3299 TCGv_i32 t = tcg_temp_new_i32();
3301 gen_srshr32_i32(t, a, sh);
3302 tcg_gen_add_i32(d, d, t);
3303 tcg_temp_free_i32(t);
3306 static void gen_srsra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3308 TCGv_i64 t = tcg_temp_new_i64();
3310 gen_srshr64_i64(t, a, sh);
3311 tcg_gen_add_i64(d, d, t);
3312 tcg_temp_free_i64(t);
3315 static void gen_srsra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3317 TCGv_vec t = tcg_temp_new_vec_matching(d);
3319 gen_srshr_vec(vece, t, a, sh);
3320 tcg_gen_add_vec(vece, d, d, t);
3321 tcg_temp_free_vec(t);
3324 void gen_gvec_srsra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3325 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3327 static const TCGOpcode vecop_list[] = {
3328 INDEX_op_shri_vec, INDEX_op_sari_vec, INDEX_op_add_vec, 0
3330 static const GVecGen2i ops[4] = {
3331 { .fni8 = gen_srsra8_i64,
3332 .fniv = gen_srsra_vec,
3333 .fno = gen_helper_gvec_srsra_b,
3334 .opt_opc = vecop_list,
3335 .load_dest = true,
3336 .vece = MO_8 },
3337 { .fni8 = gen_srsra16_i64,
3338 .fniv = gen_srsra_vec,
3339 .fno = gen_helper_gvec_srsra_h,
3340 .opt_opc = vecop_list,
3341 .load_dest = true,
3342 .vece = MO_16 },
3343 { .fni4 = gen_srsra32_i32,
3344 .fniv = gen_srsra_vec,
3345 .fno = gen_helper_gvec_srsra_s,
3346 .opt_opc = vecop_list,
3347 .load_dest = true,
3348 .vece = MO_32 },
3349 { .fni8 = gen_srsra64_i64,
3350 .fniv = gen_srsra_vec,
3351 .fno = gen_helper_gvec_srsra_d,
3352 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3353 .opt_opc = vecop_list,
3354 .load_dest = true,
3355 .vece = MO_64 },
3358 /* tszimm encoding produces immediates in the range [1..esize] */
3359 tcg_debug_assert(shift > 0);
3360 tcg_debug_assert(shift <= (8 << vece));
3363 * Shifts larger than the element size are architecturally valid.
3364 * Signed results in all sign bits. With rounding, this produces
3365 * (-1 + 1) >> 1 == 0, or (0 + 1) >> 1 == 0.
3366 * I.e. always zero. With accumulation, this leaves D unchanged.
3368 if (shift == (8 << vece)) {
3369 /* Nop, but we do need to clear the tail. */
3370 tcg_gen_gvec_mov(vece, rd_ofs, rd_ofs, opr_sz, max_sz);
3371 } else {
3372 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3376 static void gen_urshr8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3378 TCGv_i64 t = tcg_temp_new_i64();
3380 tcg_gen_shri_i64(t, a, sh - 1);
3381 tcg_gen_andi_i64(t, t, dup_const(MO_8, 1));
3382 tcg_gen_vec_shr8i_i64(d, a, sh);
3383 tcg_gen_vec_add8_i64(d, d, t);
3384 tcg_temp_free_i64(t);
3387 static void gen_urshr16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3389 TCGv_i64 t = tcg_temp_new_i64();
3391 tcg_gen_shri_i64(t, a, sh - 1);
3392 tcg_gen_andi_i64(t, t, dup_const(MO_16, 1));
3393 tcg_gen_vec_shr16i_i64(d, a, sh);
3394 tcg_gen_vec_add16_i64(d, d, t);
3395 tcg_temp_free_i64(t);
3398 static void gen_urshr32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
3400 TCGv_i32 t = tcg_temp_new_i32();
3402 tcg_gen_extract_i32(t, a, sh - 1, 1);
3403 tcg_gen_shri_i32(d, a, sh);
3404 tcg_gen_add_i32(d, d, t);
3405 tcg_temp_free_i32(t);
3408 static void gen_urshr64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3410 TCGv_i64 t = tcg_temp_new_i64();
3412 tcg_gen_extract_i64(t, a, sh - 1, 1);
3413 tcg_gen_shri_i64(d, a, sh);
3414 tcg_gen_add_i64(d, d, t);
3415 tcg_temp_free_i64(t);
3418 static void gen_urshr_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t shift)
3420 TCGv_vec t = tcg_temp_new_vec_matching(d);
3421 TCGv_vec ones = tcg_temp_new_vec_matching(d);
3423 tcg_gen_shri_vec(vece, t, a, shift - 1);
3424 tcg_gen_dupi_vec(vece, ones, 1);
3425 tcg_gen_and_vec(vece, t, t, ones);
3426 tcg_gen_shri_vec(vece, d, a, shift);
3427 tcg_gen_add_vec(vece, d, d, t);
3429 tcg_temp_free_vec(t);
3430 tcg_temp_free_vec(ones);
3433 void gen_gvec_urshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3434 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3436 static const TCGOpcode vecop_list[] = {
3437 INDEX_op_shri_vec, INDEX_op_add_vec, 0
3439 static const GVecGen2i ops[4] = {
3440 { .fni8 = gen_urshr8_i64,
3441 .fniv = gen_urshr_vec,
3442 .fno = gen_helper_gvec_urshr_b,
3443 .opt_opc = vecop_list,
3444 .vece = MO_8 },
3445 { .fni8 = gen_urshr16_i64,
3446 .fniv = gen_urshr_vec,
3447 .fno = gen_helper_gvec_urshr_h,
3448 .opt_opc = vecop_list,
3449 .vece = MO_16 },
3450 { .fni4 = gen_urshr32_i32,
3451 .fniv = gen_urshr_vec,
3452 .fno = gen_helper_gvec_urshr_s,
3453 .opt_opc = vecop_list,
3454 .vece = MO_32 },
3455 { .fni8 = gen_urshr64_i64,
3456 .fniv = gen_urshr_vec,
3457 .fno = gen_helper_gvec_urshr_d,
3458 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3459 .opt_opc = vecop_list,
3460 .vece = MO_64 },
3463 /* tszimm encoding produces immediates in the range [1..esize] */
3464 tcg_debug_assert(shift > 0);
3465 tcg_debug_assert(shift <= (8 << vece));
3467 if (shift == (8 << vece)) {
3469 * Shifts larger than the element size are architecturally valid.
3470 * Unsigned results in zero. With rounding, this produces a
3471 * copy of the most significant bit.
3473 tcg_gen_gvec_shri(vece, rd_ofs, rm_ofs, shift - 1, opr_sz, max_sz);
3474 } else {
3475 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3479 static void gen_ursra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3481 TCGv_i64 t = tcg_temp_new_i64();
3483 if (sh == 8) {
3484 tcg_gen_vec_shr8i_i64(t, a, 7);
3485 } else {
3486 gen_urshr8_i64(t, a, sh);
3488 tcg_gen_vec_add8_i64(d, d, t);
3489 tcg_temp_free_i64(t);
3492 static void gen_ursra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3494 TCGv_i64 t = tcg_temp_new_i64();
3496 if (sh == 16) {
3497 tcg_gen_vec_shr16i_i64(t, a, 15);
3498 } else {
3499 gen_urshr16_i64(t, a, sh);
3501 tcg_gen_vec_add16_i64(d, d, t);
3502 tcg_temp_free_i64(t);
3505 static void gen_ursra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
3507 TCGv_i32 t = tcg_temp_new_i32();
3509 if (sh == 32) {
3510 tcg_gen_shri_i32(t, a, 31);
3511 } else {
3512 gen_urshr32_i32(t, a, sh);
3514 tcg_gen_add_i32(d, d, t);
3515 tcg_temp_free_i32(t);
3518 static void gen_ursra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3520 TCGv_i64 t = tcg_temp_new_i64();
3522 if (sh == 64) {
3523 tcg_gen_shri_i64(t, a, 63);
3524 } else {
3525 gen_urshr64_i64(t, a, sh);
3527 tcg_gen_add_i64(d, d, t);
3528 tcg_temp_free_i64(t);
3531 static void gen_ursra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3533 TCGv_vec t = tcg_temp_new_vec_matching(d);
3535 if (sh == (8 << vece)) {
3536 tcg_gen_shri_vec(vece, t, a, sh - 1);
3537 } else {
3538 gen_urshr_vec(vece, t, a, sh);
3540 tcg_gen_add_vec(vece, d, d, t);
3541 tcg_temp_free_vec(t);
3544 void gen_gvec_ursra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3545 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3547 static const TCGOpcode vecop_list[] = {
3548 INDEX_op_shri_vec, INDEX_op_add_vec, 0
3550 static const GVecGen2i ops[4] = {
3551 { .fni8 = gen_ursra8_i64,
3552 .fniv = gen_ursra_vec,
3553 .fno = gen_helper_gvec_ursra_b,
3554 .opt_opc = vecop_list,
3555 .load_dest = true,
3556 .vece = MO_8 },
3557 { .fni8 = gen_ursra16_i64,
3558 .fniv = gen_ursra_vec,
3559 .fno = gen_helper_gvec_ursra_h,
3560 .opt_opc = vecop_list,
3561 .load_dest = true,
3562 .vece = MO_16 },
3563 { .fni4 = gen_ursra32_i32,
3564 .fniv = gen_ursra_vec,
3565 .fno = gen_helper_gvec_ursra_s,
3566 .opt_opc = vecop_list,
3567 .load_dest = true,
3568 .vece = MO_32 },
3569 { .fni8 = gen_ursra64_i64,
3570 .fniv = gen_ursra_vec,
3571 .fno = gen_helper_gvec_ursra_d,
3572 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3573 .opt_opc = vecop_list,
3574 .load_dest = true,
3575 .vece = MO_64 },
3578 /* tszimm encoding produces immediates in the range [1..esize] */
3579 tcg_debug_assert(shift > 0);
3580 tcg_debug_assert(shift <= (8 << vece));
3582 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3585 static void gen_shr8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3587 uint64_t mask = dup_const(MO_8, 0xff >> shift);
3588 TCGv_i64 t = tcg_temp_new_i64();
3590 tcg_gen_shri_i64(t, a, shift);
3591 tcg_gen_andi_i64(t, t, mask);
3592 tcg_gen_andi_i64(d, d, ~mask);
3593 tcg_gen_or_i64(d, d, t);
3594 tcg_temp_free_i64(t);
3597 static void gen_shr16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3599 uint64_t mask = dup_const(MO_16, 0xffff >> shift);
3600 TCGv_i64 t = tcg_temp_new_i64();
3602 tcg_gen_shri_i64(t, a, shift);
3603 tcg_gen_andi_i64(t, t, mask);
3604 tcg_gen_andi_i64(d, d, ~mask);
3605 tcg_gen_or_i64(d, d, t);
3606 tcg_temp_free_i64(t);
3609 static void gen_shr32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
3611 tcg_gen_shri_i32(a, a, shift);
3612 tcg_gen_deposit_i32(d, d, a, 0, 32 - shift);
3615 static void gen_shr64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3617 tcg_gen_shri_i64(a, a, shift);
3618 tcg_gen_deposit_i64(d, d, a, 0, 64 - shift);
3621 static void gen_shr_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3623 TCGv_vec t = tcg_temp_new_vec_matching(d);
3624 TCGv_vec m = tcg_temp_new_vec_matching(d);
3626 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK((8 << vece) - sh, sh));
3627 tcg_gen_shri_vec(vece, t, a, sh);
3628 tcg_gen_and_vec(vece, d, d, m);
3629 tcg_gen_or_vec(vece, d, d, t);
3631 tcg_temp_free_vec(t);
3632 tcg_temp_free_vec(m);
3635 void gen_gvec_sri(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3636 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3638 static const TCGOpcode vecop_list[] = { INDEX_op_shri_vec, 0 };
3639 const GVecGen2i ops[4] = {
3640 { .fni8 = gen_shr8_ins_i64,
3641 .fniv = gen_shr_ins_vec,
3642 .fno = gen_helper_gvec_sri_b,
3643 .load_dest = true,
3644 .opt_opc = vecop_list,
3645 .vece = MO_8 },
3646 { .fni8 = gen_shr16_ins_i64,
3647 .fniv = gen_shr_ins_vec,
3648 .fno = gen_helper_gvec_sri_h,
3649 .load_dest = true,
3650 .opt_opc = vecop_list,
3651 .vece = MO_16 },
3652 { .fni4 = gen_shr32_ins_i32,
3653 .fniv = gen_shr_ins_vec,
3654 .fno = gen_helper_gvec_sri_s,
3655 .load_dest = true,
3656 .opt_opc = vecop_list,
3657 .vece = MO_32 },
3658 { .fni8 = gen_shr64_ins_i64,
3659 .fniv = gen_shr_ins_vec,
3660 .fno = gen_helper_gvec_sri_d,
3661 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3662 .load_dest = true,
3663 .opt_opc = vecop_list,
3664 .vece = MO_64 },
3667 /* tszimm encoding produces immediates in the range [1..esize]. */
3668 tcg_debug_assert(shift > 0);
3669 tcg_debug_assert(shift <= (8 << vece));
3671 /* Shift of esize leaves destination unchanged. */
3672 if (shift < (8 << vece)) {
3673 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3674 } else {
3675 /* Nop, but we do need to clear the tail. */
3676 tcg_gen_gvec_mov(vece, rd_ofs, rd_ofs, opr_sz, max_sz);
3680 static void gen_shl8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3682 uint64_t mask = dup_const(MO_8, 0xff << shift);
3683 TCGv_i64 t = tcg_temp_new_i64();
3685 tcg_gen_shli_i64(t, a, shift);
3686 tcg_gen_andi_i64(t, t, mask);
3687 tcg_gen_andi_i64(d, d, ~mask);
3688 tcg_gen_or_i64(d, d, t);
3689 tcg_temp_free_i64(t);
3692 static void gen_shl16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3694 uint64_t mask = dup_const(MO_16, 0xffff << shift);
3695 TCGv_i64 t = tcg_temp_new_i64();
3697 tcg_gen_shli_i64(t, a, shift);
3698 tcg_gen_andi_i64(t, t, mask);
3699 tcg_gen_andi_i64(d, d, ~mask);
3700 tcg_gen_or_i64(d, d, t);
3701 tcg_temp_free_i64(t);
3704 static void gen_shl32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
3706 tcg_gen_deposit_i32(d, d, a, shift, 32 - shift);
3709 static void gen_shl64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3711 tcg_gen_deposit_i64(d, d, a, shift, 64 - shift);
3714 static void gen_shl_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3716 TCGv_vec t = tcg_temp_new_vec_matching(d);
3717 TCGv_vec m = tcg_temp_new_vec_matching(d);
3719 tcg_gen_shli_vec(vece, t, a, sh);
3720 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK(0, sh));
3721 tcg_gen_and_vec(vece, d, d, m);
3722 tcg_gen_or_vec(vece, d, d, t);
3724 tcg_temp_free_vec(t);
3725 tcg_temp_free_vec(m);
3728 void gen_gvec_sli(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3729 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3731 static const TCGOpcode vecop_list[] = { INDEX_op_shli_vec, 0 };
3732 const GVecGen2i ops[4] = {
3733 { .fni8 = gen_shl8_ins_i64,
3734 .fniv = gen_shl_ins_vec,
3735 .fno = gen_helper_gvec_sli_b,
3736 .load_dest = true,
3737 .opt_opc = vecop_list,
3738 .vece = MO_8 },
3739 { .fni8 = gen_shl16_ins_i64,
3740 .fniv = gen_shl_ins_vec,
3741 .fno = gen_helper_gvec_sli_h,
3742 .load_dest = true,
3743 .opt_opc = vecop_list,
3744 .vece = MO_16 },
3745 { .fni4 = gen_shl32_ins_i32,
3746 .fniv = gen_shl_ins_vec,
3747 .fno = gen_helper_gvec_sli_s,
3748 .load_dest = true,
3749 .opt_opc = vecop_list,
3750 .vece = MO_32 },
3751 { .fni8 = gen_shl64_ins_i64,
3752 .fniv = gen_shl_ins_vec,
3753 .fno = gen_helper_gvec_sli_d,
3754 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3755 .load_dest = true,
3756 .opt_opc = vecop_list,
3757 .vece = MO_64 },
3760 /* tszimm encoding produces immediates in the range [0..esize-1]. */
3761 tcg_debug_assert(shift >= 0);
3762 tcg_debug_assert(shift < (8 << vece));
3764 if (shift == 0) {
3765 tcg_gen_gvec_mov(vece, rd_ofs, rm_ofs, opr_sz, max_sz);
3766 } else {
3767 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3771 static void gen_mla8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3773 gen_helper_neon_mul_u8(a, a, b);
3774 gen_helper_neon_add_u8(d, d, a);
3777 static void gen_mls8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3779 gen_helper_neon_mul_u8(a, a, b);
3780 gen_helper_neon_sub_u8(d, d, a);
3783 static void gen_mla16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3785 gen_helper_neon_mul_u16(a, a, b);
3786 gen_helper_neon_add_u16(d, d, a);
3789 static void gen_mls16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3791 gen_helper_neon_mul_u16(a, a, b);
3792 gen_helper_neon_sub_u16(d, d, a);
3795 static void gen_mla32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3797 tcg_gen_mul_i32(a, a, b);
3798 tcg_gen_add_i32(d, d, a);
3801 static void gen_mls32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3803 tcg_gen_mul_i32(a, a, b);
3804 tcg_gen_sub_i32(d, d, a);
3807 static void gen_mla64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
3809 tcg_gen_mul_i64(a, a, b);
3810 tcg_gen_add_i64(d, d, a);
3813 static void gen_mls64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
3815 tcg_gen_mul_i64(a, a, b);
3816 tcg_gen_sub_i64(d, d, a);
3819 static void gen_mla_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
3821 tcg_gen_mul_vec(vece, a, a, b);
3822 tcg_gen_add_vec(vece, d, d, a);
3825 static void gen_mls_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
3827 tcg_gen_mul_vec(vece, a, a, b);
3828 tcg_gen_sub_vec(vece, d, d, a);
3831 /* Note that while NEON does not support VMLA and VMLS as 64-bit ops,
3832 * these tables are shared with AArch64 which does support them.
3834 void gen_gvec_mla(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
3835 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
3837 static const TCGOpcode vecop_list[] = {
3838 INDEX_op_mul_vec, INDEX_op_add_vec, 0
3840 static const GVecGen3 ops[4] = {
3841 { .fni4 = gen_mla8_i32,
3842 .fniv = gen_mla_vec,
3843 .load_dest = true,
3844 .opt_opc = vecop_list,
3845 .vece = MO_8 },
3846 { .fni4 = gen_mla16_i32,
3847 .fniv = gen_mla_vec,
3848 .load_dest = true,
3849 .opt_opc = vecop_list,
3850 .vece = MO_16 },
3851 { .fni4 = gen_mla32_i32,
3852 .fniv = gen_mla_vec,
3853 .load_dest = true,
3854 .opt_opc = vecop_list,
3855 .vece = MO_32 },
3856 { .fni8 = gen_mla64_i64,
3857 .fniv = gen_mla_vec,
3858 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3859 .load_dest = true,
3860 .opt_opc = vecop_list,
3861 .vece = MO_64 },
3863 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
3866 void gen_gvec_mls(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
3867 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
3869 static const TCGOpcode vecop_list[] = {
3870 INDEX_op_mul_vec, INDEX_op_sub_vec, 0
3872 static const GVecGen3 ops[4] = {
3873 { .fni4 = gen_mls8_i32,
3874 .fniv = gen_mls_vec,
3875 .load_dest = true,
3876 .opt_opc = vecop_list,
3877 .vece = MO_8 },
3878 { .fni4 = gen_mls16_i32,
3879 .fniv = gen_mls_vec,
3880 .load_dest = true,
3881 .opt_opc = vecop_list,
3882 .vece = MO_16 },
3883 { .fni4 = gen_mls32_i32,
3884 .fniv = gen_mls_vec,
3885 .load_dest = true,
3886 .opt_opc = vecop_list,
3887 .vece = MO_32 },
3888 { .fni8 = gen_mls64_i64,
3889 .fniv = gen_mls_vec,
3890 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3891 .load_dest = true,
3892 .opt_opc = vecop_list,
3893 .vece = MO_64 },
3895 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
3898 /* CMTST : test is "if (X & Y != 0)". */
3899 static void gen_cmtst_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3901 tcg_gen_and_i32(d, a, b);
3902 tcg_gen_setcondi_i32(TCG_COND_NE, d, d, 0);
3903 tcg_gen_neg_i32(d, d);
3906 void gen_cmtst_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
3908 tcg_gen_and_i64(d, a, b);
3909 tcg_gen_setcondi_i64(TCG_COND_NE, d, d, 0);
3910 tcg_gen_neg_i64(d, d);
3913 static void gen_cmtst_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
3915 tcg_gen_and_vec(vece, d, a, b);
3916 tcg_gen_dupi_vec(vece, a, 0);
3917 tcg_gen_cmp_vec(TCG_COND_NE, vece, d, d, a);
3920 void gen_gvec_cmtst(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
3921 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
3923 static const TCGOpcode vecop_list[] = { INDEX_op_cmp_vec, 0 };
3924 static const GVecGen3 ops[4] = {
3925 { .fni4 = gen_helper_neon_tst_u8,
3926 .fniv = gen_cmtst_vec,
3927 .opt_opc = vecop_list,
3928 .vece = MO_8 },
3929 { .fni4 = gen_helper_neon_tst_u16,
3930 .fniv = gen_cmtst_vec,
3931 .opt_opc = vecop_list,
3932 .vece = MO_16 },
3933 { .fni4 = gen_cmtst_i32,
3934 .fniv = gen_cmtst_vec,
3935 .opt_opc = vecop_list,
3936 .vece = MO_32 },
3937 { .fni8 = gen_cmtst_i64,
3938 .fniv = gen_cmtst_vec,
3939 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3940 .opt_opc = vecop_list,
3941 .vece = MO_64 },
3943 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
3946 void gen_ushl_i32(TCGv_i32 dst, TCGv_i32 src, TCGv_i32 shift)
3948 TCGv_i32 lval = tcg_temp_new_i32();
3949 TCGv_i32 rval = tcg_temp_new_i32();
3950 TCGv_i32 lsh = tcg_temp_new_i32();
3951 TCGv_i32 rsh = tcg_temp_new_i32();
3952 TCGv_i32 zero = tcg_const_i32(0);
3953 TCGv_i32 max = tcg_const_i32(32);
3956 * Rely on the TCG guarantee that out of range shifts produce
3957 * unspecified results, not undefined behaviour (i.e. no trap).
3958 * Discard out-of-range results after the fact.
3960 tcg_gen_ext8s_i32(lsh, shift);
3961 tcg_gen_neg_i32(rsh, lsh);
3962 tcg_gen_shl_i32(lval, src, lsh);
3963 tcg_gen_shr_i32(rval, src, rsh);
3964 tcg_gen_movcond_i32(TCG_COND_LTU, dst, lsh, max, lval, zero);
3965 tcg_gen_movcond_i32(TCG_COND_LTU, dst, rsh, max, rval, dst);
3967 tcg_temp_free_i32(lval);
3968 tcg_temp_free_i32(rval);
3969 tcg_temp_free_i32(lsh);
3970 tcg_temp_free_i32(rsh);
3971 tcg_temp_free_i32(zero);
3972 tcg_temp_free_i32(max);
3975 void gen_ushl_i64(TCGv_i64 dst, TCGv_i64 src, TCGv_i64 shift)
3977 TCGv_i64 lval = tcg_temp_new_i64();
3978 TCGv_i64 rval = tcg_temp_new_i64();
3979 TCGv_i64 lsh = tcg_temp_new_i64();
3980 TCGv_i64 rsh = tcg_temp_new_i64();
3981 TCGv_i64 zero = tcg_const_i64(0);
3982 TCGv_i64 max = tcg_const_i64(64);
3985 * Rely on the TCG guarantee that out of range shifts produce
3986 * unspecified results, not undefined behaviour (i.e. no trap).
3987 * Discard out-of-range results after the fact.
3989 tcg_gen_ext8s_i64(lsh, shift);
3990 tcg_gen_neg_i64(rsh, lsh);
3991 tcg_gen_shl_i64(lval, src, lsh);
3992 tcg_gen_shr_i64(rval, src, rsh);
3993 tcg_gen_movcond_i64(TCG_COND_LTU, dst, lsh, max, lval, zero);
3994 tcg_gen_movcond_i64(TCG_COND_LTU, dst, rsh, max, rval, dst);
3996 tcg_temp_free_i64(lval);
3997 tcg_temp_free_i64(rval);
3998 tcg_temp_free_i64(lsh);
3999 tcg_temp_free_i64(rsh);
4000 tcg_temp_free_i64(zero);
4001 tcg_temp_free_i64(max);
4004 static void gen_ushl_vec(unsigned vece, TCGv_vec dst,
4005 TCGv_vec src, TCGv_vec shift)
4007 TCGv_vec lval = tcg_temp_new_vec_matching(dst);
4008 TCGv_vec rval = tcg_temp_new_vec_matching(dst);
4009 TCGv_vec lsh = tcg_temp_new_vec_matching(dst);
4010 TCGv_vec rsh = tcg_temp_new_vec_matching(dst);
4011 TCGv_vec msk, max;
4013 tcg_gen_neg_vec(vece, rsh, shift);
4014 if (vece == MO_8) {
4015 tcg_gen_mov_vec(lsh, shift);
4016 } else {
4017 msk = tcg_temp_new_vec_matching(dst);
4018 tcg_gen_dupi_vec(vece, msk, 0xff);
4019 tcg_gen_and_vec(vece, lsh, shift, msk);
4020 tcg_gen_and_vec(vece, rsh, rsh, msk);
4021 tcg_temp_free_vec(msk);
4025 * Rely on the TCG guarantee that out of range shifts produce
4026 * unspecified results, not undefined behaviour (i.e. no trap).
4027 * Discard out-of-range results after the fact.
4029 tcg_gen_shlv_vec(vece, lval, src, lsh);
4030 tcg_gen_shrv_vec(vece, rval, src, rsh);
4032 max = tcg_temp_new_vec_matching(dst);
4033 tcg_gen_dupi_vec(vece, max, 8 << vece);
4036 * The choice of LT (signed) and GEU (unsigned) are biased toward
4037 * the instructions of the x86_64 host. For MO_8, the whole byte
4038 * is significant so we must use an unsigned compare; otherwise we
4039 * have already masked to a byte and so a signed compare works.
4040 * Other tcg hosts have a full set of comparisons and do not care.
4042 if (vece == MO_8) {
4043 tcg_gen_cmp_vec(TCG_COND_GEU, vece, lsh, lsh, max);
4044 tcg_gen_cmp_vec(TCG_COND_GEU, vece, rsh, rsh, max);
4045 tcg_gen_andc_vec(vece, lval, lval, lsh);
4046 tcg_gen_andc_vec(vece, rval, rval, rsh);
4047 } else {
4048 tcg_gen_cmp_vec(TCG_COND_LT, vece, lsh, lsh, max);
4049 tcg_gen_cmp_vec(TCG_COND_LT, vece, rsh, rsh, max);
4050 tcg_gen_and_vec(vece, lval, lval, lsh);
4051 tcg_gen_and_vec(vece, rval, rval, rsh);
4053 tcg_gen_or_vec(vece, dst, lval, rval);
4055 tcg_temp_free_vec(max);
4056 tcg_temp_free_vec(lval);
4057 tcg_temp_free_vec(rval);
4058 tcg_temp_free_vec(lsh);
4059 tcg_temp_free_vec(rsh);
4062 void gen_gvec_ushl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4063 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4065 static const TCGOpcode vecop_list[] = {
4066 INDEX_op_neg_vec, INDEX_op_shlv_vec,
4067 INDEX_op_shrv_vec, INDEX_op_cmp_vec, 0
4069 static const GVecGen3 ops[4] = {
4070 { .fniv = gen_ushl_vec,
4071 .fno = gen_helper_gvec_ushl_b,
4072 .opt_opc = vecop_list,
4073 .vece = MO_8 },
4074 { .fniv = gen_ushl_vec,
4075 .fno = gen_helper_gvec_ushl_h,
4076 .opt_opc = vecop_list,
4077 .vece = MO_16 },
4078 { .fni4 = gen_ushl_i32,
4079 .fniv = gen_ushl_vec,
4080 .opt_opc = vecop_list,
4081 .vece = MO_32 },
4082 { .fni8 = gen_ushl_i64,
4083 .fniv = gen_ushl_vec,
4084 .opt_opc = vecop_list,
4085 .vece = MO_64 },
4087 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4090 void gen_sshl_i32(TCGv_i32 dst, TCGv_i32 src, TCGv_i32 shift)
4092 TCGv_i32 lval = tcg_temp_new_i32();
4093 TCGv_i32 rval = tcg_temp_new_i32();
4094 TCGv_i32 lsh = tcg_temp_new_i32();
4095 TCGv_i32 rsh = tcg_temp_new_i32();
4096 TCGv_i32 zero = tcg_const_i32(0);
4097 TCGv_i32 max = tcg_const_i32(31);
4100 * Rely on the TCG guarantee that out of range shifts produce
4101 * unspecified results, not undefined behaviour (i.e. no trap).
4102 * Discard out-of-range results after the fact.
4104 tcg_gen_ext8s_i32(lsh, shift);
4105 tcg_gen_neg_i32(rsh, lsh);
4106 tcg_gen_shl_i32(lval, src, lsh);
4107 tcg_gen_umin_i32(rsh, rsh, max);
4108 tcg_gen_sar_i32(rval, src, rsh);
4109 tcg_gen_movcond_i32(TCG_COND_LEU, lval, lsh, max, lval, zero);
4110 tcg_gen_movcond_i32(TCG_COND_LT, dst, lsh, zero, rval, lval);
4112 tcg_temp_free_i32(lval);
4113 tcg_temp_free_i32(rval);
4114 tcg_temp_free_i32(lsh);
4115 tcg_temp_free_i32(rsh);
4116 tcg_temp_free_i32(zero);
4117 tcg_temp_free_i32(max);
4120 void gen_sshl_i64(TCGv_i64 dst, TCGv_i64 src, TCGv_i64 shift)
4122 TCGv_i64 lval = tcg_temp_new_i64();
4123 TCGv_i64 rval = tcg_temp_new_i64();
4124 TCGv_i64 lsh = tcg_temp_new_i64();
4125 TCGv_i64 rsh = tcg_temp_new_i64();
4126 TCGv_i64 zero = tcg_const_i64(0);
4127 TCGv_i64 max = tcg_const_i64(63);
4130 * Rely on the TCG guarantee that out of range shifts produce
4131 * unspecified results, not undefined behaviour (i.e. no trap).
4132 * Discard out-of-range results after the fact.
4134 tcg_gen_ext8s_i64(lsh, shift);
4135 tcg_gen_neg_i64(rsh, lsh);
4136 tcg_gen_shl_i64(lval, src, lsh);
4137 tcg_gen_umin_i64(rsh, rsh, max);
4138 tcg_gen_sar_i64(rval, src, rsh);
4139 tcg_gen_movcond_i64(TCG_COND_LEU, lval, lsh, max, lval, zero);
4140 tcg_gen_movcond_i64(TCG_COND_LT, dst, lsh, zero, rval, lval);
4142 tcg_temp_free_i64(lval);
4143 tcg_temp_free_i64(rval);
4144 tcg_temp_free_i64(lsh);
4145 tcg_temp_free_i64(rsh);
4146 tcg_temp_free_i64(zero);
4147 tcg_temp_free_i64(max);
4150 static void gen_sshl_vec(unsigned vece, TCGv_vec dst,
4151 TCGv_vec src, TCGv_vec shift)
4153 TCGv_vec lval = tcg_temp_new_vec_matching(dst);
4154 TCGv_vec rval = tcg_temp_new_vec_matching(dst);
4155 TCGv_vec lsh = tcg_temp_new_vec_matching(dst);
4156 TCGv_vec rsh = tcg_temp_new_vec_matching(dst);
4157 TCGv_vec tmp = tcg_temp_new_vec_matching(dst);
4160 * Rely on the TCG guarantee that out of range shifts produce
4161 * unspecified results, not undefined behaviour (i.e. no trap).
4162 * Discard out-of-range results after the fact.
4164 tcg_gen_neg_vec(vece, rsh, shift);
4165 if (vece == MO_8) {
4166 tcg_gen_mov_vec(lsh, shift);
4167 } else {
4168 tcg_gen_dupi_vec(vece, tmp, 0xff);
4169 tcg_gen_and_vec(vece, lsh, shift, tmp);
4170 tcg_gen_and_vec(vece, rsh, rsh, tmp);
4173 /* Bound rsh so out of bound right shift gets -1. */
4174 tcg_gen_dupi_vec(vece, tmp, (8 << vece) - 1);
4175 tcg_gen_umin_vec(vece, rsh, rsh, tmp);
4176 tcg_gen_cmp_vec(TCG_COND_GT, vece, tmp, lsh, tmp);
4178 tcg_gen_shlv_vec(vece, lval, src, lsh);
4179 tcg_gen_sarv_vec(vece, rval, src, rsh);
4181 /* Select in-bound left shift. */
4182 tcg_gen_andc_vec(vece, lval, lval, tmp);
4184 /* Select between left and right shift. */
4185 if (vece == MO_8) {
4186 tcg_gen_dupi_vec(vece, tmp, 0);
4187 tcg_gen_cmpsel_vec(TCG_COND_LT, vece, dst, lsh, tmp, rval, lval);
4188 } else {
4189 tcg_gen_dupi_vec(vece, tmp, 0x80);
4190 tcg_gen_cmpsel_vec(TCG_COND_LT, vece, dst, lsh, tmp, lval, rval);
4193 tcg_temp_free_vec(lval);
4194 tcg_temp_free_vec(rval);
4195 tcg_temp_free_vec(lsh);
4196 tcg_temp_free_vec(rsh);
4197 tcg_temp_free_vec(tmp);
4200 void gen_gvec_sshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4201 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4203 static const TCGOpcode vecop_list[] = {
4204 INDEX_op_neg_vec, INDEX_op_umin_vec, INDEX_op_shlv_vec,
4205 INDEX_op_sarv_vec, INDEX_op_cmp_vec, INDEX_op_cmpsel_vec, 0
4207 static const GVecGen3 ops[4] = {
4208 { .fniv = gen_sshl_vec,
4209 .fno = gen_helper_gvec_sshl_b,
4210 .opt_opc = vecop_list,
4211 .vece = MO_8 },
4212 { .fniv = gen_sshl_vec,
4213 .fno = gen_helper_gvec_sshl_h,
4214 .opt_opc = vecop_list,
4215 .vece = MO_16 },
4216 { .fni4 = gen_sshl_i32,
4217 .fniv = gen_sshl_vec,
4218 .opt_opc = vecop_list,
4219 .vece = MO_32 },
4220 { .fni8 = gen_sshl_i64,
4221 .fniv = gen_sshl_vec,
4222 .opt_opc = vecop_list,
4223 .vece = MO_64 },
4225 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4228 static void gen_uqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4229 TCGv_vec a, TCGv_vec b)
4231 TCGv_vec x = tcg_temp_new_vec_matching(t);
4232 tcg_gen_add_vec(vece, x, a, b);
4233 tcg_gen_usadd_vec(vece, t, a, b);
4234 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4235 tcg_gen_or_vec(vece, sat, sat, x);
4236 tcg_temp_free_vec(x);
4239 void gen_gvec_uqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4240 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4242 static const TCGOpcode vecop_list[] = {
4243 INDEX_op_usadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
4245 static const GVecGen4 ops[4] = {
4246 { .fniv = gen_uqadd_vec,
4247 .fno = gen_helper_gvec_uqadd_b,
4248 .write_aofs = true,
4249 .opt_opc = vecop_list,
4250 .vece = MO_8 },
4251 { .fniv = gen_uqadd_vec,
4252 .fno = gen_helper_gvec_uqadd_h,
4253 .write_aofs = true,
4254 .opt_opc = vecop_list,
4255 .vece = MO_16 },
4256 { .fniv = gen_uqadd_vec,
4257 .fno = gen_helper_gvec_uqadd_s,
4258 .write_aofs = true,
4259 .opt_opc = vecop_list,
4260 .vece = MO_32 },
4261 { .fniv = gen_uqadd_vec,
4262 .fno = gen_helper_gvec_uqadd_d,
4263 .write_aofs = true,
4264 .opt_opc = vecop_list,
4265 .vece = MO_64 },
4267 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
4268 rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4271 static void gen_sqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4272 TCGv_vec a, TCGv_vec b)
4274 TCGv_vec x = tcg_temp_new_vec_matching(t);
4275 tcg_gen_add_vec(vece, x, a, b);
4276 tcg_gen_ssadd_vec(vece, t, a, b);
4277 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4278 tcg_gen_or_vec(vece, sat, sat, x);
4279 tcg_temp_free_vec(x);
4282 void gen_gvec_sqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4283 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4285 static const TCGOpcode vecop_list[] = {
4286 INDEX_op_ssadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
4288 static const GVecGen4 ops[4] = {
4289 { .fniv = gen_sqadd_vec,
4290 .fno = gen_helper_gvec_sqadd_b,
4291 .opt_opc = vecop_list,
4292 .write_aofs = true,
4293 .vece = MO_8 },
4294 { .fniv = gen_sqadd_vec,
4295 .fno = gen_helper_gvec_sqadd_h,
4296 .opt_opc = vecop_list,
4297 .write_aofs = true,
4298 .vece = MO_16 },
4299 { .fniv = gen_sqadd_vec,
4300 .fno = gen_helper_gvec_sqadd_s,
4301 .opt_opc = vecop_list,
4302 .write_aofs = true,
4303 .vece = MO_32 },
4304 { .fniv = gen_sqadd_vec,
4305 .fno = gen_helper_gvec_sqadd_d,
4306 .opt_opc = vecop_list,
4307 .write_aofs = true,
4308 .vece = MO_64 },
4310 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
4311 rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4314 static void gen_uqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4315 TCGv_vec a, TCGv_vec b)
4317 TCGv_vec x = tcg_temp_new_vec_matching(t);
4318 tcg_gen_sub_vec(vece, x, a, b);
4319 tcg_gen_ussub_vec(vece, t, a, b);
4320 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4321 tcg_gen_or_vec(vece, sat, sat, x);
4322 tcg_temp_free_vec(x);
4325 void gen_gvec_uqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4326 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4328 static const TCGOpcode vecop_list[] = {
4329 INDEX_op_ussub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
4331 static const GVecGen4 ops[4] = {
4332 { .fniv = gen_uqsub_vec,
4333 .fno = gen_helper_gvec_uqsub_b,
4334 .opt_opc = vecop_list,
4335 .write_aofs = true,
4336 .vece = MO_8 },
4337 { .fniv = gen_uqsub_vec,
4338 .fno = gen_helper_gvec_uqsub_h,
4339 .opt_opc = vecop_list,
4340 .write_aofs = true,
4341 .vece = MO_16 },
4342 { .fniv = gen_uqsub_vec,
4343 .fno = gen_helper_gvec_uqsub_s,
4344 .opt_opc = vecop_list,
4345 .write_aofs = true,
4346 .vece = MO_32 },
4347 { .fniv = gen_uqsub_vec,
4348 .fno = gen_helper_gvec_uqsub_d,
4349 .opt_opc = vecop_list,
4350 .write_aofs = true,
4351 .vece = MO_64 },
4353 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
4354 rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4357 static void gen_sqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4358 TCGv_vec a, TCGv_vec b)
4360 TCGv_vec x = tcg_temp_new_vec_matching(t);
4361 tcg_gen_sub_vec(vece, x, a, b);
4362 tcg_gen_sssub_vec(vece, t, a, b);
4363 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4364 tcg_gen_or_vec(vece, sat, sat, x);
4365 tcg_temp_free_vec(x);
4368 void gen_gvec_sqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4369 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4371 static const TCGOpcode vecop_list[] = {
4372 INDEX_op_sssub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
4374 static const GVecGen4 ops[4] = {
4375 { .fniv = gen_sqsub_vec,
4376 .fno = gen_helper_gvec_sqsub_b,
4377 .opt_opc = vecop_list,
4378 .write_aofs = true,
4379 .vece = MO_8 },
4380 { .fniv = gen_sqsub_vec,
4381 .fno = gen_helper_gvec_sqsub_h,
4382 .opt_opc = vecop_list,
4383 .write_aofs = true,
4384 .vece = MO_16 },
4385 { .fniv = gen_sqsub_vec,
4386 .fno = gen_helper_gvec_sqsub_s,
4387 .opt_opc = vecop_list,
4388 .write_aofs = true,
4389 .vece = MO_32 },
4390 { .fniv = gen_sqsub_vec,
4391 .fno = gen_helper_gvec_sqsub_d,
4392 .opt_opc = vecop_list,
4393 .write_aofs = true,
4394 .vece = MO_64 },
4396 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
4397 rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4400 static void gen_sabd_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4402 TCGv_i32 t = tcg_temp_new_i32();
4404 tcg_gen_sub_i32(t, a, b);
4405 tcg_gen_sub_i32(d, b, a);
4406 tcg_gen_movcond_i32(TCG_COND_LT, d, a, b, d, t);
4407 tcg_temp_free_i32(t);
4410 static void gen_sabd_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4412 TCGv_i64 t = tcg_temp_new_i64();
4414 tcg_gen_sub_i64(t, a, b);
4415 tcg_gen_sub_i64(d, b, a);
4416 tcg_gen_movcond_i64(TCG_COND_LT, d, a, b, d, t);
4417 tcg_temp_free_i64(t);
4420 static void gen_sabd_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4422 TCGv_vec t = tcg_temp_new_vec_matching(d);
4424 tcg_gen_smin_vec(vece, t, a, b);
4425 tcg_gen_smax_vec(vece, d, a, b);
4426 tcg_gen_sub_vec(vece, d, d, t);
4427 tcg_temp_free_vec(t);
4430 void gen_gvec_sabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4431 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4433 static const TCGOpcode vecop_list[] = {
4434 INDEX_op_sub_vec, INDEX_op_smin_vec, INDEX_op_smax_vec, 0
4436 static const GVecGen3 ops[4] = {
4437 { .fniv = gen_sabd_vec,
4438 .fno = gen_helper_gvec_sabd_b,
4439 .opt_opc = vecop_list,
4440 .vece = MO_8 },
4441 { .fniv = gen_sabd_vec,
4442 .fno = gen_helper_gvec_sabd_h,
4443 .opt_opc = vecop_list,
4444 .vece = MO_16 },
4445 { .fni4 = gen_sabd_i32,
4446 .fniv = gen_sabd_vec,
4447 .fno = gen_helper_gvec_sabd_s,
4448 .opt_opc = vecop_list,
4449 .vece = MO_32 },
4450 { .fni8 = gen_sabd_i64,
4451 .fniv = gen_sabd_vec,
4452 .fno = gen_helper_gvec_sabd_d,
4453 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4454 .opt_opc = vecop_list,
4455 .vece = MO_64 },
4457 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4460 static void gen_uabd_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4462 TCGv_i32 t = tcg_temp_new_i32();
4464 tcg_gen_sub_i32(t, a, b);
4465 tcg_gen_sub_i32(d, b, a);
4466 tcg_gen_movcond_i32(TCG_COND_LTU, d, a, b, d, t);
4467 tcg_temp_free_i32(t);
4470 static void gen_uabd_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4472 TCGv_i64 t = tcg_temp_new_i64();
4474 tcg_gen_sub_i64(t, a, b);
4475 tcg_gen_sub_i64(d, b, a);
4476 tcg_gen_movcond_i64(TCG_COND_LTU, d, a, b, d, t);
4477 tcg_temp_free_i64(t);
4480 static void gen_uabd_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4482 TCGv_vec t = tcg_temp_new_vec_matching(d);
4484 tcg_gen_umin_vec(vece, t, a, b);
4485 tcg_gen_umax_vec(vece, d, a, b);
4486 tcg_gen_sub_vec(vece, d, d, t);
4487 tcg_temp_free_vec(t);
4490 void gen_gvec_uabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4491 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4493 static const TCGOpcode vecop_list[] = {
4494 INDEX_op_sub_vec, INDEX_op_umin_vec, INDEX_op_umax_vec, 0
4496 static const GVecGen3 ops[4] = {
4497 { .fniv = gen_uabd_vec,
4498 .fno = gen_helper_gvec_uabd_b,
4499 .opt_opc = vecop_list,
4500 .vece = MO_8 },
4501 { .fniv = gen_uabd_vec,
4502 .fno = gen_helper_gvec_uabd_h,
4503 .opt_opc = vecop_list,
4504 .vece = MO_16 },
4505 { .fni4 = gen_uabd_i32,
4506 .fniv = gen_uabd_vec,
4507 .fno = gen_helper_gvec_uabd_s,
4508 .opt_opc = vecop_list,
4509 .vece = MO_32 },
4510 { .fni8 = gen_uabd_i64,
4511 .fniv = gen_uabd_vec,
4512 .fno = gen_helper_gvec_uabd_d,
4513 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4514 .opt_opc = vecop_list,
4515 .vece = MO_64 },
4517 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4520 static void gen_saba_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4522 TCGv_i32 t = tcg_temp_new_i32();
4523 gen_sabd_i32(t, a, b);
4524 tcg_gen_add_i32(d, d, t);
4525 tcg_temp_free_i32(t);
4528 static void gen_saba_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4530 TCGv_i64 t = tcg_temp_new_i64();
4531 gen_sabd_i64(t, a, b);
4532 tcg_gen_add_i64(d, d, t);
4533 tcg_temp_free_i64(t);
4536 static void gen_saba_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4538 TCGv_vec t = tcg_temp_new_vec_matching(d);
4539 gen_sabd_vec(vece, t, a, b);
4540 tcg_gen_add_vec(vece, d, d, t);
4541 tcg_temp_free_vec(t);
4544 void gen_gvec_saba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4545 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4547 static const TCGOpcode vecop_list[] = {
4548 INDEX_op_sub_vec, INDEX_op_add_vec,
4549 INDEX_op_smin_vec, INDEX_op_smax_vec, 0
4551 static const GVecGen3 ops[4] = {
4552 { .fniv = gen_saba_vec,
4553 .fno = gen_helper_gvec_saba_b,
4554 .opt_opc = vecop_list,
4555 .load_dest = true,
4556 .vece = MO_8 },
4557 { .fniv = gen_saba_vec,
4558 .fno = gen_helper_gvec_saba_h,
4559 .opt_opc = vecop_list,
4560 .load_dest = true,
4561 .vece = MO_16 },
4562 { .fni4 = gen_saba_i32,
4563 .fniv = gen_saba_vec,
4564 .fno = gen_helper_gvec_saba_s,
4565 .opt_opc = vecop_list,
4566 .load_dest = true,
4567 .vece = MO_32 },
4568 { .fni8 = gen_saba_i64,
4569 .fniv = gen_saba_vec,
4570 .fno = gen_helper_gvec_saba_d,
4571 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4572 .opt_opc = vecop_list,
4573 .load_dest = true,
4574 .vece = MO_64 },
4576 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4579 static void gen_uaba_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4581 TCGv_i32 t = tcg_temp_new_i32();
4582 gen_uabd_i32(t, a, b);
4583 tcg_gen_add_i32(d, d, t);
4584 tcg_temp_free_i32(t);
4587 static void gen_uaba_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4589 TCGv_i64 t = tcg_temp_new_i64();
4590 gen_uabd_i64(t, a, b);
4591 tcg_gen_add_i64(d, d, t);
4592 tcg_temp_free_i64(t);
4595 static void gen_uaba_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4597 TCGv_vec t = tcg_temp_new_vec_matching(d);
4598 gen_uabd_vec(vece, t, a, b);
4599 tcg_gen_add_vec(vece, d, d, t);
4600 tcg_temp_free_vec(t);
4603 void gen_gvec_uaba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4604 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4606 static const TCGOpcode vecop_list[] = {
4607 INDEX_op_sub_vec, INDEX_op_add_vec,
4608 INDEX_op_umin_vec, INDEX_op_umax_vec, 0
4610 static const GVecGen3 ops[4] = {
4611 { .fniv = gen_uaba_vec,
4612 .fno = gen_helper_gvec_uaba_b,
4613 .opt_opc = vecop_list,
4614 .load_dest = true,
4615 .vece = MO_8 },
4616 { .fniv = gen_uaba_vec,
4617 .fno = gen_helper_gvec_uaba_h,
4618 .opt_opc = vecop_list,
4619 .load_dest = true,
4620 .vece = MO_16 },
4621 { .fni4 = gen_uaba_i32,
4622 .fniv = gen_uaba_vec,
4623 .fno = gen_helper_gvec_uaba_s,
4624 .opt_opc = vecop_list,
4625 .load_dest = true,
4626 .vece = MO_32 },
4627 { .fni8 = gen_uaba_i64,
4628 .fniv = gen_uaba_vec,
4629 .fno = gen_helper_gvec_uaba_d,
4630 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4631 .opt_opc = vecop_list,
4632 .load_dest = true,
4633 .vece = MO_64 },
4635 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4638 static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
4639 int opc1, int crn, int crm, int opc2,
4640 bool isread, int rt, int rt2)
4642 const ARMCPRegInfo *ri;
4644 ri = get_arm_cp_reginfo(s->cp_regs,
4645 ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2));
4646 if (ri) {
4647 bool need_exit_tb;
4649 /* Check access permissions */
4650 if (!cp_access_ok(s->current_el, ri, isread)) {
4651 unallocated_encoding(s);
4652 return;
4655 if (s->hstr_active || ri->accessfn ||
4656 (arm_dc_feature(s, ARM_FEATURE_XSCALE) && cpnum < 14)) {
4657 /* Emit code to perform further access permissions checks at
4658 * runtime; this may result in an exception.
4659 * Note that on XScale all cp0..c13 registers do an access check
4660 * call in order to handle c15_cpar.
4662 TCGv_ptr tmpptr;
4663 TCGv_i32 tcg_syn, tcg_isread;
4664 uint32_t syndrome;
4666 /* Note that since we are an implementation which takes an
4667 * exception on a trapped conditional instruction only if the
4668 * instruction passes its condition code check, we can take
4669 * advantage of the clause in the ARM ARM that allows us to set
4670 * the COND field in the instruction to 0xE in all cases.
4671 * We could fish the actual condition out of the insn (ARM)
4672 * or the condexec bits (Thumb) but it isn't necessary.
4674 switch (cpnum) {
4675 case 14:
4676 if (is64) {
4677 syndrome = syn_cp14_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
4678 isread, false);
4679 } else {
4680 syndrome = syn_cp14_rt_trap(1, 0xe, opc1, opc2, crn, crm,
4681 rt, isread, false);
4683 break;
4684 case 15:
4685 if (is64) {
4686 syndrome = syn_cp15_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
4687 isread, false);
4688 } else {
4689 syndrome = syn_cp15_rt_trap(1, 0xe, opc1, opc2, crn, crm,
4690 rt, isread, false);
4692 break;
4693 default:
4694 /* ARMv8 defines that only coprocessors 14 and 15 exist,
4695 * so this can only happen if this is an ARMv7 or earlier CPU,
4696 * in which case the syndrome information won't actually be
4697 * guest visible.
4699 assert(!arm_dc_feature(s, ARM_FEATURE_V8));
4700 syndrome = syn_uncategorized();
4701 break;
4704 gen_set_condexec(s);
4705 gen_set_pc_im(s, s->pc_curr);
4706 tmpptr = tcg_const_ptr(ri);
4707 tcg_syn = tcg_const_i32(syndrome);
4708 tcg_isread = tcg_const_i32(isread);
4709 gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn,
4710 tcg_isread);
4711 tcg_temp_free_ptr(tmpptr);
4712 tcg_temp_free_i32(tcg_syn);
4713 tcg_temp_free_i32(tcg_isread);
4714 } else if (ri->type & ARM_CP_RAISES_EXC) {
4716 * The readfn or writefn might raise an exception;
4717 * synchronize the CPU state in case it does.
4719 gen_set_condexec(s);
4720 gen_set_pc_im(s, s->pc_curr);
4723 /* Handle special cases first */
4724 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
4725 case ARM_CP_NOP:
4726 return;
4727 case ARM_CP_WFI:
4728 if (isread) {
4729 unallocated_encoding(s);
4730 return;
4732 gen_set_pc_im(s, s->base.pc_next);
4733 s->base.is_jmp = DISAS_WFI;
4734 return;
4735 default:
4736 break;
4739 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
4740 gen_io_start();
4743 if (isread) {
4744 /* Read */
4745 if (is64) {
4746 TCGv_i64 tmp64;
4747 TCGv_i32 tmp;
4748 if (ri->type & ARM_CP_CONST) {
4749 tmp64 = tcg_const_i64(ri->resetvalue);
4750 } else if (ri->readfn) {
4751 TCGv_ptr tmpptr;
4752 tmp64 = tcg_temp_new_i64();
4753 tmpptr = tcg_const_ptr(ri);
4754 gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr);
4755 tcg_temp_free_ptr(tmpptr);
4756 } else {
4757 tmp64 = tcg_temp_new_i64();
4758 tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
4760 tmp = tcg_temp_new_i32();
4761 tcg_gen_extrl_i64_i32(tmp, tmp64);
4762 store_reg(s, rt, tmp);
4763 tmp = tcg_temp_new_i32();
4764 tcg_gen_extrh_i64_i32(tmp, tmp64);
4765 tcg_temp_free_i64(tmp64);
4766 store_reg(s, rt2, tmp);
4767 } else {
4768 TCGv_i32 tmp;
4769 if (ri->type & ARM_CP_CONST) {
4770 tmp = tcg_const_i32(ri->resetvalue);
4771 } else if (ri->readfn) {
4772 TCGv_ptr tmpptr;
4773 tmp = tcg_temp_new_i32();
4774 tmpptr = tcg_const_ptr(ri);
4775 gen_helper_get_cp_reg(tmp, cpu_env, tmpptr);
4776 tcg_temp_free_ptr(tmpptr);
4777 } else {
4778 tmp = load_cpu_offset(ri->fieldoffset);
4780 if (rt == 15) {
4781 /* Destination register of r15 for 32 bit loads sets
4782 * the condition codes from the high 4 bits of the value
4784 gen_set_nzcv(tmp);
4785 tcg_temp_free_i32(tmp);
4786 } else {
4787 store_reg(s, rt, tmp);
4790 } else {
4791 /* Write */
4792 if (ri->type & ARM_CP_CONST) {
4793 /* If not forbidden by access permissions, treat as WI */
4794 return;
4797 if (is64) {
4798 TCGv_i32 tmplo, tmphi;
4799 TCGv_i64 tmp64 = tcg_temp_new_i64();
4800 tmplo = load_reg(s, rt);
4801 tmphi = load_reg(s, rt2);
4802 tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
4803 tcg_temp_free_i32(tmplo);
4804 tcg_temp_free_i32(tmphi);
4805 if (ri->writefn) {
4806 TCGv_ptr tmpptr = tcg_const_ptr(ri);
4807 gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64);
4808 tcg_temp_free_ptr(tmpptr);
4809 } else {
4810 tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
4812 tcg_temp_free_i64(tmp64);
4813 } else {
4814 if (ri->writefn) {
4815 TCGv_i32 tmp;
4816 TCGv_ptr tmpptr;
4817 tmp = load_reg(s, rt);
4818 tmpptr = tcg_const_ptr(ri);
4819 gen_helper_set_cp_reg(cpu_env, tmpptr, tmp);
4820 tcg_temp_free_ptr(tmpptr);
4821 tcg_temp_free_i32(tmp);
4822 } else {
4823 TCGv_i32 tmp = load_reg(s, rt);
4824 store_cpu_offset(tmp, ri->fieldoffset);
4829 /* I/O operations must end the TB here (whether read or write) */
4830 need_exit_tb = ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) &&
4831 (ri->type & ARM_CP_IO));
4833 if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
4835 * A write to any coprocessor register that ends a TB
4836 * must rebuild the hflags for the next TB.
4838 TCGv_i32 tcg_el = tcg_const_i32(s->current_el);
4839 if (arm_dc_feature(s, ARM_FEATURE_M)) {
4840 gen_helper_rebuild_hflags_m32(cpu_env, tcg_el);
4841 } else {
4842 if (ri->type & ARM_CP_NEWEL) {
4843 gen_helper_rebuild_hflags_a32_newel(cpu_env);
4844 } else {
4845 gen_helper_rebuild_hflags_a32(cpu_env, tcg_el);
4848 tcg_temp_free_i32(tcg_el);
4850 * We default to ending the TB on a coprocessor register write,
4851 * but allow this to be suppressed by the register definition
4852 * (usually only necessary to work around guest bugs).
4854 need_exit_tb = true;
4856 if (need_exit_tb) {
4857 gen_lookup_tb(s);
4860 return;
4863 /* Unknown register; this might be a guest error or a QEMU
4864 * unimplemented feature.
4866 if (is64) {
4867 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
4868 "64 bit system register cp:%d opc1: %d crm:%d "
4869 "(%s)\n",
4870 isread ? "read" : "write", cpnum, opc1, crm,
4871 s->ns ? "non-secure" : "secure");
4872 } else {
4873 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
4874 "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d "
4875 "(%s)\n",
4876 isread ? "read" : "write", cpnum, opc1, crn, crm, opc2,
4877 s->ns ? "non-secure" : "secure");
4880 unallocated_encoding(s);
4881 return;
4884 /* Decode XScale DSP or iWMMXt insn (in the copro space, cp=0 or 1) */
4885 static void disas_xscale_insn(DisasContext *s, uint32_t insn)
4887 int cpnum = (insn >> 8) & 0xf;
4889 if (extract32(s->c15_cpar, cpnum, 1) == 0) {
4890 unallocated_encoding(s);
4891 } else if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
4892 if (disas_iwmmxt_insn(s, insn)) {
4893 unallocated_encoding(s);
4895 } else if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) {
4896 if (disas_dsp_insn(s, insn)) {
4897 unallocated_encoding(s);
4902 /* Store a 64-bit value to a register pair. Clobbers val. */
4903 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
4905 TCGv_i32 tmp;
4906 tmp = tcg_temp_new_i32();
4907 tcg_gen_extrl_i64_i32(tmp, val);
4908 store_reg(s, rlow, tmp);
4909 tmp = tcg_temp_new_i32();
4910 tcg_gen_extrh_i64_i32(tmp, val);
4911 store_reg(s, rhigh, tmp);
4914 /* load and add a 64-bit value from a register pair. */
4915 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
4917 TCGv_i64 tmp;
4918 TCGv_i32 tmpl;
4919 TCGv_i32 tmph;
4921 /* Load 64-bit value rd:rn. */
4922 tmpl = load_reg(s, rlow);
4923 tmph = load_reg(s, rhigh);
4924 tmp = tcg_temp_new_i64();
4925 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
4926 tcg_temp_free_i32(tmpl);
4927 tcg_temp_free_i32(tmph);
4928 tcg_gen_add_i64(val, val, tmp);
4929 tcg_temp_free_i64(tmp);
4932 /* Set N and Z flags from hi|lo. */
4933 static void gen_logicq_cc(TCGv_i32 lo, TCGv_i32 hi)
4935 tcg_gen_mov_i32(cpu_NF, hi);
4936 tcg_gen_or_i32(cpu_ZF, lo, hi);
4939 /* Load/Store exclusive instructions are implemented by remembering
4940 the value/address loaded, and seeing if these are the same
4941 when the store is performed. This should be sufficient to implement
4942 the architecturally mandated semantics, and avoids having to monitor
4943 regular stores. The compare vs the remembered value is done during
4944 the cmpxchg operation, but we must compare the addresses manually. */
4945 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
4946 TCGv_i32 addr, int size)
4948 TCGv_i32 tmp = tcg_temp_new_i32();
4949 MemOp opc = size | MO_ALIGN | s->be_data;
4951 s->is_ldex = true;
4953 if (size == 3) {
4954 TCGv_i32 tmp2 = tcg_temp_new_i32();
4955 TCGv_i64 t64 = tcg_temp_new_i64();
4957 /* For AArch32, architecturally the 32-bit word at the lowest
4958 * address is always Rt and the one at addr+4 is Rt2, even if
4959 * the CPU is big-endian. That means we don't want to do a
4960 * gen_aa32_ld_i64(), which invokes gen_aa32_frob64() as if
4961 * for an architecturally 64-bit access, but instead do a
4962 * 64-bit access using MO_BE if appropriate and then split
4963 * the two halves.
4964 * This only makes a difference for BE32 user-mode, where
4965 * frob64() must not flip the two halves of the 64-bit data
4966 * but this code must treat BE32 user-mode like BE32 system.
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);
5026 /* For AArch32, architecturally the 32-bit word at the lowest
5027 * address is always Rt and the one at addr+4 is Rt2, even if
5028 * the CPU is big-endian. Since we're going to treat this as a
5029 * single 64-bit BE store, we need to put the two halves in the
5030 * opposite order for BE to LE, so that they end up in the right
5031 * places.
5032 * We don't want gen_aa32_frob64() because that does the wrong
5033 * thing for BE32 usermode.
5035 if (s->be_data == MO_BE) {
5036 tcg_gen_concat_i32_i64(n64, t2, t1);
5037 } else {
5038 tcg_gen_concat_i32_i64(n64, t1, t2);
5040 tcg_temp_free_i32(t2);
5042 tcg_gen_atomic_cmpxchg_i64(o64, taddr, cpu_exclusive_val, n64,
5043 get_mem_index(s), opc);
5044 tcg_temp_free_i64(n64);
5046 tcg_gen_setcond_i64(TCG_COND_NE, o64, o64, cpu_exclusive_val);
5047 tcg_gen_extrl_i64_i32(t0, o64);
5049 tcg_temp_free_i64(o64);
5050 } else {
5051 t2 = tcg_temp_new_i32();
5052 tcg_gen_extrl_i64_i32(t2, cpu_exclusive_val);
5053 tcg_gen_atomic_cmpxchg_i32(t0, taddr, t2, t1, get_mem_index(s), opc);
5054 tcg_gen_setcond_i32(TCG_COND_NE, t0, t0, t2);
5055 tcg_temp_free_i32(t2);
5057 tcg_temp_free_i32(t1);
5058 tcg_temp_free(taddr);
5059 tcg_gen_mov_i32(cpu_R[rd], t0);
5060 tcg_temp_free_i32(t0);
5061 tcg_gen_br(done_label);
5063 gen_set_label(fail_label);
5064 tcg_gen_movi_i32(cpu_R[rd], 1);
5065 gen_set_label(done_label);
5066 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
5069 /* gen_srs:
5070 * @env: CPUARMState
5071 * @s: DisasContext
5072 * @mode: mode field from insn (which stack to store to)
5073 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
5074 * @writeback: true if writeback bit set
5076 * Generate code for the SRS (Store Return State) insn.
5078 static void gen_srs(DisasContext *s,
5079 uint32_t mode, uint32_t amode, bool writeback)
5081 int32_t offset;
5082 TCGv_i32 addr, tmp;
5083 bool undef = false;
5085 /* SRS is:
5086 * - trapped to EL3 if EL3 is AArch64 and we are at Secure EL1
5087 * and specified mode is monitor mode
5088 * - UNDEFINED in Hyp mode
5089 * - UNPREDICTABLE in User or System mode
5090 * - UNPREDICTABLE if the specified mode is:
5091 * -- not implemented
5092 * -- not a valid mode number
5093 * -- a mode that's at a higher exception level
5094 * -- Monitor, if we are Non-secure
5095 * For the UNPREDICTABLE cases we choose to UNDEF.
5097 if (s->current_el == 1 && !s->ns && mode == ARM_CPU_MODE_MON) {
5098 gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(), 3);
5099 return;
5102 if (s->current_el == 0 || s->current_el == 2) {
5103 undef = true;
5106 switch (mode) {
5107 case ARM_CPU_MODE_USR:
5108 case ARM_CPU_MODE_FIQ:
5109 case ARM_CPU_MODE_IRQ:
5110 case ARM_CPU_MODE_SVC:
5111 case ARM_CPU_MODE_ABT:
5112 case ARM_CPU_MODE_UND:
5113 case ARM_CPU_MODE_SYS:
5114 break;
5115 case ARM_CPU_MODE_HYP:
5116 if (s->current_el == 1 || !arm_dc_feature(s, ARM_FEATURE_EL2)) {
5117 undef = true;
5119 break;
5120 case ARM_CPU_MODE_MON:
5121 /* No need to check specifically for "are we non-secure" because
5122 * we've already made EL0 UNDEF and handled the trap for S-EL1;
5123 * so if this isn't EL3 then we must be non-secure.
5125 if (s->current_el != 3) {
5126 undef = true;
5128 break;
5129 default:
5130 undef = true;
5133 if (undef) {
5134 unallocated_encoding(s);
5135 return;
5138 addr = tcg_temp_new_i32();
5139 tmp = tcg_const_i32(mode);
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, tmp);
5144 tcg_temp_free_i32(tmp);
5145 switch (amode) {
5146 case 0: /* DA */
5147 offset = -4;
5148 break;
5149 case 1: /* IA */
5150 offset = 0;
5151 break;
5152 case 2: /* DB */
5153 offset = -8;
5154 break;
5155 case 3: /* IB */
5156 offset = 4;
5157 break;
5158 default:
5159 abort();
5161 tcg_gen_addi_i32(addr, addr, offset);
5162 tmp = load_reg(s, 14);
5163 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5164 tcg_temp_free_i32(tmp);
5165 tmp = load_cpu_field(spsr);
5166 tcg_gen_addi_i32(addr, addr, 4);
5167 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5168 tcg_temp_free_i32(tmp);
5169 if (writeback) {
5170 switch (amode) {
5171 case 0:
5172 offset = -8;
5173 break;
5174 case 1:
5175 offset = 4;
5176 break;
5177 case 2:
5178 offset = -4;
5179 break;
5180 case 3:
5181 offset = 0;
5182 break;
5183 default:
5184 abort();
5186 tcg_gen_addi_i32(addr, addr, offset);
5187 tmp = tcg_const_i32(mode);
5188 gen_helper_set_r13_banked(cpu_env, tmp, addr);
5189 tcg_temp_free_i32(tmp);
5191 tcg_temp_free_i32(addr);
5192 s->base.is_jmp = DISAS_UPDATE_EXIT;
5195 /* Skip this instruction if the ARM condition is false */
5196 static void arm_skip_unless(DisasContext *s, uint32_t cond)
5198 arm_gen_condlabel(s);
5199 arm_gen_test_cc(cond ^ 1, s->condlabel);
5204 * Constant expanders used by T16/T32 decode
5207 /* Return only the rotation part of T32ExpandImm. */
5208 static int t32_expandimm_rot(DisasContext *s, int x)
5210 return x & 0xc00 ? extract32(x, 7, 5) : 0;
5213 /* Return the unrotated immediate from T32ExpandImm. */
5214 static int t32_expandimm_imm(DisasContext *s, int x)
5216 int imm = extract32(x, 0, 8);
5218 switch (extract32(x, 8, 4)) {
5219 case 0: /* XY */
5220 /* Nothing to do. */
5221 break;
5222 case 1: /* 00XY00XY */
5223 imm *= 0x00010001;
5224 break;
5225 case 2: /* XY00XY00 */
5226 imm *= 0x01000100;
5227 break;
5228 case 3: /* XYXYXYXY */
5229 imm *= 0x01010101;
5230 break;
5231 default:
5232 /* Rotated constant. */
5233 imm |= 0x80;
5234 break;
5236 return imm;
5239 static int t32_branch24(DisasContext *s, int x)
5241 /* Convert J1:J2 at x[22:21] to I2:I1, which involves I=J^~S. */
5242 x ^= !(x < 0) * (3 << 21);
5243 /* Append the final zero. */
5244 return x << 1;
5247 static int t16_setflags(DisasContext *s)
5249 return s->condexec_mask == 0;
5252 static int t16_push_list(DisasContext *s, int x)
5254 return (x & 0xff) | (x & 0x100) << (14 - 8);
5257 static int t16_pop_list(DisasContext *s, int x)
5259 return (x & 0xff) | (x & 0x100) << (15 - 8);
5263 * Include the generated decoders.
5266 #include "decode-a32.c.inc"
5267 #include "decode-a32-uncond.c.inc"
5268 #include "decode-t32.c.inc"
5269 #include "decode-t16.c.inc"
5271 static bool valid_cp(DisasContext *s, int cp)
5274 * Return true if this coprocessor field indicates something
5275 * that's really a possible coprocessor.
5276 * For v7 and earlier, coprocessors 8..15 were reserved for Arm use,
5277 * and of those only cp14 and cp15 were used for registers.
5278 * cp10 and cp11 were used for VFP and Neon, whose decode is
5279 * dealt with elsewhere. With the advent of fp16, cp9 is also
5280 * now part of VFP.
5281 * For v8A and later, the encoding has been tightened so that
5282 * only cp14 and cp15 are valid, and other values aren't considered
5283 * to be in the coprocessor-instruction space at all. v8M still
5284 * permits coprocessors 0..7.
5286 if (arm_dc_feature(s, ARM_FEATURE_V8) &&
5287 !arm_dc_feature(s, ARM_FEATURE_M)) {
5288 return cp >= 14;
5290 return cp < 8 || cp >= 14;
5293 static bool trans_MCR(DisasContext *s, arg_MCR *a)
5295 if (!valid_cp(s, a->cp)) {
5296 return false;
5298 do_coproc_insn(s, a->cp, false, a->opc1, a->crn, a->crm, a->opc2,
5299 false, a->rt, 0);
5300 return true;
5303 static bool trans_MRC(DisasContext *s, arg_MRC *a)
5305 if (!valid_cp(s, a->cp)) {
5306 return false;
5308 do_coproc_insn(s, a->cp, false, a->opc1, a->crn, a->crm, a->opc2,
5309 true, a->rt, 0);
5310 return true;
5313 static bool trans_MCRR(DisasContext *s, arg_MCRR *a)
5315 if (!valid_cp(s, a->cp)) {
5316 return false;
5318 do_coproc_insn(s, a->cp, true, a->opc1, 0, a->crm, 0,
5319 false, a->rt, a->rt2);
5320 return true;
5323 static bool trans_MRRC(DisasContext *s, arg_MRRC *a)
5325 if (!valid_cp(s, a->cp)) {
5326 return false;
5328 do_coproc_insn(s, a->cp, true, a->opc1, 0, a->crm, 0,
5329 true, a->rt, a->rt2);
5330 return true;
5333 /* Helpers to swap operands for reverse-subtract. */
5334 static void gen_rsb(TCGv_i32 dst, TCGv_i32 a, TCGv_i32 b)
5336 tcg_gen_sub_i32(dst, b, a);
5339 static void gen_rsb_CC(TCGv_i32 dst, TCGv_i32 a, TCGv_i32 b)
5341 gen_sub_CC(dst, b, a);
5344 static void gen_rsc(TCGv_i32 dest, TCGv_i32 a, TCGv_i32 b)
5346 gen_sub_carry(dest, b, a);
5349 static void gen_rsc_CC(TCGv_i32 dest, TCGv_i32 a, TCGv_i32 b)
5351 gen_sbc_CC(dest, b, a);
5355 * Helpers for the data processing routines.
5357 * After the computation store the results back.
5358 * This may be suppressed altogether (STREG_NONE), require a runtime
5359 * check against the stack limits (STREG_SP_CHECK), or generate an
5360 * exception return. Oh, or store into a register.
5362 * Always return true, indicating success for a trans_* function.
5364 typedef enum {
5365 STREG_NONE,
5366 STREG_NORMAL,
5367 STREG_SP_CHECK,
5368 STREG_EXC_RET,
5369 } StoreRegKind;
5371 static bool store_reg_kind(DisasContext *s, int rd,
5372 TCGv_i32 val, StoreRegKind kind)
5374 switch (kind) {
5375 case STREG_NONE:
5376 tcg_temp_free_i32(val);
5377 return true;
5378 case STREG_NORMAL:
5379 /* See ALUWritePC: Interworking only from a32 mode. */
5380 if (s->thumb) {
5381 store_reg(s, rd, val);
5382 } else {
5383 store_reg_bx(s, rd, val);
5385 return true;
5386 case STREG_SP_CHECK:
5387 store_sp_checked(s, val);
5388 return true;
5389 case STREG_EXC_RET:
5390 gen_exception_return(s, val);
5391 return true;
5393 g_assert_not_reached();
5397 * Data Processing (register)
5399 * Operate, with set flags, one register source,
5400 * one immediate shifted register source, and a destination.
5402 static bool op_s_rrr_shi(DisasContext *s, arg_s_rrr_shi *a,
5403 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32),
5404 int logic_cc, StoreRegKind kind)
5406 TCGv_i32 tmp1, tmp2;
5408 tmp2 = load_reg(s, a->rm);
5409 gen_arm_shift_im(tmp2, a->shty, a->shim, logic_cc);
5410 tmp1 = load_reg(s, a->rn);
5412 gen(tmp1, tmp1, tmp2);
5413 tcg_temp_free_i32(tmp2);
5415 if (logic_cc) {
5416 gen_logic_CC(tmp1);
5418 return store_reg_kind(s, a->rd, tmp1, kind);
5421 static bool op_s_rxr_shi(DisasContext *s, arg_s_rrr_shi *a,
5422 void (*gen)(TCGv_i32, TCGv_i32),
5423 int logic_cc, StoreRegKind kind)
5425 TCGv_i32 tmp;
5427 tmp = load_reg(s, a->rm);
5428 gen_arm_shift_im(tmp, a->shty, a->shim, logic_cc);
5430 gen(tmp, tmp);
5431 if (logic_cc) {
5432 gen_logic_CC(tmp);
5434 return store_reg_kind(s, a->rd, tmp, kind);
5438 * Data-processing (register-shifted register)
5440 * Operate, with set flags, one register source,
5441 * one register shifted register source, and a destination.
5443 static bool op_s_rrr_shr(DisasContext *s, arg_s_rrr_shr *a,
5444 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32),
5445 int logic_cc, StoreRegKind kind)
5447 TCGv_i32 tmp1, tmp2;
5449 tmp1 = load_reg(s, a->rs);
5450 tmp2 = load_reg(s, a->rm);
5451 gen_arm_shift_reg(tmp2, a->shty, tmp1, logic_cc);
5452 tmp1 = load_reg(s, a->rn);
5454 gen(tmp1, tmp1, tmp2);
5455 tcg_temp_free_i32(tmp2);
5457 if (logic_cc) {
5458 gen_logic_CC(tmp1);
5460 return store_reg_kind(s, a->rd, tmp1, kind);
5463 static bool op_s_rxr_shr(DisasContext *s, arg_s_rrr_shr *a,
5464 void (*gen)(TCGv_i32, TCGv_i32),
5465 int logic_cc, StoreRegKind kind)
5467 TCGv_i32 tmp1, tmp2;
5469 tmp1 = load_reg(s, a->rs);
5470 tmp2 = load_reg(s, a->rm);
5471 gen_arm_shift_reg(tmp2, a->shty, tmp1, logic_cc);
5473 gen(tmp2, tmp2);
5474 if (logic_cc) {
5475 gen_logic_CC(tmp2);
5477 return store_reg_kind(s, a->rd, tmp2, kind);
5481 * Data-processing (immediate)
5483 * Operate, with set flags, one register source,
5484 * one rotated immediate, and a destination.
5486 * Note that logic_cc && a->rot setting CF based on the msb of the
5487 * immediate is the reason why we must pass in the unrotated form
5488 * of the immediate.
5490 static bool op_s_rri_rot(DisasContext *s, arg_s_rri_rot *a,
5491 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32),
5492 int logic_cc, StoreRegKind kind)
5494 TCGv_i32 tmp1, tmp2;
5495 uint32_t imm;
5497 imm = ror32(a->imm, a->rot);
5498 if (logic_cc && a->rot) {
5499 tcg_gen_movi_i32(cpu_CF, imm >> 31);
5501 tmp2 = tcg_const_i32(imm);
5502 tmp1 = load_reg(s, a->rn);
5504 gen(tmp1, tmp1, tmp2);
5505 tcg_temp_free_i32(tmp2);
5507 if (logic_cc) {
5508 gen_logic_CC(tmp1);
5510 return store_reg_kind(s, a->rd, tmp1, kind);
5513 static bool op_s_rxi_rot(DisasContext *s, arg_s_rri_rot *a,
5514 void (*gen)(TCGv_i32, TCGv_i32),
5515 int logic_cc, StoreRegKind kind)
5517 TCGv_i32 tmp;
5518 uint32_t imm;
5520 imm = ror32(a->imm, a->rot);
5521 if (logic_cc && a->rot) {
5522 tcg_gen_movi_i32(cpu_CF, imm >> 31);
5524 tmp = tcg_const_i32(imm);
5526 gen(tmp, tmp);
5527 if (logic_cc) {
5528 gen_logic_CC(tmp);
5530 return store_reg_kind(s, a->rd, tmp, kind);
5533 #define DO_ANY3(NAME, OP, L, K) \
5534 static bool trans_##NAME##_rrri(DisasContext *s, arg_s_rrr_shi *a) \
5535 { StoreRegKind k = (K); return op_s_rrr_shi(s, a, OP, L, k); } \
5536 static bool trans_##NAME##_rrrr(DisasContext *s, arg_s_rrr_shr *a) \
5537 { StoreRegKind k = (K); return op_s_rrr_shr(s, a, OP, L, k); } \
5538 static bool trans_##NAME##_rri(DisasContext *s, arg_s_rri_rot *a) \
5539 { StoreRegKind k = (K); return op_s_rri_rot(s, a, OP, L, k); }
5541 #define DO_ANY2(NAME, OP, L, K) \
5542 static bool trans_##NAME##_rxri(DisasContext *s, arg_s_rrr_shi *a) \
5543 { StoreRegKind k = (K); return op_s_rxr_shi(s, a, OP, L, k); } \
5544 static bool trans_##NAME##_rxrr(DisasContext *s, arg_s_rrr_shr *a) \
5545 { StoreRegKind k = (K); return op_s_rxr_shr(s, a, OP, L, k); } \
5546 static bool trans_##NAME##_rxi(DisasContext *s, arg_s_rri_rot *a) \
5547 { StoreRegKind k = (K); return op_s_rxi_rot(s, a, OP, L, k); }
5549 #define DO_CMP2(NAME, OP, L) \
5550 static bool trans_##NAME##_xrri(DisasContext *s, arg_s_rrr_shi *a) \
5551 { return op_s_rrr_shi(s, a, OP, L, STREG_NONE); } \
5552 static bool trans_##NAME##_xrrr(DisasContext *s, arg_s_rrr_shr *a) \
5553 { return op_s_rrr_shr(s, a, OP, L, STREG_NONE); } \
5554 static bool trans_##NAME##_xri(DisasContext *s, arg_s_rri_rot *a) \
5555 { return op_s_rri_rot(s, a, OP, L, STREG_NONE); }
5557 DO_ANY3(AND, tcg_gen_and_i32, a->s, STREG_NORMAL)
5558 DO_ANY3(EOR, tcg_gen_xor_i32, a->s, STREG_NORMAL)
5559 DO_ANY3(ORR, tcg_gen_or_i32, a->s, STREG_NORMAL)
5560 DO_ANY3(BIC, tcg_gen_andc_i32, a->s, STREG_NORMAL)
5562 DO_ANY3(RSB, a->s ? gen_rsb_CC : gen_rsb, false, STREG_NORMAL)
5563 DO_ANY3(ADC, a->s ? gen_adc_CC : gen_add_carry, false, STREG_NORMAL)
5564 DO_ANY3(SBC, a->s ? gen_sbc_CC : gen_sub_carry, false, STREG_NORMAL)
5565 DO_ANY3(RSC, a->s ? gen_rsc_CC : gen_rsc, false, STREG_NORMAL)
5567 DO_CMP2(TST, tcg_gen_and_i32, true)
5568 DO_CMP2(TEQ, tcg_gen_xor_i32, true)
5569 DO_CMP2(CMN, gen_add_CC, false)
5570 DO_CMP2(CMP, gen_sub_CC, false)
5572 DO_ANY3(ADD, a->s ? gen_add_CC : tcg_gen_add_i32, false,
5573 a->rd == 13 && a->rn == 13 ? STREG_SP_CHECK : STREG_NORMAL)
5576 * Note for the computation of StoreRegKind we return out of the
5577 * middle of the functions that are expanded by DO_ANY3, and that
5578 * we modify a->s via that parameter before it is used by OP.
5580 DO_ANY3(SUB, a->s ? gen_sub_CC : tcg_gen_sub_i32, false,
5582 StoreRegKind ret = STREG_NORMAL;
5583 if (a->rd == 15 && a->s) {
5585 * See ALUExceptionReturn:
5586 * In User mode, UNPREDICTABLE; we choose UNDEF.
5587 * In Hyp mode, UNDEFINED.
5589 if (IS_USER(s) || s->current_el == 2) {
5590 unallocated_encoding(s);
5591 return true;
5593 /* There is no writeback of nzcv to PSTATE. */
5594 a->s = 0;
5595 ret = STREG_EXC_RET;
5596 } else if (a->rd == 13 && a->rn == 13) {
5597 ret = STREG_SP_CHECK;
5599 ret;
5602 DO_ANY2(MOV, tcg_gen_mov_i32, a->s,
5604 StoreRegKind ret = STREG_NORMAL;
5605 if (a->rd == 15 && a->s) {
5607 * See ALUExceptionReturn:
5608 * In User mode, UNPREDICTABLE; we choose UNDEF.
5609 * In Hyp mode, UNDEFINED.
5611 if (IS_USER(s) || s->current_el == 2) {
5612 unallocated_encoding(s);
5613 return true;
5615 /* There is no writeback of nzcv to PSTATE. */
5616 a->s = 0;
5617 ret = STREG_EXC_RET;
5618 } else if (a->rd == 13) {
5619 ret = STREG_SP_CHECK;
5621 ret;
5624 DO_ANY2(MVN, tcg_gen_not_i32, a->s, STREG_NORMAL)
5627 * ORN is only available with T32, so there is no register-shifted-register
5628 * form of the insn. Using the DO_ANY3 macro would create an unused function.
5630 static bool trans_ORN_rrri(DisasContext *s, arg_s_rrr_shi *a)
5632 return op_s_rrr_shi(s, a, tcg_gen_orc_i32, a->s, STREG_NORMAL);
5635 static bool trans_ORN_rri(DisasContext *s, arg_s_rri_rot *a)
5637 return op_s_rri_rot(s, a, tcg_gen_orc_i32, a->s, STREG_NORMAL);
5640 #undef DO_ANY3
5641 #undef DO_ANY2
5642 #undef DO_CMP2
5644 static bool trans_ADR(DisasContext *s, arg_ri *a)
5646 store_reg_bx(s, a->rd, add_reg_for_lit(s, 15, a->imm));
5647 return true;
5650 static bool trans_MOVW(DisasContext *s, arg_MOVW *a)
5652 TCGv_i32 tmp;
5654 if (!ENABLE_ARCH_6T2) {
5655 return false;
5658 tmp = tcg_const_i32(a->imm);
5659 store_reg(s, a->rd, tmp);
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 * Multiply and multiply accumulate
5682 static bool op_mla(DisasContext *s, arg_s_rrrr *a, bool add)
5684 TCGv_i32 t1, t2;
5686 t1 = load_reg(s, a->rn);
5687 t2 = load_reg(s, a->rm);
5688 tcg_gen_mul_i32(t1, t1, t2);
5689 tcg_temp_free_i32(t2);
5690 if (add) {
5691 t2 = load_reg(s, a->ra);
5692 tcg_gen_add_i32(t1, t1, t2);
5693 tcg_temp_free_i32(t2);
5695 if (a->s) {
5696 gen_logic_CC(t1);
5698 store_reg(s, a->rd, t1);
5699 return true;
5702 static bool trans_MUL(DisasContext *s, arg_MUL *a)
5704 return op_mla(s, a, false);
5707 static bool trans_MLA(DisasContext *s, arg_MLA *a)
5709 return op_mla(s, a, true);
5712 static bool trans_MLS(DisasContext *s, arg_MLS *a)
5714 TCGv_i32 t1, t2;
5716 if (!ENABLE_ARCH_6T2) {
5717 return false;
5719 t1 = load_reg(s, a->rn);
5720 t2 = load_reg(s, a->rm);
5721 tcg_gen_mul_i32(t1, t1, t2);
5722 tcg_temp_free_i32(t2);
5723 t2 = load_reg(s, a->ra);
5724 tcg_gen_sub_i32(t1, t2, t1);
5725 tcg_temp_free_i32(t2);
5726 store_reg(s, a->rd, t1);
5727 return true;
5730 static bool op_mlal(DisasContext *s, arg_s_rrrr *a, bool uns, bool add)
5732 TCGv_i32 t0, t1, t2, t3;
5734 t0 = load_reg(s, a->rm);
5735 t1 = load_reg(s, a->rn);
5736 if (uns) {
5737 tcg_gen_mulu2_i32(t0, t1, t0, t1);
5738 } else {
5739 tcg_gen_muls2_i32(t0, t1, t0, t1);
5741 if (add) {
5742 t2 = load_reg(s, a->ra);
5743 t3 = load_reg(s, a->rd);
5744 tcg_gen_add2_i32(t0, t1, t0, t1, t2, t3);
5745 tcg_temp_free_i32(t2);
5746 tcg_temp_free_i32(t3);
5748 if (a->s) {
5749 gen_logicq_cc(t0, t1);
5751 store_reg(s, a->ra, t0);
5752 store_reg(s, a->rd, t1);
5753 return true;
5756 static bool trans_UMULL(DisasContext *s, arg_UMULL *a)
5758 return op_mlal(s, a, true, false);
5761 static bool trans_SMULL(DisasContext *s, arg_SMULL *a)
5763 return op_mlal(s, a, false, false);
5766 static bool trans_UMLAL(DisasContext *s, arg_UMLAL *a)
5768 return op_mlal(s, a, true, true);
5771 static bool trans_SMLAL(DisasContext *s, arg_SMLAL *a)
5773 return op_mlal(s, a, false, true);
5776 static bool trans_UMAAL(DisasContext *s, arg_UMAAL *a)
5778 TCGv_i32 t0, t1, t2, zero;
5780 if (s->thumb
5781 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
5782 : !ENABLE_ARCH_6) {
5783 return false;
5786 t0 = load_reg(s, a->rm);
5787 t1 = load_reg(s, a->rn);
5788 tcg_gen_mulu2_i32(t0, t1, t0, t1);
5789 zero = tcg_const_i32(0);
5790 t2 = load_reg(s, a->ra);
5791 tcg_gen_add2_i32(t0, t1, t0, t1, t2, zero);
5792 tcg_temp_free_i32(t2);
5793 t2 = load_reg(s, a->rd);
5794 tcg_gen_add2_i32(t0, t1, t0, t1, t2, zero);
5795 tcg_temp_free_i32(t2);
5796 tcg_temp_free_i32(zero);
5797 store_reg(s, a->ra, t0);
5798 store_reg(s, a->rd, t1);
5799 return true;
5803 * Saturating addition and subtraction
5806 static bool op_qaddsub(DisasContext *s, arg_rrr *a, bool add, bool doub)
5808 TCGv_i32 t0, t1;
5810 if (s->thumb
5811 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
5812 : !ENABLE_ARCH_5TE) {
5813 return false;
5816 t0 = load_reg(s, a->rm);
5817 t1 = load_reg(s, a->rn);
5818 if (doub) {
5819 gen_helper_add_saturate(t1, cpu_env, t1, t1);
5821 if (add) {
5822 gen_helper_add_saturate(t0, cpu_env, t0, t1);
5823 } else {
5824 gen_helper_sub_saturate(t0, cpu_env, t0, t1);
5826 tcg_temp_free_i32(t1);
5827 store_reg(s, a->rd, t0);
5828 return true;
5831 #define DO_QADDSUB(NAME, ADD, DOUB) \
5832 static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
5834 return op_qaddsub(s, a, ADD, DOUB); \
5837 DO_QADDSUB(QADD, true, false)
5838 DO_QADDSUB(QSUB, false, false)
5839 DO_QADDSUB(QDADD, true, true)
5840 DO_QADDSUB(QDSUB, false, true)
5842 #undef DO_QADDSUB
5845 * Halfword multiply and multiply accumulate
5848 static bool op_smlaxxx(DisasContext *s, arg_rrrr *a,
5849 int add_long, bool nt, bool mt)
5851 TCGv_i32 t0, t1, tl, th;
5853 if (s->thumb
5854 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
5855 : !ENABLE_ARCH_5TE) {
5856 return false;
5859 t0 = load_reg(s, a->rn);
5860 t1 = load_reg(s, a->rm);
5861 gen_mulxy(t0, t1, nt, mt);
5862 tcg_temp_free_i32(t1);
5864 switch (add_long) {
5865 case 0:
5866 store_reg(s, a->rd, t0);
5867 break;
5868 case 1:
5869 t1 = load_reg(s, a->ra);
5870 gen_helper_add_setq(t0, cpu_env, t0, t1);
5871 tcg_temp_free_i32(t1);
5872 store_reg(s, a->rd, t0);
5873 break;
5874 case 2:
5875 tl = load_reg(s, a->ra);
5876 th = load_reg(s, a->rd);
5877 /* Sign-extend the 32-bit product to 64 bits. */
5878 t1 = tcg_temp_new_i32();
5879 tcg_gen_sari_i32(t1, t0, 31);
5880 tcg_gen_add2_i32(tl, th, tl, th, t0, t1);
5881 tcg_temp_free_i32(t0);
5882 tcg_temp_free_i32(t1);
5883 store_reg(s, a->ra, tl);
5884 store_reg(s, a->rd, th);
5885 break;
5886 default:
5887 g_assert_not_reached();
5889 return true;
5892 #define DO_SMLAX(NAME, add, nt, mt) \
5893 static bool trans_##NAME(DisasContext *s, arg_rrrr *a) \
5895 return op_smlaxxx(s, a, add, nt, mt); \
5898 DO_SMLAX(SMULBB, 0, 0, 0)
5899 DO_SMLAX(SMULBT, 0, 0, 1)
5900 DO_SMLAX(SMULTB, 0, 1, 0)
5901 DO_SMLAX(SMULTT, 0, 1, 1)
5903 DO_SMLAX(SMLABB, 1, 0, 0)
5904 DO_SMLAX(SMLABT, 1, 0, 1)
5905 DO_SMLAX(SMLATB, 1, 1, 0)
5906 DO_SMLAX(SMLATT, 1, 1, 1)
5908 DO_SMLAX(SMLALBB, 2, 0, 0)
5909 DO_SMLAX(SMLALBT, 2, 0, 1)
5910 DO_SMLAX(SMLALTB, 2, 1, 0)
5911 DO_SMLAX(SMLALTT, 2, 1, 1)
5913 #undef DO_SMLAX
5915 static bool op_smlawx(DisasContext *s, arg_rrrr *a, bool add, bool mt)
5917 TCGv_i32 t0, t1;
5919 if (!ENABLE_ARCH_5TE) {
5920 return false;
5923 t0 = load_reg(s, a->rn);
5924 t1 = load_reg(s, a->rm);
5926 * Since the nominal result is product<47:16>, shift the 16-bit
5927 * input up by 16 bits, so that the result is at product<63:32>.
5929 if (mt) {
5930 tcg_gen_andi_i32(t1, t1, 0xffff0000);
5931 } else {
5932 tcg_gen_shli_i32(t1, t1, 16);
5934 tcg_gen_muls2_i32(t0, t1, t0, t1);
5935 tcg_temp_free_i32(t0);
5936 if (add) {
5937 t0 = load_reg(s, a->ra);
5938 gen_helper_add_setq(t1, cpu_env, t1, t0);
5939 tcg_temp_free_i32(t0);
5941 store_reg(s, a->rd, t1);
5942 return true;
5945 #define DO_SMLAWX(NAME, add, mt) \
5946 static bool trans_##NAME(DisasContext *s, arg_rrrr *a) \
5948 return op_smlawx(s, a, add, mt); \
5951 DO_SMLAWX(SMULWB, 0, 0)
5952 DO_SMLAWX(SMULWT, 0, 1)
5953 DO_SMLAWX(SMLAWB, 1, 0)
5954 DO_SMLAWX(SMLAWT, 1, 1)
5956 #undef DO_SMLAWX
5959 * MSR (immediate) and hints
5962 static bool trans_YIELD(DisasContext *s, arg_YIELD *a)
5965 * When running single-threaded TCG code, use the helper to ensure that
5966 * the next round-robin scheduled vCPU gets a crack. When running in
5967 * MTTCG we don't generate jumps to the helper as it won't affect the
5968 * scheduling of other vCPUs.
5970 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
5971 gen_set_pc_im(s, s->base.pc_next);
5972 s->base.is_jmp = DISAS_YIELD;
5974 return true;
5977 static bool trans_WFE(DisasContext *s, arg_WFE *a)
5980 * When running single-threaded TCG code, use the helper to ensure that
5981 * the next round-robin scheduled vCPU gets a crack. In MTTCG mode we
5982 * just skip this instruction. Currently the SEV/SEVL instructions,
5983 * which are *one* of many ways to wake the CPU from WFE, are not
5984 * implemented so we can't sleep like WFI does.
5986 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
5987 gen_set_pc_im(s, s->base.pc_next);
5988 s->base.is_jmp = DISAS_WFE;
5990 return true;
5993 static bool trans_WFI(DisasContext *s, arg_WFI *a)
5995 /* For WFI, halt the vCPU until an IRQ. */
5996 gen_set_pc_im(s, s->base.pc_next);
5997 s->base.is_jmp = DISAS_WFI;
5998 return true;
6001 static bool trans_NOP(DisasContext *s, arg_NOP *a)
6003 return true;
6006 static bool trans_MSR_imm(DisasContext *s, arg_MSR_imm *a)
6008 uint32_t val = ror32(a->imm, a->rot * 2);
6009 uint32_t mask = msr_mask(s, a->mask, a->r);
6011 if (gen_set_psr_im(s, mask, a->r, val)) {
6012 unallocated_encoding(s);
6014 return true;
6018 * Cyclic Redundancy Check
6021 static bool op_crc32(DisasContext *s, arg_rrr *a, bool c, MemOp sz)
6023 TCGv_i32 t1, t2, t3;
6025 if (!dc_isar_feature(aa32_crc32, s)) {
6026 return false;
6029 t1 = load_reg(s, a->rn);
6030 t2 = load_reg(s, a->rm);
6031 switch (sz) {
6032 case MO_8:
6033 gen_uxtb(t2);
6034 break;
6035 case MO_16:
6036 gen_uxth(t2);
6037 break;
6038 case MO_32:
6039 break;
6040 default:
6041 g_assert_not_reached();
6043 t3 = tcg_const_i32(1 << sz);
6044 if (c) {
6045 gen_helper_crc32c(t1, t1, t2, t3);
6046 } else {
6047 gen_helper_crc32(t1, t1, t2, t3);
6049 tcg_temp_free_i32(t2);
6050 tcg_temp_free_i32(t3);
6051 store_reg(s, a->rd, t1);
6052 return true;
6055 #define DO_CRC32(NAME, c, sz) \
6056 static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
6057 { return op_crc32(s, a, c, sz); }
6059 DO_CRC32(CRC32B, false, MO_8)
6060 DO_CRC32(CRC32H, false, MO_16)
6061 DO_CRC32(CRC32W, false, MO_32)
6062 DO_CRC32(CRC32CB, true, MO_8)
6063 DO_CRC32(CRC32CH, true, MO_16)
6064 DO_CRC32(CRC32CW, true, MO_32)
6066 #undef DO_CRC32
6069 * Miscellaneous instructions
6072 static bool trans_MRS_bank(DisasContext *s, arg_MRS_bank *a)
6074 if (arm_dc_feature(s, ARM_FEATURE_M)) {
6075 return false;
6077 gen_mrs_banked(s, a->r, a->sysm, a->rd);
6078 return true;
6081 static bool trans_MSR_bank(DisasContext *s, arg_MSR_bank *a)
6083 if (arm_dc_feature(s, ARM_FEATURE_M)) {
6084 return false;
6086 gen_msr_banked(s, a->r, a->sysm, a->rn);
6087 return true;
6090 static bool trans_MRS_reg(DisasContext *s, arg_MRS_reg *a)
6092 TCGv_i32 tmp;
6094 if (arm_dc_feature(s, ARM_FEATURE_M)) {
6095 return false;
6097 if (a->r) {
6098 if (IS_USER(s)) {
6099 unallocated_encoding(s);
6100 return true;
6102 tmp = load_cpu_field(spsr);
6103 } else {
6104 tmp = tcg_temp_new_i32();
6105 gen_helper_cpsr_read(tmp, cpu_env);
6107 store_reg(s, a->rd, tmp);
6108 return true;
6111 static bool trans_MSR_reg(DisasContext *s, arg_MSR_reg *a)
6113 TCGv_i32 tmp;
6114 uint32_t mask = msr_mask(s, a->mask, a->r);
6116 if (arm_dc_feature(s, ARM_FEATURE_M)) {
6117 return false;
6119 tmp = load_reg(s, a->rn);
6120 if (gen_set_psr(s, mask, a->r, tmp)) {
6121 unallocated_encoding(s);
6123 return true;
6126 static bool trans_MRS_v7m(DisasContext *s, arg_MRS_v7m *a)
6128 TCGv_i32 tmp;
6130 if (!arm_dc_feature(s, ARM_FEATURE_M)) {
6131 return false;
6133 tmp = tcg_const_i32(a->sysm);
6134 gen_helper_v7m_mrs(tmp, cpu_env, tmp);
6135 store_reg(s, a->rd, tmp);
6136 return true;
6139 static bool trans_MSR_v7m(DisasContext *s, arg_MSR_v7m *a)
6141 TCGv_i32 addr, reg;
6143 if (!arm_dc_feature(s, ARM_FEATURE_M)) {
6144 return false;
6146 addr = tcg_const_i32((a->mask << 10) | a->sysm);
6147 reg = load_reg(s, a->rn);
6148 gen_helper_v7m_msr(cpu_env, addr, reg);
6149 tcg_temp_free_i32(addr);
6150 tcg_temp_free_i32(reg);
6151 /* If we wrote to CONTROL, the EL might have changed */
6152 gen_helper_rebuild_hflags_m32_newel(cpu_env);
6153 gen_lookup_tb(s);
6154 return true;
6157 static bool trans_BX(DisasContext *s, arg_BX *a)
6159 if (!ENABLE_ARCH_4T) {
6160 return false;
6162 gen_bx_excret(s, load_reg(s, a->rm));
6163 return true;
6166 static bool trans_BXJ(DisasContext *s, arg_BXJ *a)
6168 if (!ENABLE_ARCH_5J || arm_dc_feature(s, ARM_FEATURE_M)) {
6169 return false;
6171 /* Trivial implementation equivalent to bx. */
6172 gen_bx(s, load_reg(s, a->rm));
6173 return true;
6176 static bool trans_BLX_r(DisasContext *s, arg_BLX_r *a)
6178 TCGv_i32 tmp;
6180 if (!ENABLE_ARCH_5) {
6181 return false;
6183 tmp = load_reg(s, a->rm);
6184 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
6185 gen_bx(s, tmp);
6186 return true;
6190 * BXNS/BLXNS: only exist for v8M with the security extensions,
6191 * and always UNDEF if NonSecure. We don't implement these in
6192 * the user-only mode either (in theory you can use them from
6193 * Secure User mode but they are too tied in to system emulation).
6195 static bool trans_BXNS(DisasContext *s, arg_BXNS *a)
6197 if (!s->v8m_secure || IS_USER_ONLY) {
6198 unallocated_encoding(s);
6199 } else {
6200 gen_bxns(s, a->rm);
6202 return true;
6205 static bool trans_BLXNS(DisasContext *s, arg_BLXNS *a)
6207 if (!s->v8m_secure || IS_USER_ONLY) {
6208 unallocated_encoding(s);
6209 } else {
6210 gen_blxns(s, a->rm);
6212 return true;
6215 static bool trans_CLZ(DisasContext *s, arg_CLZ *a)
6217 TCGv_i32 tmp;
6219 if (!ENABLE_ARCH_5) {
6220 return false;
6222 tmp = load_reg(s, a->rm);
6223 tcg_gen_clzi_i32(tmp, tmp, 32);
6224 store_reg(s, a->rd, tmp);
6225 return true;
6228 static bool trans_ERET(DisasContext *s, arg_ERET *a)
6230 TCGv_i32 tmp;
6232 if (!arm_dc_feature(s, ARM_FEATURE_V7VE)) {
6233 return false;
6235 if (IS_USER(s)) {
6236 unallocated_encoding(s);
6237 return true;
6239 if (s->current_el == 2) {
6240 /* ERET from Hyp uses ELR_Hyp, not LR */
6241 tmp = load_cpu_field(elr_el[2]);
6242 } else {
6243 tmp = load_reg(s, 14);
6245 gen_exception_return(s, tmp);
6246 return true;
6249 static bool trans_HLT(DisasContext *s, arg_HLT *a)
6251 gen_hlt(s, a->imm);
6252 return true;
6255 static bool trans_BKPT(DisasContext *s, arg_BKPT *a)
6257 if (!ENABLE_ARCH_5) {
6258 return false;
6260 if (arm_dc_feature(s, ARM_FEATURE_M) &&
6261 semihosting_enabled() &&
6262 #ifndef CONFIG_USER_ONLY
6263 !IS_USER(s) &&
6264 #endif
6265 (a->imm == 0xab)) {
6266 gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
6267 } else {
6268 gen_exception_bkpt_insn(s, syn_aa32_bkpt(a->imm, false));
6270 return true;
6273 static bool trans_HVC(DisasContext *s, arg_HVC *a)
6275 if (!ENABLE_ARCH_7 || arm_dc_feature(s, ARM_FEATURE_M)) {
6276 return false;
6278 if (IS_USER(s)) {
6279 unallocated_encoding(s);
6280 } else {
6281 gen_hvc(s, a->imm);
6283 return true;
6286 static bool trans_SMC(DisasContext *s, arg_SMC *a)
6288 if (!ENABLE_ARCH_6K || arm_dc_feature(s, ARM_FEATURE_M)) {
6289 return false;
6291 if (IS_USER(s)) {
6292 unallocated_encoding(s);
6293 } else {
6294 gen_smc(s);
6296 return true;
6299 static bool trans_SG(DisasContext *s, arg_SG *a)
6301 if (!arm_dc_feature(s, ARM_FEATURE_M) ||
6302 !arm_dc_feature(s, ARM_FEATURE_V8)) {
6303 return false;
6306 * SG (v8M only)
6307 * The bulk of the behaviour for this instruction is implemented
6308 * in v7m_handle_execute_nsc(), which deals with the insn when
6309 * it is executed by a CPU in non-secure state from memory
6310 * which is Secure & NonSecure-Callable.
6311 * Here we only need to handle the remaining cases:
6312 * * in NS memory (including the "security extension not
6313 * implemented" case) : NOP
6314 * * in S memory but CPU already secure (clear IT bits)
6315 * We know that the attribute for the memory this insn is
6316 * in must match the current CPU state, because otherwise
6317 * get_phys_addr_pmsav8 would have generated an exception.
6319 if (s->v8m_secure) {
6320 /* Like the IT insn, we don't need to generate any code */
6321 s->condexec_cond = 0;
6322 s->condexec_mask = 0;
6324 return true;
6327 static bool trans_TT(DisasContext *s, arg_TT *a)
6329 TCGv_i32 addr, tmp;
6331 if (!arm_dc_feature(s, ARM_FEATURE_M) ||
6332 !arm_dc_feature(s, ARM_FEATURE_V8)) {
6333 return false;
6335 if (a->rd == 13 || a->rd == 15 || a->rn == 15) {
6336 /* We UNDEF for these UNPREDICTABLE cases */
6337 unallocated_encoding(s);
6338 return true;
6340 if (a->A && !s->v8m_secure) {
6341 /* This case is UNDEFINED. */
6342 unallocated_encoding(s);
6343 return true;
6346 addr = load_reg(s, a->rn);
6347 tmp = tcg_const_i32((a->A << 1) | a->T);
6348 gen_helper_v7m_tt(tmp, cpu_env, addr, tmp);
6349 tcg_temp_free_i32(addr);
6350 store_reg(s, a->rd, tmp);
6351 return true;
6355 * Load/store register index
6358 static ISSInfo make_issinfo(DisasContext *s, int rd, bool p, bool w)
6360 ISSInfo ret;
6362 /* ISS not valid if writeback */
6363 if (p && !w) {
6364 ret = rd;
6365 if (s->base.pc_next - s->pc_curr == 2) {
6366 ret |= ISSIs16Bit;
6368 } else {
6369 ret = ISSInvalid;
6371 return ret;
6374 static TCGv_i32 op_addr_rr_pre(DisasContext *s, arg_ldst_rr *a)
6376 TCGv_i32 addr = load_reg(s, a->rn);
6378 if (s->v8m_stackcheck && a->rn == 13 && a->w) {
6379 gen_helper_v8m_stackcheck(cpu_env, addr);
6382 if (a->p) {
6383 TCGv_i32 ofs = load_reg(s, a->rm);
6384 gen_arm_shift_im(ofs, a->shtype, a->shimm, 0);
6385 if (a->u) {
6386 tcg_gen_add_i32(addr, addr, ofs);
6387 } else {
6388 tcg_gen_sub_i32(addr, addr, ofs);
6390 tcg_temp_free_i32(ofs);
6392 return addr;
6395 static void op_addr_rr_post(DisasContext *s, arg_ldst_rr *a,
6396 TCGv_i32 addr, int address_offset)
6398 if (!a->p) {
6399 TCGv_i32 ofs = load_reg(s, a->rm);
6400 gen_arm_shift_im(ofs, a->shtype, a->shimm, 0);
6401 if (a->u) {
6402 tcg_gen_add_i32(addr, addr, ofs);
6403 } else {
6404 tcg_gen_sub_i32(addr, addr, ofs);
6406 tcg_temp_free_i32(ofs);
6407 } else if (!a->w) {
6408 tcg_temp_free_i32(addr);
6409 return;
6411 tcg_gen_addi_i32(addr, addr, address_offset);
6412 store_reg(s, a->rn, addr);
6415 static bool op_load_rr(DisasContext *s, arg_ldst_rr *a,
6416 MemOp mop, int mem_idx)
6418 ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w);
6419 TCGv_i32 addr, tmp;
6421 addr = op_addr_rr_pre(s, a);
6423 tmp = tcg_temp_new_i32();
6424 gen_aa32_ld_i32(s, tmp, addr, mem_idx, mop | s->be_data);
6425 disas_set_da_iss(s, mop, issinfo);
6428 * Perform base writeback before the loaded value to
6429 * ensure correct behavior with overlapping index registers.
6431 op_addr_rr_post(s, a, addr, 0);
6432 store_reg_from_load(s, a->rt, tmp);
6433 return true;
6436 static bool op_store_rr(DisasContext *s, arg_ldst_rr *a,
6437 MemOp mop, int mem_idx)
6439 ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w) | ISSIsWrite;
6440 TCGv_i32 addr, tmp;
6442 addr = op_addr_rr_pre(s, a);
6444 tmp = load_reg(s, a->rt);
6445 gen_aa32_st_i32(s, tmp, addr, mem_idx, mop | s->be_data);
6446 disas_set_da_iss(s, mop, issinfo);
6447 tcg_temp_free_i32(tmp);
6449 op_addr_rr_post(s, a, addr, 0);
6450 return true;
6453 static bool trans_LDRD_rr(DisasContext *s, arg_ldst_rr *a)
6455 int mem_idx = get_mem_index(s);
6456 TCGv_i32 addr, tmp;
6458 if (!ENABLE_ARCH_5TE) {
6459 return false;
6461 if (a->rt & 1) {
6462 unallocated_encoding(s);
6463 return true;
6465 addr = op_addr_rr_pre(s, a);
6467 tmp = tcg_temp_new_i32();
6468 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
6469 store_reg(s, a->rt, tmp);
6471 tcg_gen_addi_i32(addr, addr, 4);
6473 tmp = tcg_temp_new_i32();
6474 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
6475 store_reg(s, a->rt + 1, tmp);
6477 /* LDRD w/ base writeback is undefined if the registers overlap. */
6478 op_addr_rr_post(s, a, addr, -4);
6479 return true;
6482 static bool trans_STRD_rr(DisasContext *s, arg_ldst_rr *a)
6484 int mem_idx = get_mem_index(s);
6485 TCGv_i32 addr, tmp;
6487 if (!ENABLE_ARCH_5TE) {
6488 return false;
6490 if (a->rt & 1) {
6491 unallocated_encoding(s);
6492 return true;
6494 addr = op_addr_rr_pre(s, a);
6496 tmp = load_reg(s, a->rt);
6497 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
6498 tcg_temp_free_i32(tmp);
6500 tcg_gen_addi_i32(addr, addr, 4);
6502 tmp = load_reg(s, a->rt + 1);
6503 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
6504 tcg_temp_free_i32(tmp);
6506 op_addr_rr_post(s, a, addr, -4);
6507 return true;
6511 * Load/store immediate index
6514 static TCGv_i32 op_addr_ri_pre(DisasContext *s, arg_ldst_ri *a)
6516 int ofs = a->imm;
6518 if (!a->u) {
6519 ofs = -ofs;
6522 if (s->v8m_stackcheck && a->rn == 13 && a->w) {
6524 * Stackcheck. Here we know 'addr' is the current SP;
6525 * U is set if we're moving SP up, else down. It is
6526 * UNKNOWN whether the limit check triggers when SP starts
6527 * below the limit and ends up above it; we chose to do so.
6529 if (!a->u) {
6530 TCGv_i32 newsp = tcg_temp_new_i32();
6531 tcg_gen_addi_i32(newsp, cpu_R[13], ofs);
6532 gen_helper_v8m_stackcheck(cpu_env, newsp);
6533 tcg_temp_free_i32(newsp);
6534 } else {
6535 gen_helper_v8m_stackcheck(cpu_env, cpu_R[13]);
6539 return add_reg_for_lit(s, a->rn, a->p ? ofs : 0);
6542 static void op_addr_ri_post(DisasContext *s, arg_ldst_ri *a,
6543 TCGv_i32 addr, int address_offset)
6545 if (!a->p) {
6546 if (a->u) {
6547 address_offset += a->imm;
6548 } else {
6549 address_offset -= a->imm;
6551 } else if (!a->w) {
6552 tcg_temp_free_i32(addr);
6553 return;
6555 tcg_gen_addi_i32(addr, addr, address_offset);
6556 store_reg(s, a->rn, addr);
6559 static bool op_load_ri(DisasContext *s, arg_ldst_ri *a,
6560 MemOp mop, int mem_idx)
6562 ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w);
6563 TCGv_i32 addr, tmp;
6565 addr = op_addr_ri_pre(s, a);
6567 tmp = tcg_temp_new_i32();
6568 gen_aa32_ld_i32(s, tmp, addr, mem_idx, mop | s->be_data);
6569 disas_set_da_iss(s, mop, issinfo);
6572 * Perform base writeback before the loaded value to
6573 * ensure correct behavior with overlapping index registers.
6575 op_addr_ri_post(s, a, addr, 0);
6576 store_reg_from_load(s, a->rt, tmp);
6577 return true;
6580 static bool op_store_ri(DisasContext *s, arg_ldst_ri *a,
6581 MemOp mop, int mem_idx)
6583 ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w) | ISSIsWrite;
6584 TCGv_i32 addr, tmp;
6586 addr = op_addr_ri_pre(s, a);
6588 tmp = load_reg(s, a->rt);
6589 gen_aa32_st_i32(s, tmp, addr, mem_idx, mop | s->be_data);
6590 disas_set_da_iss(s, mop, issinfo);
6591 tcg_temp_free_i32(tmp);
6593 op_addr_ri_post(s, a, addr, 0);
6594 return true;
6597 static bool op_ldrd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
6599 int mem_idx = get_mem_index(s);
6600 TCGv_i32 addr, tmp;
6602 addr = op_addr_ri_pre(s, a);
6604 tmp = tcg_temp_new_i32();
6605 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
6606 store_reg(s, a->rt, tmp);
6608 tcg_gen_addi_i32(addr, addr, 4);
6610 tmp = tcg_temp_new_i32();
6611 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
6612 store_reg(s, rt2, tmp);
6614 /* LDRD w/ base writeback is undefined if the registers overlap. */
6615 op_addr_ri_post(s, a, addr, -4);
6616 return true;
6619 static bool trans_LDRD_ri_a32(DisasContext *s, arg_ldst_ri *a)
6621 if (!ENABLE_ARCH_5TE || (a->rt & 1)) {
6622 return false;
6624 return op_ldrd_ri(s, a, a->rt + 1);
6627 static bool trans_LDRD_ri_t32(DisasContext *s, arg_ldst_ri2 *a)
6629 arg_ldst_ri b = {
6630 .u = a->u, .w = a->w, .p = a->p,
6631 .rn = a->rn, .rt = a->rt, .imm = a->imm
6633 return op_ldrd_ri(s, &b, a->rt2);
6636 static bool op_strd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
6638 int mem_idx = get_mem_index(s);
6639 TCGv_i32 addr, tmp;
6641 addr = op_addr_ri_pre(s, a);
6643 tmp = load_reg(s, a->rt);
6644 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
6645 tcg_temp_free_i32(tmp);
6647 tcg_gen_addi_i32(addr, addr, 4);
6649 tmp = load_reg(s, rt2);
6650 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
6651 tcg_temp_free_i32(tmp);
6653 op_addr_ri_post(s, a, addr, -4);
6654 return true;
6657 static bool trans_STRD_ri_a32(DisasContext *s, arg_ldst_ri *a)
6659 if (!ENABLE_ARCH_5TE || (a->rt & 1)) {
6660 return false;
6662 return op_strd_ri(s, a, a->rt + 1);
6665 static bool trans_STRD_ri_t32(DisasContext *s, arg_ldst_ri2 *a)
6667 arg_ldst_ri b = {
6668 .u = a->u, .w = a->w, .p = a->p,
6669 .rn = a->rn, .rt = a->rt, .imm = a->imm
6671 return op_strd_ri(s, &b, a->rt2);
6674 #define DO_LDST(NAME, WHICH, MEMOP) \
6675 static bool trans_##NAME##_ri(DisasContext *s, arg_ldst_ri *a) \
6677 return op_##WHICH##_ri(s, a, MEMOP, get_mem_index(s)); \
6679 static bool trans_##NAME##T_ri(DisasContext *s, arg_ldst_ri *a) \
6681 return op_##WHICH##_ri(s, a, MEMOP, get_a32_user_mem_index(s)); \
6683 static bool trans_##NAME##_rr(DisasContext *s, arg_ldst_rr *a) \
6685 return op_##WHICH##_rr(s, a, MEMOP, get_mem_index(s)); \
6687 static bool trans_##NAME##T_rr(DisasContext *s, arg_ldst_rr *a) \
6689 return op_##WHICH##_rr(s, a, MEMOP, get_a32_user_mem_index(s)); \
6692 DO_LDST(LDR, load, MO_UL)
6693 DO_LDST(LDRB, load, MO_UB)
6694 DO_LDST(LDRH, load, MO_UW)
6695 DO_LDST(LDRSB, load, MO_SB)
6696 DO_LDST(LDRSH, load, MO_SW)
6698 DO_LDST(STR, store, MO_UL)
6699 DO_LDST(STRB, store, MO_UB)
6700 DO_LDST(STRH, store, MO_UW)
6702 #undef DO_LDST
6705 * Synchronization primitives
6708 static bool op_swp(DisasContext *s, arg_SWP *a, MemOp opc)
6710 TCGv_i32 addr, tmp;
6711 TCGv taddr;
6713 opc |= s->be_data;
6714 addr = load_reg(s, a->rn);
6715 taddr = gen_aa32_addr(s, addr, opc);
6716 tcg_temp_free_i32(addr);
6718 tmp = load_reg(s, a->rt2);
6719 tcg_gen_atomic_xchg_i32(tmp, taddr, tmp, get_mem_index(s), opc);
6720 tcg_temp_free(taddr);
6722 store_reg(s, a->rt, tmp);
6723 return true;
6726 static bool trans_SWP(DisasContext *s, arg_SWP *a)
6728 return op_swp(s, a, MO_UL | MO_ALIGN);
6731 static bool trans_SWPB(DisasContext *s, arg_SWP *a)
6733 return op_swp(s, a, MO_UB);
6737 * Load/Store Exclusive and Load-Acquire/Store-Release
6740 static bool op_strex(DisasContext *s, arg_STREX *a, MemOp mop, bool rel)
6742 TCGv_i32 addr;
6743 /* Some cases stopped being UNPREDICTABLE in v8A (but not v8M) */
6744 bool v8a = ENABLE_ARCH_8 && !arm_dc_feature(s, ARM_FEATURE_M);
6746 /* We UNDEF for these UNPREDICTABLE cases. */
6747 if (a->rd == 15 || a->rn == 15 || a->rt == 15
6748 || a->rd == a->rn || a->rd == a->rt
6749 || (!v8a && s->thumb && (a->rd == 13 || a->rt == 13))
6750 || (mop == MO_64
6751 && (a->rt2 == 15
6752 || a->rd == a->rt2
6753 || (!v8a && s->thumb && a->rt2 == 13)))) {
6754 unallocated_encoding(s);
6755 return true;
6758 if (rel) {
6759 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
6762 addr = tcg_temp_local_new_i32();
6763 load_reg_var(s, addr, a->rn);
6764 tcg_gen_addi_i32(addr, addr, a->imm);
6766 gen_store_exclusive(s, a->rd, a->rt, a->rt2, addr, mop);
6767 tcg_temp_free_i32(addr);
6768 return true;
6771 static bool trans_STREX(DisasContext *s, arg_STREX *a)
6773 if (!ENABLE_ARCH_6) {
6774 return false;
6776 return op_strex(s, a, MO_32, false);
6779 static bool trans_STREXD_a32(DisasContext *s, arg_STREX *a)
6781 if (!ENABLE_ARCH_6K) {
6782 return false;
6784 /* We UNDEF for these UNPREDICTABLE cases. */
6785 if (a->rt & 1) {
6786 unallocated_encoding(s);
6787 return true;
6789 a->rt2 = a->rt + 1;
6790 return op_strex(s, a, MO_64, false);
6793 static bool trans_STREXD_t32(DisasContext *s, arg_STREX *a)
6795 return op_strex(s, a, MO_64, false);
6798 static bool trans_STREXB(DisasContext *s, arg_STREX *a)
6800 if (s->thumb ? !ENABLE_ARCH_7 : !ENABLE_ARCH_6K) {
6801 return false;
6803 return op_strex(s, a, MO_8, false);
6806 static bool trans_STREXH(DisasContext *s, arg_STREX *a)
6808 if (s->thumb ? !ENABLE_ARCH_7 : !ENABLE_ARCH_6K) {
6809 return false;
6811 return op_strex(s, a, MO_16, false);
6814 static bool trans_STLEX(DisasContext *s, arg_STREX *a)
6816 if (!ENABLE_ARCH_8) {
6817 return false;
6819 return op_strex(s, a, MO_32, true);
6822 static bool trans_STLEXD_a32(DisasContext *s, arg_STREX *a)
6824 if (!ENABLE_ARCH_8) {
6825 return false;
6827 /* We UNDEF for these UNPREDICTABLE cases. */
6828 if (a->rt & 1) {
6829 unallocated_encoding(s);
6830 return true;
6832 a->rt2 = a->rt + 1;
6833 return op_strex(s, a, MO_64, true);
6836 static bool trans_STLEXD_t32(DisasContext *s, arg_STREX *a)
6838 if (!ENABLE_ARCH_8) {
6839 return false;
6841 return op_strex(s, a, MO_64, true);
6844 static bool trans_STLEXB(DisasContext *s, arg_STREX *a)
6846 if (!ENABLE_ARCH_8) {
6847 return false;
6849 return op_strex(s, a, MO_8, true);
6852 static bool trans_STLEXH(DisasContext *s, arg_STREX *a)
6854 if (!ENABLE_ARCH_8) {
6855 return false;
6857 return op_strex(s, a, MO_16, true);
6860 static bool op_stl(DisasContext *s, arg_STL *a, MemOp mop)
6862 TCGv_i32 addr, tmp;
6864 if (!ENABLE_ARCH_8) {
6865 return false;
6867 /* We UNDEF for these UNPREDICTABLE cases. */
6868 if (a->rn == 15 || a->rt == 15) {
6869 unallocated_encoding(s);
6870 return true;
6873 addr = load_reg(s, a->rn);
6874 tmp = load_reg(s, a->rt);
6875 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
6876 gen_aa32_st_i32(s, tmp, addr, get_mem_index(s), mop | s->be_data);
6877 disas_set_da_iss(s, mop, a->rt | ISSIsAcqRel | ISSIsWrite);
6879 tcg_temp_free_i32(tmp);
6880 tcg_temp_free_i32(addr);
6881 return true;
6884 static bool trans_STL(DisasContext *s, arg_STL *a)
6886 return op_stl(s, a, MO_UL);
6889 static bool trans_STLB(DisasContext *s, arg_STL *a)
6891 return op_stl(s, a, MO_UB);
6894 static bool trans_STLH(DisasContext *s, arg_STL *a)
6896 return op_stl(s, a, MO_UW);
6899 static bool op_ldrex(DisasContext *s, arg_LDREX *a, MemOp mop, bool acq)
6901 TCGv_i32 addr;
6902 /* Some cases stopped being UNPREDICTABLE in v8A (but not v8M) */
6903 bool v8a = ENABLE_ARCH_8 && !arm_dc_feature(s, ARM_FEATURE_M);
6905 /* We UNDEF for these UNPREDICTABLE cases. */
6906 if (a->rn == 15 || a->rt == 15
6907 || (!v8a && s->thumb && a->rt == 13)
6908 || (mop == MO_64
6909 && (a->rt2 == 15 || a->rt == a->rt2
6910 || (!v8a && s->thumb && a->rt2 == 13)))) {
6911 unallocated_encoding(s);
6912 return true;
6915 addr = tcg_temp_local_new_i32();
6916 load_reg_var(s, addr, a->rn);
6917 tcg_gen_addi_i32(addr, addr, a->imm);
6919 gen_load_exclusive(s, a->rt, a->rt2, addr, mop);
6920 tcg_temp_free_i32(addr);
6922 if (acq) {
6923 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
6925 return true;
6928 static bool trans_LDREX(DisasContext *s, arg_LDREX *a)
6930 if (!ENABLE_ARCH_6) {
6931 return false;
6933 return op_ldrex(s, a, MO_32, false);
6936 static bool trans_LDREXD_a32(DisasContext *s, arg_LDREX *a)
6938 if (!ENABLE_ARCH_6K) {
6939 return false;
6941 /* We UNDEF for these UNPREDICTABLE cases. */
6942 if (a->rt & 1) {
6943 unallocated_encoding(s);
6944 return true;
6946 a->rt2 = a->rt + 1;
6947 return op_ldrex(s, a, MO_64, false);
6950 static bool trans_LDREXD_t32(DisasContext *s, arg_LDREX *a)
6952 return op_ldrex(s, a, MO_64, false);
6955 static bool trans_LDREXB(DisasContext *s, arg_LDREX *a)
6957 if (s->thumb ? !ENABLE_ARCH_7 : !ENABLE_ARCH_6K) {
6958 return false;
6960 return op_ldrex(s, a, MO_8, false);
6963 static bool trans_LDREXH(DisasContext *s, arg_LDREX *a)
6965 if (s->thumb ? !ENABLE_ARCH_7 : !ENABLE_ARCH_6K) {
6966 return false;
6968 return op_ldrex(s, a, MO_16, false);
6971 static bool trans_LDAEX(DisasContext *s, arg_LDREX *a)
6973 if (!ENABLE_ARCH_8) {
6974 return false;
6976 return op_ldrex(s, a, MO_32, true);
6979 static bool trans_LDAEXD_a32(DisasContext *s, arg_LDREX *a)
6981 if (!ENABLE_ARCH_8) {
6982 return false;
6984 /* We UNDEF for these UNPREDICTABLE cases. */
6985 if (a->rt & 1) {
6986 unallocated_encoding(s);
6987 return true;
6989 a->rt2 = a->rt + 1;
6990 return op_ldrex(s, a, MO_64, true);
6993 static bool trans_LDAEXD_t32(DisasContext *s, arg_LDREX *a)
6995 if (!ENABLE_ARCH_8) {
6996 return false;
6998 return op_ldrex(s, a, MO_64, true);
7001 static bool trans_LDAEXB(DisasContext *s, arg_LDREX *a)
7003 if (!ENABLE_ARCH_8) {
7004 return false;
7006 return op_ldrex(s, a, MO_8, true);
7009 static bool trans_LDAEXH(DisasContext *s, arg_LDREX *a)
7011 if (!ENABLE_ARCH_8) {
7012 return false;
7014 return op_ldrex(s, a, MO_16, true);
7017 static bool op_lda(DisasContext *s, arg_LDA *a, MemOp mop)
7019 TCGv_i32 addr, tmp;
7021 if (!ENABLE_ARCH_8) {
7022 return false;
7024 /* We UNDEF for these UNPREDICTABLE cases. */
7025 if (a->rn == 15 || a->rt == 15) {
7026 unallocated_encoding(s);
7027 return true;
7030 addr = load_reg(s, a->rn);
7031 tmp = tcg_temp_new_i32();
7032 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), mop | s->be_data);
7033 disas_set_da_iss(s, mop, a->rt | ISSIsAcqRel);
7034 tcg_temp_free_i32(addr);
7036 store_reg(s, a->rt, tmp);
7037 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
7038 return true;
7041 static bool trans_LDA(DisasContext *s, arg_LDA *a)
7043 return op_lda(s, a, MO_UL);
7046 static bool trans_LDAB(DisasContext *s, arg_LDA *a)
7048 return op_lda(s, a, MO_UB);
7051 static bool trans_LDAH(DisasContext *s, arg_LDA *a)
7053 return op_lda(s, a, MO_UW);
7057 * Media instructions
7060 static bool trans_USADA8(DisasContext *s, arg_USADA8 *a)
7062 TCGv_i32 t1, t2;
7064 if (!ENABLE_ARCH_6) {
7065 return false;
7068 t1 = load_reg(s, a->rn);
7069 t2 = load_reg(s, a->rm);
7070 gen_helper_usad8(t1, t1, t2);
7071 tcg_temp_free_i32(t2);
7072 if (a->ra != 15) {
7073 t2 = load_reg(s, a->ra);
7074 tcg_gen_add_i32(t1, t1, t2);
7075 tcg_temp_free_i32(t2);
7077 store_reg(s, a->rd, t1);
7078 return true;
7081 static bool op_bfx(DisasContext *s, arg_UBFX *a, bool u)
7083 TCGv_i32 tmp;
7084 int width = a->widthm1 + 1;
7085 int shift = a->lsb;
7087 if (!ENABLE_ARCH_6T2) {
7088 return false;
7090 if (shift + width > 32) {
7091 /* UNPREDICTABLE; we choose to UNDEF */
7092 unallocated_encoding(s);
7093 return true;
7096 tmp = load_reg(s, a->rn);
7097 if (u) {
7098 tcg_gen_extract_i32(tmp, tmp, shift, width);
7099 } else {
7100 tcg_gen_sextract_i32(tmp, tmp, shift, width);
7102 store_reg(s, a->rd, tmp);
7103 return true;
7106 static bool trans_SBFX(DisasContext *s, arg_SBFX *a)
7108 return op_bfx(s, a, false);
7111 static bool trans_UBFX(DisasContext *s, arg_UBFX *a)
7113 return op_bfx(s, a, true);
7116 static bool trans_BFCI(DisasContext *s, arg_BFCI *a)
7118 TCGv_i32 tmp;
7119 int msb = a->msb, lsb = a->lsb;
7120 int width;
7122 if (!ENABLE_ARCH_6T2) {
7123 return false;
7125 if (msb < lsb) {
7126 /* UNPREDICTABLE; we choose to UNDEF */
7127 unallocated_encoding(s);
7128 return true;
7131 width = msb + 1 - lsb;
7132 if (a->rn == 15) {
7133 /* BFC */
7134 tmp = tcg_const_i32(0);
7135 } else {
7136 /* BFI */
7137 tmp = load_reg(s, a->rn);
7139 if (width != 32) {
7140 TCGv_i32 tmp2 = load_reg(s, a->rd);
7141 tcg_gen_deposit_i32(tmp, tmp2, tmp, lsb, width);
7142 tcg_temp_free_i32(tmp2);
7144 store_reg(s, a->rd, tmp);
7145 return true;
7148 static bool trans_UDF(DisasContext *s, arg_UDF *a)
7150 unallocated_encoding(s);
7151 return true;
7155 * Parallel addition and subtraction
7158 static bool op_par_addsub(DisasContext *s, arg_rrr *a,
7159 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32))
7161 TCGv_i32 t0, t1;
7163 if (s->thumb
7164 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
7165 : !ENABLE_ARCH_6) {
7166 return false;
7169 t0 = load_reg(s, a->rn);
7170 t1 = load_reg(s, a->rm);
7172 gen(t0, t0, t1);
7174 tcg_temp_free_i32(t1);
7175 store_reg(s, a->rd, t0);
7176 return true;
7179 static bool op_par_addsub_ge(DisasContext *s, arg_rrr *a,
7180 void (*gen)(TCGv_i32, TCGv_i32,
7181 TCGv_i32, TCGv_ptr))
7183 TCGv_i32 t0, t1;
7184 TCGv_ptr ge;
7186 if (s->thumb
7187 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
7188 : !ENABLE_ARCH_6) {
7189 return false;
7192 t0 = load_reg(s, a->rn);
7193 t1 = load_reg(s, a->rm);
7195 ge = tcg_temp_new_ptr();
7196 tcg_gen_addi_ptr(ge, cpu_env, offsetof(CPUARMState, GE));
7197 gen(t0, t0, t1, ge);
7199 tcg_temp_free_ptr(ge);
7200 tcg_temp_free_i32(t1);
7201 store_reg(s, a->rd, t0);
7202 return true;
7205 #define DO_PAR_ADDSUB(NAME, helper) \
7206 static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
7208 return op_par_addsub(s, a, helper); \
7211 #define DO_PAR_ADDSUB_GE(NAME, helper) \
7212 static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
7214 return op_par_addsub_ge(s, a, helper); \
7217 DO_PAR_ADDSUB_GE(SADD16, gen_helper_sadd16)
7218 DO_PAR_ADDSUB_GE(SASX, gen_helper_saddsubx)
7219 DO_PAR_ADDSUB_GE(SSAX, gen_helper_ssubaddx)
7220 DO_PAR_ADDSUB_GE(SSUB16, gen_helper_ssub16)
7221 DO_PAR_ADDSUB_GE(SADD8, gen_helper_sadd8)
7222 DO_PAR_ADDSUB_GE(SSUB8, gen_helper_ssub8)
7224 DO_PAR_ADDSUB_GE(UADD16, gen_helper_uadd16)
7225 DO_PAR_ADDSUB_GE(UASX, gen_helper_uaddsubx)
7226 DO_PAR_ADDSUB_GE(USAX, gen_helper_usubaddx)
7227 DO_PAR_ADDSUB_GE(USUB16, gen_helper_usub16)
7228 DO_PAR_ADDSUB_GE(UADD8, gen_helper_uadd8)
7229 DO_PAR_ADDSUB_GE(USUB8, gen_helper_usub8)
7231 DO_PAR_ADDSUB(QADD16, gen_helper_qadd16)
7232 DO_PAR_ADDSUB(QASX, gen_helper_qaddsubx)
7233 DO_PAR_ADDSUB(QSAX, gen_helper_qsubaddx)
7234 DO_PAR_ADDSUB(QSUB16, gen_helper_qsub16)
7235 DO_PAR_ADDSUB(QADD8, gen_helper_qadd8)
7236 DO_PAR_ADDSUB(QSUB8, gen_helper_qsub8)
7238 DO_PAR_ADDSUB(UQADD16, gen_helper_uqadd16)
7239 DO_PAR_ADDSUB(UQASX, gen_helper_uqaddsubx)
7240 DO_PAR_ADDSUB(UQSAX, gen_helper_uqsubaddx)
7241 DO_PAR_ADDSUB(UQSUB16, gen_helper_uqsub16)
7242 DO_PAR_ADDSUB(UQADD8, gen_helper_uqadd8)
7243 DO_PAR_ADDSUB(UQSUB8, gen_helper_uqsub8)
7245 DO_PAR_ADDSUB(SHADD16, gen_helper_shadd16)
7246 DO_PAR_ADDSUB(SHASX, gen_helper_shaddsubx)
7247 DO_PAR_ADDSUB(SHSAX, gen_helper_shsubaddx)
7248 DO_PAR_ADDSUB(SHSUB16, gen_helper_shsub16)
7249 DO_PAR_ADDSUB(SHADD8, gen_helper_shadd8)
7250 DO_PAR_ADDSUB(SHSUB8, gen_helper_shsub8)
7252 DO_PAR_ADDSUB(UHADD16, gen_helper_uhadd16)
7253 DO_PAR_ADDSUB(UHASX, gen_helper_uhaddsubx)
7254 DO_PAR_ADDSUB(UHSAX, gen_helper_uhsubaddx)
7255 DO_PAR_ADDSUB(UHSUB16, gen_helper_uhsub16)
7256 DO_PAR_ADDSUB(UHADD8, gen_helper_uhadd8)
7257 DO_PAR_ADDSUB(UHSUB8, gen_helper_uhsub8)
7259 #undef DO_PAR_ADDSUB
7260 #undef DO_PAR_ADDSUB_GE
7263 * Packing, unpacking, saturation, and reversal
7266 static bool trans_PKH(DisasContext *s, arg_PKH *a)
7268 TCGv_i32 tn, tm;
7269 int shift = a->imm;
7271 if (s->thumb
7272 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
7273 : !ENABLE_ARCH_6) {
7274 return false;
7277 tn = load_reg(s, a->rn);
7278 tm = load_reg(s, a->rm);
7279 if (a->tb) {
7280 /* PKHTB */
7281 if (shift == 0) {
7282 shift = 31;
7284 tcg_gen_sari_i32(tm, tm, shift);
7285 tcg_gen_deposit_i32(tn, tn, tm, 0, 16);
7286 } else {
7287 /* PKHBT */
7288 tcg_gen_shli_i32(tm, tm, shift);
7289 tcg_gen_deposit_i32(tn, tm, tn, 0, 16);
7291 tcg_temp_free_i32(tm);
7292 store_reg(s, a->rd, tn);
7293 return true;
7296 static bool op_sat(DisasContext *s, arg_sat *a,
7297 void (*gen)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32))
7299 TCGv_i32 tmp, satimm;
7300 int shift = a->imm;
7302 if (!ENABLE_ARCH_6) {
7303 return false;
7306 tmp = load_reg(s, a->rn);
7307 if (a->sh) {
7308 tcg_gen_sari_i32(tmp, tmp, shift ? shift : 31);
7309 } else {
7310 tcg_gen_shli_i32(tmp, tmp, shift);
7313 satimm = tcg_const_i32(a->satimm);
7314 gen(tmp, cpu_env, tmp, satimm);
7315 tcg_temp_free_i32(satimm);
7317 store_reg(s, a->rd, tmp);
7318 return true;
7321 static bool trans_SSAT(DisasContext *s, arg_sat *a)
7323 return op_sat(s, a, gen_helper_ssat);
7326 static bool trans_USAT(DisasContext *s, arg_sat *a)
7328 return op_sat(s, a, gen_helper_usat);
7331 static bool trans_SSAT16(DisasContext *s, arg_sat *a)
7333 if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
7334 return false;
7336 return op_sat(s, a, gen_helper_ssat16);
7339 static bool trans_USAT16(DisasContext *s, arg_sat *a)
7341 if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
7342 return false;
7344 return op_sat(s, a, gen_helper_usat16);
7347 static bool op_xta(DisasContext *s, arg_rrr_rot *a,
7348 void (*gen_extract)(TCGv_i32, TCGv_i32),
7349 void (*gen_add)(TCGv_i32, TCGv_i32, TCGv_i32))
7351 TCGv_i32 tmp;
7353 if (!ENABLE_ARCH_6) {
7354 return false;
7357 tmp = load_reg(s, a->rm);
7359 * TODO: In many cases we could do a shift instead of a rotate.
7360 * Combined with a simple extend, that becomes an extract.
7362 tcg_gen_rotri_i32(tmp, tmp, a->rot * 8);
7363 gen_extract(tmp, tmp);
7365 if (a->rn != 15) {
7366 TCGv_i32 tmp2 = load_reg(s, a->rn);
7367 gen_add(tmp, tmp, tmp2);
7368 tcg_temp_free_i32(tmp2);
7370 store_reg(s, a->rd, tmp);
7371 return true;
7374 static bool trans_SXTAB(DisasContext *s, arg_rrr_rot *a)
7376 return op_xta(s, a, tcg_gen_ext8s_i32, tcg_gen_add_i32);
7379 static bool trans_SXTAH(DisasContext *s, arg_rrr_rot *a)
7381 return op_xta(s, a, tcg_gen_ext16s_i32, tcg_gen_add_i32);
7384 static bool trans_SXTAB16(DisasContext *s, arg_rrr_rot *a)
7386 if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
7387 return false;
7389 return op_xta(s, a, gen_helper_sxtb16, gen_add16);
7392 static bool trans_UXTAB(DisasContext *s, arg_rrr_rot *a)
7394 return op_xta(s, a, tcg_gen_ext8u_i32, tcg_gen_add_i32);
7397 static bool trans_UXTAH(DisasContext *s, arg_rrr_rot *a)
7399 return op_xta(s, a, tcg_gen_ext16u_i32, tcg_gen_add_i32);
7402 static bool trans_UXTAB16(DisasContext *s, arg_rrr_rot *a)
7404 if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
7405 return false;
7407 return op_xta(s, a, gen_helper_uxtb16, gen_add16);
7410 static bool trans_SEL(DisasContext *s, arg_rrr *a)
7412 TCGv_i32 t1, t2, t3;
7414 if (s->thumb
7415 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
7416 : !ENABLE_ARCH_6) {
7417 return false;
7420 t1 = load_reg(s, a->rn);
7421 t2 = load_reg(s, a->rm);
7422 t3 = tcg_temp_new_i32();
7423 tcg_gen_ld_i32(t3, cpu_env, offsetof(CPUARMState, GE));
7424 gen_helper_sel_flags(t1, t3, t1, t2);
7425 tcg_temp_free_i32(t3);
7426 tcg_temp_free_i32(t2);
7427 store_reg(s, a->rd, t1);
7428 return true;
7431 static bool op_rr(DisasContext *s, arg_rr *a,
7432 void (*gen)(TCGv_i32, TCGv_i32))
7434 TCGv_i32 tmp;
7436 tmp = load_reg(s, a->rm);
7437 gen(tmp, tmp);
7438 store_reg(s, a->rd, tmp);
7439 return true;
7442 static bool trans_REV(DisasContext *s, arg_rr *a)
7444 if (!ENABLE_ARCH_6) {
7445 return false;
7447 return op_rr(s, a, tcg_gen_bswap32_i32);
7450 static bool trans_REV16(DisasContext *s, arg_rr *a)
7452 if (!ENABLE_ARCH_6) {
7453 return false;
7455 return op_rr(s, a, gen_rev16);
7458 static bool trans_REVSH(DisasContext *s, arg_rr *a)
7460 if (!ENABLE_ARCH_6) {
7461 return false;
7463 return op_rr(s, a, gen_revsh);
7466 static bool trans_RBIT(DisasContext *s, arg_rr *a)
7468 if (!ENABLE_ARCH_6T2) {
7469 return false;
7471 return op_rr(s, a, gen_helper_rbit);
7475 * Signed multiply, signed and unsigned divide
7478 static bool op_smlad(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub)
7480 TCGv_i32 t1, t2;
7482 if (!ENABLE_ARCH_6) {
7483 return false;
7486 t1 = load_reg(s, a->rn);
7487 t2 = load_reg(s, a->rm);
7488 if (m_swap) {
7489 gen_swap_half(t2, t2);
7491 gen_smul_dual(t1, t2);
7493 if (sub) {
7495 * This subtraction cannot overflow, so we can do a simple
7496 * 32-bit subtraction and then a possible 32-bit saturating
7497 * addition of Ra.
7499 tcg_gen_sub_i32(t1, t1, t2);
7500 tcg_temp_free_i32(t2);
7502 if (a->ra != 15) {
7503 t2 = load_reg(s, a->ra);
7504 gen_helper_add_setq(t1, cpu_env, t1, t2);
7505 tcg_temp_free_i32(t2);
7507 } else if (a->ra == 15) {
7508 /* Single saturation-checking addition */
7509 gen_helper_add_setq(t1, cpu_env, t1, t2);
7510 tcg_temp_free_i32(t2);
7511 } else {
7513 * We need to add the products and Ra together and then
7514 * determine whether the final result overflowed. Doing
7515 * this as two separate add-and-check-overflow steps incorrectly
7516 * sets Q for cases like (-32768 * -32768) + (-32768 * -32768) + -1.
7517 * Do all the arithmetic at 64-bits and then check for overflow.
7519 TCGv_i64 p64, q64;
7520 TCGv_i32 t3, qf, one;
7522 p64 = tcg_temp_new_i64();
7523 q64 = tcg_temp_new_i64();
7524 tcg_gen_ext_i32_i64(p64, t1);
7525 tcg_gen_ext_i32_i64(q64, t2);
7526 tcg_gen_add_i64(p64, p64, q64);
7527 load_reg_var(s, t2, a->ra);
7528 tcg_gen_ext_i32_i64(q64, t2);
7529 tcg_gen_add_i64(p64, p64, q64);
7530 tcg_temp_free_i64(q64);
7532 tcg_gen_extr_i64_i32(t1, t2, p64);
7533 tcg_temp_free_i64(p64);
7535 * t1 is the low half of the result which goes into Rd.
7536 * We have overflow and must set Q if the high half (t2)
7537 * is different from the sign-extension of t1.
7539 t3 = tcg_temp_new_i32();
7540 tcg_gen_sari_i32(t3, t1, 31);
7541 qf = load_cpu_field(QF);
7542 one = tcg_const_i32(1);
7543 tcg_gen_movcond_i32(TCG_COND_NE, qf, t2, t3, one, qf);
7544 store_cpu_field(qf, QF);
7545 tcg_temp_free_i32(one);
7546 tcg_temp_free_i32(t3);
7547 tcg_temp_free_i32(t2);
7549 store_reg(s, a->rd, t1);
7550 return true;
7553 static bool trans_SMLAD(DisasContext *s, arg_rrrr *a)
7555 return op_smlad(s, a, false, false);
7558 static bool trans_SMLADX(DisasContext *s, arg_rrrr *a)
7560 return op_smlad(s, a, true, false);
7563 static bool trans_SMLSD(DisasContext *s, arg_rrrr *a)
7565 return op_smlad(s, a, false, true);
7568 static bool trans_SMLSDX(DisasContext *s, arg_rrrr *a)
7570 return op_smlad(s, a, true, true);
7573 static bool op_smlald(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub)
7575 TCGv_i32 t1, t2;
7576 TCGv_i64 l1, l2;
7578 if (!ENABLE_ARCH_6) {
7579 return false;
7582 t1 = load_reg(s, a->rn);
7583 t2 = load_reg(s, a->rm);
7584 if (m_swap) {
7585 gen_swap_half(t2, t2);
7587 gen_smul_dual(t1, t2);
7589 l1 = tcg_temp_new_i64();
7590 l2 = tcg_temp_new_i64();
7591 tcg_gen_ext_i32_i64(l1, t1);
7592 tcg_gen_ext_i32_i64(l2, t2);
7593 tcg_temp_free_i32(t1);
7594 tcg_temp_free_i32(t2);
7596 if (sub) {
7597 tcg_gen_sub_i64(l1, l1, l2);
7598 } else {
7599 tcg_gen_add_i64(l1, l1, l2);
7601 tcg_temp_free_i64(l2);
7603 gen_addq(s, l1, a->ra, a->rd);
7604 gen_storeq_reg(s, a->ra, a->rd, l1);
7605 tcg_temp_free_i64(l1);
7606 return true;
7609 static bool trans_SMLALD(DisasContext *s, arg_rrrr *a)
7611 return op_smlald(s, a, false, false);
7614 static bool trans_SMLALDX(DisasContext *s, arg_rrrr *a)
7616 return op_smlald(s, a, true, false);
7619 static bool trans_SMLSLD(DisasContext *s, arg_rrrr *a)
7621 return op_smlald(s, a, false, true);
7624 static bool trans_SMLSLDX(DisasContext *s, arg_rrrr *a)
7626 return op_smlald(s, a, true, true);
7629 static bool op_smmla(DisasContext *s, arg_rrrr *a, bool round, bool sub)
7631 TCGv_i32 t1, t2;
7633 if (s->thumb
7634 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
7635 : !ENABLE_ARCH_6) {
7636 return false;
7639 t1 = load_reg(s, a->rn);
7640 t2 = load_reg(s, a->rm);
7641 tcg_gen_muls2_i32(t2, t1, t1, t2);
7643 if (a->ra != 15) {
7644 TCGv_i32 t3 = load_reg(s, a->ra);
7645 if (sub) {
7647 * For SMMLS, we need a 64-bit subtract. Borrow caused by
7648 * a non-zero multiplicand lowpart, and the correct result
7649 * lowpart for rounding.
7651 TCGv_i32 zero = tcg_const_i32(0);
7652 tcg_gen_sub2_i32(t2, t1, zero, t3, t2, t1);
7653 tcg_temp_free_i32(zero);
7654 } else {
7655 tcg_gen_add_i32(t1, t1, t3);
7657 tcg_temp_free_i32(t3);
7659 if (round) {
7661 * Adding 0x80000000 to the 64-bit quantity means that we have
7662 * carry in to the high word when the low word has the msb set.
7664 tcg_gen_shri_i32(t2, t2, 31);
7665 tcg_gen_add_i32(t1, t1, t2);
7667 tcg_temp_free_i32(t2);
7668 store_reg(s, a->rd, t1);
7669 return true;
7672 static bool trans_SMMLA(DisasContext *s, arg_rrrr *a)
7674 return op_smmla(s, a, false, false);
7677 static bool trans_SMMLAR(DisasContext *s, arg_rrrr *a)
7679 return op_smmla(s, a, true, false);
7682 static bool trans_SMMLS(DisasContext *s, arg_rrrr *a)
7684 return op_smmla(s, a, false, true);
7687 static bool trans_SMMLSR(DisasContext *s, arg_rrrr *a)
7689 return op_smmla(s, a, true, true);
7692 static bool op_div(DisasContext *s, arg_rrr *a, bool u)
7694 TCGv_i32 t1, t2;
7696 if (s->thumb
7697 ? !dc_isar_feature(aa32_thumb_div, s)
7698 : !dc_isar_feature(aa32_arm_div, s)) {
7699 return false;
7702 t1 = load_reg(s, a->rn);
7703 t2 = load_reg(s, a->rm);
7704 if (u) {
7705 gen_helper_udiv(t1, t1, t2);
7706 } else {
7707 gen_helper_sdiv(t1, t1, t2);
7709 tcg_temp_free_i32(t2);
7710 store_reg(s, a->rd, t1);
7711 return true;
7714 static bool trans_SDIV(DisasContext *s, arg_rrr *a)
7716 return op_div(s, a, false);
7719 static bool trans_UDIV(DisasContext *s, arg_rrr *a)
7721 return op_div(s, a, true);
7725 * Block data transfer
7728 static TCGv_i32 op_addr_block_pre(DisasContext *s, arg_ldst_block *a, int n)
7730 TCGv_i32 addr = load_reg(s, a->rn);
7732 if (a->b) {
7733 if (a->i) {
7734 /* pre increment */
7735 tcg_gen_addi_i32(addr, addr, 4);
7736 } else {
7737 /* pre decrement */
7738 tcg_gen_addi_i32(addr, addr, -(n * 4));
7740 } else if (!a->i && n != 1) {
7741 /* post decrement */
7742 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7745 if (s->v8m_stackcheck && a->rn == 13 && a->w) {
7747 * If the writeback is incrementing SP rather than
7748 * decrementing it, and the initial SP is below the
7749 * stack limit but the final written-back SP would
7750 * be above, then then we must not perform any memory
7751 * accesses, but it is IMPDEF whether we generate
7752 * an exception. We choose to do so in this case.
7753 * At this point 'addr' is the lowest address, so
7754 * either the original SP (if incrementing) or our
7755 * final SP (if decrementing), so that's what we check.
7757 gen_helper_v8m_stackcheck(cpu_env, addr);
7760 return addr;
7763 static void op_addr_block_post(DisasContext *s, arg_ldst_block *a,
7764 TCGv_i32 addr, int n)
7766 if (a->w) {
7767 /* write back */
7768 if (!a->b) {
7769 if (a->i) {
7770 /* post increment */
7771 tcg_gen_addi_i32(addr, addr, 4);
7772 } else {
7773 /* post decrement */
7774 tcg_gen_addi_i32(addr, addr, -(n * 4));
7776 } else if (!a->i && n != 1) {
7777 /* pre decrement */
7778 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7780 store_reg(s, a->rn, addr);
7781 } else {
7782 tcg_temp_free_i32(addr);
7786 static bool op_stm(DisasContext *s, arg_ldst_block *a, int min_n)
7788 int i, j, n, list, mem_idx;
7789 bool user = a->u;
7790 TCGv_i32 addr, tmp, tmp2;
7792 if (user) {
7793 /* STM (user) */
7794 if (IS_USER(s)) {
7795 /* Only usable in supervisor mode. */
7796 unallocated_encoding(s);
7797 return true;
7801 list = a->list;
7802 n = ctpop16(list);
7803 if (n < min_n || a->rn == 15) {
7804 unallocated_encoding(s);
7805 return true;
7808 addr = op_addr_block_pre(s, a, n);
7809 mem_idx = get_mem_index(s);
7811 for (i = j = 0; i < 16; i++) {
7812 if (!(list & (1 << i))) {
7813 continue;
7816 if (user && i != 15) {
7817 tmp = tcg_temp_new_i32();
7818 tmp2 = tcg_const_i32(i);
7819 gen_helper_get_user_reg(tmp, cpu_env, tmp2);
7820 tcg_temp_free_i32(tmp2);
7821 } else {
7822 tmp = load_reg(s, i);
7824 gen_aa32_st32(s, tmp, addr, mem_idx);
7825 tcg_temp_free_i32(tmp);
7827 /* No need to add after the last transfer. */
7828 if (++j != n) {
7829 tcg_gen_addi_i32(addr, addr, 4);
7833 op_addr_block_post(s, a, addr, n);
7834 return true;
7837 static bool trans_STM(DisasContext *s, arg_ldst_block *a)
7839 /* BitCount(list) < 1 is UNPREDICTABLE */
7840 return op_stm(s, a, 1);
7843 static bool trans_STM_t32(DisasContext *s, arg_ldst_block *a)
7845 /* Writeback register in register list is UNPREDICTABLE for T32. */
7846 if (a->w && (a->list & (1 << a->rn))) {
7847 unallocated_encoding(s);
7848 return true;
7850 /* BitCount(list) < 2 is UNPREDICTABLE */
7851 return op_stm(s, a, 2);
7854 static bool do_ldm(DisasContext *s, arg_ldst_block *a, int min_n)
7856 int i, j, n, list, mem_idx;
7857 bool loaded_base;
7858 bool user = a->u;
7859 bool exc_return = false;
7860 TCGv_i32 addr, tmp, tmp2, loaded_var;
7862 if (user) {
7863 /* LDM (user), LDM (exception return) */
7864 if (IS_USER(s)) {
7865 /* Only usable in supervisor mode. */
7866 unallocated_encoding(s);
7867 return true;
7869 if (extract32(a->list, 15, 1)) {
7870 exc_return = true;
7871 user = false;
7872 } else {
7873 /* LDM (user) does not allow writeback. */
7874 if (a->w) {
7875 unallocated_encoding(s);
7876 return true;
7881 list = a->list;
7882 n = ctpop16(list);
7883 if (n < min_n || a->rn == 15) {
7884 unallocated_encoding(s);
7885 return true;
7888 addr = op_addr_block_pre(s, a, n);
7889 mem_idx = get_mem_index(s);
7890 loaded_base = false;
7891 loaded_var = NULL;
7893 for (i = j = 0; i < 16; i++) {
7894 if (!(list & (1 << i))) {
7895 continue;
7898 tmp = tcg_temp_new_i32();
7899 gen_aa32_ld32u(s, tmp, addr, mem_idx);
7900 if (user) {
7901 tmp2 = tcg_const_i32(i);
7902 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
7903 tcg_temp_free_i32(tmp2);
7904 tcg_temp_free_i32(tmp);
7905 } else if (i == a->rn) {
7906 loaded_var = tmp;
7907 loaded_base = true;
7908 } else if (i == 15 && exc_return) {
7909 store_pc_exc_ret(s, tmp);
7910 } else {
7911 store_reg_from_load(s, i, tmp);
7914 /* No need to add after the last transfer. */
7915 if (++j != n) {
7916 tcg_gen_addi_i32(addr, addr, 4);
7920 op_addr_block_post(s, a, addr, n);
7922 if (loaded_base) {
7923 /* Note that we reject base == pc above. */
7924 store_reg(s, a->rn, loaded_var);
7927 if (exc_return) {
7928 /* Restore CPSR from SPSR. */
7929 tmp = load_cpu_field(spsr);
7930 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
7931 gen_io_start();
7933 gen_helper_cpsr_write_eret(cpu_env, tmp);
7934 tcg_temp_free_i32(tmp);
7935 /* Must exit loop to check un-masked IRQs */
7936 s->base.is_jmp = DISAS_EXIT;
7938 return true;
7941 static bool trans_LDM_a32(DisasContext *s, arg_ldst_block *a)
7944 * Writeback register in register list is UNPREDICTABLE
7945 * for ArchVersion() >= 7. Prior to v7, A32 would write
7946 * an UNKNOWN value to the base register.
7948 if (ENABLE_ARCH_7 && a->w && (a->list & (1 << a->rn))) {
7949 unallocated_encoding(s);
7950 return true;
7952 /* BitCount(list) < 1 is UNPREDICTABLE */
7953 return do_ldm(s, a, 1);
7956 static bool trans_LDM_t32(DisasContext *s, arg_ldst_block *a)
7958 /* Writeback register in register list is UNPREDICTABLE for T32. */
7959 if (a->w && (a->list & (1 << a->rn))) {
7960 unallocated_encoding(s);
7961 return true;
7963 /* BitCount(list) < 2 is UNPREDICTABLE */
7964 return do_ldm(s, a, 2);
7967 static bool trans_LDM_t16(DisasContext *s, arg_ldst_block *a)
7969 /* Writeback is conditional on the base register not being loaded. */
7970 a->w = !(a->list & (1 << a->rn));
7971 /* BitCount(list) < 1 is UNPREDICTABLE */
7972 return do_ldm(s, a, 1);
7975 static bool trans_CLRM(DisasContext *s, arg_CLRM *a)
7977 int i;
7978 TCGv_i32 zero;
7980 if (!dc_isar_feature(aa32_m_sec_state, s)) {
7981 return false;
7984 if (extract32(a->list, 13, 1)) {
7985 return false;
7988 if (!a->list) {
7989 /* UNPREDICTABLE; we choose to UNDEF */
7990 return false;
7993 zero = tcg_const_i32(0);
7994 for (i = 0; i < 15; i++) {
7995 if (extract32(a->list, i, 1)) {
7996 /* Clear R[i] */
7997 tcg_gen_mov_i32(cpu_R[i], zero);
8000 if (extract32(a->list, 15, 1)) {
8002 * Clear APSR (by calling the MSR helper with the same argument
8003 * as for "MSR APSR_nzcvqg, Rn": mask = 0b1100, SYSM=0)
8005 TCGv_i32 maskreg = tcg_const_i32(0xc << 8);
8006 gen_helper_v7m_msr(cpu_env, maskreg, zero);
8007 tcg_temp_free_i32(maskreg);
8009 tcg_temp_free_i32(zero);
8010 return true;
8014 * Branch, branch with link
8017 static bool trans_B(DisasContext *s, arg_i *a)
8019 gen_jmp(s, read_pc(s) + a->imm);
8020 return true;
8023 static bool trans_B_cond_thumb(DisasContext *s, arg_ci *a)
8025 /* This has cond from encoding, required to be outside IT block. */
8026 if (a->cond >= 0xe) {
8027 return false;
8029 if (s->condexec_mask) {
8030 unallocated_encoding(s);
8031 return true;
8033 arm_skip_unless(s, a->cond);
8034 gen_jmp(s, read_pc(s) + a->imm);
8035 return true;
8038 static bool trans_BL(DisasContext *s, arg_i *a)
8040 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
8041 gen_jmp(s, read_pc(s) + a->imm);
8042 return true;
8045 static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
8047 TCGv_i32 tmp;
8050 * BLX <imm> would be useless on M-profile; the encoding space
8051 * is used for other insns from v8.1M onward, and UNDEFs before that.
8053 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8054 return false;
8057 /* For A32, ARM_FEATURE_V5 is checked near the start of the uncond block. */
8058 if (s->thumb && (a->imm & 2)) {
8059 return false;
8061 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
8062 tmp = tcg_const_i32(!s->thumb);
8063 store_cpu_field(tmp, thumb);
8064 gen_jmp(s, (read_pc(s) & ~3) + a->imm);
8065 return true;
8068 static bool trans_BL_BLX_prefix(DisasContext *s, arg_BL_BLX_prefix *a)
8070 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
8071 tcg_gen_movi_i32(cpu_R[14], read_pc(s) + (a->imm << 12));
8072 return true;
8075 static bool trans_BL_suffix(DisasContext *s, arg_BL_suffix *a)
8077 TCGv_i32 tmp = tcg_temp_new_i32();
8079 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
8080 tcg_gen_addi_i32(tmp, cpu_R[14], (a->imm << 1) | 1);
8081 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | 1);
8082 gen_bx(s, tmp);
8083 return true;
8086 static bool trans_BLX_suffix(DisasContext *s, arg_BLX_suffix *a)
8088 TCGv_i32 tmp;
8090 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
8091 if (!ENABLE_ARCH_5) {
8092 return false;
8094 tmp = tcg_temp_new_i32();
8095 tcg_gen_addi_i32(tmp, cpu_R[14], a->imm << 1);
8096 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
8097 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | 1);
8098 gen_bx(s, tmp);
8099 return true;
8102 static bool trans_BF(DisasContext *s, arg_BF *a)
8105 * M-profile branch future insns. The architecture permits an
8106 * implementation to implement these as NOPs (equivalent to
8107 * discarding the LO_BRANCH_INFO cache immediately), and we
8108 * take that IMPDEF option because for QEMU a "real" implementation
8109 * would be complicated and wouldn't execute any faster.
8111 if (!dc_isar_feature(aa32_lob, s)) {
8112 return false;
8114 if (a->boff == 0) {
8115 /* SEE "Related encodings" (loop insns) */
8116 return false;
8118 /* Handle as NOP */
8119 return true;
8122 static bool trans_DLS(DisasContext *s, arg_DLS *a)
8124 /* M-profile low-overhead loop start */
8125 TCGv_i32 tmp;
8127 if (!dc_isar_feature(aa32_lob, s)) {
8128 return false;
8130 if (a->rn == 13 || a->rn == 15) {
8131 /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
8132 return false;
8135 /* Not a while loop, no tail predication: just set LR to the count */
8136 tmp = load_reg(s, a->rn);
8137 store_reg(s, 14, tmp);
8138 return true;
8141 static bool trans_WLS(DisasContext *s, arg_WLS *a)
8143 /* M-profile low-overhead while-loop start */
8144 TCGv_i32 tmp;
8145 TCGLabel *nextlabel;
8147 if (!dc_isar_feature(aa32_lob, s)) {
8148 return false;
8150 if (a->rn == 13 || a->rn == 15) {
8151 /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
8152 return false;
8154 if (s->condexec_mask) {
8156 * WLS in an IT block is CONSTRAINED UNPREDICTABLE;
8157 * we choose to UNDEF, because otherwise our use of
8158 * gen_goto_tb(1) would clash with the use of TB exit 1
8159 * in the dc->condjmp condition-failed codepath in
8160 * arm_tr_tb_stop() and we'd get an assertion.
8162 return false;
8164 nextlabel = gen_new_label();
8165 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_R[a->rn], 0, nextlabel);
8166 tmp = load_reg(s, a->rn);
8167 store_reg(s, 14, tmp);
8168 gen_jmp_tb(s, s->base.pc_next, 1);
8170 gen_set_label(nextlabel);
8171 gen_jmp(s, read_pc(s) + a->imm);
8172 return true;
8175 static bool trans_LE(DisasContext *s, arg_LE *a)
8178 * M-profile low-overhead loop end. The architecture permits an
8179 * implementation to discard the LO_BRANCH_INFO cache at any time,
8180 * and we take the IMPDEF option to never set it in the first place
8181 * (equivalent to always discarding it immediately), because for QEMU
8182 * a "real" implementation would be complicated and wouldn't execute
8183 * any faster.
8185 TCGv_i32 tmp;
8187 if (!dc_isar_feature(aa32_lob, s)) {
8188 return false;
8191 if (!a->f) {
8192 /* Not loop-forever. If LR <= 1 this is the last loop: do nothing. */
8193 arm_gen_condlabel(s);
8194 tcg_gen_brcondi_i32(TCG_COND_LEU, cpu_R[14], 1, s->condlabel);
8195 /* Decrement LR */
8196 tmp = load_reg(s, 14);
8197 tcg_gen_addi_i32(tmp, tmp, -1);
8198 store_reg(s, 14, tmp);
8200 /* Jump back to the loop start */
8201 gen_jmp(s, read_pc(s) - a->imm);
8202 return true;
8205 static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
8207 TCGv_i32 addr, tmp;
8209 tmp = load_reg(s, a->rm);
8210 if (half) {
8211 tcg_gen_add_i32(tmp, tmp, tmp);
8213 addr = load_reg(s, a->rn);
8214 tcg_gen_add_i32(addr, addr, tmp);
8216 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s),
8217 half ? MO_UW | s->be_data : MO_UB);
8218 tcg_temp_free_i32(addr);
8220 tcg_gen_add_i32(tmp, tmp, tmp);
8221 tcg_gen_addi_i32(tmp, tmp, read_pc(s));
8222 store_reg(s, 15, tmp);
8223 return true;
8226 static bool trans_TBB(DisasContext *s, arg_tbranch *a)
8228 return op_tbranch(s, a, false);
8231 static bool trans_TBH(DisasContext *s, arg_tbranch *a)
8233 return op_tbranch(s, a, true);
8236 static bool trans_CBZ(DisasContext *s, arg_CBZ *a)
8238 TCGv_i32 tmp = load_reg(s, a->rn);
8240 arm_gen_condlabel(s);
8241 tcg_gen_brcondi_i32(a->nz ? TCG_COND_EQ : TCG_COND_NE,
8242 tmp, 0, s->condlabel);
8243 tcg_temp_free_i32(tmp);
8244 gen_jmp(s, read_pc(s) + a->imm);
8245 return true;
8249 * Supervisor call - both T32 & A32 come here so we need to check
8250 * which mode we are in when checking for semihosting.
8253 static bool trans_SVC(DisasContext *s, arg_SVC *a)
8255 const uint32_t semihost_imm = s->thumb ? 0xab : 0x123456;
8257 if (!arm_dc_feature(s, ARM_FEATURE_M) && semihosting_enabled() &&
8258 #ifndef CONFIG_USER_ONLY
8259 !IS_USER(s) &&
8260 #endif
8261 (a->imm == semihost_imm)) {
8262 gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
8263 } else {
8264 gen_set_pc_im(s, s->base.pc_next);
8265 s->svc_imm = a->imm;
8266 s->base.is_jmp = DISAS_SWI;
8268 return true;
8272 * Unconditional system instructions
8275 static bool trans_RFE(DisasContext *s, arg_RFE *a)
8277 static const int8_t pre_offset[4] = {
8278 /* DA */ -4, /* IA */ 0, /* DB */ -8, /* IB */ 4
8280 static const int8_t post_offset[4] = {
8281 /* DA */ -8, /* IA */ 4, /* DB */ -4, /* IB */ 0
8283 TCGv_i32 addr, t1, t2;
8285 if (!ENABLE_ARCH_6 || arm_dc_feature(s, ARM_FEATURE_M)) {
8286 return false;
8288 if (IS_USER(s)) {
8289 unallocated_encoding(s);
8290 return true;
8293 addr = load_reg(s, a->rn);
8294 tcg_gen_addi_i32(addr, addr, pre_offset[a->pu]);
8296 /* Load PC into tmp and CPSR into tmp2. */
8297 t1 = tcg_temp_new_i32();
8298 gen_aa32_ld32u(s, t1, addr, get_mem_index(s));
8299 tcg_gen_addi_i32(addr, addr, 4);
8300 t2 = tcg_temp_new_i32();
8301 gen_aa32_ld32u(s, t2, addr, get_mem_index(s));
8303 if (a->w) {
8304 /* Base writeback. */
8305 tcg_gen_addi_i32(addr, addr, post_offset[a->pu]);
8306 store_reg(s, a->rn, addr);
8307 } else {
8308 tcg_temp_free_i32(addr);
8310 gen_rfe(s, t1, t2);
8311 return true;
8314 static bool trans_SRS(DisasContext *s, arg_SRS *a)
8316 if (!ENABLE_ARCH_6 || arm_dc_feature(s, ARM_FEATURE_M)) {
8317 return false;
8319 gen_srs(s, a->mode, a->pu, a->w);
8320 return true;
8323 static bool trans_CPS(DisasContext *s, arg_CPS *a)
8325 uint32_t mask, val;
8327 if (!ENABLE_ARCH_6 || arm_dc_feature(s, ARM_FEATURE_M)) {
8328 return false;
8330 if (IS_USER(s)) {
8331 /* Implemented as NOP in user mode. */
8332 return true;
8334 /* TODO: There are quite a lot of UNPREDICTABLE argument combinations. */
8336 mask = val = 0;
8337 if (a->imod & 2) {
8338 if (a->A) {
8339 mask |= CPSR_A;
8341 if (a->I) {
8342 mask |= CPSR_I;
8344 if (a->F) {
8345 mask |= CPSR_F;
8347 if (a->imod & 1) {
8348 val |= mask;
8351 if (a->M) {
8352 mask |= CPSR_M;
8353 val |= a->mode;
8355 if (mask) {
8356 gen_set_psr_im(s, mask, 0, val);
8358 return true;
8361 static bool trans_CPS_v7m(DisasContext *s, arg_CPS_v7m *a)
8363 TCGv_i32 tmp, addr, el;
8365 if (!arm_dc_feature(s, ARM_FEATURE_M)) {
8366 return false;
8368 if (IS_USER(s)) {
8369 /* Implemented as NOP in user mode. */
8370 return true;
8373 tmp = tcg_const_i32(a->im);
8374 /* FAULTMASK */
8375 if (a->F) {
8376 addr = tcg_const_i32(19);
8377 gen_helper_v7m_msr(cpu_env, addr, tmp);
8378 tcg_temp_free_i32(addr);
8380 /* PRIMASK */
8381 if (a->I) {
8382 addr = tcg_const_i32(16);
8383 gen_helper_v7m_msr(cpu_env, addr, tmp);
8384 tcg_temp_free_i32(addr);
8386 el = tcg_const_i32(s->current_el);
8387 gen_helper_rebuild_hflags_m32(cpu_env, el);
8388 tcg_temp_free_i32(el);
8389 tcg_temp_free_i32(tmp);
8390 gen_lookup_tb(s);
8391 return true;
8395 * Clear-Exclusive, Barriers
8398 static bool trans_CLREX(DisasContext *s, arg_CLREX *a)
8400 if (s->thumb
8401 ? !ENABLE_ARCH_7 && !arm_dc_feature(s, ARM_FEATURE_M)
8402 : !ENABLE_ARCH_6K) {
8403 return false;
8405 gen_clrex(s);
8406 return true;
8409 static bool trans_DSB(DisasContext *s, arg_DSB *a)
8411 if (!ENABLE_ARCH_7 && !arm_dc_feature(s, ARM_FEATURE_M)) {
8412 return false;
8414 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
8415 return true;
8418 static bool trans_DMB(DisasContext *s, arg_DMB *a)
8420 return trans_DSB(s, NULL);
8423 static bool trans_ISB(DisasContext *s, arg_ISB *a)
8425 if (!ENABLE_ARCH_7 && !arm_dc_feature(s, ARM_FEATURE_M)) {
8426 return false;
8429 * We need to break the TB after this insn to execute
8430 * self-modifying code correctly and also to take
8431 * any pending interrupts immediately.
8433 gen_goto_tb(s, 0, s->base.pc_next);
8434 return true;
8437 static bool trans_SB(DisasContext *s, arg_SB *a)
8439 if (!dc_isar_feature(aa32_sb, s)) {
8440 return false;
8443 * TODO: There is no speculation barrier opcode
8444 * for TCG; MB and end the TB instead.
8446 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
8447 gen_goto_tb(s, 0, s->base.pc_next);
8448 return true;
8451 static bool trans_SETEND(DisasContext *s, arg_SETEND *a)
8453 if (!ENABLE_ARCH_6) {
8454 return false;
8456 if (a->E != (s->be_data == MO_BE)) {
8457 gen_helper_setend(cpu_env);
8458 s->base.is_jmp = DISAS_UPDATE_EXIT;
8460 return true;
8464 * Preload instructions
8465 * All are nops, contingent on the appropriate arch level.
8468 static bool trans_PLD(DisasContext *s, arg_PLD *a)
8470 return ENABLE_ARCH_5TE;
8473 static bool trans_PLDW(DisasContext *s, arg_PLD *a)
8475 return arm_dc_feature(s, ARM_FEATURE_V7MP);
8478 static bool trans_PLI(DisasContext *s, arg_PLD *a)
8480 return ENABLE_ARCH_7;
8484 * If-then
8487 static bool trans_IT(DisasContext *s, arg_IT *a)
8489 int cond_mask = a->cond_mask;
8492 * No actual code generated for this insn, just setup state.
8494 * Combinations of firstcond and mask which set up an 0b1111
8495 * condition are UNPREDICTABLE; we take the CONSTRAINED
8496 * UNPREDICTABLE choice to treat 0b1111 the same as 0b1110,
8497 * i.e. both meaning "execute always".
8499 s->condexec_cond = (cond_mask >> 4) & 0xe;
8500 s->condexec_mask = cond_mask & 0x1f;
8501 return true;
8504 /* v8.1M CSEL/CSINC/CSNEG/CSINV */
8505 static bool trans_CSEL(DisasContext *s, arg_CSEL *a)
8507 TCGv_i32 rn, rm, zero;
8508 DisasCompare c;
8510 if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
8511 return false;
8514 if (a->rm == 13) {
8515 /* SEE "Related encodings" (MVE shifts) */
8516 return false;
8519 if (a->rd == 13 || a->rd == 15 || a->rn == 13 || a->fcond >= 14) {
8520 /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
8521 return false;
8524 /* In this insn input reg fields of 0b1111 mean "zero", not "PC" */
8525 if (a->rn == 15) {
8526 rn = tcg_const_i32(0);
8527 } else {
8528 rn = load_reg(s, a->rn);
8530 if (a->rm == 15) {
8531 rm = tcg_const_i32(0);
8532 } else {
8533 rm = load_reg(s, a->rm);
8536 switch (a->op) {
8537 case 0: /* CSEL */
8538 break;
8539 case 1: /* CSINC */
8540 tcg_gen_addi_i32(rm, rm, 1);
8541 break;
8542 case 2: /* CSINV */
8543 tcg_gen_not_i32(rm, rm);
8544 break;
8545 case 3: /* CSNEG */
8546 tcg_gen_neg_i32(rm, rm);
8547 break;
8548 default:
8549 g_assert_not_reached();
8552 arm_test_cc(&c, a->fcond);
8553 zero = tcg_const_i32(0);
8554 tcg_gen_movcond_i32(c.cond, rn, c.value, zero, rn, rm);
8555 arm_free_cc(&c);
8556 tcg_temp_free_i32(zero);
8558 store_reg(s, a->rd, rn);
8559 tcg_temp_free_i32(rm);
8561 return true;
8565 * Legacy decoder.
8568 static void disas_arm_insn(DisasContext *s, unsigned int insn)
8570 unsigned int cond = insn >> 28;
8572 /* M variants do not implement ARM mode; this must raise the INVSTATE
8573 * UsageFault exception.
8575 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8576 gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
8577 default_exception_el(s));
8578 return;
8581 if (cond == 0xf) {
8582 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
8583 * choose to UNDEF. In ARMv5 and above the space is used
8584 * for miscellaneous unconditional instructions.
8586 if (!arm_dc_feature(s, ARM_FEATURE_V5)) {
8587 unallocated_encoding(s);
8588 return;
8591 /* Unconditional instructions. */
8592 /* TODO: Perhaps merge these into one decodetree output file. */
8593 if (disas_a32_uncond(s, insn) ||
8594 disas_vfp_uncond(s, insn) ||
8595 disas_neon_dp(s, insn) ||
8596 disas_neon_ls(s, insn) ||
8597 disas_neon_shared(s, insn)) {
8598 return;
8600 /* fall back to legacy decoder */
8602 if ((insn & 0x0e000f00) == 0x0c000100) {
8603 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
8604 /* iWMMXt register transfer. */
8605 if (extract32(s->c15_cpar, 1, 1)) {
8606 if (!disas_iwmmxt_insn(s, insn)) {
8607 return;
8612 goto illegal_op;
8614 if (cond != 0xe) {
8615 /* if not always execute, we generate a conditional jump to
8616 next instruction */
8617 arm_skip_unless(s, cond);
8620 /* TODO: Perhaps merge these into one decodetree output file. */
8621 if (disas_a32(s, insn) ||
8622 disas_vfp(s, insn)) {
8623 return;
8625 /* fall back to legacy decoder */
8626 /* TODO: convert xscale/iwmmxt decoder to decodetree ?? */
8627 if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) {
8628 if (((insn & 0x0c000e00) == 0x0c000000)
8629 && ((insn & 0x03000000) != 0x03000000)) {
8630 /* Coprocessor insn, coprocessor 0 or 1 */
8631 disas_xscale_insn(s, insn);
8632 return;
8636 illegal_op:
8637 unallocated_encoding(s);
8640 static bool thumb_insn_is_16bit(DisasContext *s, uint32_t pc, uint32_t insn)
8643 * Return true if this is a 16 bit instruction. We must be precise
8644 * about this (matching the decode).
8646 if ((insn >> 11) < 0x1d) {
8647 /* Definitely a 16-bit instruction */
8648 return true;
8651 /* Top five bits 0b11101 / 0b11110 / 0b11111 : this is the
8652 * first half of a 32-bit Thumb insn. Thumb-1 cores might
8653 * end up actually treating this as two 16-bit insns, though,
8654 * if it's half of a bl/blx pair that might span a page boundary.
8656 if (arm_dc_feature(s, ARM_FEATURE_THUMB2) ||
8657 arm_dc_feature(s, ARM_FEATURE_M)) {
8658 /* Thumb2 cores (including all M profile ones) always treat
8659 * 32-bit insns as 32-bit.
8661 return false;
8664 if ((insn >> 11) == 0x1e && pc - s->page_start < TARGET_PAGE_SIZE - 3) {
8665 /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix, and the suffix
8666 * is not on the next page; we merge this into a 32-bit
8667 * insn.
8669 return false;
8671 /* 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF);
8672 * 0b1111_1xxx_xxxx_xxxx : BL suffix;
8673 * 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix on the end of a page
8674 * -- handle as single 16 bit insn
8676 return true;
8679 /* Translate a 32-bit thumb instruction. */
8680 static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
8683 * ARMv6-M supports a limited subset of Thumb2 instructions.
8684 * Other Thumb1 architectures allow only 32-bit
8685 * combined BL/BLX prefix and suffix.
8687 if (arm_dc_feature(s, ARM_FEATURE_M) &&
8688 !arm_dc_feature(s, ARM_FEATURE_V7)) {
8689 int i;
8690 bool found = false;
8691 static const uint32_t armv6m_insn[] = {0xf3808000 /* msr */,
8692 0xf3b08040 /* dsb */,
8693 0xf3b08050 /* dmb */,
8694 0xf3b08060 /* isb */,
8695 0xf3e08000 /* mrs */,
8696 0xf000d000 /* bl */};
8697 static const uint32_t armv6m_mask[] = {0xffe0d000,
8698 0xfff0d0f0,
8699 0xfff0d0f0,
8700 0xfff0d0f0,
8701 0xffe0d000,
8702 0xf800d000};
8704 for (i = 0; i < ARRAY_SIZE(armv6m_insn); i++) {
8705 if ((insn & armv6m_mask[i]) == armv6m_insn[i]) {
8706 found = true;
8707 break;
8710 if (!found) {
8711 goto illegal_op;
8713 } else if ((insn & 0xf800e800) != 0xf000e800) {
8714 if (!arm_dc_feature(s, ARM_FEATURE_THUMB2)) {
8715 unallocated_encoding(s);
8716 return;
8720 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8722 * NOCP takes precedence over any UNDEF for (almost) the
8723 * entire wide range of coprocessor-space encodings, so check
8724 * for it first before proceeding to actually decode eg VFP
8725 * insns. This decode also handles the few insns which are
8726 * in copro space but do not have NOCP checks (eg VLLDM, VLSTM).
8728 if (disas_m_nocp(s, insn)) {
8729 return;
8733 if ((insn & 0xef000000) == 0xef000000) {
8735 * T32 encodings 0b111p_1111_qqqq_qqqq_qqqq_qqqq_qqqq_qqqq
8736 * transform into
8737 * A32 encodings 0b1111_001p_qqqq_qqqq_qqqq_qqqq_qqqq_qqqq
8739 uint32_t a32_insn = (insn & 0xe2ffffff) |
8740 ((insn & (1 << 28)) >> 4) | (1 << 28);
8742 if (disas_neon_dp(s, a32_insn)) {
8743 return;
8747 if ((insn & 0xff100000) == 0xf9000000) {
8749 * T32 encodings 0b1111_1001_ppp0_qqqq_qqqq_qqqq_qqqq_qqqq
8750 * transform into
8751 * A32 encodings 0b1111_0100_ppp0_qqqq_qqqq_qqqq_qqqq_qqqq
8753 uint32_t a32_insn = (insn & 0x00ffffff) | 0xf4000000;
8755 if (disas_neon_ls(s, a32_insn)) {
8756 return;
8761 * TODO: Perhaps merge these into one decodetree output file.
8762 * Note disas_vfp is written for a32 with cond field in the
8763 * top nibble. The t32 encoding requires 0xe in the top nibble.
8765 if (disas_t32(s, insn) ||
8766 disas_vfp_uncond(s, insn) ||
8767 disas_neon_shared(s, insn) ||
8768 ((insn >> 28) == 0xe && disas_vfp(s, insn))) {
8769 return;
8772 illegal_op:
8773 unallocated_encoding(s);
8776 static void disas_thumb_insn(DisasContext *s, uint32_t insn)
8778 if (!disas_t16(s, insn)) {
8779 unallocated_encoding(s);
8783 static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
8785 /* Return true if the insn at dc->base.pc_next might cross a page boundary.
8786 * (False positives are OK, false negatives are not.)
8787 * We know this is a Thumb insn, and our caller ensures we are
8788 * only called if dc->base.pc_next is less than 4 bytes from the page
8789 * boundary, so we cross the page if the first 16 bits indicate
8790 * that this is a 32 bit insn.
8792 uint16_t insn = arm_lduw_code(env, s->base.pc_next, s->sctlr_b);
8794 return !thumb_insn_is_16bit(s, s->base.pc_next, insn);
8797 static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
8799 DisasContext *dc = container_of(dcbase, DisasContext, base);
8800 CPUARMState *env = cs->env_ptr;
8801 ARMCPU *cpu = env_archcpu(env);
8802 uint32_t tb_flags = dc->base.tb->flags;
8803 uint32_t condexec, core_mmu_idx;
8805 dc->isar = &cpu->isar;
8806 dc->condjmp = 0;
8808 dc->aarch64 = 0;
8809 /* If we are coming from secure EL0 in a system with a 32-bit EL3, then
8810 * there is no secure EL1, so we route exceptions to EL3.
8812 dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
8813 !arm_el_is_aa64(env, 3);
8814 dc->thumb = FIELD_EX32(tb_flags, TBFLAG_AM32, THUMB);
8815 dc->be_data = FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
8816 condexec = FIELD_EX32(tb_flags, TBFLAG_AM32, CONDEXEC);
8817 dc->condexec_mask = (condexec & 0xf) << 1;
8818 dc->condexec_cond = condexec >> 4;
8820 core_mmu_idx = FIELD_EX32(tb_flags, TBFLAG_ANY, MMUIDX);
8821 dc->mmu_idx = core_to_arm_mmu_idx(env, core_mmu_idx);
8822 dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
8823 #if !defined(CONFIG_USER_ONLY)
8824 dc->user = (dc->current_el == 0);
8825 #endif
8826 dc->fp_excp_el = FIELD_EX32(tb_flags, TBFLAG_ANY, FPEXC_EL);
8828 if (arm_feature(env, ARM_FEATURE_M)) {
8829 dc->vfp_enabled = 1;
8830 dc->be_data = MO_TE;
8831 dc->v7m_handler_mode = FIELD_EX32(tb_flags, TBFLAG_M32, HANDLER);
8832 dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
8833 regime_is_secure(env, dc->mmu_idx);
8834 dc->v8m_stackcheck = FIELD_EX32(tb_flags, TBFLAG_M32, STACKCHECK);
8835 dc->v8m_fpccr_s_wrong =
8836 FIELD_EX32(tb_flags, TBFLAG_M32, FPCCR_S_WRONG);
8837 dc->v7m_new_fp_ctxt_needed =
8838 FIELD_EX32(tb_flags, TBFLAG_M32, NEW_FP_CTXT_NEEDED);
8839 dc->v7m_lspact = FIELD_EX32(tb_flags, TBFLAG_M32, LSPACT);
8840 } else {
8841 dc->be_data =
8842 FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
8843 dc->debug_target_el =
8844 FIELD_EX32(tb_flags, TBFLAG_ANY, DEBUG_TARGET_EL);
8845 dc->sctlr_b = FIELD_EX32(tb_flags, TBFLAG_A32, SCTLR_B);
8846 dc->hstr_active = FIELD_EX32(tb_flags, TBFLAG_A32, HSTR_ACTIVE);
8847 dc->ns = FIELD_EX32(tb_flags, TBFLAG_A32, NS);
8848 dc->vfp_enabled = FIELD_EX32(tb_flags, TBFLAG_A32, VFPEN);
8849 if (arm_feature(env, ARM_FEATURE_XSCALE)) {
8850 dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR);
8851 } else {
8852 dc->vec_len = FIELD_EX32(tb_flags, TBFLAG_A32, VECLEN);
8853 dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE);
8856 dc->cp_regs = cpu->cp_regs;
8857 dc->features = env->features;
8859 /* Single step state. The code-generation logic here is:
8860 * SS_ACTIVE == 0:
8861 * generate code with no special handling for single-stepping (except
8862 * that anything that can make us go to SS_ACTIVE == 1 must end the TB;
8863 * this happens anyway because those changes are all system register or
8864 * PSTATE writes).
8865 * SS_ACTIVE == 1, PSTATE.SS == 1: (active-not-pending)
8866 * emit code for one insn
8867 * emit code to clear PSTATE.SS
8868 * emit code to generate software step exception for completed step
8869 * end TB (as usual for having generated an exception)
8870 * SS_ACTIVE == 1, PSTATE.SS == 0: (active-pending)
8871 * emit code to generate a software step exception
8872 * end the TB
8874 dc->ss_active = FIELD_EX32(tb_flags, TBFLAG_ANY, SS_ACTIVE);
8875 dc->pstate_ss = FIELD_EX32(tb_flags, TBFLAG_ANY, PSTATE_SS);
8876 dc->is_ldex = false;
8878 dc->page_start = dc->base.pc_first & TARGET_PAGE_MASK;
8880 /* If architectural single step active, limit to 1. */
8881 if (is_singlestepping(dc)) {
8882 dc->base.max_insns = 1;
8885 /* ARM is a fixed-length ISA. Bound the number of insns to execute
8886 to those left on the page. */
8887 if (!dc->thumb) {
8888 int bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
8889 dc->base.max_insns = MIN(dc->base.max_insns, bound);
8892 cpu_V0 = tcg_temp_new_i64();
8893 cpu_V1 = tcg_temp_new_i64();
8894 cpu_M0 = tcg_temp_new_i64();
8897 static void arm_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
8899 DisasContext *dc = container_of(dcbase, DisasContext, base);
8901 /* A note on handling of the condexec (IT) bits:
8903 * We want to avoid the overhead of having to write the updated condexec
8904 * bits back to the CPUARMState for every instruction in an IT block. So:
8905 * (1) if the condexec bits are not already zero then we write
8906 * zero back into the CPUARMState now. This avoids complications trying
8907 * to do it at the end of the block. (For example if we don't do this
8908 * it's hard to identify whether we can safely skip writing condexec
8909 * at the end of the TB, which we definitely want to do for the case
8910 * where a TB doesn't do anything with the IT state at all.)
8911 * (2) if we are going to leave the TB then we call gen_set_condexec()
8912 * which will write the correct value into CPUARMState if zero is wrong.
8913 * This is done both for leaving the TB at the end, and for leaving
8914 * it because of an exception we know will happen, which is done in
8915 * gen_exception_insn(). The latter is necessary because we need to
8916 * leave the TB with the PC/IT state just prior to execution of the
8917 * instruction which caused the exception.
8918 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
8919 * then the CPUARMState will be wrong and we need to reset it.
8920 * This is handled in the same way as restoration of the
8921 * PC in these situations; we save the value of the condexec bits
8922 * for each PC via tcg_gen_insn_start(), and restore_state_to_opc()
8923 * then uses this to restore them after an exception.
8925 * Note that there are no instructions which can read the condexec
8926 * bits, and none which can write non-static values to them, so
8927 * we don't need to care about whether CPUARMState is correct in the
8928 * middle of a TB.
8931 /* Reset the conditional execution bits immediately. This avoids
8932 complications trying to do it at the end of the block. */
8933 if (dc->condexec_mask || dc->condexec_cond) {
8934 TCGv_i32 tmp = tcg_temp_new_i32();
8935 tcg_gen_movi_i32(tmp, 0);
8936 store_cpu_field(tmp, condexec_bits);
8940 static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
8942 DisasContext *dc = container_of(dcbase, DisasContext, base);
8944 tcg_gen_insn_start(dc->base.pc_next,
8945 (dc->condexec_cond << 4) | (dc->condexec_mask >> 1),
8947 dc->insn_start = tcg_last_op();
8950 static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
8951 const CPUBreakpoint *bp)
8953 DisasContext *dc = container_of(dcbase, DisasContext, base);
8955 if (bp->flags & BP_CPU) {
8956 gen_set_condexec(dc);
8957 gen_set_pc_im(dc, dc->base.pc_next);
8958 gen_helper_check_breakpoints(cpu_env);
8959 /* End the TB early; it's likely not going to be executed */
8960 dc->base.is_jmp = DISAS_TOO_MANY;
8961 } else {
8962 gen_exception_internal_insn(dc, dc->base.pc_next, EXCP_DEBUG);
8963 /* The address covered by the breakpoint must be
8964 included in [tb->pc, tb->pc + tb->size) in order
8965 to for it to be properly cleared -- thus we
8966 increment the PC here so that the logic setting
8967 tb->size below does the right thing. */
8968 /* TODO: Advance PC by correct instruction length to
8969 * avoid disassembler error messages */
8970 dc->base.pc_next += 2;
8971 dc->base.is_jmp = DISAS_NORETURN;
8974 return true;
8977 static bool arm_pre_translate_insn(DisasContext *dc)
8979 #ifdef CONFIG_USER_ONLY
8980 /* Intercept jump to the magic kernel page. */
8981 if (dc->base.pc_next >= 0xffff0000) {
8982 /* We always get here via a jump, so know we are not in a
8983 conditional execution block. */
8984 gen_exception_internal(EXCP_KERNEL_TRAP);
8985 dc->base.is_jmp = DISAS_NORETURN;
8986 return true;
8988 #endif
8990 if (dc->ss_active && !dc->pstate_ss) {
8991 /* Singlestep state is Active-pending.
8992 * If we're in this state at the start of a TB then either
8993 * a) we just took an exception to an EL which is being debugged
8994 * and this is the first insn in the exception handler
8995 * b) debug exceptions were masked and we just unmasked them
8996 * without changing EL (eg by clearing PSTATE.D)
8997 * In either case we're going to take a swstep exception in the
8998 * "did not step an insn" case, and so the syndrome ISV and EX
8999 * bits should be zero.
9001 assert(dc->base.num_insns == 1);
9002 gen_swstep_exception(dc, 0, 0);
9003 dc->base.is_jmp = DISAS_NORETURN;
9004 return true;
9007 return false;
9010 static void arm_post_translate_insn(DisasContext *dc)
9012 if (dc->condjmp && !dc->base.is_jmp) {
9013 gen_set_label(dc->condlabel);
9014 dc->condjmp = 0;
9016 translator_loop_temp_check(&dc->base);
9019 static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
9021 DisasContext *dc = container_of(dcbase, DisasContext, base);
9022 CPUARMState *env = cpu->env_ptr;
9023 unsigned int insn;
9025 if (arm_pre_translate_insn(dc)) {
9026 return;
9029 dc->pc_curr = dc->base.pc_next;
9030 insn = arm_ldl_code(env, dc->base.pc_next, dc->sctlr_b);
9031 dc->insn = insn;
9032 dc->base.pc_next += 4;
9033 disas_arm_insn(dc, insn);
9035 arm_post_translate_insn(dc);
9037 /* ARM is a fixed-length ISA. We performed the cross-page check
9038 in init_disas_context by adjusting max_insns. */
9041 static bool thumb_insn_is_unconditional(DisasContext *s, uint32_t insn)
9043 /* Return true if this Thumb insn is always unconditional,
9044 * even inside an IT block. This is true of only a very few
9045 * instructions: BKPT, HLT, and SG.
9047 * A larger class of instructions are UNPREDICTABLE if used
9048 * inside an IT block; we do not need to detect those here, because
9049 * what we do by default (perform the cc check and update the IT
9050 * bits state machine) is a permitted CONSTRAINED UNPREDICTABLE
9051 * choice for those situations.
9053 * insn is either a 16-bit or a 32-bit instruction; the two are
9054 * distinguishable because for the 16-bit case the top 16 bits
9055 * are zeroes, and that isn't a valid 32-bit encoding.
9057 if ((insn & 0xffffff00) == 0xbe00) {
9058 /* BKPT */
9059 return true;
9062 if ((insn & 0xffffffc0) == 0xba80 && arm_dc_feature(s, ARM_FEATURE_V8) &&
9063 !arm_dc_feature(s, ARM_FEATURE_M)) {
9064 /* HLT: v8A only. This is unconditional even when it is going to
9065 * UNDEF; see the v8A ARM ARM DDI0487B.a H3.3.
9066 * For v7 cores this was a plain old undefined encoding and so
9067 * honours its cc check. (We might be using the encoding as
9068 * a semihosting trap, but we don't change the cc check behaviour
9069 * on that account, because a debugger connected to a real v7A
9070 * core and emulating semihosting traps by catching the UNDEF
9071 * exception would also only see cases where the cc check passed.
9072 * No guest code should be trying to do a HLT semihosting trap
9073 * in an IT block anyway.
9075 return true;
9078 if (insn == 0xe97fe97f && arm_dc_feature(s, ARM_FEATURE_V8) &&
9079 arm_dc_feature(s, ARM_FEATURE_M)) {
9080 /* SG: v8M only */
9081 return true;
9084 return false;
9087 static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
9089 DisasContext *dc = container_of(dcbase, DisasContext, base);
9090 CPUARMState *env = cpu->env_ptr;
9091 uint32_t insn;
9092 bool is_16bit;
9094 if (arm_pre_translate_insn(dc)) {
9095 return;
9098 dc->pc_curr = dc->base.pc_next;
9099 insn = arm_lduw_code(env, dc->base.pc_next, dc->sctlr_b);
9100 is_16bit = thumb_insn_is_16bit(dc, dc->base.pc_next, insn);
9101 dc->base.pc_next += 2;
9102 if (!is_16bit) {
9103 uint32_t insn2 = arm_lduw_code(env, dc->base.pc_next, dc->sctlr_b);
9105 insn = insn << 16 | insn2;
9106 dc->base.pc_next += 2;
9108 dc->insn = insn;
9110 if (dc->condexec_mask && !thumb_insn_is_unconditional(dc, insn)) {
9111 uint32_t cond = dc->condexec_cond;
9114 * Conditionally skip the insn. Note that both 0xe and 0xf mean
9115 * "always"; 0xf is not "never".
9117 if (cond < 0x0e) {
9118 arm_skip_unless(dc, cond);
9122 if (is_16bit) {
9123 disas_thumb_insn(dc, insn);
9124 } else {
9125 disas_thumb2_insn(dc, insn);
9128 /* Advance the Thumb condexec condition. */
9129 if (dc->condexec_mask) {
9130 dc->condexec_cond = ((dc->condexec_cond & 0xe) |
9131 ((dc->condexec_mask >> 4) & 1));
9132 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
9133 if (dc->condexec_mask == 0) {
9134 dc->condexec_cond = 0;
9138 arm_post_translate_insn(dc);
9140 /* Thumb is a variable-length ISA. Stop translation when the next insn
9141 * will touch a new page. This ensures that prefetch aborts occur at
9142 * the right place.
9144 * We want to stop the TB if the next insn starts in a new page,
9145 * or if it spans between this page and the next. This means that
9146 * if we're looking at the last halfword in the page we need to
9147 * see if it's a 16-bit Thumb insn (which will fit in this TB)
9148 * or a 32-bit Thumb insn (which won't).
9149 * This is to avoid generating a silly TB with a single 16-bit insn
9150 * in it at the end of this page (which would execute correctly
9151 * but isn't very efficient).
9153 if (dc->base.is_jmp == DISAS_NEXT
9154 && (dc->base.pc_next - dc->page_start >= TARGET_PAGE_SIZE
9155 || (dc->base.pc_next - dc->page_start >= TARGET_PAGE_SIZE - 3
9156 && insn_crosses_page(env, dc)))) {
9157 dc->base.is_jmp = DISAS_TOO_MANY;
9161 static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
9163 DisasContext *dc = container_of(dcbase, DisasContext, base);
9165 if (tb_cflags(dc->base.tb) & CF_LAST_IO && dc->condjmp) {
9166 /* FIXME: This can theoretically happen with self-modifying code. */
9167 cpu_abort(cpu, "IO on conditional branch instruction");
9170 /* At this stage dc->condjmp will only be set when the skipped
9171 instruction was a conditional branch or trap, and the PC has
9172 already been written. */
9173 gen_set_condexec(dc);
9174 if (dc->base.is_jmp == DISAS_BX_EXCRET) {
9175 /* Exception return branches need some special case code at the
9176 * end of the TB, which is complex enough that it has to
9177 * handle the single-step vs not and the condition-failed
9178 * insn codepath itself.
9180 gen_bx_excret_final_code(dc);
9181 } else if (unlikely(is_singlestepping(dc))) {
9182 /* Unconditional and "condition passed" instruction codepath. */
9183 switch (dc->base.is_jmp) {
9184 case DISAS_SWI:
9185 gen_ss_advance(dc);
9186 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
9187 default_exception_el(dc));
9188 break;
9189 case DISAS_HVC:
9190 gen_ss_advance(dc);
9191 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
9192 break;
9193 case DISAS_SMC:
9194 gen_ss_advance(dc);
9195 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
9196 break;
9197 case DISAS_NEXT:
9198 case DISAS_TOO_MANY:
9199 case DISAS_UPDATE_EXIT:
9200 case DISAS_UPDATE_NOCHAIN:
9201 gen_set_pc_im(dc, dc->base.pc_next);
9202 /* fall through */
9203 default:
9204 /* FIXME: Single stepping a WFI insn will not halt the CPU. */
9205 gen_singlestep_exception(dc);
9206 break;
9207 case DISAS_NORETURN:
9208 break;
9210 } else {
9211 /* While branches must always occur at the end of an IT block,
9212 there are a few other things that can cause us to terminate
9213 the TB in the middle of an IT block:
9214 - Exception generating instructions (bkpt, swi, undefined).
9215 - Page boundaries.
9216 - Hardware watchpoints.
9217 Hardware breakpoints have already been handled and skip this code.
9219 switch (dc->base.is_jmp) {
9220 case DISAS_NEXT:
9221 case DISAS_TOO_MANY:
9222 gen_goto_tb(dc, 1, dc->base.pc_next);
9223 break;
9224 case DISAS_UPDATE_NOCHAIN:
9225 gen_set_pc_im(dc, dc->base.pc_next);
9226 /* fall through */
9227 case DISAS_JUMP:
9228 gen_goto_ptr();
9229 break;
9230 case DISAS_UPDATE_EXIT:
9231 gen_set_pc_im(dc, dc->base.pc_next);
9232 /* fall through */
9233 default:
9234 /* indicate that the hash table must be used to find the next TB */
9235 tcg_gen_exit_tb(NULL, 0);
9236 break;
9237 case DISAS_NORETURN:
9238 /* nothing more to generate */
9239 break;
9240 case DISAS_WFI:
9242 TCGv_i32 tmp = tcg_const_i32((dc->thumb &&
9243 !(dc->insn & (1U << 31))) ? 2 : 4);
9245 gen_helper_wfi(cpu_env, tmp);
9246 tcg_temp_free_i32(tmp);
9247 /* The helper doesn't necessarily throw an exception, but we
9248 * must go back to the main loop to check for interrupts anyway.
9250 tcg_gen_exit_tb(NULL, 0);
9251 break;
9253 case DISAS_WFE:
9254 gen_helper_wfe(cpu_env);
9255 break;
9256 case DISAS_YIELD:
9257 gen_helper_yield(cpu_env);
9258 break;
9259 case DISAS_SWI:
9260 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
9261 default_exception_el(dc));
9262 break;
9263 case DISAS_HVC:
9264 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
9265 break;
9266 case DISAS_SMC:
9267 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
9268 break;
9272 if (dc->condjmp) {
9273 /* "Condition failed" instruction codepath for the branch/trap insn */
9274 gen_set_label(dc->condlabel);
9275 gen_set_condexec(dc);
9276 if (unlikely(is_singlestepping(dc))) {
9277 gen_set_pc_im(dc, dc->base.pc_next);
9278 gen_singlestep_exception(dc);
9279 } else {
9280 gen_goto_tb(dc, 1, dc->base.pc_next);
9285 static void arm_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
9287 DisasContext *dc = container_of(dcbase, DisasContext, base);
9289 qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
9290 log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size);
9293 static const TranslatorOps arm_translator_ops = {
9294 .init_disas_context = arm_tr_init_disas_context,
9295 .tb_start = arm_tr_tb_start,
9296 .insn_start = arm_tr_insn_start,
9297 .breakpoint_check = arm_tr_breakpoint_check,
9298 .translate_insn = arm_tr_translate_insn,
9299 .tb_stop = arm_tr_tb_stop,
9300 .disas_log = arm_tr_disas_log,
9303 static const TranslatorOps thumb_translator_ops = {
9304 .init_disas_context = arm_tr_init_disas_context,
9305 .tb_start = arm_tr_tb_start,
9306 .insn_start = arm_tr_insn_start,
9307 .breakpoint_check = arm_tr_breakpoint_check,
9308 .translate_insn = thumb_tr_translate_insn,
9309 .tb_stop = arm_tr_tb_stop,
9310 .disas_log = arm_tr_disas_log,
9313 /* generate intermediate code for basic block 'tb'. */
9314 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
9316 DisasContext dc = { };
9317 const TranslatorOps *ops = &arm_translator_ops;
9319 if (FIELD_EX32(tb->flags, TBFLAG_AM32, THUMB)) {
9320 ops = &thumb_translator_ops;
9322 #ifdef TARGET_AARCH64
9323 if (FIELD_EX32(tb->flags, TBFLAG_ANY, AARCH64_STATE)) {
9324 ops = &aarch64_translator_ops;
9326 #endif
9328 translator_loop(ops, &dc.base, cpu, tb, max_insns);
9331 void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb,
9332 target_ulong *data)
9334 if (is_a64(env)) {
9335 env->pc = data[0];
9336 env->condexec_bits = 0;
9337 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
9338 } else {
9339 env->regs[15] = data[0];
9340 env->condexec_bits = data[1];
9341 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;