4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2005-2007 CodeSourcery
6 * Copyright (c) 2007 OpenedHand, Ltd.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #include "qemu/osdep.h"
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"
30 #include "qemu/bitops.h"
32 #include "hw/semihosting/semihost.h"
34 #include "exec/helper-proto.h"
35 #include "exec/helper-gen.h"
37 #include "trace-tcg.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)
57 #define IS_USER(s) (s->user)
60 /* We reuse the same 64-bit temporaries for efficiency. */
61 static TCGv_i64 cpu_V0
, cpu_V1
, cpu_M0
;
62 static TCGv_i32 cpu_R
[16];
63 TCGv_i32 cpu_CF
, cpu_NF
, cpu_VF
, cpu_ZF
;
64 TCGv_i64 cpu_exclusive_addr
;
65 TCGv_i64 cpu_exclusive_val
;
67 #include "exec/gen-icount.h"
69 static const char * const regnames
[] =
70 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
71 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
73 /* Function prototypes for gen_ functions calling Neon helpers. */
74 typedef void NeonGenThreeOpEnvFn(TCGv_i32
, TCGv_env
, TCGv_i32
,
76 /* Function prototypes for gen_ functions for fix point conversions */
77 typedef void VFPGenFixPointFn(TCGv_i32
, TCGv_i32
, TCGv_i32
, TCGv_ptr
);
79 /* initialize TCG globals. */
80 void arm_translate_init(void)
84 for (i
= 0; i
< 16; i
++) {
85 cpu_R
[i
] = tcg_global_mem_new_i32(cpu_env
,
86 offsetof(CPUARMState
, regs
[i
]),
89 cpu_CF
= tcg_global_mem_new_i32(cpu_env
, offsetof(CPUARMState
, CF
), "CF");
90 cpu_NF
= tcg_global_mem_new_i32(cpu_env
, offsetof(CPUARMState
, NF
), "NF");
91 cpu_VF
= tcg_global_mem_new_i32(cpu_env
, offsetof(CPUARMState
, VF
), "VF");
92 cpu_ZF
= tcg_global_mem_new_i32(cpu_env
, offsetof(CPUARMState
, ZF
), "ZF");
94 cpu_exclusive_addr
= tcg_global_mem_new_i64(cpu_env
,
95 offsetof(CPUARMState
, exclusive_addr
), "exclusive_addr");
96 cpu_exclusive_val
= tcg_global_mem_new_i64(cpu_env
,
97 offsetof(CPUARMState
, exclusive_val
), "exclusive_val");
102 /* Flags for the disas_set_da_iss info argument:
103 * lower bits hold the Rt register number, higher bits are flags.
105 typedef enum ISSInfo
{
108 ISSInvalid
= (1 << 5),
109 ISSIsAcqRel
= (1 << 6),
110 ISSIsWrite
= (1 << 7),
111 ISSIs16Bit
= (1 << 8),
114 /* Save the syndrome information for a Data Abort */
115 static void disas_set_da_iss(DisasContext
*s
, MemOp memop
, ISSInfo issinfo
)
118 int sas
= memop
& MO_SIZE
;
119 bool sse
= memop
& MO_SIGN
;
120 bool is_acqrel
= issinfo
& ISSIsAcqRel
;
121 bool is_write
= issinfo
& ISSIsWrite
;
122 bool is_16bit
= issinfo
& ISSIs16Bit
;
123 int srt
= issinfo
& ISSRegMask
;
125 if (issinfo
& ISSInvalid
) {
126 /* Some callsites want to conditionally provide ISS info,
127 * eg "only if this was not a writeback"
133 /* For AArch32, insns where the src/dest is R15 never generate
134 * ISS information. Catching that here saves checking at all
140 syn
= syn_data_abort_with_iss(0, sas
, sse
, srt
, 0, is_acqrel
,
141 0, 0, 0, is_write
, 0, is_16bit
);
142 disas_set_insn_syndrome(s
, syn
);
145 static inline int get_a32_user_mem_index(DisasContext
*s
)
147 /* Return the core mmu_idx to use for A32/T32 "unprivileged load/store"
149 * if PL2, UNPREDICTABLE (we choose to implement as if PL0)
150 * otherwise, access as if at PL0.
152 switch (s
->mmu_idx
) {
153 case ARMMMUIdx_E2
: /* this one is UNPREDICTABLE */
154 case ARMMMUIdx_E10_0
:
155 case ARMMMUIdx_E10_1
:
156 case ARMMMUIdx_E10_1_PAN
:
157 return arm_to_core_mmu_idx(ARMMMUIdx_E10_0
);
159 case ARMMMUIdx_SE10_0
:
160 case ARMMMUIdx_SE10_1
:
161 case ARMMMUIdx_SE10_1_PAN
:
162 return arm_to_core_mmu_idx(ARMMMUIdx_SE10_0
);
163 case ARMMMUIdx_MUser
:
164 case ARMMMUIdx_MPriv
:
165 return arm_to_core_mmu_idx(ARMMMUIdx_MUser
);
166 case ARMMMUIdx_MUserNegPri
:
167 case ARMMMUIdx_MPrivNegPri
:
168 return arm_to_core_mmu_idx(ARMMMUIdx_MUserNegPri
);
169 case ARMMMUIdx_MSUser
:
170 case ARMMMUIdx_MSPriv
:
171 return arm_to_core_mmu_idx(ARMMMUIdx_MSUser
);
172 case ARMMMUIdx_MSUserNegPri
:
173 case ARMMMUIdx_MSPrivNegPri
:
174 return arm_to_core_mmu_idx(ARMMMUIdx_MSUserNegPri
);
176 g_assert_not_reached();
180 static inline TCGv_i32
load_cpu_offset(int offset
)
182 TCGv_i32 tmp
= tcg_temp_new_i32();
183 tcg_gen_ld_i32(tmp
, cpu_env
, offset
);
187 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
189 static inline void store_cpu_offset(TCGv_i32 var
, int offset
)
191 tcg_gen_st_i32(var
, cpu_env
, offset
);
192 tcg_temp_free_i32(var
);
195 #define store_cpu_field(var, name) \
196 store_cpu_offset(var, offsetof(CPUARMState, name))
198 /* The architectural value of PC. */
199 static uint32_t read_pc(DisasContext
*s
)
201 return s
->pc_curr
+ (s
->thumb
? 4 : 8);
204 /* Set a variable to the value of a CPU register. */
205 static void load_reg_var(DisasContext
*s
, TCGv_i32 var
, int reg
)
208 tcg_gen_movi_i32(var
, read_pc(s
));
210 tcg_gen_mov_i32(var
, cpu_R
[reg
]);
214 /* Create a new temporary and set it to the value of a CPU register. */
215 static inline TCGv_i32
load_reg(DisasContext
*s
, int reg
)
217 TCGv_i32 tmp
= tcg_temp_new_i32();
218 load_reg_var(s
, tmp
, reg
);
223 * Create a new temp, REG + OFS, except PC is ALIGN(PC, 4).
224 * This is used for load/store for which use of PC implies (literal),
225 * or ADD that implies ADR.
227 static TCGv_i32
add_reg_for_lit(DisasContext
*s
, int reg
, int ofs
)
229 TCGv_i32 tmp
= tcg_temp_new_i32();
232 tcg_gen_movi_i32(tmp
, (read_pc(s
) & ~3) + ofs
);
234 tcg_gen_addi_i32(tmp
, cpu_R
[reg
], ofs
);
239 /* Set a CPU register. The source must be a temporary and will be
241 static void store_reg(DisasContext
*s
, int reg
, TCGv_i32 var
)
244 /* In Thumb mode, we must ignore bit 0.
245 * In ARM mode, for ARMv4 and ARMv5, it is UNPREDICTABLE if bits [1:0]
246 * are not 0b00, but for ARMv6 and above, we must ignore bits [1:0].
247 * We choose to ignore [1:0] in ARM mode for all architecture versions.
249 tcg_gen_andi_i32(var
, var
, s
->thumb
? ~1 : ~3);
250 s
->base
.is_jmp
= DISAS_JUMP
;
252 tcg_gen_mov_i32(cpu_R
[reg
], var
);
253 tcg_temp_free_i32(var
);
257 * Variant of store_reg which applies v8M stack-limit checks before updating
258 * SP. If the check fails this will result in an exception being taken.
259 * We disable the stack checks for CONFIG_USER_ONLY because we have
260 * no idea what the stack limits should be in that case.
261 * If stack checking is not being done this just acts like store_reg().
263 static void store_sp_checked(DisasContext
*s
, TCGv_i32 var
)
265 #ifndef CONFIG_USER_ONLY
266 if (s
->v8m_stackcheck
) {
267 gen_helper_v8m_stackcheck(cpu_env
, var
);
270 store_reg(s
, 13, var
);
273 /* Value extensions. */
274 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
275 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
276 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
277 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
279 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
280 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
283 static inline void gen_set_cpsr(TCGv_i32 var
, uint32_t mask
)
285 TCGv_i32 tmp_mask
= tcg_const_i32(mask
);
286 gen_helper_cpsr_write(cpu_env
, var
, tmp_mask
);
287 tcg_temp_free_i32(tmp_mask
);
289 /* Set NZCV flags from the high 4 bits of var. */
290 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
292 static void gen_exception_internal(int excp
)
294 TCGv_i32 tcg_excp
= tcg_const_i32(excp
);
296 assert(excp_is_internal(excp
));
297 gen_helper_exception_internal(cpu_env
, tcg_excp
);
298 tcg_temp_free_i32(tcg_excp
);
301 static void gen_step_complete_exception(DisasContext
*s
)
303 /* We just completed step of an insn. Move from Active-not-pending
304 * to Active-pending, and then also take the swstep exception.
305 * This corresponds to making the (IMPDEF) choice to prioritize
306 * swstep exceptions over asynchronous exceptions taken to an exception
307 * level where debug is disabled. This choice has the advantage that
308 * we do not need to maintain internal state corresponding to the
309 * ISV/EX syndrome bits between completion of the step and generation
310 * of the exception, and our syndrome information is always correct.
313 gen_swstep_exception(s
, 1, s
->is_ldex
);
314 s
->base
.is_jmp
= DISAS_NORETURN
;
317 static void gen_singlestep_exception(DisasContext
*s
)
319 /* Generate the right kind of exception for singlestep, which is
320 * either the architectural singlestep or EXCP_DEBUG for QEMU's
321 * gdb singlestepping.
324 gen_step_complete_exception(s
);
326 gen_exception_internal(EXCP_DEBUG
);
330 static inline bool is_singlestepping(DisasContext
*s
)
332 /* Return true if we are singlestepping either because of
333 * architectural singlestep or QEMU gdbstub singlestep. This does
334 * not include the command line '-singlestep' mode which is rather
335 * misnamed as it only means "one instruction per TB" and doesn't
336 * affect the code we generate.
338 return s
->base
.singlestep_enabled
|| s
->ss_active
;
341 static void gen_smul_dual(TCGv_i32 a
, TCGv_i32 b
)
343 TCGv_i32 tmp1
= tcg_temp_new_i32();
344 TCGv_i32 tmp2
= tcg_temp_new_i32();
345 tcg_gen_ext16s_i32(tmp1
, a
);
346 tcg_gen_ext16s_i32(tmp2
, b
);
347 tcg_gen_mul_i32(tmp1
, tmp1
, tmp2
);
348 tcg_temp_free_i32(tmp2
);
349 tcg_gen_sari_i32(a
, a
, 16);
350 tcg_gen_sari_i32(b
, b
, 16);
351 tcg_gen_mul_i32(b
, b
, a
);
352 tcg_gen_mov_i32(a
, tmp1
);
353 tcg_temp_free_i32(tmp1
);
356 /* Byteswap each halfword. */
357 static void gen_rev16(TCGv_i32 dest
, TCGv_i32 var
)
359 TCGv_i32 tmp
= tcg_temp_new_i32();
360 TCGv_i32 mask
= tcg_const_i32(0x00ff00ff);
361 tcg_gen_shri_i32(tmp
, var
, 8);
362 tcg_gen_and_i32(tmp
, tmp
, mask
);
363 tcg_gen_and_i32(var
, var
, mask
);
364 tcg_gen_shli_i32(var
, var
, 8);
365 tcg_gen_or_i32(dest
, var
, tmp
);
366 tcg_temp_free_i32(mask
);
367 tcg_temp_free_i32(tmp
);
370 /* Byteswap low halfword and sign extend. */
371 static void gen_revsh(TCGv_i32 dest
, TCGv_i32 var
)
373 tcg_gen_ext16u_i32(var
, var
);
374 tcg_gen_bswap16_i32(var
, var
);
375 tcg_gen_ext16s_i32(dest
, var
);
378 /* Swap low and high halfwords. */
379 static void gen_swap_half(TCGv_i32 dest
, TCGv_i32 var
)
381 tcg_gen_rotri_i32(dest
, var
, 16);
384 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
385 tmp = (t0 ^ t1) & 0x8000;
388 t0 = (t0 + t1) ^ tmp;
391 static void gen_add16(TCGv_i32 dest
, TCGv_i32 t0
, TCGv_i32 t1
)
393 TCGv_i32 tmp
= tcg_temp_new_i32();
394 tcg_gen_xor_i32(tmp
, t0
, t1
);
395 tcg_gen_andi_i32(tmp
, tmp
, 0x8000);
396 tcg_gen_andi_i32(t0
, t0
, ~0x8000);
397 tcg_gen_andi_i32(t1
, t1
, ~0x8000);
398 tcg_gen_add_i32(t0
, t0
, t1
);
399 tcg_gen_xor_i32(dest
, t0
, tmp
);
400 tcg_temp_free_i32(tmp
);
403 /* Set N and Z flags from var. */
404 static inline void gen_logic_CC(TCGv_i32 var
)
406 tcg_gen_mov_i32(cpu_NF
, var
);
407 tcg_gen_mov_i32(cpu_ZF
, var
);
410 /* dest = T0 + T1 + CF. */
411 static void gen_add_carry(TCGv_i32 dest
, TCGv_i32 t0
, TCGv_i32 t1
)
413 tcg_gen_add_i32(dest
, t0
, t1
);
414 tcg_gen_add_i32(dest
, dest
, cpu_CF
);
417 /* dest = T0 - T1 + CF - 1. */
418 static void gen_sub_carry(TCGv_i32 dest
, TCGv_i32 t0
, TCGv_i32 t1
)
420 tcg_gen_sub_i32(dest
, t0
, t1
);
421 tcg_gen_add_i32(dest
, dest
, cpu_CF
);
422 tcg_gen_subi_i32(dest
, dest
, 1);
425 /* dest = T0 + T1. Compute C, N, V and Z flags */
426 static void gen_add_CC(TCGv_i32 dest
, TCGv_i32 t0
, TCGv_i32 t1
)
428 TCGv_i32 tmp
= tcg_temp_new_i32();
429 tcg_gen_movi_i32(tmp
, 0);
430 tcg_gen_add2_i32(cpu_NF
, cpu_CF
, t0
, tmp
, t1
, tmp
);
431 tcg_gen_mov_i32(cpu_ZF
, cpu_NF
);
432 tcg_gen_xor_i32(cpu_VF
, cpu_NF
, t0
);
433 tcg_gen_xor_i32(tmp
, t0
, t1
);
434 tcg_gen_andc_i32(cpu_VF
, cpu_VF
, tmp
);
435 tcg_temp_free_i32(tmp
);
436 tcg_gen_mov_i32(dest
, cpu_NF
);
439 /* dest = T0 + T1 + CF. Compute C, N, V and Z flags */
440 static void gen_adc_CC(TCGv_i32 dest
, TCGv_i32 t0
, TCGv_i32 t1
)
442 TCGv_i32 tmp
= tcg_temp_new_i32();
443 if (TCG_TARGET_HAS_add2_i32
) {
444 tcg_gen_movi_i32(tmp
, 0);
445 tcg_gen_add2_i32(cpu_NF
, cpu_CF
, t0
, tmp
, cpu_CF
, tmp
);
446 tcg_gen_add2_i32(cpu_NF
, cpu_CF
, cpu_NF
, cpu_CF
, t1
, tmp
);
448 TCGv_i64 q0
= tcg_temp_new_i64();
449 TCGv_i64 q1
= tcg_temp_new_i64();
450 tcg_gen_extu_i32_i64(q0
, t0
);
451 tcg_gen_extu_i32_i64(q1
, t1
);
452 tcg_gen_add_i64(q0
, q0
, q1
);
453 tcg_gen_extu_i32_i64(q1
, cpu_CF
);
454 tcg_gen_add_i64(q0
, q0
, q1
);
455 tcg_gen_extr_i64_i32(cpu_NF
, cpu_CF
, q0
);
456 tcg_temp_free_i64(q0
);
457 tcg_temp_free_i64(q1
);
459 tcg_gen_mov_i32(cpu_ZF
, cpu_NF
);
460 tcg_gen_xor_i32(cpu_VF
, cpu_NF
, t0
);
461 tcg_gen_xor_i32(tmp
, t0
, t1
);
462 tcg_gen_andc_i32(cpu_VF
, cpu_VF
, tmp
);
463 tcg_temp_free_i32(tmp
);
464 tcg_gen_mov_i32(dest
, cpu_NF
);
467 /* dest = T0 - T1. Compute C, N, V and Z flags */
468 static void gen_sub_CC(TCGv_i32 dest
, TCGv_i32 t0
, TCGv_i32 t1
)
471 tcg_gen_sub_i32(cpu_NF
, t0
, t1
);
472 tcg_gen_mov_i32(cpu_ZF
, cpu_NF
);
473 tcg_gen_setcond_i32(TCG_COND_GEU
, cpu_CF
, t0
, t1
);
474 tcg_gen_xor_i32(cpu_VF
, cpu_NF
, t0
);
475 tmp
= tcg_temp_new_i32();
476 tcg_gen_xor_i32(tmp
, t0
, t1
);
477 tcg_gen_and_i32(cpu_VF
, cpu_VF
, tmp
);
478 tcg_temp_free_i32(tmp
);
479 tcg_gen_mov_i32(dest
, cpu_NF
);
482 /* dest = T0 + ~T1 + CF. Compute C, N, V and Z flags */
483 static void gen_sbc_CC(TCGv_i32 dest
, TCGv_i32 t0
, TCGv_i32 t1
)
485 TCGv_i32 tmp
= tcg_temp_new_i32();
486 tcg_gen_not_i32(tmp
, t1
);
487 gen_adc_CC(dest
, t0
, tmp
);
488 tcg_temp_free_i32(tmp
);
491 #define GEN_SHIFT(name) \
492 static void gen_##name(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) \
494 TCGv_i32 tmp1, tmp2, tmp3; \
495 tmp1 = tcg_temp_new_i32(); \
496 tcg_gen_andi_i32(tmp1, t1, 0xff); \
497 tmp2 = tcg_const_i32(0); \
498 tmp3 = tcg_const_i32(0x1f); \
499 tcg_gen_movcond_i32(TCG_COND_GTU, tmp2, tmp1, tmp3, tmp2, t0); \
500 tcg_temp_free_i32(tmp3); \
501 tcg_gen_andi_i32(tmp1, tmp1, 0x1f); \
502 tcg_gen_##name##_i32(dest, tmp2, tmp1); \
503 tcg_temp_free_i32(tmp2); \
504 tcg_temp_free_i32(tmp1); \
510 static void gen_sar(TCGv_i32 dest
, TCGv_i32 t0
, TCGv_i32 t1
)
513 tmp1
= tcg_temp_new_i32();
514 tcg_gen_andi_i32(tmp1
, t1
, 0xff);
515 tmp2
= tcg_const_i32(0x1f);
516 tcg_gen_movcond_i32(TCG_COND_GTU
, tmp1
, tmp1
, tmp2
, tmp2
, tmp1
);
517 tcg_temp_free_i32(tmp2
);
518 tcg_gen_sar_i32(dest
, t0
, tmp1
);
519 tcg_temp_free_i32(tmp1
);
522 static void shifter_out_im(TCGv_i32 var
, int shift
)
524 tcg_gen_extract_i32(cpu_CF
, var
, shift
, 1);
527 /* Shift by immediate. Includes special handling for shift == 0. */
528 static inline void gen_arm_shift_im(TCGv_i32 var
, int shiftop
,
529 int shift
, int flags
)
535 shifter_out_im(var
, 32 - shift
);
536 tcg_gen_shli_i32(var
, var
, shift
);
542 tcg_gen_shri_i32(cpu_CF
, var
, 31);
544 tcg_gen_movi_i32(var
, 0);
547 shifter_out_im(var
, shift
- 1);
548 tcg_gen_shri_i32(var
, var
, shift
);
555 shifter_out_im(var
, shift
- 1);
558 tcg_gen_sari_i32(var
, var
, shift
);
560 case 3: /* ROR/RRX */
563 shifter_out_im(var
, shift
- 1);
564 tcg_gen_rotri_i32(var
, var
, shift
); break;
566 TCGv_i32 tmp
= tcg_temp_new_i32();
567 tcg_gen_shli_i32(tmp
, cpu_CF
, 31);
569 shifter_out_im(var
, 0);
570 tcg_gen_shri_i32(var
, var
, 1);
571 tcg_gen_or_i32(var
, var
, tmp
);
572 tcg_temp_free_i32(tmp
);
577 static inline void gen_arm_shift_reg(TCGv_i32 var
, int shiftop
,
578 TCGv_i32 shift
, int flags
)
582 case 0: gen_helper_shl_cc(var
, cpu_env
, var
, shift
); break;
583 case 1: gen_helper_shr_cc(var
, cpu_env
, var
, shift
); break;
584 case 2: gen_helper_sar_cc(var
, cpu_env
, var
, shift
); break;
585 case 3: gen_helper_ror_cc(var
, cpu_env
, var
, shift
); break;
590 gen_shl(var
, var
, shift
);
593 gen_shr(var
, var
, shift
);
596 gen_sar(var
, var
, shift
);
598 case 3: tcg_gen_andi_i32(shift
, shift
, 0x1f);
599 tcg_gen_rotr_i32(var
, var
, shift
); break;
602 tcg_temp_free_i32(shift
);
606 * Generate a conditional based on ARM condition code cc.
607 * This is common between ARM and Aarch64 targets.
609 void arm_test_cc(DisasCompare
*cmp
, int cc
)
640 case 8: /* hi: C && !Z */
641 case 9: /* ls: !C || Z -> !(C && !Z) */
643 value
= tcg_temp_new_i32();
645 /* CF is 1 for C, so -CF is an all-bits-set mask for C;
646 ZF is non-zero for !Z; so AND the two subexpressions. */
647 tcg_gen_neg_i32(value
, cpu_CF
);
648 tcg_gen_and_i32(value
, value
, cpu_ZF
);
651 case 10: /* ge: N == V -> N ^ V == 0 */
652 case 11: /* lt: N != V -> N ^ V != 0 */
653 /* Since we're only interested in the sign bit, == 0 is >= 0. */
655 value
= tcg_temp_new_i32();
657 tcg_gen_xor_i32(value
, cpu_VF
, cpu_NF
);
660 case 12: /* gt: !Z && N == V */
661 case 13: /* le: Z || N != V */
663 value
= tcg_temp_new_i32();
665 /* (N == V) is equal to the sign bit of ~(NF ^ VF). Propagate
666 * the sign bit then AND with ZF to yield the result. */
667 tcg_gen_xor_i32(value
, cpu_VF
, cpu_NF
);
668 tcg_gen_sari_i32(value
, value
, 31);
669 tcg_gen_andc_i32(value
, cpu_ZF
, value
);
672 case 14: /* always */
673 case 15: /* always */
674 /* Use the ALWAYS condition, which will fold early.
675 * It doesn't matter what we use for the value. */
676 cond
= TCG_COND_ALWAYS
;
681 fprintf(stderr
, "Bad condition code 0x%x\n", cc
);
686 cond
= tcg_invert_cond(cond
);
692 cmp
->value_global
= global
;
695 void arm_free_cc(DisasCompare
*cmp
)
697 if (!cmp
->value_global
) {
698 tcg_temp_free_i32(cmp
->value
);
702 void arm_jump_cc(DisasCompare
*cmp
, TCGLabel
*label
)
704 tcg_gen_brcondi_i32(cmp
->cond
, cmp
->value
, 0, label
);
707 void arm_gen_test_cc(int cc
, TCGLabel
*label
)
710 arm_test_cc(&cmp
, cc
);
711 arm_jump_cc(&cmp
, label
);
715 static inline void gen_set_condexec(DisasContext
*s
)
717 if (s
->condexec_mask
) {
718 uint32_t val
= (s
->condexec_cond
<< 4) | (s
->condexec_mask
>> 1);
719 TCGv_i32 tmp
= tcg_temp_new_i32();
720 tcg_gen_movi_i32(tmp
, val
);
721 store_cpu_field(tmp
, condexec_bits
);
725 static inline void gen_set_pc_im(DisasContext
*s
, target_ulong val
)
727 tcg_gen_movi_i32(cpu_R
[15], val
);
730 /* Set PC and Thumb state from var. var is marked as dead. */
731 static inline void gen_bx(DisasContext
*s
, TCGv_i32 var
)
733 s
->base
.is_jmp
= DISAS_JUMP
;
734 tcg_gen_andi_i32(cpu_R
[15], var
, ~1);
735 tcg_gen_andi_i32(var
, var
, 1);
736 store_cpu_field(var
, thumb
);
740 * Set PC and Thumb state from var. var is marked as dead.
741 * For M-profile CPUs, include logic to detect exception-return
742 * branches and handle them. This is needed for Thumb POP/LDM to PC, LDR to PC,
743 * and BX reg, and no others, and happens only for code in Handler mode.
744 * The Security Extension also requires us to check for the FNC_RETURN
745 * which signals a function return from non-secure state; this can happen
746 * in both Handler and Thread mode.
747 * To avoid having to do multiple comparisons in inline generated code,
748 * we make the check we do here loose, so it will match for EXC_RETURN
749 * in Thread mode. For system emulation do_v7m_exception_exit() checks
750 * for these spurious cases and returns without doing anything (giving
751 * the same behaviour as for a branch to a non-magic address).
753 * In linux-user mode it is unclear what the right behaviour for an
754 * attempted FNC_RETURN should be, because in real hardware this will go
755 * directly to Secure code (ie not the Linux kernel) which will then treat
756 * the error in any way it chooses. For QEMU we opt to make the FNC_RETURN
757 * attempt behave the way it would on a CPU without the security extension,
758 * which is to say "like a normal branch". That means we can simply treat
759 * all branches as normal with no magic address behaviour.
761 static inline void gen_bx_excret(DisasContext
*s
, TCGv_i32 var
)
763 /* Generate the same code here as for a simple bx, but flag via
764 * s->base.is_jmp that we need to do the rest of the work later.
767 #ifndef CONFIG_USER_ONLY
768 if (arm_dc_feature(s
, ARM_FEATURE_M_SECURITY
) ||
769 (s
->v7m_handler_mode
&& arm_dc_feature(s
, ARM_FEATURE_M
))) {
770 s
->base
.is_jmp
= DISAS_BX_EXCRET
;
775 static inline void gen_bx_excret_final_code(DisasContext
*s
)
777 /* Generate the code to finish possible exception return and end the TB */
778 TCGLabel
*excret_label
= gen_new_label();
781 if (arm_dc_feature(s
, ARM_FEATURE_M_SECURITY
)) {
782 /* Covers FNC_RETURN and EXC_RETURN magic */
783 min_magic
= FNC_RETURN_MIN_MAGIC
;
785 /* EXC_RETURN magic only */
786 min_magic
= EXC_RETURN_MIN_MAGIC
;
789 /* Is the new PC value in the magic range indicating exception return? */
790 tcg_gen_brcondi_i32(TCG_COND_GEU
, cpu_R
[15], min_magic
, excret_label
);
791 /* No: end the TB as we would for a DISAS_JMP */
792 if (is_singlestepping(s
)) {
793 gen_singlestep_exception(s
);
795 tcg_gen_exit_tb(NULL
, 0);
797 gen_set_label(excret_label
);
798 /* Yes: this is an exception return.
799 * At this point in runtime env->regs[15] and env->thumb will hold
800 * the exception-return magic number, which do_v7m_exception_exit()
801 * will read. Nothing else will be able to see those values because
802 * the cpu-exec main loop guarantees that we will always go straight
803 * from raising the exception to the exception-handling code.
805 * gen_ss_advance(s) does nothing on M profile currently but
806 * calling it is conceptually the right thing as we have executed
807 * this instruction (compare SWI, HVC, SMC handling).
810 gen_exception_internal(EXCP_EXCEPTION_EXIT
);
813 static inline void gen_bxns(DisasContext
*s
, int rm
)
815 TCGv_i32 var
= load_reg(s
, rm
);
817 /* The bxns helper may raise an EXCEPTION_EXIT exception, so in theory
818 * we need to sync state before calling it, but:
819 * - we don't need to do gen_set_pc_im() because the bxns helper will
820 * always set the PC itself
821 * - we don't need to do gen_set_condexec() because BXNS is UNPREDICTABLE
822 * unless it's outside an IT block or the last insn in an IT block,
823 * so we know that condexec == 0 (already set at the top of the TB)
824 * is correct in the non-UNPREDICTABLE cases, and we can choose
825 * "zeroes the IT bits" as our UNPREDICTABLE behaviour otherwise.
827 gen_helper_v7m_bxns(cpu_env
, var
);
828 tcg_temp_free_i32(var
);
829 s
->base
.is_jmp
= DISAS_EXIT
;
832 static inline void gen_blxns(DisasContext
*s
, int rm
)
834 TCGv_i32 var
= load_reg(s
, rm
);
836 /* We don't need to sync condexec state, for the same reason as bxns.
837 * We do however need to set the PC, because the blxns helper reads it.
838 * The blxns helper may throw an exception.
840 gen_set_pc_im(s
, s
->base
.pc_next
);
841 gen_helper_v7m_blxns(cpu_env
, var
);
842 tcg_temp_free_i32(var
);
843 s
->base
.is_jmp
= DISAS_EXIT
;
846 /* Variant of store_reg which uses branch&exchange logic when storing
847 to r15 in ARM architecture v7 and above. The source must be a temporary
848 and will be marked as dead. */
849 static inline void store_reg_bx(DisasContext
*s
, int reg
, TCGv_i32 var
)
851 if (reg
== 15 && ENABLE_ARCH_7
) {
854 store_reg(s
, reg
, var
);
858 /* Variant of store_reg which uses branch&exchange logic when storing
859 * to r15 in ARM architecture v5T and above. This is used for storing
860 * the results of a LDR/LDM/POP into r15, and corresponds to the cases
861 * in the ARM ARM which use the LoadWritePC() pseudocode function. */
862 static inline void store_reg_from_load(DisasContext
*s
, int reg
, TCGv_i32 var
)
864 if (reg
== 15 && ENABLE_ARCH_5
) {
865 gen_bx_excret(s
, var
);
867 store_reg(s
, reg
, var
);
871 #ifdef CONFIG_USER_ONLY
872 #define IS_USER_ONLY 1
874 #define IS_USER_ONLY 0
877 /* Abstractions of "generate code to do a guest load/store for
878 * AArch32", where a vaddr is always 32 bits (and is zero
879 * extended if we're a 64 bit core) and data is also
880 * 32 bits unless specifically doing a 64 bit access.
881 * These functions work like tcg_gen_qemu_{ld,st}* except
882 * that the address argument is TCGv_i32 rather than TCGv.
885 static inline TCGv
gen_aa32_addr(DisasContext
*s
, TCGv_i32 a32
, MemOp op
)
887 TCGv addr
= tcg_temp_new();
888 tcg_gen_extu_i32_tl(addr
, a32
);
890 /* Not needed for user-mode BE32, where we use MO_BE instead. */
891 if (!IS_USER_ONLY
&& s
->sctlr_b
&& (op
& MO_SIZE
) < MO_32
) {
892 tcg_gen_xori_tl(addr
, addr
, 4 - (1 << (op
& MO_SIZE
)));
897 static void gen_aa32_ld_i32(DisasContext
*s
, TCGv_i32 val
, TCGv_i32 a32
,
898 int index
, MemOp opc
)
902 if (arm_dc_feature(s
, ARM_FEATURE_M
) &&
903 !arm_dc_feature(s
, ARM_FEATURE_M_MAIN
)) {
907 addr
= gen_aa32_addr(s
, a32
, opc
);
908 tcg_gen_qemu_ld_i32(val
, addr
, index
, opc
);
912 static void gen_aa32_st_i32(DisasContext
*s
, TCGv_i32 val
, TCGv_i32 a32
,
913 int index
, MemOp opc
)
917 if (arm_dc_feature(s
, ARM_FEATURE_M
) &&
918 !arm_dc_feature(s
, ARM_FEATURE_M_MAIN
)) {
922 addr
= gen_aa32_addr(s
, a32
, opc
);
923 tcg_gen_qemu_st_i32(val
, addr
, index
, opc
);
927 #define DO_GEN_LD(SUFF, OPC) \
928 static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \
929 TCGv_i32 a32, int index) \
931 gen_aa32_ld_i32(s, val, a32, index, OPC | s->be_data); \
934 #define DO_GEN_ST(SUFF, OPC) \
935 static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, \
936 TCGv_i32 a32, int index) \
938 gen_aa32_st_i32(s, val, a32, index, OPC | s->be_data); \
941 static inline void gen_aa32_frob64(DisasContext
*s
, TCGv_i64 val
)
943 /* Not needed for user-mode BE32, where we use MO_BE instead. */
944 if (!IS_USER_ONLY
&& s
->sctlr_b
) {
945 tcg_gen_rotri_i64(val
, val
, 32);
949 static void gen_aa32_ld_i64(DisasContext
*s
, TCGv_i64 val
, TCGv_i32 a32
,
950 int index
, MemOp opc
)
952 TCGv addr
= gen_aa32_addr(s
, a32
, opc
);
953 tcg_gen_qemu_ld_i64(val
, addr
, index
, opc
);
954 gen_aa32_frob64(s
, val
);
958 static inline void gen_aa32_ld64(DisasContext
*s
, TCGv_i64 val
,
959 TCGv_i32 a32
, int index
)
961 gen_aa32_ld_i64(s
, val
, a32
, index
, MO_Q
| s
->be_data
);
964 static void gen_aa32_st_i64(DisasContext
*s
, TCGv_i64 val
, TCGv_i32 a32
,
965 int index
, MemOp opc
)
967 TCGv addr
= gen_aa32_addr(s
, a32
, opc
);
969 /* Not needed for user-mode BE32, where we use MO_BE instead. */
970 if (!IS_USER_ONLY
&& s
->sctlr_b
) {
971 TCGv_i64 tmp
= tcg_temp_new_i64();
972 tcg_gen_rotri_i64(tmp
, val
, 32);
973 tcg_gen_qemu_st_i64(tmp
, addr
, index
, opc
);
974 tcg_temp_free_i64(tmp
);
976 tcg_gen_qemu_st_i64(val
, addr
, index
, opc
);
981 static inline void gen_aa32_st64(DisasContext
*s
, TCGv_i64 val
,
982 TCGv_i32 a32
, int index
)
984 gen_aa32_st_i64(s
, val
, a32
, index
, MO_Q
| s
->be_data
);
988 DO_GEN_LD(16u, MO_UW
)
989 DO_GEN_LD(32u, MO_UL
)
994 static inline void gen_hvc(DisasContext
*s
, int imm16
)
996 /* The pre HVC helper handles cases when HVC gets trapped
997 * as an undefined insn by runtime configuration (ie before
998 * the insn really executes).
1000 gen_set_pc_im(s
, s
->pc_curr
);
1001 gen_helper_pre_hvc(cpu_env
);
1002 /* Otherwise we will treat this as a real exception which
1003 * happens after execution of the insn. (The distinction matters
1004 * for the PC value reported to the exception handler and also
1005 * for single stepping.)
1008 gen_set_pc_im(s
, s
->base
.pc_next
);
1009 s
->base
.is_jmp
= DISAS_HVC
;
1012 static inline void gen_smc(DisasContext
*s
)
1014 /* As with HVC, we may take an exception either before or after
1015 * the insn executes.
1019 gen_set_pc_im(s
, s
->pc_curr
);
1020 tmp
= tcg_const_i32(syn_aa32_smc());
1021 gen_helper_pre_smc(cpu_env
, tmp
);
1022 tcg_temp_free_i32(tmp
);
1023 gen_set_pc_im(s
, s
->base
.pc_next
);
1024 s
->base
.is_jmp
= DISAS_SMC
;
1027 static void gen_exception_internal_insn(DisasContext
*s
, uint32_t pc
, int excp
)
1029 gen_set_condexec(s
);
1030 gen_set_pc_im(s
, pc
);
1031 gen_exception_internal(excp
);
1032 s
->base
.is_jmp
= DISAS_NORETURN
;
1035 static void gen_exception_insn(DisasContext
*s
, uint32_t pc
, int excp
,
1036 int syn
, uint32_t target_el
)
1038 gen_set_condexec(s
);
1039 gen_set_pc_im(s
, pc
);
1040 gen_exception(excp
, syn
, target_el
);
1041 s
->base
.is_jmp
= DISAS_NORETURN
;
1044 static void gen_exception_bkpt_insn(DisasContext
*s
, uint32_t syn
)
1048 gen_set_condexec(s
);
1049 gen_set_pc_im(s
, s
->pc_curr
);
1050 tcg_syn
= tcg_const_i32(syn
);
1051 gen_helper_exception_bkpt_insn(cpu_env
, tcg_syn
);
1052 tcg_temp_free_i32(tcg_syn
);
1053 s
->base
.is_jmp
= DISAS_NORETURN
;
1056 static void unallocated_encoding(DisasContext
*s
)
1058 /* Unallocated and reserved encodings are uncategorized */
1059 gen_exception_insn(s
, s
->pc_curr
, EXCP_UDEF
, syn_uncategorized(),
1060 default_exception_el(s
));
1063 /* Force a TB lookup after an instruction that changes the CPU state. */
1064 static inline void gen_lookup_tb(DisasContext
*s
)
1066 tcg_gen_movi_i32(cpu_R
[15], s
->base
.pc_next
);
1067 s
->base
.is_jmp
= DISAS_EXIT
;
1070 static inline void gen_hlt(DisasContext
*s
, int imm
)
1072 /* HLT. This has two purposes.
1073 * Architecturally, it is an external halting debug instruction.
1074 * Since QEMU doesn't implement external debug, we treat this as
1075 * it is required for halting debug disabled: it will UNDEF.
1076 * Secondly, "HLT 0x3C" is a T32 semihosting trap instruction,
1077 * and "HLT 0xF000" is an A32 semihosting syscall. These traps
1078 * must trigger semihosting even for ARMv7 and earlier, where
1079 * HLT was an undefined encoding.
1080 * In system mode, we don't allow userspace access to
1081 * semihosting, to provide some semblance of security
1082 * (and for consistency with our 32-bit semihosting).
1084 if (semihosting_enabled() &&
1085 #ifndef CONFIG_USER_ONLY
1086 s
->current_el
!= 0 &&
1088 (imm
== (s
->thumb
? 0x3c : 0xf000))) {
1089 gen_exception_internal_insn(s
, s
->pc_curr
, EXCP_SEMIHOST
);
1093 unallocated_encoding(s
);
1096 static TCGv_ptr
get_fpstatus_ptr(int neon
)
1098 TCGv_ptr statusptr
= tcg_temp_new_ptr();
1101 offset
= offsetof(CPUARMState
, vfp
.standard_fp_status
);
1103 offset
= offsetof(CPUARMState
, vfp
.fp_status
);
1105 tcg_gen_addi_ptr(statusptr
, cpu_env
, offset
);
1109 static inline long vfp_reg_offset(bool dp
, unsigned reg
)
1112 return offsetof(CPUARMState
, vfp
.zregs
[reg
>> 1].d
[reg
& 1]);
1114 long ofs
= offsetof(CPUARMState
, vfp
.zregs
[reg
>> 2].d
[(reg
>> 1) & 1]);
1116 ofs
+= offsetof(CPU_DoubleU
, l
.upper
);
1118 ofs
+= offsetof(CPU_DoubleU
, l
.lower
);
1124 /* Return the offset of a 32-bit piece of a NEON register.
1125 zero is the least significant end of the register. */
1127 neon_reg_offset (int reg
, int n
)
1131 return vfp_reg_offset(0, sreg
);
1134 static TCGv_i32
neon_load_reg(int reg
, int pass
)
1136 TCGv_i32 tmp
= tcg_temp_new_i32();
1137 tcg_gen_ld_i32(tmp
, cpu_env
, neon_reg_offset(reg
, pass
));
1141 static void neon_store_reg(int reg
, int pass
, TCGv_i32 var
)
1143 tcg_gen_st_i32(var
, cpu_env
, neon_reg_offset(reg
, pass
));
1144 tcg_temp_free_i32(var
);
1147 static inline void neon_load_reg64(TCGv_i64 var
, int reg
)
1149 tcg_gen_ld_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1152 static inline void neon_store_reg64(TCGv_i64 var
, int reg
)
1154 tcg_gen_st_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1157 static inline void neon_load_reg32(TCGv_i32 var
, int reg
)
1159 tcg_gen_ld_i32(var
, cpu_env
, vfp_reg_offset(false, reg
));
1162 static inline void neon_store_reg32(TCGv_i32 var
, int reg
)
1164 tcg_gen_st_i32(var
, cpu_env
, vfp_reg_offset(false, reg
));
1167 static TCGv_ptr
vfp_reg_ptr(bool dp
, int reg
)
1169 TCGv_ptr ret
= tcg_temp_new_ptr();
1170 tcg_gen_addi_ptr(ret
, cpu_env
, vfp_reg_offset(dp
, reg
));
1174 #define ARM_CP_RW_BIT (1 << 20)
1176 /* Include the VFP and Neon decoders */
1177 #include "decode-m-nocp.c.inc"
1178 #include "translate-vfp.c.inc"
1179 #include "translate-neon.c.inc"
1181 static inline void iwmmxt_load_reg(TCGv_i64 var
, int reg
)
1183 tcg_gen_ld_i64(var
, cpu_env
, offsetof(CPUARMState
, iwmmxt
.regs
[reg
]));
1186 static inline void iwmmxt_store_reg(TCGv_i64 var
, int reg
)
1188 tcg_gen_st_i64(var
, cpu_env
, offsetof(CPUARMState
, iwmmxt
.regs
[reg
]));
1191 static inline TCGv_i32
iwmmxt_load_creg(int reg
)
1193 TCGv_i32 var
= tcg_temp_new_i32();
1194 tcg_gen_ld_i32(var
, cpu_env
, offsetof(CPUARMState
, iwmmxt
.cregs
[reg
]));
1198 static inline void iwmmxt_store_creg(int reg
, TCGv_i32 var
)
1200 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUARMState
, iwmmxt
.cregs
[reg
]));
1201 tcg_temp_free_i32(var
);
1204 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn
)
1206 iwmmxt_store_reg(cpu_M0
, rn
);
1209 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn
)
1211 iwmmxt_load_reg(cpu_M0
, rn
);
1214 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn
)
1216 iwmmxt_load_reg(cpu_V1
, rn
);
1217 tcg_gen_or_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1220 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn
)
1222 iwmmxt_load_reg(cpu_V1
, rn
);
1223 tcg_gen_and_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1226 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn
)
1228 iwmmxt_load_reg(cpu_V1
, rn
);
1229 tcg_gen_xor_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1232 #define IWMMXT_OP(name) \
1233 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1235 iwmmxt_load_reg(cpu_V1, rn); \
1236 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1239 #define IWMMXT_OP_ENV(name) \
1240 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1242 iwmmxt_load_reg(cpu_V1, rn); \
1243 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1246 #define IWMMXT_OP_ENV_SIZE(name) \
1247 IWMMXT_OP_ENV(name##b) \
1248 IWMMXT_OP_ENV(name##w) \
1249 IWMMXT_OP_ENV(name##l)
1251 #define IWMMXT_OP_ENV1(name) \
1252 static inline void gen_op_iwmmxt_##name##_M0(void) \
1254 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1268 IWMMXT_OP_ENV_SIZE(unpackl
)
1269 IWMMXT_OP_ENV_SIZE(unpackh
)
1271 IWMMXT_OP_ENV1(unpacklub
)
1272 IWMMXT_OP_ENV1(unpackluw
)
1273 IWMMXT_OP_ENV1(unpacklul
)
1274 IWMMXT_OP_ENV1(unpackhub
)
1275 IWMMXT_OP_ENV1(unpackhuw
)
1276 IWMMXT_OP_ENV1(unpackhul
)
1277 IWMMXT_OP_ENV1(unpacklsb
)
1278 IWMMXT_OP_ENV1(unpacklsw
)
1279 IWMMXT_OP_ENV1(unpacklsl
)
1280 IWMMXT_OP_ENV1(unpackhsb
)
1281 IWMMXT_OP_ENV1(unpackhsw
)
1282 IWMMXT_OP_ENV1(unpackhsl
)
1284 IWMMXT_OP_ENV_SIZE(cmpeq
)
1285 IWMMXT_OP_ENV_SIZE(cmpgtu
)
1286 IWMMXT_OP_ENV_SIZE(cmpgts
)
1288 IWMMXT_OP_ENV_SIZE(mins
)
1289 IWMMXT_OP_ENV_SIZE(minu
)
1290 IWMMXT_OP_ENV_SIZE(maxs
)
1291 IWMMXT_OP_ENV_SIZE(maxu
)
1293 IWMMXT_OP_ENV_SIZE(subn
)
1294 IWMMXT_OP_ENV_SIZE(addn
)
1295 IWMMXT_OP_ENV_SIZE(subu
)
1296 IWMMXT_OP_ENV_SIZE(addu
)
1297 IWMMXT_OP_ENV_SIZE(subs
)
1298 IWMMXT_OP_ENV_SIZE(adds
)
1300 IWMMXT_OP_ENV(avgb0
)
1301 IWMMXT_OP_ENV(avgb1
)
1302 IWMMXT_OP_ENV(avgw0
)
1303 IWMMXT_OP_ENV(avgw1
)
1305 IWMMXT_OP_ENV(packuw
)
1306 IWMMXT_OP_ENV(packul
)
1307 IWMMXT_OP_ENV(packuq
)
1308 IWMMXT_OP_ENV(packsw
)
1309 IWMMXT_OP_ENV(packsl
)
1310 IWMMXT_OP_ENV(packsq
)
1312 static void gen_op_iwmmxt_set_mup(void)
1315 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1316 tcg_gen_ori_i32(tmp
, tmp
, 2);
1317 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1320 static void gen_op_iwmmxt_set_cup(void)
1323 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1324 tcg_gen_ori_i32(tmp
, tmp
, 1);
1325 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1328 static void gen_op_iwmmxt_setpsr_nz(void)
1330 TCGv_i32 tmp
= tcg_temp_new_i32();
1331 gen_helper_iwmmxt_setpsr_nz(tmp
, cpu_M0
);
1332 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCASF
]);
1335 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn
)
1337 iwmmxt_load_reg(cpu_V1
, rn
);
1338 tcg_gen_ext32u_i64(cpu_V1
, cpu_V1
);
1339 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1342 static inline int gen_iwmmxt_address(DisasContext
*s
, uint32_t insn
,
1349 rd
= (insn
>> 16) & 0xf;
1350 tmp
= load_reg(s
, rd
);
1352 offset
= (insn
& 0xff) << ((insn
>> 7) & 2);
1353 if (insn
& (1 << 24)) {
1355 if (insn
& (1 << 23))
1356 tcg_gen_addi_i32(tmp
, tmp
, offset
);
1358 tcg_gen_addi_i32(tmp
, tmp
, -offset
);
1359 tcg_gen_mov_i32(dest
, tmp
);
1360 if (insn
& (1 << 21))
1361 store_reg(s
, rd
, tmp
);
1363 tcg_temp_free_i32(tmp
);
1364 } else if (insn
& (1 << 21)) {
1366 tcg_gen_mov_i32(dest
, tmp
);
1367 if (insn
& (1 << 23))
1368 tcg_gen_addi_i32(tmp
, tmp
, offset
);
1370 tcg_gen_addi_i32(tmp
, tmp
, -offset
);
1371 store_reg(s
, rd
, tmp
);
1372 } else if (!(insn
& (1 << 23)))
1377 static inline int gen_iwmmxt_shift(uint32_t insn
, uint32_t mask
, TCGv_i32 dest
)
1379 int rd
= (insn
>> 0) & 0xf;
1382 if (insn
& (1 << 8)) {
1383 if (rd
< ARM_IWMMXT_wCGR0
|| rd
> ARM_IWMMXT_wCGR3
) {
1386 tmp
= iwmmxt_load_creg(rd
);
1389 tmp
= tcg_temp_new_i32();
1390 iwmmxt_load_reg(cpu_V0
, rd
);
1391 tcg_gen_extrl_i64_i32(tmp
, cpu_V0
);
1393 tcg_gen_andi_i32(tmp
, tmp
, mask
);
1394 tcg_gen_mov_i32(dest
, tmp
);
1395 tcg_temp_free_i32(tmp
);
1399 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
1400 (ie. an undefined instruction). */
1401 static int disas_iwmmxt_insn(DisasContext
*s
, uint32_t insn
)
1404 int rdhi
, rdlo
, rd0
, rd1
, i
;
1406 TCGv_i32 tmp
, tmp2
, tmp3
;
1408 if ((insn
& 0x0e000e00) == 0x0c000000) {
1409 if ((insn
& 0x0fe00ff0) == 0x0c400000) {
1411 rdlo
= (insn
>> 12) & 0xf;
1412 rdhi
= (insn
>> 16) & 0xf;
1413 if (insn
& ARM_CP_RW_BIT
) { /* TMRRC */
1414 iwmmxt_load_reg(cpu_V0
, wrd
);
1415 tcg_gen_extrl_i64_i32(cpu_R
[rdlo
], cpu_V0
);
1416 tcg_gen_extrh_i64_i32(cpu_R
[rdhi
], cpu_V0
);
1417 } else { /* TMCRR */
1418 tcg_gen_concat_i32_i64(cpu_V0
, cpu_R
[rdlo
], cpu_R
[rdhi
]);
1419 iwmmxt_store_reg(cpu_V0
, wrd
);
1420 gen_op_iwmmxt_set_mup();
1425 wrd
= (insn
>> 12) & 0xf;
1426 addr
= tcg_temp_new_i32();
1427 if (gen_iwmmxt_address(s
, insn
, addr
)) {
1428 tcg_temp_free_i32(addr
);
1431 if (insn
& ARM_CP_RW_BIT
) {
1432 if ((insn
>> 28) == 0xf) { /* WLDRW wCx */
1433 tmp
= tcg_temp_new_i32();
1434 gen_aa32_ld32u(s
, tmp
, addr
, get_mem_index(s
));
1435 iwmmxt_store_creg(wrd
, tmp
);
1438 if (insn
& (1 << 8)) {
1439 if (insn
& (1 << 22)) { /* WLDRD */
1440 gen_aa32_ld64(s
, cpu_M0
, addr
, get_mem_index(s
));
1442 } else { /* WLDRW wRd */
1443 tmp
= tcg_temp_new_i32();
1444 gen_aa32_ld32u(s
, tmp
, addr
, get_mem_index(s
));
1447 tmp
= tcg_temp_new_i32();
1448 if (insn
& (1 << 22)) { /* WLDRH */
1449 gen_aa32_ld16u(s
, tmp
, addr
, get_mem_index(s
));
1450 } else { /* WLDRB */
1451 gen_aa32_ld8u(s
, tmp
, addr
, get_mem_index(s
));
1455 tcg_gen_extu_i32_i64(cpu_M0
, tmp
);
1456 tcg_temp_free_i32(tmp
);
1458 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1461 if ((insn
>> 28) == 0xf) { /* WSTRW wCx */
1462 tmp
= iwmmxt_load_creg(wrd
);
1463 gen_aa32_st32(s
, tmp
, addr
, get_mem_index(s
));
1465 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1466 tmp
= tcg_temp_new_i32();
1467 if (insn
& (1 << 8)) {
1468 if (insn
& (1 << 22)) { /* WSTRD */
1469 gen_aa32_st64(s
, cpu_M0
, addr
, get_mem_index(s
));
1470 } else { /* WSTRW wRd */
1471 tcg_gen_extrl_i64_i32(tmp
, cpu_M0
);
1472 gen_aa32_st32(s
, tmp
, addr
, get_mem_index(s
));
1475 if (insn
& (1 << 22)) { /* WSTRH */
1476 tcg_gen_extrl_i64_i32(tmp
, cpu_M0
);
1477 gen_aa32_st16(s
, tmp
, addr
, get_mem_index(s
));
1478 } else { /* WSTRB */
1479 tcg_gen_extrl_i64_i32(tmp
, cpu_M0
);
1480 gen_aa32_st8(s
, tmp
, addr
, get_mem_index(s
));
1484 tcg_temp_free_i32(tmp
);
1486 tcg_temp_free_i32(addr
);
1490 if ((insn
& 0x0f000000) != 0x0e000000)
1493 switch (((insn
>> 12) & 0xf00) | ((insn
>> 4) & 0xff)) {
1494 case 0x000: /* WOR */
1495 wrd
= (insn
>> 12) & 0xf;
1496 rd0
= (insn
>> 0) & 0xf;
1497 rd1
= (insn
>> 16) & 0xf;
1498 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1499 gen_op_iwmmxt_orq_M0_wRn(rd1
);
1500 gen_op_iwmmxt_setpsr_nz();
1501 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1502 gen_op_iwmmxt_set_mup();
1503 gen_op_iwmmxt_set_cup();
1505 case 0x011: /* TMCR */
1508 rd
= (insn
>> 12) & 0xf;
1509 wrd
= (insn
>> 16) & 0xf;
1511 case ARM_IWMMXT_wCID
:
1512 case ARM_IWMMXT_wCASF
:
1514 case ARM_IWMMXT_wCon
:
1515 gen_op_iwmmxt_set_cup();
1517 case ARM_IWMMXT_wCSSF
:
1518 tmp
= iwmmxt_load_creg(wrd
);
1519 tmp2
= load_reg(s
, rd
);
1520 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
1521 tcg_temp_free_i32(tmp2
);
1522 iwmmxt_store_creg(wrd
, tmp
);
1524 case ARM_IWMMXT_wCGR0
:
1525 case ARM_IWMMXT_wCGR1
:
1526 case ARM_IWMMXT_wCGR2
:
1527 case ARM_IWMMXT_wCGR3
:
1528 gen_op_iwmmxt_set_cup();
1529 tmp
= load_reg(s
, rd
);
1530 iwmmxt_store_creg(wrd
, tmp
);
1536 case 0x100: /* WXOR */
1537 wrd
= (insn
>> 12) & 0xf;
1538 rd0
= (insn
>> 0) & 0xf;
1539 rd1
= (insn
>> 16) & 0xf;
1540 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1541 gen_op_iwmmxt_xorq_M0_wRn(rd1
);
1542 gen_op_iwmmxt_setpsr_nz();
1543 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1544 gen_op_iwmmxt_set_mup();
1545 gen_op_iwmmxt_set_cup();
1547 case 0x111: /* TMRC */
1550 rd
= (insn
>> 12) & 0xf;
1551 wrd
= (insn
>> 16) & 0xf;
1552 tmp
= iwmmxt_load_creg(wrd
);
1553 store_reg(s
, rd
, tmp
);
1555 case 0x300: /* WANDN */
1556 wrd
= (insn
>> 12) & 0xf;
1557 rd0
= (insn
>> 0) & 0xf;
1558 rd1
= (insn
>> 16) & 0xf;
1559 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1560 tcg_gen_neg_i64(cpu_M0
, cpu_M0
);
1561 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1562 gen_op_iwmmxt_setpsr_nz();
1563 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1564 gen_op_iwmmxt_set_mup();
1565 gen_op_iwmmxt_set_cup();
1567 case 0x200: /* WAND */
1568 wrd
= (insn
>> 12) & 0xf;
1569 rd0
= (insn
>> 0) & 0xf;
1570 rd1
= (insn
>> 16) & 0xf;
1571 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1572 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1573 gen_op_iwmmxt_setpsr_nz();
1574 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1575 gen_op_iwmmxt_set_mup();
1576 gen_op_iwmmxt_set_cup();
1578 case 0x810: case 0xa10: /* WMADD */
1579 wrd
= (insn
>> 12) & 0xf;
1580 rd0
= (insn
>> 0) & 0xf;
1581 rd1
= (insn
>> 16) & 0xf;
1582 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1583 if (insn
& (1 << 21))
1584 gen_op_iwmmxt_maddsq_M0_wRn(rd1
);
1586 gen_op_iwmmxt_madduq_M0_wRn(rd1
);
1587 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1588 gen_op_iwmmxt_set_mup();
1590 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1591 wrd
= (insn
>> 12) & 0xf;
1592 rd0
= (insn
>> 16) & 0xf;
1593 rd1
= (insn
>> 0) & 0xf;
1594 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1595 switch ((insn
>> 22) & 3) {
1597 gen_op_iwmmxt_unpacklb_M0_wRn(rd1
);
1600 gen_op_iwmmxt_unpacklw_M0_wRn(rd1
);
1603 gen_op_iwmmxt_unpackll_M0_wRn(rd1
);
1608 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1609 gen_op_iwmmxt_set_mup();
1610 gen_op_iwmmxt_set_cup();
1612 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1613 wrd
= (insn
>> 12) & 0xf;
1614 rd0
= (insn
>> 16) & 0xf;
1615 rd1
= (insn
>> 0) & 0xf;
1616 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1617 switch ((insn
>> 22) & 3) {
1619 gen_op_iwmmxt_unpackhb_M0_wRn(rd1
);
1622 gen_op_iwmmxt_unpackhw_M0_wRn(rd1
);
1625 gen_op_iwmmxt_unpackhl_M0_wRn(rd1
);
1630 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1631 gen_op_iwmmxt_set_mup();
1632 gen_op_iwmmxt_set_cup();
1634 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1635 wrd
= (insn
>> 12) & 0xf;
1636 rd0
= (insn
>> 16) & 0xf;
1637 rd1
= (insn
>> 0) & 0xf;
1638 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1639 if (insn
& (1 << 22))
1640 gen_op_iwmmxt_sadw_M0_wRn(rd1
);
1642 gen_op_iwmmxt_sadb_M0_wRn(rd1
);
1643 if (!(insn
& (1 << 20)))
1644 gen_op_iwmmxt_addl_M0_wRn(wrd
);
1645 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1646 gen_op_iwmmxt_set_mup();
1648 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1649 wrd
= (insn
>> 12) & 0xf;
1650 rd0
= (insn
>> 16) & 0xf;
1651 rd1
= (insn
>> 0) & 0xf;
1652 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1653 if (insn
& (1 << 21)) {
1654 if (insn
& (1 << 20))
1655 gen_op_iwmmxt_mulshw_M0_wRn(rd1
);
1657 gen_op_iwmmxt_mulslw_M0_wRn(rd1
);
1659 if (insn
& (1 << 20))
1660 gen_op_iwmmxt_muluhw_M0_wRn(rd1
);
1662 gen_op_iwmmxt_mululw_M0_wRn(rd1
);
1664 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1665 gen_op_iwmmxt_set_mup();
1667 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1668 wrd
= (insn
>> 12) & 0xf;
1669 rd0
= (insn
>> 16) & 0xf;
1670 rd1
= (insn
>> 0) & 0xf;
1671 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1672 if (insn
& (1 << 21))
1673 gen_op_iwmmxt_macsw_M0_wRn(rd1
);
1675 gen_op_iwmmxt_macuw_M0_wRn(rd1
);
1676 if (!(insn
& (1 << 20))) {
1677 iwmmxt_load_reg(cpu_V1
, wrd
);
1678 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1680 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1681 gen_op_iwmmxt_set_mup();
1683 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1684 wrd
= (insn
>> 12) & 0xf;
1685 rd0
= (insn
>> 16) & 0xf;
1686 rd1
= (insn
>> 0) & 0xf;
1687 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1688 switch ((insn
>> 22) & 3) {
1690 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1
);
1693 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1
);
1696 gen_op_iwmmxt_cmpeql_M0_wRn(rd1
);
1701 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1702 gen_op_iwmmxt_set_mup();
1703 gen_op_iwmmxt_set_cup();
1705 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1706 wrd
= (insn
>> 12) & 0xf;
1707 rd0
= (insn
>> 16) & 0xf;
1708 rd1
= (insn
>> 0) & 0xf;
1709 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1710 if (insn
& (1 << 22)) {
1711 if (insn
& (1 << 20))
1712 gen_op_iwmmxt_avgw1_M0_wRn(rd1
);
1714 gen_op_iwmmxt_avgw0_M0_wRn(rd1
);
1716 if (insn
& (1 << 20))
1717 gen_op_iwmmxt_avgb1_M0_wRn(rd1
);
1719 gen_op_iwmmxt_avgb0_M0_wRn(rd1
);
1721 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1722 gen_op_iwmmxt_set_mup();
1723 gen_op_iwmmxt_set_cup();
1725 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1726 wrd
= (insn
>> 12) & 0xf;
1727 rd0
= (insn
>> 16) & 0xf;
1728 rd1
= (insn
>> 0) & 0xf;
1729 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1730 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCGR0
+ ((insn
>> 20) & 3));
1731 tcg_gen_andi_i32(tmp
, tmp
, 7);
1732 iwmmxt_load_reg(cpu_V1
, rd1
);
1733 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, tmp
);
1734 tcg_temp_free_i32(tmp
);
1735 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1736 gen_op_iwmmxt_set_mup();
1738 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1739 if (((insn
>> 6) & 3) == 3)
1741 rd
= (insn
>> 12) & 0xf;
1742 wrd
= (insn
>> 16) & 0xf;
1743 tmp
= load_reg(s
, rd
);
1744 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1745 switch ((insn
>> 6) & 3) {
1747 tmp2
= tcg_const_i32(0xff);
1748 tmp3
= tcg_const_i32((insn
& 7) << 3);
1751 tmp2
= tcg_const_i32(0xffff);
1752 tmp3
= tcg_const_i32((insn
& 3) << 4);
1755 tmp2
= tcg_const_i32(0xffffffff);
1756 tmp3
= tcg_const_i32((insn
& 1) << 5);
1762 gen_helper_iwmmxt_insr(cpu_M0
, cpu_M0
, tmp
, tmp2
, tmp3
);
1763 tcg_temp_free_i32(tmp3
);
1764 tcg_temp_free_i32(tmp2
);
1765 tcg_temp_free_i32(tmp
);
1766 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1767 gen_op_iwmmxt_set_mup();
1769 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1770 rd
= (insn
>> 12) & 0xf;
1771 wrd
= (insn
>> 16) & 0xf;
1772 if (rd
== 15 || ((insn
>> 22) & 3) == 3)
1774 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1775 tmp
= tcg_temp_new_i32();
1776 switch ((insn
>> 22) & 3) {
1778 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 7) << 3);
1779 tcg_gen_extrl_i64_i32(tmp
, cpu_M0
);
1781 tcg_gen_ext8s_i32(tmp
, tmp
);
1783 tcg_gen_andi_i32(tmp
, tmp
, 0xff);
1787 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 3) << 4);
1788 tcg_gen_extrl_i64_i32(tmp
, cpu_M0
);
1790 tcg_gen_ext16s_i32(tmp
, tmp
);
1792 tcg_gen_andi_i32(tmp
, tmp
, 0xffff);
1796 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 1) << 5);
1797 tcg_gen_extrl_i64_i32(tmp
, cpu_M0
);
1800 store_reg(s
, rd
, tmp
);
1802 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1803 if ((insn
& 0x000ff008) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1805 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1806 switch ((insn
>> 22) & 3) {
1808 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 7) << 2) + 0);
1811 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 3) << 3) + 4);
1814 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 1) << 4) + 12);
1817 tcg_gen_shli_i32(tmp
, tmp
, 28);
1819 tcg_temp_free_i32(tmp
);
1821 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1822 if (((insn
>> 6) & 3) == 3)
1824 rd
= (insn
>> 12) & 0xf;
1825 wrd
= (insn
>> 16) & 0xf;
1826 tmp
= load_reg(s
, rd
);
1827 switch ((insn
>> 6) & 3) {
1829 gen_helper_iwmmxt_bcstb(cpu_M0
, tmp
);
1832 gen_helper_iwmmxt_bcstw(cpu_M0
, tmp
);
1835 gen_helper_iwmmxt_bcstl(cpu_M0
, tmp
);
1838 tcg_temp_free_i32(tmp
);
1839 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1840 gen_op_iwmmxt_set_mup();
1842 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1843 if ((insn
& 0x000ff00f) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1845 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1846 tmp2
= tcg_temp_new_i32();
1847 tcg_gen_mov_i32(tmp2
, tmp
);
1848 switch ((insn
>> 22) & 3) {
1850 for (i
= 0; i
< 7; i
++) {
1851 tcg_gen_shli_i32(tmp2
, tmp2
, 4);
1852 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1856 for (i
= 0; i
< 3; i
++) {
1857 tcg_gen_shli_i32(tmp2
, tmp2
, 8);
1858 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1862 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
1863 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1867 tcg_temp_free_i32(tmp2
);
1868 tcg_temp_free_i32(tmp
);
1870 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1871 wrd
= (insn
>> 12) & 0xf;
1872 rd0
= (insn
>> 16) & 0xf;
1873 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1874 switch ((insn
>> 22) & 3) {
1876 gen_helper_iwmmxt_addcb(cpu_M0
, cpu_M0
);
1879 gen_helper_iwmmxt_addcw(cpu_M0
, cpu_M0
);
1882 gen_helper_iwmmxt_addcl(cpu_M0
, cpu_M0
);
1887 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1888 gen_op_iwmmxt_set_mup();
1890 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1891 if ((insn
& 0x000ff00f) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1893 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1894 tmp2
= tcg_temp_new_i32();
1895 tcg_gen_mov_i32(tmp2
, tmp
);
1896 switch ((insn
>> 22) & 3) {
1898 for (i
= 0; i
< 7; i
++) {
1899 tcg_gen_shli_i32(tmp2
, tmp2
, 4);
1900 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1904 for (i
= 0; i
< 3; i
++) {
1905 tcg_gen_shli_i32(tmp2
, tmp2
, 8);
1906 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1910 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
1911 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1915 tcg_temp_free_i32(tmp2
);
1916 tcg_temp_free_i32(tmp
);
1918 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1919 rd
= (insn
>> 12) & 0xf;
1920 rd0
= (insn
>> 16) & 0xf;
1921 if ((insn
& 0xf) != 0 || ((insn
>> 22) & 3) == 3)
1923 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1924 tmp
= tcg_temp_new_i32();
1925 switch ((insn
>> 22) & 3) {
1927 gen_helper_iwmmxt_msbb(tmp
, cpu_M0
);
1930 gen_helper_iwmmxt_msbw(tmp
, cpu_M0
);
1933 gen_helper_iwmmxt_msbl(tmp
, cpu_M0
);
1936 store_reg(s
, rd
, tmp
);
1938 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1939 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1940 wrd
= (insn
>> 12) & 0xf;
1941 rd0
= (insn
>> 16) & 0xf;
1942 rd1
= (insn
>> 0) & 0xf;
1943 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1944 switch ((insn
>> 22) & 3) {
1946 if (insn
& (1 << 21))
1947 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1
);
1949 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1
);
1952 if (insn
& (1 << 21))
1953 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1
);
1955 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1
);
1958 if (insn
& (1 << 21))
1959 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1
);
1961 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1
);
1966 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1967 gen_op_iwmmxt_set_mup();
1968 gen_op_iwmmxt_set_cup();
1970 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
1971 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1972 wrd
= (insn
>> 12) & 0xf;
1973 rd0
= (insn
>> 16) & 0xf;
1974 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1975 switch ((insn
>> 22) & 3) {
1977 if (insn
& (1 << 21))
1978 gen_op_iwmmxt_unpacklsb_M0();
1980 gen_op_iwmmxt_unpacklub_M0();
1983 if (insn
& (1 << 21))
1984 gen_op_iwmmxt_unpacklsw_M0();
1986 gen_op_iwmmxt_unpackluw_M0();
1989 if (insn
& (1 << 21))
1990 gen_op_iwmmxt_unpacklsl_M0();
1992 gen_op_iwmmxt_unpacklul_M0();
1997 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1998 gen_op_iwmmxt_set_mup();
1999 gen_op_iwmmxt_set_cup();
2001 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2002 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2003 wrd
= (insn
>> 12) & 0xf;
2004 rd0
= (insn
>> 16) & 0xf;
2005 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2006 switch ((insn
>> 22) & 3) {
2008 if (insn
& (1 << 21))
2009 gen_op_iwmmxt_unpackhsb_M0();
2011 gen_op_iwmmxt_unpackhub_M0();
2014 if (insn
& (1 << 21))
2015 gen_op_iwmmxt_unpackhsw_M0();
2017 gen_op_iwmmxt_unpackhuw_M0();
2020 if (insn
& (1 << 21))
2021 gen_op_iwmmxt_unpackhsl_M0();
2023 gen_op_iwmmxt_unpackhul_M0();
2028 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2029 gen_op_iwmmxt_set_mup();
2030 gen_op_iwmmxt_set_cup();
2032 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2033 case 0x214: case 0x614: case 0xa14: case 0xe14:
2034 if (((insn
>> 22) & 3) == 0)
2036 wrd
= (insn
>> 12) & 0xf;
2037 rd0
= (insn
>> 16) & 0xf;
2038 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2039 tmp
= tcg_temp_new_i32();
2040 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
2041 tcg_temp_free_i32(tmp
);
2044 switch ((insn
>> 22) & 3) {
2046 gen_helper_iwmmxt_srlw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2049 gen_helper_iwmmxt_srll(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2052 gen_helper_iwmmxt_srlq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2055 tcg_temp_free_i32(tmp
);
2056 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2057 gen_op_iwmmxt_set_mup();
2058 gen_op_iwmmxt_set_cup();
2060 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2061 case 0x014: case 0x414: case 0x814: case 0xc14:
2062 if (((insn
>> 22) & 3) == 0)
2064 wrd
= (insn
>> 12) & 0xf;
2065 rd0
= (insn
>> 16) & 0xf;
2066 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2067 tmp
= tcg_temp_new_i32();
2068 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
2069 tcg_temp_free_i32(tmp
);
2072 switch ((insn
>> 22) & 3) {
2074 gen_helper_iwmmxt_sraw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2077 gen_helper_iwmmxt_sral(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2080 gen_helper_iwmmxt_sraq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2083 tcg_temp_free_i32(tmp
);
2084 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2085 gen_op_iwmmxt_set_mup();
2086 gen_op_iwmmxt_set_cup();
2088 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2089 case 0x114: case 0x514: case 0x914: case 0xd14:
2090 if (((insn
>> 22) & 3) == 0)
2092 wrd
= (insn
>> 12) & 0xf;
2093 rd0
= (insn
>> 16) & 0xf;
2094 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2095 tmp
= tcg_temp_new_i32();
2096 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
2097 tcg_temp_free_i32(tmp
);
2100 switch ((insn
>> 22) & 3) {
2102 gen_helper_iwmmxt_sllw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2105 gen_helper_iwmmxt_slll(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2108 gen_helper_iwmmxt_sllq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2111 tcg_temp_free_i32(tmp
);
2112 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2113 gen_op_iwmmxt_set_mup();
2114 gen_op_iwmmxt_set_cup();
2116 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2117 case 0x314: case 0x714: case 0xb14: case 0xf14:
2118 if (((insn
>> 22) & 3) == 0)
2120 wrd
= (insn
>> 12) & 0xf;
2121 rd0
= (insn
>> 16) & 0xf;
2122 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2123 tmp
= tcg_temp_new_i32();
2124 switch ((insn
>> 22) & 3) {
2126 if (gen_iwmmxt_shift(insn
, 0xf, tmp
)) {
2127 tcg_temp_free_i32(tmp
);
2130 gen_helper_iwmmxt_rorw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2133 if (gen_iwmmxt_shift(insn
, 0x1f, tmp
)) {
2134 tcg_temp_free_i32(tmp
);
2137 gen_helper_iwmmxt_rorl(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2140 if (gen_iwmmxt_shift(insn
, 0x3f, tmp
)) {
2141 tcg_temp_free_i32(tmp
);
2144 gen_helper_iwmmxt_rorq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2147 tcg_temp_free_i32(tmp
);
2148 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2149 gen_op_iwmmxt_set_mup();
2150 gen_op_iwmmxt_set_cup();
2152 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2153 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2154 wrd
= (insn
>> 12) & 0xf;
2155 rd0
= (insn
>> 16) & 0xf;
2156 rd1
= (insn
>> 0) & 0xf;
2157 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2158 switch ((insn
>> 22) & 3) {
2160 if (insn
& (1 << 21))
2161 gen_op_iwmmxt_minsb_M0_wRn(rd1
);
2163 gen_op_iwmmxt_minub_M0_wRn(rd1
);
2166 if (insn
& (1 << 21))
2167 gen_op_iwmmxt_minsw_M0_wRn(rd1
);
2169 gen_op_iwmmxt_minuw_M0_wRn(rd1
);
2172 if (insn
& (1 << 21))
2173 gen_op_iwmmxt_minsl_M0_wRn(rd1
);
2175 gen_op_iwmmxt_minul_M0_wRn(rd1
);
2180 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2181 gen_op_iwmmxt_set_mup();
2183 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2184 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2185 wrd
= (insn
>> 12) & 0xf;
2186 rd0
= (insn
>> 16) & 0xf;
2187 rd1
= (insn
>> 0) & 0xf;
2188 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2189 switch ((insn
>> 22) & 3) {
2191 if (insn
& (1 << 21))
2192 gen_op_iwmmxt_maxsb_M0_wRn(rd1
);
2194 gen_op_iwmmxt_maxub_M0_wRn(rd1
);
2197 if (insn
& (1 << 21))
2198 gen_op_iwmmxt_maxsw_M0_wRn(rd1
);
2200 gen_op_iwmmxt_maxuw_M0_wRn(rd1
);
2203 if (insn
& (1 << 21))
2204 gen_op_iwmmxt_maxsl_M0_wRn(rd1
);
2206 gen_op_iwmmxt_maxul_M0_wRn(rd1
);
2211 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2212 gen_op_iwmmxt_set_mup();
2214 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2215 case 0x402: case 0x502: case 0x602: case 0x702:
2216 wrd
= (insn
>> 12) & 0xf;
2217 rd0
= (insn
>> 16) & 0xf;
2218 rd1
= (insn
>> 0) & 0xf;
2219 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2220 tmp
= tcg_const_i32((insn
>> 20) & 3);
2221 iwmmxt_load_reg(cpu_V1
, rd1
);
2222 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, tmp
);
2223 tcg_temp_free_i32(tmp
);
2224 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2225 gen_op_iwmmxt_set_mup();
2227 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2228 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2229 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2230 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2231 wrd
= (insn
>> 12) & 0xf;
2232 rd0
= (insn
>> 16) & 0xf;
2233 rd1
= (insn
>> 0) & 0xf;
2234 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2235 switch ((insn
>> 20) & 0xf) {
2237 gen_op_iwmmxt_subnb_M0_wRn(rd1
);
2240 gen_op_iwmmxt_subub_M0_wRn(rd1
);
2243 gen_op_iwmmxt_subsb_M0_wRn(rd1
);
2246 gen_op_iwmmxt_subnw_M0_wRn(rd1
);
2249 gen_op_iwmmxt_subuw_M0_wRn(rd1
);
2252 gen_op_iwmmxt_subsw_M0_wRn(rd1
);
2255 gen_op_iwmmxt_subnl_M0_wRn(rd1
);
2258 gen_op_iwmmxt_subul_M0_wRn(rd1
);
2261 gen_op_iwmmxt_subsl_M0_wRn(rd1
);
2266 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2267 gen_op_iwmmxt_set_mup();
2268 gen_op_iwmmxt_set_cup();
2270 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2271 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2272 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2273 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2274 wrd
= (insn
>> 12) & 0xf;
2275 rd0
= (insn
>> 16) & 0xf;
2276 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2277 tmp
= tcg_const_i32(((insn
>> 16) & 0xf0) | (insn
& 0x0f));
2278 gen_helper_iwmmxt_shufh(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2279 tcg_temp_free_i32(tmp
);
2280 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2281 gen_op_iwmmxt_set_mup();
2282 gen_op_iwmmxt_set_cup();
2284 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2285 case 0x418: case 0x518: case 0x618: case 0x718:
2286 case 0x818: case 0x918: case 0xa18: case 0xb18:
2287 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2288 wrd
= (insn
>> 12) & 0xf;
2289 rd0
= (insn
>> 16) & 0xf;
2290 rd1
= (insn
>> 0) & 0xf;
2291 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2292 switch ((insn
>> 20) & 0xf) {
2294 gen_op_iwmmxt_addnb_M0_wRn(rd1
);
2297 gen_op_iwmmxt_addub_M0_wRn(rd1
);
2300 gen_op_iwmmxt_addsb_M0_wRn(rd1
);
2303 gen_op_iwmmxt_addnw_M0_wRn(rd1
);
2306 gen_op_iwmmxt_adduw_M0_wRn(rd1
);
2309 gen_op_iwmmxt_addsw_M0_wRn(rd1
);
2312 gen_op_iwmmxt_addnl_M0_wRn(rd1
);
2315 gen_op_iwmmxt_addul_M0_wRn(rd1
);
2318 gen_op_iwmmxt_addsl_M0_wRn(rd1
);
2323 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2324 gen_op_iwmmxt_set_mup();
2325 gen_op_iwmmxt_set_cup();
2327 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2328 case 0x408: case 0x508: case 0x608: case 0x708:
2329 case 0x808: case 0x908: case 0xa08: case 0xb08:
2330 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2331 if (!(insn
& (1 << 20)) || ((insn
>> 22) & 3) == 0)
2333 wrd
= (insn
>> 12) & 0xf;
2334 rd0
= (insn
>> 16) & 0xf;
2335 rd1
= (insn
>> 0) & 0xf;
2336 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2337 switch ((insn
>> 22) & 3) {
2339 if (insn
& (1 << 21))
2340 gen_op_iwmmxt_packsw_M0_wRn(rd1
);
2342 gen_op_iwmmxt_packuw_M0_wRn(rd1
);
2345 if (insn
& (1 << 21))
2346 gen_op_iwmmxt_packsl_M0_wRn(rd1
);
2348 gen_op_iwmmxt_packul_M0_wRn(rd1
);
2351 if (insn
& (1 << 21))
2352 gen_op_iwmmxt_packsq_M0_wRn(rd1
);
2354 gen_op_iwmmxt_packuq_M0_wRn(rd1
);
2357 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2358 gen_op_iwmmxt_set_mup();
2359 gen_op_iwmmxt_set_cup();
2361 case 0x201: case 0x203: case 0x205: case 0x207:
2362 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2363 case 0x211: case 0x213: case 0x215: case 0x217:
2364 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2365 wrd
= (insn
>> 5) & 0xf;
2366 rd0
= (insn
>> 12) & 0xf;
2367 rd1
= (insn
>> 0) & 0xf;
2368 if (rd0
== 0xf || rd1
== 0xf)
2370 gen_op_iwmmxt_movq_M0_wRn(wrd
);
2371 tmp
= load_reg(s
, rd0
);
2372 tmp2
= load_reg(s
, rd1
);
2373 switch ((insn
>> 16) & 0xf) {
2374 case 0x0: /* TMIA */
2375 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2377 case 0x8: /* TMIAPH */
2378 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2380 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2381 if (insn
& (1 << 16))
2382 tcg_gen_shri_i32(tmp
, tmp
, 16);
2383 if (insn
& (1 << 17))
2384 tcg_gen_shri_i32(tmp2
, tmp2
, 16);
2385 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2388 tcg_temp_free_i32(tmp2
);
2389 tcg_temp_free_i32(tmp
);
2392 tcg_temp_free_i32(tmp2
);
2393 tcg_temp_free_i32(tmp
);
2394 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2395 gen_op_iwmmxt_set_mup();
2404 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
2405 (ie. an undefined instruction). */
2406 static int disas_dsp_insn(DisasContext
*s
, uint32_t insn
)
2408 int acc
, rd0
, rd1
, rdhi
, rdlo
;
2411 if ((insn
& 0x0ff00f10) == 0x0e200010) {
2412 /* Multiply with Internal Accumulate Format */
2413 rd0
= (insn
>> 12) & 0xf;
2415 acc
= (insn
>> 5) & 7;
2420 tmp
= load_reg(s
, rd0
);
2421 tmp2
= load_reg(s
, rd1
);
2422 switch ((insn
>> 16) & 0xf) {
2424 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2426 case 0x8: /* MIAPH */
2427 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2429 case 0xc: /* MIABB */
2430 case 0xd: /* MIABT */
2431 case 0xe: /* MIATB */
2432 case 0xf: /* MIATT */
2433 if (insn
& (1 << 16))
2434 tcg_gen_shri_i32(tmp
, tmp
, 16);
2435 if (insn
& (1 << 17))
2436 tcg_gen_shri_i32(tmp2
, tmp2
, 16);
2437 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2442 tcg_temp_free_i32(tmp2
);
2443 tcg_temp_free_i32(tmp
);
2445 gen_op_iwmmxt_movq_wRn_M0(acc
);
2449 if ((insn
& 0x0fe00ff8) == 0x0c400000) {
2450 /* Internal Accumulator Access Format */
2451 rdhi
= (insn
>> 16) & 0xf;
2452 rdlo
= (insn
>> 12) & 0xf;
2458 if (insn
& ARM_CP_RW_BIT
) { /* MRA */
2459 iwmmxt_load_reg(cpu_V0
, acc
);
2460 tcg_gen_extrl_i64_i32(cpu_R
[rdlo
], cpu_V0
);
2461 tcg_gen_extrh_i64_i32(cpu_R
[rdhi
], cpu_V0
);
2462 tcg_gen_andi_i32(cpu_R
[rdhi
], cpu_R
[rdhi
], (1 << (40 - 32)) - 1);
2464 tcg_gen_concat_i32_i64(cpu_V0
, cpu_R
[rdlo
], cpu_R
[rdhi
]);
2465 iwmmxt_store_reg(cpu_V0
, acc
);
2473 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2474 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2475 if (dc_isar_feature(aa32_simd_r32, s)) { \
2476 reg = (((insn) >> (bigbit)) & 0x0f) \
2477 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2479 if (insn & (1 << (smallbit))) \
2481 reg = ((insn) >> (bigbit)) & 0x0f; \
2484 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2485 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2486 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2488 static inline bool use_goto_tb(DisasContext
*s
, target_ulong dest
)
2490 #ifndef CONFIG_USER_ONLY
2491 return (s
->base
.tb
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
) ||
2492 ((s
->base
.pc_next
- 1) & TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
);
2498 static void gen_goto_ptr(void)
2500 tcg_gen_lookup_and_goto_ptr();
2503 /* This will end the TB but doesn't guarantee we'll return to
2504 * cpu_loop_exec. Any live exit_requests will be processed as we
2505 * enter the next TB.
2507 static void gen_goto_tb(DisasContext
*s
, int n
, target_ulong dest
)
2509 if (use_goto_tb(s
, dest
)) {
2511 gen_set_pc_im(s
, dest
);
2512 tcg_gen_exit_tb(s
->base
.tb
, n
);
2514 gen_set_pc_im(s
, dest
);
2517 s
->base
.is_jmp
= DISAS_NORETURN
;
2520 static inline void gen_jmp (DisasContext
*s
, uint32_t dest
)
2522 if (unlikely(is_singlestepping(s
))) {
2523 /* An indirect jump so that we still trigger the debug exception. */
2524 gen_set_pc_im(s
, dest
);
2525 s
->base
.is_jmp
= DISAS_JUMP
;
2527 gen_goto_tb(s
, 0, dest
);
2531 static inline void gen_mulxy(TCGv_i32 t0
, TCGv_i32 t1
, int x
, int y
)
2534 tcg_gen_sari_i32(t0
, t0
, 16);
2538 tcg_gen_sari_i32(t1
, t1
, 16);
2541 tcg_gen_mul_i32(t0
, t0
, t1
);
2544 /* Return the mask of PSR bits set by a MSR instruction. */
2545 static uint32_t msr_mask(DisasContext
*s
, int flags
, int spsr
)
2549 if (flags
& (1 << 0)) {
2552 if (flags
& (1 << 1)) {
2555 if (flags
& (1 << 2)) {
2558 if (flags
& (1 << 3)) {
2562 /* Mask out undefined and reserved bits. */
2563 mask
&= aarch32_cpsr_valid_mask(s
->features
, s
->isar
);
2565 /* Mask out execution state. */
2570 /* Mask out privileged bits. */
2577 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
2578 static int gen_set_psr(DisasContext
*s
, uint32_t mask
, int spsr
, TCGv_i32 t0
)
2582 /* ??? This is also undefined in system mode. */
2586 tmp
= load_cpu_field(spsr
);
2587 tcg_gen_andi_i32(tmp
, tmp
, ~mask
);
2588 tcg_gen_andi_i32(t0
, t0
, mask
);
2589 tcg_gen_or_i32(tmp
, tmp
, t0
);
2590 store_cpu_field(tmp
, spsr
);
2592 gen_set_cpsr(t0
, mask
);
2594 tcg_temp_free_i32(t0
);
2599 /* Returns nonzero if access to the PSR is not permitted. */
2600 static int gen_set_psr_im(DisasContext
*s
, uint32_t mask
, int spsr
, uint32_t val
)
2603 tmp
= tcg_temp_new_i32();
2604 tcg_gen_movi_i32(tmp
, val
);
2605 return gen_set_psr(s
, mask
, spsr
, tmp
);
2608 static bool msr_banked_access_decode(DisasContext
*s
, int r
, int sysm
, int rn
,
2609 int *tgtmode
, int *regno
)
2611 /* Decode the r and sysm fields of MSR/MRS banked accesses into
2612 * the target mode and register number, and identify the various
2613 * unpredictable cases.
2614 * MSR (banked) and MRS (banked) are CONSTRAINED UNPREDICTABLE if:
2615 * + executed in user mode
2616 * + using R15 as the src/dest register
2617 * + accessing an unimplemented register
2618 * + accessing a register that's inaccessible at current PL/security state*
2619 * + accessing a register that you could access with a different insn
2620 * We choose to UNDEF in all these cases.
2621 * Since we don't know which of the various AArch32 modes we are in
2622 * we have to defer some checks to runtime.
2623 * Accesses to Monitor mode registers from Secure EL1 (which implies
2624 * that EL3 is AArch64) must trap to EL3.
2626 * If the access checks fail this function will emit code to take
2627 * an exception and return false. Otherwise it will return true,
2628 * and set *tgtmode and *regno appropriately.
2630 int exc_target
= default_exception_el(s
);
2632 /* These instructions are present only in ARMv8, or in ARMv7 with the
2633 * Virtualization Extensions.
2635 if (!arm_dc_feature(s
, ARM_FEATURE_V8
) &&
2636 !arm_dc_feature(s
, ARM_FEATURE_EL2
)) {
2640 if (IS_USER(s
) || rn
== 15) {
2644 /* The table in the v8 ARM ARM section F5.2.3 describes the encoding
2645 * of registers into (r, sysm).
2648 /* SPSRs for other modes */
2650 case 0xe: /* SPSR_fiq */
2651 *tgtmode
= ARM_CPU_MODE_FIQ
;
2653 case 0x10: /* SPSR_irq */
2654 *tgtmode
= ARM_CPU_MODE_IRQ
;
2656 case 0x12: /* SPSR_svc */
2657 *tgtmode
= ARM_CPU_MODE_SVC
;
2659 case 0x14: /* SPSR_abt */
2660 *tgtmode
= ARM_CPU_MODE_ABT
;
2662 case 0x16: /* SPSR_und */
2663 *tgtmode
= ARM_CPU_MODE_UND
;
2665 case 0x1c: /* SPSR_mon */
2666 *tgtmode
= ARM_CPU_MODE_MON
;
2668 case 0x1e: /* SPSR_hyp */
2669 *tgtmode
= ARM_CPU_MODE_HYP
;
2671 default: /* unallocated */
2674 /* We arbitrarily assign SPSR a register number of 16. */
2677 /* general purpose registers for other modes */
2679 case 0x0 ... 0x6: /* 0b00xxx : r8_usr ... r14_usr */
2680 *tgtmode
= ARM_CPU_MODE_USR
;
2683 case 0x8 ... 0xe: /* 0b01xxx : r8_fiq ... r14_fiq */
2684 *tgtmode
= ARM_CPU_MODE_FIQ
;
2687 case 0x10 ... 0x11: /* 0b1000x : r14_irq, r13_irq */
2688 *tgtmode
= ARM_CPU_MODE_IRQ
;
2689 *regno
= sysm
& 1 ? 13 : 14;
2691 case 0x12 ... 0x13: /* 0b1001x : r14_svc, r13_svc */
2692 *tgtmode
= ARM_CPU_MODE_SVC
;
2693 *regno
= sysm
& 1 ? 13 : 14;
2695 case 0x14 ... 0x15: /* 0b1010x : r14_abt, r13_abt */
2696 *tgtmode
= ARM_CPU_MODE_ABT
;
2697 *regno
= sysm
& 1 ? 13 : 14;
2699 case 0x16 ... 0x17: /* 0b1011x : r14_und, r13_und */
2700 *tgtmode
= ARM_CPU_MODE_UND
;
2701 *regno
= sysm
& 1 ? 13 : 14;
2703 case 0x1c ... 0x1d: /* 0b1110x : r14_mon, r13_mon */
2704 *tgtmode
= ARM_CPU_MODE_MON
;
2705 *regno
= sysm
& 1 ? 13 : 14;
2707 case 0x1e ... 0x1f: /* 0b1111x : elr_hyp, r13_hyp */
2708 *tgtmode
= ARM_CPU_MODE_HYP
;
2709 /* Arbitrarily pick 17 for ELR_Hyp (which is not a banked LR!) */
2710 *regno
= sysm
& 1 ? 13 : 17;
2712 default: /* unallocated */
2717 /* Catch the 'accessing inaccessible register' cases we can detect
2718 * at translate time.
2721 case ARM_CPU_MODE_MON
:
2722 if (!arm_dc_feature(s
, ARM_FEATURE_EL3
) || s
->ns
) {
2725 if (s
->current_el
== 1) {
2726 /* If we're in Secure EL1 (which implies that EL3 is AArch64)
2727 * then accesses to Mon registers trap to EL3
2733 case ARM_CPU_MODE_HYP
:
2735 * SPSR_hyp and r13_hyp can only be accessed from Monitor mode
2736 * (and so we can forbid accesses from EL2 or below). elr_hyp
2737 * can be accessed also from Hyp mode, so forbid accesses from
2740 if (!arm_dc_feature(s
, ARM_FEATURE_EL2
) || s
->current_el
< 2 ||
2741 (s
->current_el
< 3 && *regno
!= 17)) {
2752 /* If we get here then some access check did not pass */
2753 gen_exception_insn(s
, s
->pc_curr
, EXCP_UDEF
,
2754 syn_uncategorized(), exc_target
);
2758 static void gen_msr_banked(DisasContext
*s
, int r
, int sysm
, int rn
)
2760 TCGv_i32 tcg_reg
, tcg_tgtmode
, tcg_regno
;
2761 int tgtmode
= 0, regno
= 0;
2763 if (!msr_banked_access_decode(s
, r
, sysm
, rn
, &tgtmode
, ®no
)) {
2767 /* Sync state because msr_banked() can raise exceptions */
2768 gen_set_condexec(s
);
2769 gen_set_pc_im(s
, s
->pc_curr
);
2770 tcg_reg
= load_reg(s
, rn
);
2771 tcg_tgtmode
= tcg_const_i32(tgtmode
);
2772 tcg_regno
= tcg_const_i32(regno
);
2773 gen_helper_msr_banked(cpu_env
, tcg_reg
, tcg_tgtmode
, tcg_regno
);
2774 tcg_temp_free_i32(tcg_tgtmode
);
2775 tcg_temp_free_i32(tcg_regno
);
2776 tcg_temp_free_i32(tcg_reg
);
2777 s
->base
.is_jmp
= DISAS_UPDATE_EXIT
;
2780 static void gen_mrs_banked(DisasContext
*s
, int r
, int sysm
, int rn
)
2782 TCGv_i32 tcg_reg
, tcg_tgtmode
, tcg_regno
;
2783 int tgtmode
= 0, regno
= 0;
2785 if (!msr_banked_access_decode(s
, r
, sysm
, rn
, &tgtmode
, ®no
)) {
2789 /* Sync state because mrs_banked() can raise exceptions */
2790 gen_set_condexec(s
);
2791 gen_set_pc_im(s
, s
->pc_curr
);
2792 tcg_reg
= tcg_temp_new_i32();
2793 tcg_tgtmode
= tcg_const_i32(tgtmode
);
2794 tcg_regno
= tcg_const_i32(regno
);
2795 gen_helper_mrs_banked(tcg_reg
, cpu_env
, tcg_tgtmode
, tcg_regno
);
2796 tcg_temp_free_i32(tcg_tgtmode
);
2797 tcg_temp_free_i32(tcg_regno
);
2798 store_reg(s
, rn
, tcg_reg
);
2799 s
->base
.is_jmp
= DISAS_UPDATE_EXIT
;
2802 /* Store value to PC as for an exception return (ie don't
2803 * mask bits). The subsequent call to gen_helper_cpsr_write_eret()
2804 * will do the masking based on the new value of the Thumb bit.
2806 static void store_pc_exc_ret(DisasContext
*s
, TCGv_i32 pc
)
2808 tcg_gen_mov_i32(cpu_R
[15], pc
);
2809 tcg_temp_free_i32(pc
);
2812 /* Generate a v6 exception return. Marks both values as dead. */
2813 static void gen_rfe(DisasContext
*s
, TCGv_i32 pc
, TCGv_i32 cpsr
)
2815 store_pc_exc_ret(s
, pc
);
2816 /* The cpsr_write_eret helper will mask the low bits of PC
2817 * appropriately depending on the new Thumb bit, so it must
2818 * be called after storing the new PC.
2820 if (tb_cflags(s
->base
.tb
) & CF_USE_ICOUNT
) {
2823 gen_helper_cpsr_write_eret(cpu_env
, cpsr
);
2824 tcg_temp_free_i32(cpsr
);
2825 /* Must exit loop to check un-masked IRQs */
2826 s
->base
.is_jmp
= DISAS_EXIT
;
2829 /* Generate an old-style exception return. Marks pc as dead. */
2830 static void gen_exception_return(DisasContext
*s
, TCGv_i32 pc
)
2832 gen_rfe(s
, pc
, load_cpu_field(spsr
));
2835 static void gen_gvec_fn3_qc(uint32_t rd_ofs
, uint32_t rn_ofs
, uint32_t rm_ofs
,
2836 uint32_t opr_sz
, uint32_t max_sz
,
2837 gen_helper_gvec_3_ptr
*fn
)
2839 TCGv_ptr qc_ptr
= tcg_temp_new_ptr();
2841 tcg_gen_addi_ptr(qc_ptr
, cpu_env
, offsetof(CPUARMState
, vfp
.qc
));
2842 tcg_gen_gvec_3_ptr(rd_ofs
, rn_ofs
, rm_ofs
, qc_ptr
,
2843 opr_sz
, max_sz
, 0, fn
);
2844 tcg_temp_free_ptr(qc_ptr
);
2847 void gen_gvec_sqrdmlah_qc(unsigned vece
, uint32_t rd_ofs
, uint32_t rn_ofs
,
2848 uint32_t rm_ofs
, uint32_t opr_sz
, uint32_t max_sz
)
2850 static gen_helper_gvec_3_ptr
* const fns
[2] = {
2851 gen_helper_gvec_qrdmlah_s16
, gen_helper_gvec_qrdmlah_s32
2853 tcg_debug_assert(vece
>= 1 && vece
<= 2);
2854 gen_gvec_fn3_qc(rd_ofs
, rn_ofs
, rm_ofs
, opr_sz
, max_sz
, fns
[vece
- 1]);
2857 void gen_gvec_sqrdmlsh_qc(unsigned vece
, uint32_t rd_ofs
, uint32_t rn_ofs
,
2858 uint32_t rm_ofs
, uint32_t opr_sz
, uint32_t max_sz
)
2860 static gen_helper_gvec_3_ptr
* const fns
[2] = {
2861 gen_helper_gvec_qrdmlsh_s16
, gen_helper_gvec_qrdmlsh_s32
2863 tcg_debug_assert(vece
>= 1 && vece
<= 2);
2864 gen_gvec_fn3_qc(rd_ofs
, rn_ofs
, rm_ofs
, opr_sz
, max_sz
, fns
[vece
- 1]);
2867 #define GEN_CMP0(NAME, COND) \
2868 static void gen_##NAME##0_i32(TCGv_i32 d, TCGv_i32 a) \
2870 tcg_gen_setcondi_i32(COND, d, a, 0); \
2871 tcg_gen_neg_i32(d, d); \
2873 static void gen_##NAME##0_i64(TCGv_i64 d, TCGv_i64 a) \
2875 tcg_gen_setcondi_i64(COND, d, a, 0); \
2876 tcg_gen_neg_i64(d, d); \
2878 static void gen_##NAME##0_vec(unsigned vece, TCGv_vec d, TCGv_vec a) \
2880 TCGv_vec zero = tcg_const_zeros_vec_matching(d); \
2881 tcg_gen_cmp_vec(COND, vece, d, a, zero); \
2882 tcg_temp_free_vec(zero); \
2884 void gen_gvec_##NAME##0(unsigned vece, uint32_t d, uint32_t m, \
2885 uint32_t opr_sz, uint32_t max_sz) \
2887 const GVecGen2 op[4] = { \
2888 { .fno = gen_helper_gvec_##NAME##0_b, \
2889 .fniv = gen_##NAME##0_vec, \
2890 .opt_opc = vecop_list_cmp, \
2892 { .fno = gen_helper_gvec_##NAME##0_h, \
2893 .fniv = gen_##NAME##0_vec, \
2894 .opt_opc = vecop_list_cmp, \
2896 { .fni4 = gen_##NAME##0_i32, \
2897 .fniv = gen_##NAME##0_vec, \
2898 .opt_opc = vecop_list_cmp, \
2900 { .fni8 = gen_##NAME##0_i64, \
2901 .fniv = gen_##NAME##0_vec, \
2902 .opt_opc = vecop_list_cmp, \
2903 .prefer_i64 = TCG_TARGET_REG_BITS == 64, \
2906 tcg_gen_gvec_2(d, m, opr_sz, max_sz, &op[vece]); \
2909 static const TCGOpcode vecop_list_cmp
[] = {
2913 GEN_CMP0(ceq
, TCG_COND_EQ
)
2914 GEN_CMP0(cle
, TCG_COND_LE
)
2915 GEN_CMP0(cge
, TCG_COND_GE
)
2916 GEN_CMP0(clt
, TCG_COND_LT
)
2917 GEN_CMP0(cgt
, TCG_COND_GT
)
2921 static void gen_ssra8_i64(TCGv_i64 d
, TCGv_i64 a
, int64_t shift
)
2923 tcg_gen_vec_sar8i_i64(a
, a
, shift
);
2924 tcg_gen_vec_add8_i64(d
, d
, a
);
2927 static void gen_ssra16_i64(TCGv_i64 d
, TCGv_i64 a
, int64_t shift
)
2929 tcg_gen_vec_sar16i_i64(a
, a
, shift
);
2930 tcg_gen_vec_add16_i64(d
, d
, a
);
2933 static void gen_ssra32_i32(TCGv_i32 d
, TCGv_i32 a
, int32_t shift
)
2935 tcg_gen_sari_i32(a
, a
, shift
);
2936 tcg_gen_add_i32(d
, d
, a
);
2939 static void gen_ssra64_i64(TCGv_i64 d
, TCGv_i64 a
, int64_t shift
)
2941 tcg_gen_sari_i64(a
, a
, shift
);
2942 tcg_gen_add_i64(d
, d
, a
);
2945 static void gen_ssra_vec(unsigned vece
, TCGv_vec d
, TCGv_vec a
, int64_t sh
)
2947 tcg_gen_sari_vec(vece
, a
, a
, sh
);
2948 tcg_gen_add_vec(vece
, d
, d
, a
);
2951 void gen_gvec_ssra(unsigned vece
, uint32_t rd_ofs
, uint32_t rm_ofs
,
2952 int64_t shift
, uint32_t opr_sz
, uint32_t max_sz
)
2954 static const TCGOpcode vecop_list
[] = {
2955 INDEX_op_sari_vec
, INDEX_op_add_vec
, 0
2957 static const GVecGen2i ops
[4] = {
2958 { .fni8
= gen_ssra8_i64
,
2959 .fniv
= gen_ssra_vec
,
2960 .fno
= gen_helper_gvec_ssra_b
,
2962 .opt_opc
= vecop_list
,
2964 { .fni8
= gen_ssra16_i64
,
2965 .fniv
= gen_ssra_vec
,
2966 .fno
= gen_helper_gvec_ssra_h
,
2968 .opt_opc
= vecop_list
,
2970 { .fni4
= gen_ssra32_i32
,
2971 .fniv
= gen_ssra_vec
,
2972 .fno
= gen_helper_gvec_ssra_s
,
2974 .opt_opc
= vecop_list
,
2976 { .fni8
= gen_ssra64_i64
,
2977 .fniv
= gen_ssra_vec
,
2978 .fno
= gen_helper_gvec_ssra_b
,
2979 .prefer_i64
= TCG_TARGET_REG_BITS
== 64,
2980 .opt_opc
= vecop_list
,
2985 /* tszimm encoding produces immediates in the range [1..esize]. */
2986 tcg_debug_assert(shift
> 0);
2987 tcg_debug_assert(shift
<= (8 << vece
));
2990 * Shifts larger than the element size are architecturally valid.
2991 * Signed results in all sign bits.
2993 shift
= MIN(shift
, (8 << vece
) - 1);
2994 tcg_gen_gvec_2i(rd_ofs
, rm_ofs
, opr_sz
, max_sz
, shift
, &ops
[vece
]);
2997 static void gen_usra8_i64(TCGv_i64 d
, TCGv_i64 a
, int64_t shift
)
2999 tcg_gen_vec_shr8i_i64(a
, a
, shift
);
3000 tcg_gen_vec_add8_i64(d
, d
, a
);
3003 static void gen_usra16_i64(TCGv_i64 d
, TCGv_i64 a
, int64_t shift
)
3005 tcg_gen_vec_shr16i_i64(a
, a
, shift
);
3006 tcg_gen_vec_add16_i64(d
, d
, a
);
3009 static void gen_usra32_i32(TCGv_i32 d
, TCGv_i32 a
, int32_t shift
)
3011 tcg_gen_shri_i32(a
, a
, shift
);
3012 tcg_gen_add_i32(d
, d
, a
);
3015 static void gen_usra64_i64(TCGv_i64 d
, TCGv_i64 a
, int64_t shift
)
3017 tcg_gen_shri_i64(a
, a
, shift
);
3018 tcg_gen_add_i64(d
, d
, a
);
3021 static void gen_usra_vec(unsigned vece
, TCGv_vec d
, TCGv_vec a
, int64_t sh
)
3023 tcg_gen_shri_vec(vece
, a
, a
, sh
);
3024 tcg_gen_add_vec(vece
, d
, d
, a
);
3027 void gen_gvec_usra(unsigned vece
, uint32_t rd_ofs
, uint32_t rm_ofs
,
3028 int64_t shift
, uint32_t opr_sz
, uint32_t max_sz
)
3030 static const TCGOpcode vecop_list
[] = {
3031 INDEX_op_shri_vec
, INDEX_op_add_vec
, 0
3033 static const GVecGen2i ops
[4] = {
3034 { .fni8
= gen_usra8_i64
,
3035 .fniv
= gen_usra_vec
,
3036 .fno
= gen_helper_gvec_usra_b
,
3038 .opt_opc
= vecop_list
,
3040 { .fni8
= gen_usra16_i64
,
3041 .fniv
= gen_usra_vec
,
3042 .fno
= gen_helper_gvec_usra_h
,
3044 .opt_opc
= vecop_list
,
3046 { .fni4
= gen_usra32_i32
,
3047 .fniv
= gen_usra_vec
,
3048 .fno
= gen_helper_gvec_usra_s
,
3050 .opt_opc
= vecop_list
,
3052 { .fni8
= gen_usra64_i64
,
3053 .fniv
= gen_usra_vec
,
3054 .fno
= gen_helper_gvec_usra_d
,
3055 .prefer_i64
= TCG_TARGET_REG_BITS
== 64,
3057 .opt_opc
= vecop_list
,
3061 /* tszimm encoding produces immediates in the range [1..esize]. */
3062 tcg_debug_assert(shift
> 0);
3063 tcg_debug_assert(shift
<= (8 << vece
));
3066 * Shifts larger than the element size are architecturally valid.
3067 * Unsigned results in all zeros as input to accumulate: nop.
3069 if (shift
< (8 << vece
)) {
3070 tcg_gen_gvec_2i(rd_ofs
, rm_ofs
, opr_sz
, max_sz
, shift
, &ops
[vece
]);
3072 /* Nop, but we do need to clear the tail. */
3073 tcg_gen_gvec_mov(vece
, rd_ofs
, rd_ofs
, opr_sz
, max_sz
);
3078 * Shift one less than the requested amount, and the low bit is
3079 * the rounding bit. For the 8 and 16-bit operations, because we
3080 * mask the low bit, we can perform a normal integer shift instead
3081 * of a vector shift.
3083 static void gen_srshr8_i64(TCGv_i64 d
, TCGv_i64 a
, int64_t sh
)
3085 TCGv_i64 t
= tcg_temp_new_i64();
3087 tcg_gen_shri_i64(t
, a
, sh
- 1);
3088 tcg_gen_andi_i64(t
, t
, dup_const(MO_8
, 1));
3089 tcg_gen_vec_sar8i_i64(d
, a
, sh
);
3090 tcg_gen_vec_add8_i64(d
, d
, t
);
3091 tcg_temp_free_i64(t
);
3094 static void gen_srshr16_i64(TCGv_i64 d
, TCGv_i64 a
, int64_t sh
)
3096 TCGv_i64 t
= tcg_temp_new_i64();
3098 tcg_gen_shri_i64(t
, a
, sh
- 1);
3099 tcg_gen_andi_i64(t
, t
, dup_const(MO_16
, 1));
3100 tcg_gen_vec_sar16i_i64(d
, a
, sh
);
3101 tcg_gen_vec_add16_i64(d
, d
, t
);
3102 tcg_temp_free_i64(t
);
3105 static void gen_srshr32_i32(TCGv_i32 d
, TCGv_i32 a
, int32_t sh
)
3107 TCGv_i32 t
= tcg_temp_new_i32();
3109 tcg_gen_extract_i32(t
, a
, sh
- 1, 1);
3110 tcg_gen_sari_i32(d
, a
, sh
);
3111 tcg_gen_add_i32(d
, d
, t
);
3112 tcg_temp_free_i32(t
);
3115 static void gen_srshr64_i64(TCGv_i64 d
, TCGv_i64 a
, int64_t sh
)
3117 TCGv_i64 t
= tcg_temp_new_i64();
3119 tcg_gen_extract_i64(t
, a
, sh
- 1, 1);
3120 tcg_gen_sari_i64(d
, a
, sh
);
3121 tcg_gen_add_i64(d
, d
, t
);
3122 tcg_temp_free_i64(t
);
3125 static void gen_srshr_vec(unsigned vece
, TCGv_vec d
, TCGv_vec a
, int64_t sh
)
3127 TCGv_vec t
= tcg_temp_new_vec_matching(d
);
3128 TCGv_vec ones
= tcg_temp_new_vec_matching(d
);
3130 tcg_gen_shri_vec(vece
, t
, a
, sh
- 1);
3131 tcg_gen_dupi_vec(vece
, ones
, 1);
3132 tcg_gen_and_vec(vece
, t
, t
, ones
);
3133 tcg_gen_sari_vec(vece
, d
, a
, sh
);
3134 tcg_gen_add_vec(vece
, d
, d
, t
);
3136 tcg_temp_free_vec(t
);
3137 tcg_temp_free_vec(ones
);
3140 void gen_gvec_srshr(unsigned vece
, uint32_t rd_ofs
, uint32_t rm_ofs
,
3141 int64_t shift
, uint32_t opr_sz
, uint32_t max_sz
)
3143 static const TCGOpcode vecop_list
[] = {
3144 INDEX_op_shri_vec
, INDEX_op_sari_vec
, INDEX_op_add_vec
, 0
3146 static const GVecGen2i ops
[4] = {
3147 { .fni8
= gen_srshr8_i64
,
3148 .fniv
= gen_srshr_vec
,
3149 .fno
= gen_helper_gvec_srshr_b
,
3150 .opt_opc
= vecop_list
,
3152 { .fni8
= gen_srshr16_i64
,
3153 .fniv
= gen_srshr_vec
,
3154 .fno
= gen_helper_gvec_srshr_h
,
3155 .opt_opc
= vecop_list
,
3157 { .fni4
= gen_srshr32_i32
,
3158 .fniv
= gen_srshr_vec
,
3159 .fno
= gen_helper_gvec_srshr_s
,
3160 .opt_opc
= vecop_list
,
3162 { .fni8
= gen_srshr64_i64
,
3163 .fniv
= gen_srshr_vec
,
3164 .fno
= gen_helper_gvec_srshr_d
,
3165 .prefer_i64
= TCG_TARGET_REG_BITS
== 64,
3166 .opt_opc
= vecop_list
,
3170 /* tszimm encoding produces immediates in the range [1..esize] */
3171 tcg_debug_assert(shift
> 0);
3172 tcg_debug_assert(shift
<= (8 << vece
));
3174 if (shift
== (8 << vece
)) {
3176 * Shifts larger than the element size are architecturally valid.
3177 * Signed results in all sign bits. With rounding, this produces
3178 * (-1 + 1) >> 1 == 0, or (0 + 1) >> 1 == 0.
3181 tcg_gen_gvec_dup_imm(vece
, rd_ofs
, opr_sz
, max_sz
, 0);
3183 tcg_gen_gvec_2i(rd_ofs
, rm_ofs
, opr_sz
, max_sz
, shift
, &ops
[vece
]);
3187 static void gen_srsra8_i64(TCGv_i64 d
, TCGv_i64 a
, int64_t sh
)
3189 TCGv_i64 t
= tcg_temp_new_i64();
3191 gen_srshr8_i64(t
, a
, sh
);
3192 tcg_gen_vec_add8_i64(d
, d
, t
);
3193 tcg_temp_free_i64(t
);
3196 static void gen_srsra16_i64(TCGv_i64 d
, TCGv_i64 a
, int64_t sh
)
3198 TCGv_i64 t
= tcg_temp_new_i64();
3200 gen_srshr16_i64(t
, a
, sh
);
3201 tcg_gen_vec_add16_i64(d
, d
, t
);
3202 tcg_temp_free_i64(t
);
3205 static void gen_srsra32_i32(TCGv_i32 d
, TCGv_i32 a
, int32_t sh
)
3207 TCGv_i32 t
= tcg_temp_new_i32();
3209 gen_srshr32_i32(t
, a
, sh
);
3210 tcg_gen_add_i32(d
, d
, t
);
3211 tcg_temp_free_i32(t
);
3214 static void gen_srsra64_i64(TCGv_i64 d
, TCGv_i64 a
, int64_t sh
)
3216 TCGv_i64 t
= tcg_temp_new_i64();
3218 gen_srshr64_i64(t
, a
, sh
);
3219 tcg_gen_add_i64(d
, d
, t
);
3220 tcg_temp_free_i64(t
);
3223 static void gen_srsra_vec(unsigned vece
, TCGv_vec d
, TCGv_vec a
, int64_t sh
)
3225 TCGv_vec t
= tcg_temp_new_vec_matching(d
);
3227 gen_srshr_vec(vece
, t
, a
, sh
);
3228 tcg_gen_add_vec(vece
, d
, d
, t
);
3229 tcg_temp_free_vec(t
);
3232 void gen_gvec_srsra(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_srsra8_i64
,
3240 .fniv
= gen_srsra_vec
,
3241 .fno
= gen_helper_gvec_srsra_b
,
3242 .opt_opc
= vecop_list
,
3245 { .fni8
= gen_srsra16_i64
,
3246 .fniv
= gen_srsra_vec
,
3247 .fno
= gen_helper_gvec_srsra_h
,
3248 .opt_opc
= vecop_list
,
3251 { .fni4
= gen_srsra32_i32
,
3252 .fniv
= gen_srsra_vec
,
3253 .fno
= gen_helper_gvec_srsra_s
,
3254 .opt_opc
= vecop_list
,
3257 { .fni8
= gen_srsra64_i64
,
3258 .fniv
= gen_srsra_vec
,
3259 .fno
= gen_helper_gvec_srsra_d
,
3260 .prefer_i64
= TCG_TARGET_REG_BITS
== 64,
3261 .opt_opc
= vecop_list
,
3266 /* tszimm encoding produces immediates in the range [1..esize] */
3267 tcg_debug_assert(shift
> 0);
3268 tcg_debug_assert(shift
<= (8 << vece
));
3271 * Shifts larger than the element size are architecturally valid.
3272 * Signed results in all sign bits. With rounding, this produces
3273 * (-1 + 1) >> 1 == 0, or (0 + 1) >> 1 == 0.
3274 * I.e. always zero. With accumulation, this leaves D unchanged.
3276 if (shift
== (8 << vece
)) {
3277 /* Nop, but we do need to clear the tail. */
3278 tcg_gen_gvec_mov(vece
, rd_ofs
, rd_ofs
, opr_sz
, max_sz
);
3280 tcg_gen_gvec_2i(rd_ofs
, rm_ofs
, opr_sz
, max_sz
, shift
, &ops
[vece
]);
3284 static void gen_urshr8_i64(TCGv_i64 d
, TCGv_i64 a
, int64_t sh
)
3286 TCGv_i64 t
= tcg_temp_new_i64();
3288 tcg_gen_shri_i64(t
, a
, sh
- 1);
3289 tcg_gen_andi_i64(t
, t
, dup_const(MO_8
, 1));
3290 tcg_gen_vec_shr8i_i64(d
, a
, sh
);
3291 tcg_gen_vec_add8_i64(d
, d
, t
);
3292 tcg_temp_free_i64(t
);
3295 static void gen_urshr16_i64(TCGv_i64 d
, TCGv_i64 a
, int64_t sh
)
3297 TCGv_i64 t
= tcg_temp_new_i64();
3299 tcg_gen_shri_i64(t
, a
, sh
- 1);
3300 tcg_gen_andi_i64(t
, t
, dup_const(MO_16
, 1));
3301 tcg_gen_vec_shr16i_i64(d
, a
, sh
);
3302 tcg_gen_vec_add16_i64(d
, d
, t
);
3303 tcg_temp_free_i64(t
);
3306 static void gen_urshr32_i32(TCGv_i32 d
, TCGv_i32 a
, int32_t sh
)
3308 TCGv_i32 t
= tcg_temp_new_i32();
3310 tcg_gen_extract_i32(t
, a
, sh
- 1, 1);
3311 tcg_gen_shri_i32(d
, a
, sh
);
3312 tcg_gen_add_i32(d
, d
, t
);
3313 tcg_temp_free_i32(t
);
3316 static void gen_urshr64_i64(TCGv_i64 d
, TCGv_i64 a
, int64_t sh
)
3318 TCGv_i64 t
= tcg_temp_new_i64();
3320 tcg_gen_extract_i64(t
, a
, sh
- 1, 1);
3321 tcg_gen_shri_i64(d
, a
, sh
);
3322 tcg_gen_add_i64(d
, d
, t
);
3323 tcg_temp_free_i64(t
);
3326 static void gen_urshr_vec(unsigned vece
, TCGv_vec d
, TCGv_vec a
, int64_t shift
)
3328 TCGv_vec t
= tcg_temp_new_vec_matching(d
);
3329 TCGv_vec ones
= tcg_temp_new_vec_matching(d
);
3331 tcg_gen_shri_vec(vece
, t
, a
, shift
- 1);
3332 tcg_gen_dupi_vec(vece
, ones
, 1);
3333 tcg_gen_and_vec(vece
, t
, t
, ones
);
3334 tcg_gen_shri_vec(vece
, d
, a
, shift
);
3335 tcg_gen_add_vec(vece
, d
, d
, t
);
3337 tcg_temp_free_vec(t
);
3338 tcg_temp_free_vec(ones
);
3341 void gen_gvec_urshr(unsigned vece
, uint32_t rd_ofs
, uint32_t rm_ofs
,
3342 int64_t shift
, uint32_t opr_sz
, uint32_t max_sz
)
3344 static const TCGOpcode vecop_list
[] = {
3345 INDEX_op_shri_vec
, INDEX_op_add_vec
, 0
3347 static const GVecGen2i ops
[4] = {
3348 { .fni8
= gen_urshr8_i64
,
3349 .fniv
= gen_urshr_vec
,
3350 .fno
= gen_helper_gvec_urshr_b
,
3351 .opt_opc
= vecop_list
,
3353 { .fni8
= gen_urshr16_i64
,
3354 .fniv
= gen_urshr_vec
,
3355 .fno
= gen_helper_gvec_urshr_h
,
3356 .opt_opc
= vecop_list
,
3358 { .fni4
= gen_urshr32_i32
,
3359 .fniv
= gen_urshr_vec
,
3360 .fno
= gen_helper_gvec_urshr_s
,
3361 .opt_opc
= vecop_list
,
3363 { .fni8
= gen_urshr64_i64
,
3364 .fniv
= gen_urshr_vec
,
3365 .fno
= gen_helper_gvec_urshr_d
,
3366 .prefer_i64
= TCG_TARGET_REG_BITS
== 64,
3367 .opt_opc
= vecop_list
,
3371 /* tszimm encoding produces immediates in the range [1..esize] */
3372 tcg_debug_assert(shift
> 0);
3373 tcg_debug_assert(shift
<= (8 << vece
));
3375 if (shift
== (8 << vece
)) {
3377 * Shifts larger than the element size are architecturally valid.
3378 * Unsigned results in zero. With rounding, this produces a
3379 * copy of the most significant bit.
3381 tcg_gen_gvec_shri(vece
, rd_ofs
, rm_ofs
, shift
- 1, opr_sz
, max_sz
);
3383 tcg_gen_gvec_2i(rd_ofs
, rm_ofs
, opr_sz
, max_sz
, shift
, &ops
[vece
]);
3387 static void gen_ursra8_i64(TCGv_i64 d
, TCGv_i64 a
, int64_t sh
)
3389 TCGv_i64 t
= tcg_temp_new_i64();
3392 tcg_gen_vec_shr8i_i64(t
, a
, 7);
3394 gen_urshr8_i64(t
, a
, sh
);
3396 tcg_gen_vec_add8_i64(d
, d
, t
);
3397 tcg_temp_free_i64(t
);
3400 static void gen_ursra16_i64(TCGv_i64 d
, TCGv_i64 a
, int64_t sh
)
3402 TCGv_i64 t
= tcg_temp_new_i64();
3405 tcg_gen_vec_shr16i_i64(t
, a
, 15);
3407 gen_urshr16_i64(t
, a
, sh
);
3409 tcg_gen_vec_add16_i64(d
, d
, t
);
3410 tcg_temp_free_i64(t
);
3413 static void gen_ursra32_i32(TCGv_i32 d
, TCGv_i32 a
, int32_t sh
)
3415 TCGv_i32 t
= tcg_temp_new_i32();
3418 tcg_gen_shri_i32(t
, a
, 31);
3420 gen_urshr32_i32(t
, a
, sh
);
3422 tcg_gen_add_i32(d
, d
, t
);
3423 tcg_temp_free_i32(t
);
3426 static void gen_ursra64_i64(TCGv_i64 d
, TCGv_i64 a
, int64_t sh
)
3428 TCGv_i64 t
= tcg_temp_new_i64();
3431 tcg_gen_shri_i64(t
, a
, 63);
3433 gen_urshr64_i64(t
, a
, sh
);
3435 tcg_gen_add_i64(d
, d
, t
);
3436 tcg_temp_free_i64(t
);
3439 static void gen_ursra_vec(unsigned vece
, TCGv_vec d
, TCGv_vec a
, int64_t sh
)
3441 TCGv_vec t
= tcg_temp_new_vec_matching(d
);
3443 if (sh
== (8 << vece
)) {
3444 tcg_gen_shri_vec(vece
, t
, a
, sh
- 1);
3446 gen_urshr_vec(vece
, t
, a
, sh
);
3448 tcg_gen_add_vec(vece
, d
, d
, t
);
3449 tcg_temp_free_vec(t
);
3452 void gen_gvec_ursra(unsigned vece
, uint32_t rd_ofs
, uint32_t rm_ofs
,
3453 int64_t shift
, uint32_t opr_sz
, uint32_t max_sz
)
3455 static const TCGOpcode vecop_list
[] = {
3456 INDEX_op_shri_vec
, INDEX_op_add_vec
, 0
3458 static const GVecGen2i ops
[4] = {
3459 { .fni8
= gen_ursra8_i64
,
3460 .fniv
= gen_ursra_vec
,
3461 .fno
= gen_helper_gvec_ursra_b
,
3462 .opt_opc
= vecop_list
,
3465 { .fni8
= gen_ursra16_i64
,
3466 .fniv
= gen_ursra_vec
,
3467 .fno
= gen_helper_gvec_ursra_h
,
3468 .opt_opc
= vecop_list
,
3471 { .fni4
= gen_ursra32_i32
,
3472 .fniv
= gen_ursra_vec
,
3473 .fno
= gen_helper_gvec_ursra_s
,
3474 .opt_opc
= vecop_list
,
3477 { .fni8
= gen_ursra64_i64
,
3478 .fniv
= gen_ursra_vec
,
3479 .fno
= gen_helper_gvec_ursra_d
,
3480 .prefer_i64
= TCG_TARGET_REG_BITS
== 64,
3481 .opt_opc
= vecop_list
,
3486 /* tszimm encoding produces immediates in the range [1..esize] */
3487 tcg_debug_assert(shift
> 0);
3488 tcg_debug_assert(shift
<= (8 << vece
));
3490 tcg_gen_gvec_2i(rd_ofs
, rm_ofs
, opr_sz
, max_sz
, shift
, &ops
[vece
]);
3493 static void gen_shr8_ins_i64(TCGv_i64 d
, TCGv_i64 a
, int64_t shift
)
3495 uint64_t mask
= dup_const(MO_8
, 0xff >> shift
);
3496 TCGv_i64 t
= tcg_temp_new_i64();
3498 tcg_gen_shri_i64(t
, a
, shift
);
3499 tcg_gen_andi_i64(t
, t
, mask
);
3500 tcg_gen_andi_i64(d
, d
, ~mask
);
3501 tcg_gen_or_i64(d
, d
, t
);
3502 tcg_temp_free_i64(t
);
3505 static void gen_shr16_ins_i64(TCGv_i64 d
, TCGv_i64 a
, int64_t shift
)
3507 uint64_t mask
= dup_const(MO_16
, 0xffff >> shift
);
3508 TCGv_i64 t
= tcg_temp_new_i64();
3510 tcg_gen_shri_i64(t
, a
, shift
);
3511 tcg_gen_andi_i64(t
, t
, mask
);
3512 tcg_gen_andi_i64(d
, d
, ~mask
);
3513 tcg_gen_or_i64(d
, d
, t
);
3514 tcg_temp_free_i64(t
);
3517 static void gen_shr32_ins_i32(TCGv_i32 d
, TCGv_i32 a
, int32_t shift
)
3519 tcg_gen_shri_i32(a
, a
, shift
);
3520 tcg_gen_deposit_i32(d
, d
, a
, 0, 32 - shift
);
3523 static void gen_shr64_ins_i64(TCGv_i64 d
, TCGv_i64 a
, int64_t shift
)
3525 tcg_gen_shri_i64(a
, a
, shift
);
3526 tcg_gen_deposit_i64(d
, d
, a
, 0, 64 - shift
);
3529 static void gen_shr_ins_vec(unsigned vece
, TCGv_vec d
, TCGv_vec a
, int64_t sh
)
3531 TCGv_vec t
= tcg_temp_new_vec_matching(d
);
3532 TCGv_vec m
= tcg_temp_new_vec_matching(d
);
3534 tcg_gen_dupi_vec(vece
, m
, MAKE_64BIT_MASK((8 << vece
) - sh
, sh
));
3535 tcg_gen_shri_vec(vece
, t
, a
, sh
);
3536 tcg_gen_and_vec(vece
, d
, d
, m
);
3537 tcg_gen_or_vec(vece
, d
, d
, t
);
3539 tcg_temp_free_vec(t
);
3540 tcg_temp_free_vec(m
);
3543 void gen_gvec_sri(unsigned vece
, uint32_t rd_ofs
, uint32_t rm_ofs
,
3544 int64_t shift
, uint32_t opr_sz
, uint32_t max_sz
)
3546 static const TCGOpcode vecop_list
[] = { INDEX_op_shri_vec
, 0 };
3547 const GVecGen2i ops
[4] = {
3548 { .fni8
= gen_shr8_ins_i64
,
3549 .fniv
= gen_shr_ins_vec
,
3550 .fno
= gen_helper_gvec_sri_b
,
3552 .opt_opc
= vecop_list
,
3554 { .fni8
= gen_shr16_ins_i64
,
3555 .fniv
= gen_shr_ins_vec
,
3556 .fno
= gen_helper_gvec_sri_h
,
3558 .opt_opc
= vecop_list
,
3560 { .fni4
= gen_shr32_ins_i32
,
3561 .fniv
= gen_shr_ins_vec
,
3562 .fno
= gen_helper_gvec_sri_s
,
3564 .opt_opc
= vecop_list
,
3566 { .fni8
= gen_shr64_ins_i64
,
3567 .fniv
= gen_shr_ins_vec
,
3568 .fno
= gen_helper_gvec_sri_d
,
3569 .prefer_i64
= TCG_TARGET_REG_BITS
== 64,
3571 .opt_opc
= vecop_list
,
3575 /* tszimm encoding produces immediates in the range [1..esize]. */
3576 tcg_debug_assert(shift
> 0);
3577 tcg_debug_assert(shift
<= (8 << vece
));
3579 /* Shift of esize leaves destination unchanged. */
3580 if (shift
< (8 << vece
)) {
3581 tcg_gen_gvec_2i(rd_ofs
, rm_ofs
, opr_sz
, max_sz
, shift
, &ops
[vece
]);
3583 /* Nop, but we do need to clear the tail. */
3584 tcg_gen_gvec_mov(vece
, rd_ofs
, rd_ofs
, opr_sz
, max_sz
);
3588 static void gen_shl8_ins_i64(TCGv_i64 d
, TCGv_i64 a
, int64_t shift
)
3590 uint64_t mask
= dup_const(MO_8
, 0xff << shift
);
3591 TCGv_i64 t
= tcg_temp_new_i64();
3593 tcg_gen_shli_i64(t
, a
, shift
);
3594 tcg_gen_andi_i64(t
, t
, mask
);
3595 tcg_gen_andi_i64(d
, d
, ~mask
);
3596 tcg_gen_or_i64(d
, d
, t
);
3597 tcg_temp_free_i64(t
);
3600 static void gen_shl16_ins_i64(TCGv_i64 d
, TCGv_i64 a
, int64_t shift
)
3602 uint64_t mask
= dup_const(MO_16
, 0xffff << shift
);
3603 TCGv_i64 t
= tcg_temp_new_i64();
3605 tcg_gen_shli_i64(t
, a
, shift
);
3606 tcg_gen_andi_i64(t
, t
, mask
);
3607 tcg_gen_andi_i64(d
, d
, ~mask
);
3608 tcg_gen_or_i64(d
, d
, t
);
3609 tcg_temp_free_i64(t
);
3612 static void gen_shl32_ins_i32(TCGv_i32 d
, TCGv_i32 a
, int32_t shift
)
3614 tcg_gen_deposit_i32(d
, d
, a
, shift
, 32 - shift
);
3617 static void gen_shl64_ins_i64(TCGv_i64 d
, TCGv_i64 a
, int64_t shift
)
3619 tcg_gen_deposit_i64(d
, d
, a
, shift
, 64 - shift
);
3622 static void gen_shl_ins_vec(unsigned vece
, TCGv_vec d
, TCGv_vec a
, int64_t sh
)
3624 TCGv_vec t
= tcg_temp_new_vec_matching(d
);
3625 TCGv_vec m
= tcg_temp_new_vec_matching(d
);
3627 tcg_gen_shli_vec(vece
, t
, a
, sh
);
3628 tcg_gen_dupi_vec(vece
, m
, MAKE_64BIT_MASK(0, sh
));
3629 tcg_gen_and_vec(vece
, d
, d
, m
);
3630 tcg_gen_or_vec(vece
, d
, d
, t
);
3632 tcg_temp_free_vec(t
);
3633 tcg_temp_free_vec(m
);
3636 void gen_gvec_sli(unsigned vece
, uint32_t rd_ofs
, uint32_t rm_ofs
,
3637 int64_t shift
, uint32_t opr_sz
, uint32_t max_sz
)
3639 static const TCGOpcode vecop_list
[] = { INDEX_op_shli_vec
, 0 };
3640 const GVecGen2i ops
[4] = {
3641 { .fni8
= gen_shl8_ins_i64
,
3642 .fniv
= gen_shl_ins_vec
,
3643 .fno
= gen_helper_gvec_sli_b
,
3645 .opt_opc
= vecop_list
,
3647 { .fni8
= gen_shl16_ins_i64
,
3648 .fniv
= gen_shl_ins_vec
,
3649 .fno
= gen_helper_gvec_sli_h
,
3651 .opt_opc
= vecop_list
,
3653 { .fni4
= gen_shl32_ins_i32
,
3654 .fniv
= gen_shl_ins_vec
,
3655 .fno
= gen_helper_gvec_sli_s
,
3657 .opt_opc
= vecop_list
,
3659 { .fni8
= gen_shl64_ins_i64
,
3660 .fniv
= gen_shl_ins_vec
,
3661 .fno
= gen_helper_gvec_sli_d
,
3662 .prefer_i64
= TCG_TARGET_REG_BITS
== 64,
3664 .opt_opc
= vecop_list
,
3668 /* tszimm encoding produces immediates in the range [0..esize-1]. */
3669 tcg_debug_assert(shift
>= 0);
3670 tcg_debug_assert(shift
< (8 << vece
));
3673 tcg_gen_gvec_mov(vece
, rd_ofs
, rm_ofs
, opr_sz
, max_sz
);
3675 tcg_gen_gvec_2i(rd_ofs
, rm_ofs
, opr_sz
, max_sz
, shift
, &ops
[vece
]);
3679 static void gen_mla8_i32(TCGv_i32 d
, TCGv_i32 a
, TCGv_i32 b
)
3681 gen_helper_neon_mul_u8(a
, a
, b
);
3682 gen_helper_neon_add_u8(d
, d
, a
);
3685 static void gen_mls8_i32(TCGv_i32 d
, TCGv_i32 a
, TCGv_i32 b
)
3687 gen_helper_neon_mul_u8(a
, a
, b
);
3688 gen_helper_neon_sub_u8(d
, d
, a
);
3691 static void gen_mla16_i32(TCGv_i32 d
, TCGv_i32 a
, TCGv_i32 b
)
3693 gen_helper_neon_mul_u16(a
, a
, b
);
3694 gen_helper_neon_add_u16(d
, d
, a
);
3697 static void gen_mls16_i32(TCGv_i32 d
, TCGv_i32 a
, TCGv_i32 b
)
3699 gen_helper_neon_mul_u16(a
, a
, b
);
3700 gen_helper_neon_sub_u16(d
, d
, a
);
3703 static void gen_mla32_i32(TCGv_i32 d
, TCGv_i32 a
, TCGv_i32 b
)
3705 tcg_gen_mul_i32(a
, a
, b
);
3706 tcg_gen_add_i32(d
, d
, a
);
3709 static void gen_mls32_i32(TCGv_i32 d
, TCGv_i32 a
, TCGv_i32 b
)
3711 tcg_gen_mul_i32(a
, a
, b
);
3712 tcg_gen_sub_i32(d
, d
, a
);
3715 static void gen_mla64_i64(TCGv_i64 d
, TCGv_i64 a
, TCGv_i64 b
)
3717 tcg_gen_mul_i64(a
, a
, b
);
3718 tcg_gen_add_i64(d
, d
, a
);
3721 static void gen_mls64_i64(TCGv_i64 d
, TCGv_i64 a
, TCGv_i64 b
)
3723 tcg_gen_mul_i64(a
, a
, b
);
3724 tcg_gen_sub_i64(d
, d
, a
);
3727 static void gen_mla_vec(unsigned vece
, TCGv_vec d
, TCGv_vec a
, TCGv_vec b
)
3729 tcg_gen_mul_vec(vece
, a
, a
, b
);
3730 tcg_gen_add_vec(vece
, d
, d
, a
);
3733 static void gen_mls_vec(unsigned vece
, TCGv_vec d
, TCGv_vec a
, TCGv_vec b
)
3735 tcg_gen_mul_vec(vece
, a
, a
, b
);
3736 tcg_gen_sub_vec(vece
, d
, d
, a
);
3739 /* Note that while NEON does not support VMLA and VMLS as 64-bit ops,
3740 * these tables are shared with AArch64 which does support them.
3742 void gen_gvec_mla(unsigned vece
, uint32_t rd_ofs
, uint32_t rn_ofs
,
3743 uint32_t rm_ofs
, uint32_t opr_sz
, uint32_t max_sz
)
3745 static const TCGOpcode vecop_list
[] = {
3746 INDEX_op_mul_vec
, INDEX_op_add_vec
, 0
3748 static const GVecGen3 ops
[4] = {
3749 { .fni4
= gen_mla8_i32
,
3750 .fniv
= gen_mla_vec
,
3752 .opt_opc
= vecop_list
,
3754 { .fni4
= gen_mla16_i32
,
3755 .fniv
= gen_mla_vec
,
3757 .opt_opc
= vecop_list
,
3759 { .fni4
= gen_mla32_i32
,
3760 .fniv
= gen_mla_vec
,
3762 .opt_opc
= vecop_list
,
3764 { .fni8
= gen_mla64_i64
,
3765 .fniv
= gen_mla_vec
,
3766 .prefer_i64
= TCG_TARGET_REG_BITS
== 64,
3768 .opt_opc
= vecop_list
,
3771 tcg_gen_gvec_3(rd_ofs
, rn_ofs
, rm_ofs
, opr_sz
, max_sz
, &ops
[vece
]);
3774 void gen_gvec_mls(unsigned vece
, uint32_t rd_ofs
, uint32_t rn_ofs
,
3775 uint32_t rm_ofs
, uint32_t opr_sz
, uint32_t max_sz
)
3777 static const TCGOpcode vecop_list
[] = {
3778 INDEX_op_mul_vec
, INDEX_op_sub_vec
, 0
3780 static const GVecGen3 ops
[4] = {
3781 { .fni4
= gen_mls8_i32
,
3782 .fniv
= gen_mls_vec
,
3784 .opt_opc
= vecop_list
,
3786 { .fni4
= gen_mls16_i32
,
3787 .fniv
= gen_mls_vec
,
3789 .opt_opc
= vecop_list
,
3791 { .fni4
= gen_mls32_i32
,
3792 .fniv
= gen_mls_vec
,
3794 .opt_opc
= vecop_list
,
3796 { .fni8
= gen_mls64_i64
,
3797 .fniv
= gen_mls_vec
,
3798 .prefer_i64
= TCG_TARGET_REG_BITS
== 64,
3800 .opt_opc
= vecop_list
,
3803 tcg_gen_gvec_3(rd_ofs
, rn_ofs
, rm_ofs
, opr_sz
, max_sz
, &ops
[vece
]);
3806 /* CMTST : test is "if (X & Y != 0)". */
3807 static void gen_cmtst_i32(TCGv_i32 d
, TCGv_i32 a
, TCGv_i32 b
)
3809 tcg_gen_and_i32(d
, a
, b
);
3810 tcg_gen_setcondi_i32(TCG_COND_NE
, d
, d
, 0);
3811 tcg_gen_neg_i32(d
, d
);
3814 void gen_cmtst_i64(TCGv_i64 d
, TCGv_i64 a
, TCGv_i64 b
)
3816 tcg_gen_and_i64(d
, a
, b
);
3817 tcg_gen_setcondi_i64(TCG_COND_NE
, d
, d
, 0);
3818 tcg_gen_neg_i64(d
, d
);
3821 static void gen_cmtst_vec(unsigned vece
, TCGv_vec d
, TCGv_vec a
, TCGv_vec b
)
3823 tcg_gen_and_vec(vece
, d
, a
, b
);
3824 tcg_gen_dupi_vec(vece
, a
, 0);
3825 tcg_gen_cmp_vec(TCG_COND_NE
, vece
, d
, d
, a
);
3828 void gen_gvec_cmtst(unsigned vece
, uint32_t rd_ofs
, uint32_t rn_ofs
,
3829 uint32_t rm_ofs
, uint32_t opr_sz
, uint32_t max_sz
)
3831 static const TCGOpcode vecop_list
[] = { INDEX_op_cmp_vec
, 0 };
3832 static const GVecGen3 ops
[4] = {
3833 { .fni4
= gen_helper_neon_tst_u8
,
3834 .fniv
= gen_cmtst_vec
,
3835 .opt_opc
= vecop_list
,
3837 { .fni4
= gen_helper_neon_tst_u16
,
3838 .fniv
= gen_cmtst_vec
,
3839 .opt_opc
= vecop_list
,
3841 { .fni4
= gen_cmtst_i32
,
3842 .fniv
= gen_cmtst_vec
,
3843 .opt_opc
= vecop_list
,
3845 { .fni8
= gen_cmtst_i64
,
3846 .fniv
= gen_cmtst_vec
,
3847 .prefer_i64
= TCG_TARGET_REG_BITS
== 64,
3848 .opt_opc
= vecop_list
,
3851 tcg_gen_gvec_3(rd_ofs
, rn_ofs
, rm_ofs
, opr_sz
, max_sz
, &ops
[vece
]);
3854 void gen_ushl_i32(TCGv_i32 dst
, TCGv_i32 src
, TCGv_i32 shift
)
3856 TCGv_i32 lval
= tcg_temp_new_i32();
3857 TCGv_i32 rval
= tcg_temp_new_i32();
3858 TCGv_i32 lsh
= tcg_temp_new_i32();
3859 TCGv_i32 rsh
= tcg_temp_new_i32();
3860 TCGv_i32 zero
= tcg_const_i32(0);
3861 TCGv_i32 max
= tcg_const_i32(32);
3864 * Rely on the TCG guarantee that out of range shifts produce
3865 * unspecified results, not undefined behaviour (i.e. no trap).
3866 * Discard out-of-range results after the fact.
3868 tcg_gen_ext8s_i32(lsh
, shift
);
3869 tcg_gen_neg_i32(rsh
, lsh
);
3870 tcg_gen_shl_i32(lval
, src
, lsh
);
3871 tcg_gen_shr_i32(rval
, src
, rsh
);
3872 tcg_gen_movcond_i32(TCG_COND_LTU
, dst
, lsh
, max
, lval
, zero
);
3873 tcg_gen_movcond_i32(TCG_COND_LTU
, dst
, rsh
, max
, rval
, dst
);
3875 tcg_temp_free_i32(lval
);
3876 tcg_temp_free_i32(rval
);
3877 tcg_temp_free_i32(lsh
);
3878 tcg_temp_free_i32(rsh
);
3879 tcg_temp_free_i32(zero
);
3880 tcg_temp_free_i32(max
);
3883 void gen_ushl_i64(TCGv_i64 dst
, TCGv_i64 src
, TCGv_i64 shift
)
3885 TCGv_i64 lval
= tcg_temp_new_i64();
3886 TCGv_i64 rval
= tcg_temp_new_i64();
3887 TCGv_i64 lsh
= tcg_temp_new_i64();
3888 TCGv_i64 rsh
= tcg_temp_new_i64();
3889 TCGv_i64 zero
= tcg_const_i64(0);
3890 TCGv_i64 max
= tcg_const_i64(64);
3893 * Rely on the TCG guarantee that out of range shifts produce
3894 * unspecified results, not undefined behaviour (i.e. no trap).
3895 * Discard out-of-range results after the fact.
3897 tcg_gen_ext8s_i64(lsh
, shift
);
3898 tcg_gen_neg_i64(rsh
, lsh
);
3899 tcg_gen_shl_i64(lval
, src
, lsh
);
3900 tcg_gen_shr_i64(rval
, src
, rsh
);
3901 tcg_gen_movcond_i64(TCG_COND_LTU
, dst
, lsh
, max
, lval
, zero
);
3902 tcg_gen_movcond_i64(TCG_COND_LTU
, dst
, rsh
, max
, rval
, dst
);
3904 tcg_temp_free_i64(lval
);
3905 tcg_temp_free_i64(rval
);
3906 tcg_temp_free_i64(lsh
);
3907 tcg_temp_free_i64(rsh
);
3908 tcg_temp_free_i64(zero
);
3909 tcg_temp_free_i64(max
);
3912 static void gen_ushl_vec(unsigned vece
, TCGv_vec dst
,
3913 TCGv_vec src
, TCGv_vec shift
)
3915 TCGv_vec lval
= tcg_temp_new_vec_matching(dst
);
3916 TCGv_vec rval
= tcg_temp_new_vec_matching(dst
);
3917 TCGv_vec lsh
= tcg_temp_new_vec_matching(dst
);
3918 TCGv_vec rsh
= tcg_temp_new_vec_matching(dst
);
3921 tcg_gen_neg_vec(vece
, rsh
, shift
);
3923 tcg_gen_mov_vec(lsh
, shift
);
3925 msk
= tcg_temp_new_vec_matching(dst
);
3926 tcg_gen_dupi_vec(vece
, msk
, 0xff);
3927 tcg_gen_and_vec(vece
, lsh
, shift
, msk
);
3928 tcg_gen_and_vec(vece
, rsh
, rsh
, msk
);
3929 tcg_temp_free_vec(msk
);
3933 * Rely on the TCG guarantee that out of range shifts produce
3934 * unspecified results, not undefined behaviour (i.e. no trap).
3935 * Discard out-of-range results after the fact.
3937 tcg_gen_shlv_vec(vece
, lval
, src
, lsh
);
3938 tcg_gen_shrv_vec(vece
, rval
, src
, rsh
);
3940 max
= tcg_temp_new_vec_matching(dst
);
3941 tcg_gen_dupi_vec(vece
, max
, 8 << vece
);
3944 * The choice of LT (signed) and GEU (unsigned) are biased toward
3945 * the instructions of the x86_64 host. For MO_8, the whole byte
3946 * is significant so we must use an unsigned compare; otherwise we
3947 * have already masked to a byte and so a signed compare works.
3948 * Other tcg hosts have a full set of comparisons and do not care.
3951 tcg_gen_cmp_vec(TCG_COND_GEU
, vece
, lsh
, lsh
, max
);
3952 tcg_gen_cmp_vec(TCG_COND_GEU
, vece
, rsh
, rsh
, max
);
3953 tcg_gen_andc_vec(vece
, lval
, lval
, lsh
);
3954 tcg_gen_andc_vec(vece
, rval
, rval
, rsh
);
3956 tcg_gen_cmp_vec(TCG_COND_LT
, vece
, lsh
, lsh
, max
);
3957 tcg_gen_cmp_vec(TCG_COND_LT
, vece
, rsh
, rsh
, max
);
3958 tcg_gen_and_vec(vece
, lval
, lval
, lsh
);
3959 tcg_gen_and_vec(vece
, rval
, rval
, rsh
);
3961 tcg_gen_or_vec(vece
, dst
, lval
, rval
);
3963 tcg_temp_free_vec(max
);
3964 tcg_temp_free_vec(lval
);
3965 tcg_temp_free_vec(rval
);
3966 tcg_temp_free_vec(lsh
);
3967 tcg_temp_free_vec(rsh
);
3970 void gen_gvec_ushl(unsigned vece
, uint32_t rd_ofs
, uint32_t rn_ofs
,
3971 uint32_t rm_ofs
, uint32_t opr_sz
, uint32_t max_sz
)
3973 static const TCGOpcode vecop_list
[] = {
3974 INDEX_op_neg_vec
, INDEX_op_shlv_vec
,
3975 INDEX_op_shrv_vec
, INDEX_op_cmp_vec
, 0
3977 static const GVecGen3 ops
[4] = {
3978 { .fniv
= gen_ushl_vec
,
3979 .fno
= gen_helper_gvec_ushl_b
,
3980 .opt_opc
= vecop_list
,
3982 { .fniv
= gen_ushl_vec
,
3983 .fno
= gen_helper_gvec_ushl_h
,
3984 .opt_opc
= vecop_list
,
3986 { .fni4
= gen_ushl_i32
,
3987 .fniv
= gen_ushl_vec
,
3988 .opt_opc
= vecop_list
,
3990 { .fni8
= gen_ushl_i64
,
3991 .fniv
= gen_ushl_vec
,
3992 .opt_opc
= vecop_list
,
3995 tcg_gen_gvec_3(rd_ofs
, rn_ofs
, rm_ofs
, opr_sz
, max_sz
, &ops
[vece
]);
3998 void gen_sshl_i32(TCGv_i32 dst
, TCGv_i32 src
, TCGv_i32 shift
)
4000 TCGv_i32 lval
= tcg_temp_new_i32();
4001 TCGv_i32 rval
= tcg_temp_new_i32();
4002 TCGv_i32 lsh
= tcg_temp_new_i32();
4003 TCGv_i32 rsh
= tcg_temp_new_i32();
4004 TCGv_i32 zero
= tcg_const_i32(0);
4005 TCGv_i32 max
= tcg_const_i32(31);
4008 * Rely on the TCG guarantee that out of range shifts produce
4009 * unspecified results, not undefined behaviour (i.e. no trap).
4010 * Discard out-of-range results after the fact.
4012 tcg_gen_ext8s_i32(lsh
, shift
);
4013 tcg_gen_neg_i32(rsh
, lsh
);
4014 tcg_gen_shl_i32(lval
, src
, lsh
);
4015 tcg_gen_umin_i32(rsh
, rsh
, max
);
4016 tcg_gen_sar_i32(rval
, src
, rsh
);
4017 tcg_gen_movcond_i32(TCG_COND_LEU
, lval
, lsh
, max
, lval
, zero
);
4018 tcg_gen_movcond_i32(TCG_COND_LT
, dst
, lsh
, zero
, rval
, lval
);
4020 tcg_temp_free_i32(lval
);
4021 tcg_temp_free_i32(rval
);
4022 tcg_temp_free_i32(lsh
);
4023 tcg_temp_free_i32(rsh
);
4024 tcg_temp_free_i32(zero
);
4025 tcg_temp_free_i32(max
);
4028 void gen_sshl_i64(TCGv_i64 dst
, TCGv_i64 src
, TCGv_i64 shift
)
4030 TCGv_i64 lval
= tcg_temp_new_i64();
4031 TCGv_i64 rval
= tcg_temp_new_i64();
4032 TCGv_i64 lsh
= tcg_temp_new_i64();
4033 TCGv_i64 rsh
= tcg_temp_new_i64();
4034 TCGv_i64 zero
= tcg_const_i64(0);
4035 TCGv_i64 max
= tcg_const_i64(63);
4038 * Rely on the TCG guarantee that out of range shifts produce
4039 * unspecified results, not undefined behaviour (i.e. no trap).
4040 * Discard out-of-range results after the fact.
4042 tcg_gen_ext8s_i64(lsh
, shift
);
4043 tcg_gen_neg_i64(rsh
, lsh
);
4044 tcg_gen_shl_i64(lval
, src
, lsh
);
4045 tcg_gen_umin_i64(rsh
, rsh
, max
);
4046 tcg_gen_sar_i64(rval
, src
, rsh
);
4047 tcg_gen_movcond_i64(TCG_COND_LEU
, lval
, lsh
, max
, lval
, zero
);
4048 tcg_gen_movcond_i64(TCG_COND_LT
, dst
, lsh
, zero
, rval
, lval
);
4050 tcg_temp_free_i64(lval
);
4051 tcg_temp_free_i64(rval
);
4052 tcg_temp_free_i64(lsh
);
4053 tcg_temp_free_i64(rsh
);
4054 tcg_temp_free_i64(zero
);
4055 tcg_temp_free_i64(max
);
4058 static void gen_sshl_vec(unsigned vece
, TCGv_vec dst
,
4059 TCGv_vec src
, TCGv_vec shift
)
4061 TCGv_vec lval
= tcg_temp_new_vec_matching(dst
);
4062 TCGv_vec rval
= tcg_temp_new_vec_matching(dst
);
4063 TCGv_vec lsh
= tcg_temp_new_vec_matching(dst
);
4064 TCGv_vec rsh
= tcg_temp_new_vec_matching(dst
);
4065 TCGv_vec tmp
= tcg_temp_new_vec_matching(dst
);
4068 * Rely on the TCG guarantee that out of range shifts produce
4069 * unspecified results, not undefined behaviour (i.e. no trap).
4070 * Discard out-of-range results after the fact.
4072 tcg_gen_neg_vec(vece
, rsh
, shift
);
4074 tcg_gen_mov_vec(lsh
, shift
);
4076 tcg_gen_dupi_vec(vece
, tmp
, 0xff);
4077 tcg_gen_and_vec(vece
, lsh
, shift
, tmp
);
4078 tcg_gen_and_vec(vece
, rsh
, rsh
, tmp
);
4081 /* Bound rsh so out of bound right shift gets -1. */
4082 tcg_gen_dupi_vec(vece
, tmp
, (8 << vece
) - 1);
4083 tcg_gen_umin_vec(vece
, rsh
, rsh
, tmp
);
4084 tcg_gen_cmp_vec(TCG_COND_GT
, vece
, tmp
, lsh
, tmp
);
4086 tcg_gen_shlv_vec(vece
, lval
, src
, lsh
);
4087 tcg_gen_sarv_vec(vece
, rval
, src
, rsh
);
4089 /* Select in-bound left shift. */
4090 tcg_gen_andc_vec(vece
, lval
, lval
, tmp
);
4092 /* Select between left and right shift. */
4094 tcg_gen_dupi_vec(vece
, tmp
, 0);
4095 tcg_gen_cmpsel_vec(TCG_COND_LT
, vece
, dst
, lsh
, tmp
, rval
, lval
);
4097 tcg_gen_dupi_vec(vece
, tmp
, 0x80);
4098 tcg_gen_cmpsel_vec(TCG_COND_LT
, vece
, dst
, lsh
, tmp
, lval
, rval
);
4101 tcg_temp_free_vec(lval
);
4102 tcg_temp_free_vec(rval
);
4103 tcg_temp_free_vec(lsh
);
4104 tcg_temp_free_vec(rsh
);
4105 tcg_temp_free_vec(tmp
);
4108 void gen_gvec_sshl(unsigned vece
, uint32_t rd_ofs
, uint32_t rn_ofs
,
4109 uint32_t rm_ofs
, uint32_t opr_sz
, uint32_t max_sz
)
4111 static const TCGOpcode vecop_list
[] = {
4112 INDEX_op_neg_vec
, INDEX_op_umin_vec
, INDEX_op_shlv_vec
,
4113 INDEX_op_sarv_vec
, INDEX_op_cmp_vec
, INDEX_op_cmpsel_vec
, 0
4115 static const GVecGen3 ops
[4] = {
4116 { .fniv
= gen_sshl_vec
,
4117 .fno
= gen_helper_gvec_sshl_b
,
4118 .opt_opc
= vecop_list
,
4120 { .fniv
= gen_sshl_vec
,
4121 .fno
= gen_helper_gvec_sshl_h
,
4122 .opt_opc
= vecop_list
,
4124 { .fni4
= gen_sshl_i32
,
4125 .fniv
= gen_sshl_vec
,
4126 .opt_opc
= vecop_list
,
4128 { .fni8
= gen_sshl_i64
,
4129 .fniv
= gen_sshl_vec
,
4130 .opt_opc
= vecop_list
,
4133 tcg_gen_gvec_3(rd_ofs
, rn_ofs
, rm_ofs
, opr_sz
, max_sz
, &ops
[vece
]);
4136 static void gen_uqadd_vec(unsigned vece
, TCGv_vec t
, TCGv_vec sat
,
4137 TCGv_vec a
, TCGv_vec b
)
4139 TCGv_vec x
= tcg_temp_new_vec_matching(t
);
4140 tcg_gen_add_vec(vece
, x
, a
, b
);
4141 tcg_gen_usadd_vec(vece
, t
, a
, b
);
4142 tcg_gen_cmp_vec(TCG_COND_NE
, vece
, x
, x
, t
);
4143 tcg_gen_or_vec(vece
, sat
, sat
, x
);
4144 tcg_temp_free_vec(x
);
4147 void gen_gvec_uqadd_qc(unsigned vece
, uint32_t rd_ofs
, uint32_t rn_ofs
,
4148 uint32_t rm_ofs
, uint32_t opr_sz
, uint32_t max_sz
)
4150 static const TCGOpcode vecop_list
[] = {
4151 INDEX_op_usadd_vec
, INDEX_op_cmp_vec
, INDEX_op_add_vec
, 0
4153 static const GVecGen4 ops
[4] = {
4154 { .fniv
= gen_uqadd_vec
,
4155 .fno
= gen_helper_gvec_uqadd_b
,
4157 .opt_opc
= vecop_list
,
4159 { .fniv
= gen_uqadd_vec
,
4160 .fno
= gen_helper_gvec_uqadd_h
,
4162 .opt_opc
= vecop_list
,
4164 { .fniv
= gen_uqadd_vec
,
4165 .fno
= gen_helper_gvec_uqadd_s
,
4167 .opt_opc
= vecop_list
,
4169 { .fniv
= gen_uqadd_vec
,
4170 .fno
= gen_helper_gvec_uqadd_d
,
4172 .opt_opc
= vecop_list
,
4175 tcg_gen_gvec_4(rd_ofs
, offsetof(CPUARMState
, vfp
.qc
),
4176 rn_ofs
, rm_ofs
, opr_sz
, max_sz
, &ops
[vece
]);
4179 static void gen_sqadd_vec(unsigned vece
, TCGv_vec t
, TCGv_vec sat
,
4180 TCGv_vec a
, TCGv_vec b
)
4182 TCGv_vec x
= tcg_temp_new_vec_matching(t
);
4183 tcg_gen_add_vec(vece
, x
, a
, b
);
4184 tcg_gen_ssadd_vec(vece
, t
, a
, b
);
4185 tcg_gen_cmp_vec(TCG_COND_NE
, vece
, x
, x
, t
);
4186 tcg_gen_or_vec(vece
, sat
, sat
, x
);
4187 tcg_temp_free_vec(x
);
4190 void gen_gvec_sqadd_qc(unsigned vece
, uint32_t rd_ofs
, uint32_t rn_ofs
,
4191 uint32_t rm_ofs
, uint32_t opr_sz
, uint32_t max_sz
)
4193 static const TCGOpcode vecop_list
[] = {
4194 INDEX_op_ssadd_vec
, INDEX_op_cmp_vec
, INDEX_op_add_vec
, 0
4196 static const GVecGen4 ops
[4] = {
4197 { .fniv
= gen_sqadd_vec
,
4198 .fno
= gen_helper_gvec_sqadd_b
,
4199 .opt_opc
= vecop_list
,
4202 { .fniv
= gen_sqadd_vec
,
4203 .fno
= gen_helper_gvec_sqadd_h
,
4204 .opt_opc
= vecop_list
,
4207 { .fniv
= gen_sqadd_vec
,
4208 .fno
= gen_helper_gvec_sqadd_s
,
4209 .opt_opc
= vecop_list
,
4212 { .fniv
= gen_sqadd_vec
,
4213 .fno
= gen_helper_gvec_sqadd_d
,
4214 .opt_opc
= vecop_list
,
4218 tcg_gen_gvec_4(rd_ofs
, offsetof(CPUARMState
, vfp
.qc
),
4219 rn_ofs
, rm_ofs
, opr_sz
, max_sz
, &ops
[vece
]);
4222 static void gen_uqsub_vec(unsigned vece
, TCGv_vec t
, TCGv_vec sat
,
4223 TCGv_vec a
, TCGv_vec b
)
4225 TCGv_vec x
= tcg_temp_new_vec_matching(t
);
4226 tcg_gen_sub_vec(vece
, x
, a
, b
);
4227 tcg_gen_ussub_vec(vece
, t
, a
, b
);
4228 tcg_gen_cmp_vec(TCG_COND_NE
, vece
, x
, x
, t
);
4229 tcg_gen_or_vec(vece
, sat
, sat
, x
);
4230 tcg_temp_free_vec(x
);
4233 void gen_gvec_uqsub_qc(unsigned vece
, uint32_t rd_ofs
, uint32_t rn_ofs
,
4234 uint32_t rm_ofs
, uint32_t opr_sz
, uint32_t max_sz
)
4236 static const TCGOpcode vecop_list
[] = {
4237 INDEX_op_ussub_vec
, INDEX_op_cmp_vec
, INDEX_op_sub_vec
, 0
4239 static const GVecGen4 ops
[4] = {
4240 { .fniv
= gen_uqsub_vec
,
4241 .fno
= gen_helper_gvec_uqsub_b
,
4242 .opt_opc
= vecop_list
,
4245 { .fniv
= gen_uqsub_vec
,
4246 .fno
= gen_helper_gvec_uqsub_h
,
4247 .opt_opc
= vecop_list
,
4250 { .fniv
= gen_uqsub_vec
,
4251 .fno
= gen_helper_gvec_uqsub_s
,
4252 .opt_opc
= vecop_list
,
4255 { .fniv
= gen_uqsub_vec
,
4256 .fno
= gen_helper_gvec_uqsub_d
,
4257 .opt_opc
= vecop_list
,
4261 tcg_gen_gvec_4(rd_ofs
, offsetof(CPUARMState
, vfp
.qc
),
4262 rn_ofs
, rm_ofs
, opr_sz
, max_sz
, &ops
[vece
]);
4265 static void gen_sqsub_vec(unsigned vece
, TCGv_vec t
, TCGv_vec sat
,
4266 TCGv_vec a
, TCGv_vec b
)
4268 TCGv_vec x
= tcg_temp_new_vec_matching(t
);
4269 tcg_gen_sub_vec(vece
, x
, a
, b
);
4270 tcg_gen_sssub_vec(vece
, t
, a
, b
);
4271 tcg_gen_cmp_vec(TCG_COND_NE
, vece
, x
, x
, t
);
4272 tcg_gen_or_vec(vece
, sat
, sat
, x
);
4273 tcg_temp_free_vec(x
);
4276 void gen_gvec_sqsub_qc(unsigned vece
, uint32_t rd_ofs
, uint32_t rn_ofs
,
4277 uint32_t rm_ofs
, uint32_t opr_sz
, uint32_t max_sz
)
4279 static const TCGOpcode vecop_list
[] = {
4280 INDEX_op_sssub_vec
, INDEX_op_cmp_vec
, INDEX_op_sub_vec
, 0
4282 static const GVecGen4 ops
[4] = {
4283 { .fniv
= gen_sqsub_vec
,
4284 .fno
= gen_helper_gvec_sqsub_b
,
4285 .opt_opc
= vecop_list
,
4288 { .fniv
= gen_sqsub_vec
,
4289 .fno
= gen_helper_gvec_sqsub_h
,
4290 .opt_opc
= vecop_list
,
4293 { .fniv
= gen_sqsub_vec
,
4294 .fno
= gen_helper_gvec_sqsub_s
,
4295 .opt_opc
= vecop_list
,
4298 { .fniv
= gen_sqsub_vec
,
4299 .fno
= gen_helper_gvec_sqsub_d
,
4300 .opt_opc
= vecop_list
,
4304 tcg_gen_gvec_4(rd_ofs
, offsetof(CPUARMState
, vfp
.qc
),
4305 rn_ofs
, rm_ofs
, opr_sz
, max_sz
, &ops
[vece
]);
4308 static void gen_sabd_i32(TCGv_i32 d
, TCGv_i32 a
, TCGv_i32 b
)
4310 TCGv_i32 t
= tcg_temp_new_i32();
4312 tcg_gen_sub_i32(t
, a
, b
);
4313 tcg_gen_sub_i32(d
, b
, a
);
4314 tcg_gen_movcond_i32(TCG_COND_LT
, d
, a
, b
, d
, t
);
4315 tcg_temp_free_i32(t
);
4318 static void gen_sabd_i64(TCGv_i64 d
, TCGv_i64 a
, TCGv_i64 b
)
4320 TCGv_i64 t
= tcg_temp_new_i64();
4322 tcg_gen_sub_i64(t
, a
, b
);
4323 tcg_gen_sub_i64(d
, b
, a
);
4324 tcg_gen_movcond_i64(TCG_COND_LT
, d
, a
, b
, d
, t
);
4325 tcg_temp_free_i64(t
);
4328 static void gen_sabd_vec(unsigned vece
, TCGv_vec d
, TCGv_vec a
, TCGv_vec b
)
4330 TCGv_vec t
= tcg_temp_new_vec_matching(d
);
4332 tcg_gen_smin_vec(vece
, t
, a
, b
);
4333 tcg_gen_smax_vec(vece
, d
, a
, b
);
4334 tcg_gen_sub_vec(vece
, d
, d
, t
);
4335 tcg_temp_free_vec(t
);
4338 void gen_gvec_sabd(unsigned vece
, uint32_t rd_ofs
, uint32_t rn_ofs
,
4339 uint32_t rm_ofs
, uint32_t opr_sz
, uint32_t max_sz
)
4341 static const TCGOpcode vecop_list
[] = {
4342 INDEX_op_sub_vec
, INDEX_op_smin_vec
, INDEX_op_smax_vec
, 0
4344 static const GVecGen3 ops
[4] = {
4345 { .fniv
= gen_sabd_vec
,
4346 .fno
= gen_helper_gvec_sabd_b
,
4347 .opt_opc
= vecop_list
,
4349 { .fniv
= gen_sabd_vec
,
4350 .fno
= gen_helper_gvec_sabd_h
,
4351 .opt_opc
= vecop_list
,
4353 { .fni4
= gen_sabd_i32
,
4354 .fniv
= gen_sabd_vec
,
4355 .fno
= gen_helper_gvec_sabd_s
,
4356 .opt_opc
= vecop_list
,
4358 { .fni8
= gen_sabd_i64
,
4359 .fniv
= gen_sabd_vec
,
4360 .fno
= gen_helper_gvec_sabd_d
,
4361 .prefer_i64
= TCG_TARGET_REG_BITS
== 64,
4362 .opt_opc
= vecop_list
,
4365 tcg_gen_gvec_3(rd_ofs
, rn_ofs
, rm_ofs
, opr_sz
, max_sz
, &ops
[vece
]);
4368 static void gen_uabd_i32(TCGv_i32 d
, TCGv_i32 a
, TCGv_i32 b
)
4370 TCGv_i32 t
= tcg_temp_new_i32();
4372 tcg_gen_sub_i32(t
, a
, b
);
4373 tcg_gen_sub_i32(d
, b
, a
);
4374 tcg_gen_movcond_i32(TCG_COND_LTU
, d
, a
, b
, d
, t
);
4375 tcg_temp_free_i32(t
);
4378 static void gen_uabd_i64(TCGv_i64 d
, TCGv_i64 a
, TCGv_i64 b
)
4380 TCGv_i64 t
= tcg_temp_new_i64();
4382 tcg_gen_sub_i64(t
, a
, b
);
4383 tcg_gen_sub_i64(d
, b
, a
);
4384 tcg_gen_movcond_i64(TCG_COND_LTU
, d
, a
, b
, d
, t
);
4385 tcg_temp_free_i64(t
);
4388 static void gen_uabd_vec(unsigned vece
, TCGv_vec d
, TCGv_vec a
, TCGv_vec b
)
4390 TCGv_vec t
= tcg_temp_new_vec_matching(d
);
4392 tcg_gen_umin_vec(vece
, t
, a
, b
);
4393 tcg_gen_umax_vec(vece
, d
, a
, b
);
4394 tcg_gen_sub_vec(vece
, d
, d
, t
);
4395 tcg_temp_free_vec(t
);
4398 void gen_gvec_uabd(unsigned vece
, uint32_t rd_ofs
, uint32_t rn_ofs
,
4399 uint32_t rm_ofs
, uint32_t opr_sz
, uint32_t max_sz
)
4401 static const TCGOpcode vecop_list
[] = {
4402 INDEX_op_sub_vec
, INDEX_op_umin_vec
, INDEX_op_umax_vec
, 0
4404 static const GVecGen3 ops
[4] = {
4405 { .fniv
= gen_uabd_vec
,
4406 .fno
= gen_helper_gvec_uabd_b
,
4407 .opt_opc
= vecop_list
,
4409 { .fniv
= gen_uabd_vec
,
4410 .fno
= gen_helper_gvec_uabd_h
,
4411 .opt_opc
= vecop_list
,
4413 { .fni4
= gen_uabd_i32
,
4414 .fniv
= gen_uabd_vec
,
4415 .fno
= gen_helper_gvec_uabd_s
,
4416 .opt_opc
= vecop_list
,
4418 { .fni8
= gen_uabd_i64
,
4419 .fniv
= gen_uabd_vec
,
4420 .fno
= gen_helper_gvec_uabd_d
,
4421 .prefer_i64
= TCG_TARGET_REG_BITS
== 64,
4422 .opt_opc
= vecop_list
,
4425 tcg_gen_gvec_3(rd_ofs
, rn_ofs
, rm_ofs
, opr_sz
, max_sz
, &ops
[vece
]);
4428 static void gen_saba_i32(TCGv_i32 d
, TCGv_i32 a
, TCGv_i32 b
)
4430 TCGv_i32 t
= tcg_temp_new_i32();
4431 gen_sabd_i32(t
, a
, b
);
4432 tcg_gen_add_i32(d
, d
, t
);
4433 tcg_temp_free_i32(t
);
4436 static void gen_saba_i64(TCGv_i64 d
, TCGv_i64 a
, TCGv_i64 b
)
4438 TCGv_i64 t
= tcg_temp_new_i64();
4439 gen_sabd_i64(t
, a
, b
);
4440 tcg_gen_add_i64(d
, d
, t
);
4441 tcg_temp_free_i64(t
);
4444 static void gen_saba_vec(unsigned vece
, TCGv_vec d
, TCGv_vec a
, TCGv_vec b
)
4446 TCGv_vec t
= tcg_temp_new_vec_matching(d
);
4447 gen_sabd_vec(vece
, t
, a
, b
);
4448 tcg_gen_add_vec(vece
, d
, d
, t
);
4449 tcg_temp_free_vec(t
);
4452 void gen_gvec_saba(unsigned vece
, uint32_t rd_ofs
, uint32_t rn_ofs
,
4453 uint32_t rm_ofs
, uint32_t opr_sz
, uint32_t max_sz
)
4455 static const TCGOpcode vecop_list
[] = {
4456 INDEX_op_sub_vec
, INDEX_op_add_vec
,
4457 INDEX_op_smin_vec
, INDEX_op_smax_vec
, 0
4459 static const GVecGen3 ops
[4] = {
4460 { .fniv
= gen_saba_vec
,
4461 .fno
= gen_helper_gvec_saba_b
,
4462 .opt_opc
= vecop_list
,
4465 { .fniv
= gen_saba_vec
,
4466 .fno
= gen_helper_gvec_saba_h
,
4467 .opt_opc
= vecop_list
,
4470 { .fni4
= gen_saba_i32
,
4471 .fniv
= gen_saba_vec
,
4472 .fno
= gen_helper_gvec_saba_s
,
4473 .opt_opc
= vecop_list
,
4476 { .fni8
= gen_saba_i64
,
4477 .fniv
= gen_saba_vec
,
4478 .fno
= gen_helper_gvec_saba_d
,
4479 .prefer_i64
= TCG_TARGET_REG_BITS
== 64,
4480 .opt_opc
= vecop_list
,
4484 tcg_gen_gvec_3(rd_ofs
, rn_ofs
, rm_ofs
, opr_sz
, max_sz
, &ops
[vece
]);
4487 static void gen_uaba_i32(TCGv_i32 d
, TCGv_i32 a
, TCGv_i32 b
)
4489 TCGv_i32 t
= tcg_temp_new_i32();
4490 gen_uabd_i32(t
, a
, b
);
4491 tcg_gen_add_i32(d
, d
, t
);
4492 tcg_temp_free_i32(t
);
4495 static void gen_uaba_i64(TCGv_i64 d
, TCGv_i64 a
, TCGv_i64 b
)
4497 TCGv_i64 t
= tcg_temp_new_i64();
4498 gen_uabd_i64(t
, a
, b
);
4499 tcg_gen_add_i64(d
, d
, t
);
4500 tcg_temp_free_i64(t
);
4503 static void gen_uaba_vec(unsigned vece
, TCGv_vec d
, TCGv_vec a
, TCGv_vec b
)
4505 TCGv_vec t
= tcg_temp_new_vec_matching(d
);
4506 gen_uabd_vec(vece
, t
, a
, b
);
4507 tcg_gen_add_vec(vece
, d
, d
, t
);
4508 tcg_temp_free_vec(t
);
4511 void gen_gvec_uaba(unsigned vece
, uint32_t rd_ofs
, uint32_t rn_ofs
,
4512 uint32_t rm_ofs
, uint32_t opr_sz
, uint32_t max_sz
)
4514 static const TCGOpcode vecop_list
[] = {
4515 INDEX_op_sub_vec
, INDEX_op_add_vec
,
4516 INDEX_op_umin_vec
, INDEX_op_umax_vec
, 0
4518 static const GVecGen3 ops
[4] = {
4519 { .fniv
= gen_uaba_vec
,
4520 .fno
= gen_helper_gvec_uaba_b
,
4521 .opt_opc
= vecop_list
,
4524 { .fniv
= gen_uaba_vec
,
4525 .fno
= gen_helper_gvec_uaba_h
,
4526 .opt_opc
= vecop_list
,
4529 { .fni4
= gen_uaba_i32
,
4530 .fniv
= gen_uaba_vec
,
4531 .fno
= gen_helper_gvec_uaba_s
,
4532 .opt_opc
= vecop_list
,
4535 { .fni8
= gen_uaba_i64
,
4536 .fniv
= gen_uaba_vec
,
4537 .fno
= gen_helper_gvec_uaba_d
,
4538 .prefer_i64
= TCG_TARGET_REG_BITS
== 64,
4539 .opt_opc
= vecop_list
,
4543 tcg_gen_gvec_3(rd_ofs
, rn_ofs
, rm_ofs
, opr_sz
, max_sz
, &ops
[vece
]);
4546 static void do_coproc_insn(DisasContext
*s
, int cpnum
, int is64
,
4547 int opc1
, int crn
, int crm
, int opc2
,
4548 bool isread
, int rt
, int rt2
)
4550 const ARMCPRegInfo
*ri
;
4552 ri
= get_arm_cp_reginfo(s
->cp_regs
,
4553 ENCODE_CP_REG(cpnum
, is64
, s
->ns
, crn
, crm
, opc1
, opc2
));
4557 /* Check access permissions */
4558 if (!cp_access_ok(s
->current_el
, ri
, isread
)) {
4559 unallocated_encoding(s
);
4563 if (s
->hstr_active
|| ri
->accessfn
||
4564 (arm_dc_feature(s
, ARM_FEATURE_XSCALE
) && cpnum
< 14)) {
4565 /* Emit code to perform further access permissions checks at
4566 * runtime; this may result in an exception.
4567 * Note that on XScale all cp0..c13 registers do an access check
4568 * call in order to handle c15_cpar.
4571 TCGv_i32 tcg_syn
, tcg_isread
;
4574 /* Note that since we are an implementation which takes an
4575 * exception on a trapped conditional instruction only if the
4576 * instruction passes its condition code check, we can take
4577 * advantage of the clause in the ARM ARM that allows us to set
4578 * the COND field in the instruction to 0xE in all cases.
4579 * We could fish the actual condition out of the insn (ARM)
4580 * or the condexec bits (Thumb) but it isn't necessary.
4585 syndrome
= syn_cp14_rrt_trap(1, 0xe, opc1
, crm
, rt
, rt2
,
4588 syndrome
= syn_cp14_rt_trap(1, 0xe, opc1
, opc2
, crn
, crm
,
4594 syndrome
= syn_cp15_rrt_trap(1, 0xe, opc1
, crm
, rt
, rt2
,
4597 syndrome
= syn_cp15_rt_trap(1, 0xe, opc1
, opc2
, crn
, crm
,
4602 /* ARMv8 defines that only coprocessors 14 and 15 exist,
4603 * so this can only happen if this is an ARMv7 or earlier CPU,
4604 * in which case the syndrome information won't actually be
4607 assert(!arm_dc_feature(s
, ARM_FEATURE_V8
));
4608 syndrome
= syn_uncategorized();
4612 gen_set_condexec(s
);
4613 gen_set_pc_im(s
, s
->pc_curr
);
4614 tmpptr
= tcg_const_ptr(ri
);
4615 tcg_syn
= tcg_const_i32(syndrome
);
4616 tcg_isread
= tcg_const_i32(isread
);
4617 gen_helper_access_check_cp_reg(cpu_env
, tmpptr
, tcg_syn
,
4619 tcg_temp_free_ptr(tmpptr
);
4620 tcg_temp_free_i32(tcg_syn
);
4621 tcg_temp_free_i32(tcg_isread
);
4622 } else if (ri
->type
& ARM_CP_RAISES_EXC
) {
4624 * The readfn or writefn might raise an exception;
4625 * synchronize the CPU state in case it does.
4627 gen_set_condexec(s
);
4628 gen_set_pc_im(s
, s
->pc_curr
);
4631 /* Handle special cases first */
4632 switch (ri
->type
& ~(ARM_CP_FLAG_MASK
& ~ARM_CP_SPECIAL
)) {
4637 unallocated_encoding(s
);
4640 gen_set_pc_im(s
, s
->base
.pc_next
);
4641 s
->base
.is_jmp
= DISAS_WFI
;
4647 if ((tb_cflags(s
->base
.tb
) & CF_USE_ICOUNT
) && (ri
->type
& ARM_CP_IO
)) {
4656 if (ri
->type
& ARM_CP_CONST
) {
4657 tmp64
= tcg_const_i64(ri
->resetvalue
);
4658 } else if (ri
->readfn
) {
4660 tmp64
= tcg_temp_new_i64();
4661 tmpptr
= tcg_const_ptr(ri
);
4662 gen_helper_get_cp_reg64(tmp64
, cpu_env
, tmpptr
);
4663 tcg_temp_free_ptr(tmpptr
);
4665 tmp64
= tcg_temp_new_i64();
4666 tcg_gen_ld_i64(tmp64
, cpu_env
, ri
->fieldoffset
);
4668 tmp
= tcg_temp_new_i32();
4669 tcg_gen_extrl_i64_i32(tmp
, tmp64
);
4670 store_reg(s
, rt
, tmp
);
4671 tmp
= tcg_temp_new_i32();
4672 tcg_gen_extrh_i64_i32(tmp
, tmp64
);
4673 tcg_temp_free_i64(tmp64
);
4674 store_reg(s
, rt2
, tmp
);
4677 if (ri
->type
& ARM_CP_CONST
) {
4678 tmp
= tcg_const_i32(ri
->resetvalue
);
4679 } else if (ri
->readfn
) {
4681 tmp
= tcg_temp_new_i32();
4682 tmpptr
= tcg_const_ptr(ri
);
4683 gen_helper_get_cp_reg(tmp
, cpu_env
, tmpptr
);
4684 tcg_temp_free_ptr(tmpptr
);
4686 tmp
= load_cpu_offset(ri
->fieldoffset
);
4689 /* Destination register of r15 for 32 bit loads sets
4690 * the condition codes from the high 4 bits of the value
4693 tcg_temp_free_i32(tmp
);
4695 store_reg(s
, rt
, tmp
);
4700 if (ri
->type
& ARM_CP_CONST
) {
4701 /* If not forbidden by access permissions, treat as WI */
4706 TCGv_i32 tmplo
, tmphi
;
4707 TCGv_i64 tmp64
= tcg_temp_new_i64();
4708 tmplo
= load_reg(s
, rt
);
4709 tmphi
= load_reg(s
, rt2
);
4710 tcg_gen_concat_i32_i64(tmp64
, tmplo
, tmphi
);
4711 tcg_temp_free_i32(tmplo
);
4712 tcg_temp_free_i32(tmphi
);
4714 TCGv_ptr tmpptr
= tcg_const_ptr(ri
);
4715 gen_helper_set_cp_reg64(cpu_env
, tmpptr
, tmp64
);
4716 tcg_temp_free_ptr(tmpptr
);
4718 tcg_gen_st_i64(tmp64
, cpu_env
, ri
->fieldoffset
);
4720 tcg_temp_free_i64(tmp64
);
4725 tmp
= load_reg(s
, rt
);
4726 tmpptr
= tcg_const_ptr(ri
);
4727 gen_helper_set_cp_reg(cpu_env
, tmpptr
, tmp
);
4728 tcg_temp_free_ptr(tmpptr
);
4729 tcg_temp_free_i32(tmp
);
4731 TCGv_i32 tmp
= load_reg(s
, rt
);
4732 store_cpu_offset(tmp
, ri
->fieldoffset
);
4737 /* I/O operations must end the TB here (whether read or write) */
4738 need_exit_tb
= ((tb_cflags(s
->base
.tb
) & CF_USE_ICOUNT
) &&
4739 (ri
->type
& ARM_CP_IO
));
4741 if (!isread
&& !(ri
->type
& ARM_CP_SUPPRESS_TB_END
)) {
4743 * A write to any coprocessor register that ends a TB
4744 * must rebuild the hflags for the next TB.
4746 TCGv_i32 tcg_el
= tcg_const_i32(s
->current_el
);
4747 if (arm_dc_feature(s
, ARM_FEATURE_M
)) {
4748 gen_helper_rebuild_hflags_m32(cpu_env
, tcg_el
);
4750 if (ri
->type
& ARM_CP_NEWEL
) {
4751 gen_helper_rebuild_hflags_a32_newel(cpu_env
);
4753 gen_helper_rebuild_hflags_a32(cpu_env
, tcg_el
);
4756 tcg_temp_free_i32(tcg_el
);
4758 * We default to ending the TB on a coprocessor register write,
4759 * but allow this to be suppressed by the register definition
4760 * (usually only necessary to work around guest bugs).
4762 need_exit_tb
= true;
4771 /* Unknown register; this might be a guest error or a QEMU
4772 * unimplemented feature.
4775 qemu_log_mask(LOG_UNIMP
, "%s access to unsupported AArch32 "
4776 "64 bit system register cp:%d opc1: %d crm:%d "
4778 isread
? "read" : "write", cpnum
, opc1
, crm
,
4779 s
->ns
? "non-secure" : "secure");
4781 qemu_log_mask(LOG_UNIMP
, "%s access to unsupported AArch32 "
4782 "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d "
4784 isread
? "read" : "write", cpnum
, opc1
, crn
, crm
, opc2
,
4785 s
->ns
? "non-secure" : "secure");
4788 unallocated_encoding(s
);
4792 /* Decode XScale DSP or iWMMXt insn (in the copro space, cp=0 or 1) */
4793 static void disas_xscale_insn(DisasContext
*s
, uint32_t insn
)
4795 int cpnum
= (insn
>> 8) & 0xf;
4797 if (extract32(s
->c15_cpar
, cpnum
, 1) == 0) {
4798 unallocated_encoding(s
);
4799 } else if (arm_dc_feature(s
, ARM_FEATURE_IWMMXT
)) {
4800 if (disas_iwmmxt_insn(s
, insn
)) {
4801 unallocated_encoding(s
);
4803 } else if (arm_dc_feature(s
, ARM_FEATURE_XSCALE
)) {
4804 if (disas_dsp_insn(s
, insn
)) {
4805 unallocated_encoding(s
);
4810 /* Store a 64-bit value to a register pair. Clobbers val. */
4811 static void gen_storeq_reg(DisasContext
*s
, int rlow
, int rhigh
, TCGv_i64 val
)
4814 tmp
= tcg_temp_new_i32();
4815 tcg_gen_extrl_i64_i32(tmp
, val
);
4816 store_reg(s
, rlow
, tmp
);
4817 tmp
= tcg_temp_new_i32();
4818 tcg_gen_extrh_i64_i32(tmp
, val
);
4819 store_reg(s
, rhigh
, tmp
);
4822 /* load and add a 64-bit value from a register pair. */
4823 static void gen_addq(DisasContext
*s
, TCGv_i64 val
, int rlow
, int rhigh
)
4829 /* Load 64-bit value rd:rn. */
4830 tmpl
= load_reg(s
, rlow
);
4831 tmph
= load_reg(s
, rhigh
);
4832 tmp
= tcg_temp_new_i64();
4833 tcg_gen_concat_i32_i64(tmp
, tmpl
, tmph
);
4834 tcg_temp_free_i32(tmpl
);
4835 tcg_temp_free_i32(tmph
);
4836 tcg_gen_add_i64(val
, val
, tmp
);
4837 tcg_temp_free_i64(tmp
);
4840 /* Set N and Z flags from hi|lo. */
4841 static void gen_logicq_cc(TCGv_i32 lo
, TCGv_i32 hi
)
4843 tcg_gen_mov_i32(cpu_NF
, hi
);
4844 tcg_gen_or_i32(cpu_ZF
, lo
, hi
);
4847 /* Load/Store exclusive instructions are implemented by remembering
4848 the value/address loaded, and seeing if these are the same
4849 when the store is performed. This should be sufficient to implement
4850 the architecturally mandated semantics, and avoids having to monitor
4851 regular stores. The compare vs the remembered value is done during
4852 the cmpxchg operation, but we must compare the addresses manually. */
4853 static void gen_load_exclusive(DisasContext
*s
, int rt
, int rt2
,
4854 TCGv_i32 addr
, int size
)
4856 TCGv_i32 tmp
= tcg_temp_new_i32();
4857 MemOp opc
= size
| MO_ALIGN
| s
->be_data
;
4862 TCGv_i32 tmp2
= tcg_temp_new_i32();
4863 TCGv_i64 t64
= tcg_temp_new_i64();
4865 /* For AArch32, architecturally the 32-bit word at the lowest
4866 * address is always Rt and the one at addr+4 is Rt2, even if
4867 * the CPU is big-endian. That means we don't want to do a
4868 * gen_aa32_ld_i64(), which invokes gen_aa32_frob64() as if
4869 * for an architecturally 64-bit access, but instead do a
4870 * 64-bit access using MO_BE if appropriate and then split
4872 * This only makes a difference for BE32 user-mode, where
4873 * frob64() must not flip the two halves of the 64-bit data
4874 * but this code must treat BE32 user-mode like BE32 system.
4876 TCGv taddr
= gen_aa32_addr(s
, addr
, opc
);
4878 tcg_gen_qemu_ld_i64(t64
, taddr
, get_mem_index(s
), opc
);
4879 tcg_temp_free(taddr
);
4880 tcg_gen_mov_i64(cpu_exclusive_val
, t64
);
4881 if (s
->be_data
== MO_BE
) {
4882 tcg_gen_extr_i64_i32(tmp2
, tmp
, t64
);
4884 tcg_gen_extr_i64_i32(tmp
, tmp2
, t64
);
4886 tcg_temp_free_i64(t64
);
4888 store_reg(s
, rt2
, tmp2
);
4890 gen_aa32_ld_i32(s
, tmp
, addr
, get_mem_index(s
), opc
);
4891 tcg_gen_extu_i32_i64(cpu_exclusive_val
, tmp
);
4894 store_reg(s
, rt
, tmp
);
4895 tcg_gen_extu_i32_i64(cpu_exclusive_addr
, addr
);
4898 static void gen_clrex(DisasContext
*s
)
4900 tcg_gen_movi_i64(cpu_exclusive_addr
, -1);
4903 static void gen_store_exclusive(DisasContext
*s
, int rd
, int rt
, int rt2
,
4904 TCGv_i32 addr
, int size
)
4906 TCGv_i32 t0
, t1
, t2
;
4909 TCGLabel
*done_label
;
4910 TCGLabel
*fail_label
;
4911 MemOp opc
= size
| MO_ALIGN
| s
->be_data
;
4913 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
4919 fail_label
= gen_new_label();
4920 done_label
= gen_new_label();
4921 extaddr
= tcg_temp_new_i64();
4922 tcg_gen_extu_i32_i64(extaddr
, addr
);
4923 tcg_gen_brcond_i64(TCG_COND_NE
, extaddr
, cpu_exclusive_addr
, fail_label
);
4924 tcg_temp_free_i64(extaddr
);
4926 taddr
= gen_aa32_addr(s
, addr
, opc
);
4927 t0
= tcg_temp_new_i32();
4928 t1
= load_reg(s
, rt
);
4930 TCGv_i64 o64
= tcg_temp_new_i64();
4931 TCGv_i64 n64
= tcg_temp_new_i64();
4933 t2
= load_reg(s
, rt2
);
4934 /* For AArch32, architecturally the 32-bit word at the lowest
4935 * address is always Rt and the one at addr+4 is Rt2, even if
4936 * the CPU is big-endian. Since we're going to treat this as a
4937 * single 64-bit BE store, we need to put the two halves in the
4938 * opposite order for BE to LE, so that they end up in the right
4940 * We don't want gen_aa32_frob64() because that does the wrong
4941 * thing for BE32 usermode.
4943 if (s
->be_data
== MO_BE
) {
4944 tcg_gen_concat_i32_i64(n64
, t2
, t1
);
4946 tcg_gen_concat_i32_i64(n64
, t1
, t2
);
4948 tcg_temp_free_i32(t2
);
4950 tcg_gen_atomic_cmpxchg_i64(o64
, taddr
, cpu_exclusive_val
, n64
,
4951 get_mem_index(s
), opc
);
4952 tcg_temp_free_i64(n64
);
4954 tcg_gen_setcond_i64(TCG_COND_NE
, o64
, o64
, cpu_exclusive_val
);
4955 tcg_gen_extrl_i64_i32(t0
, o64
);
4957 tcg_temp_free_i64(o64
);
4959 t2
= tcg_temp_new_i32();
4960 tcg_gen_extrl_i64_i32(t2
, cpu_exclusive_val
);
4961 tcg_gen_atomic_cmpxchg_i32(t0
, taddr
, t2
, t1
, get_mem_index(s
), opc
);
4962 tcg_gen_setcond_i32(TCG_COND_NE
, t0
, t0
, t2
);
4963 tcg_temp_free_i32(t2
);
4965 tcg_temp_free_i32(t1
);
4966 tcg_temp_free(taddr
);
4967 tcg_gen_mov_i32(cpu_R
[rd
], t0
);
4968 tcg_temp_free_i32(t0
);
4969 tcg_gen_br(done_label
);
4971 gen_set_label(fail_label
);
4972 tcg_gen_movi_i32(cpu_R
[rd
], 1);
4973 gen_set_label(done_label
);
4974 tcg_gen_movi_i64(cpu_exclusive_addr
, -1);
4980 * @mode: mode field from insn (which stack to store to)
4981 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
4982 * @writeback: true if writeback bit set
4984 * Generate code for the SRS (Store Return State) insn.
4986 static void gen_srs(DisasContext
*s
,
4987 uint32_t mode
, uint32_t amode
, bool writeback
)
4994 * - trapped to EL3 if EL3 is AArch64 and we are at Secure EL1
4995 * and specified mode is monitor mode
4996 * - UNDEFINED in Hyp mode
4997 * - UNPREDICTABLE in User or System mode
4998 * - UNPREDICTABLE if the specified mode is:
4999 * -- not implemented
5000 * -- not a valid mode number
5001 * -- a mode that's at a higher exception level
5002 * -- Monitor, if we are Non-secure
5003 * For the UNPREDICTABLE cases we choose to UNDEF.
5005 if (s
->current_el
== 1 && !s
->ns
&& mode
== ARM_CPU_MODE_MON
) {
5006 gen_exception_insn(s
, s
->pc_curr
, EXCP_UDEF
, syn_uncategorized(), 3);
5010 if (s
->current_el
== 0 || s
->current_el
== 2) {
5015 case ARM_CPU_MODE_USR
:
5016 case ARM_CPU_MODE_FIQ
:
5017 case ARM_CPU_MODE_IRQ
:
5018 case ARM_CPU_MODE_SVC
:
5019 case ARM_CPU_MODE_ABT
:
5020 case ARM_CPU_MODE_UND
:
5021 case ARM_CPU_MODE_SYS
:
5023 case ARM_CPU_MODE_HYP
:
5024 if (s
->current_el
== 1 || !arm_dc_feature(s
, ARM_FEATURE_EL2
)) {
5028 case ARM_CPU_MODE_MON
:
5029 /* No need to check specifically for "are we non-secure" because
5030 * we've already made EL0 UNDEF and handled the trap for S-EL1;
5031 * so if this isn't EL3 then we must be non-secure.
5033 if (s
->current_el
!= 3) {
5042 unallocated_encoding(s
);
5046 addr
= tcg_temp_new_i32();
5047 tmp
= tcg_const_i32(mode
);
5048 /* get_r13_banked() will raise an exception if called from System mode */
5049 gen_set_condexec(s
);
5050 gen_set_pc_im(s
, s
->pc_curr
);
5051 gen_helper_get_r13_banked(addr
, cpu_env
, tmp
);
5052 tcg_temp_free_i32(tmp
);
5069 tcg_gen_addi_i32(addr
, addr
, offset
);
5070 tmp
= load_reg(s
, 14);
5071 gen_aa32_st32(s
, tmp
, addr
, get_mem_index(s
));
5072 tcg_temp_free_i32(tmp
);
5073 tmp
= load_cpu_field(spsr
);
5074 tcg_gen_addi_i32(addr
, addr
, 4);
5075 gen_aa32_st32(s
, tmp
, addr
, get_mem_index(s
));
5076 tcg_temp_free_i32(tmp
);
5094 tcg_gen_addi_i32(addr
, addr
, offset
);
5095 tmp
= tcg_const_i32(mode
);
5096 gen_helper_set_r13_banked(cpu_env
, tmp
, addr
);
5097 tcg_temp_free_i32(tmp
);
5099 tcg_temp_free_i32(addr
);
5100 s
->base
.is_jmp
= DISAS_UPDATE_EXIT
;
5103 /* Generate a label used for skipping this instruction */
5104 static void arm_gen_condlabel(DisasContext
*s
)
5107 s
->condlabel
= gen_new_label();
5112 /* Skip this instruction if the ARM condition is false */
5113 static void arm_skip_unless(DisasContext
*s
, uint32_t cond
)
5115 arm_gen_condlabel(s
);
5116 arm_gen_test_cc(cond
^ 1, s
->condlabel
);
5121 * Constant expanders for the decoders.
5124 static int negate(DisasContext
*s
, int x
)
5129 static int plus_2(DisasContext
*s
, int x
)
5134 static int times_2(DisasContext
*s
, int x
)
5139 static int times_4(DisasContext
*s
, int x
)
5144 /* Return only the rotation part of T32ExpandImm. */
5145 static int t32_expandimm_rot(DisasContext
*s
, int x
)
5147 return x
& 0xc00 ? extract32(x
, 7, 5) : 0;
5150 /* Return the unrotated immediate from T32ExpandImm. */
5151 static int t32_expandimm_imm(DisasContext
*s
, int x
)
5153 int imm
= extract32(x
, 0, 8);
5155 switch (extract32(x
, 8, 4)) {
5157 /* Nothing to do. */
5159 case 1: /* 00XY00XY */
5162 case 2: /* XY00XY00 */
5165 case 3: /* XYXYXYXY */
5169 /* Rotated constant. */
5176 static int t32_branch24(DisasContext
*s
, int x
)
5178 /* Convert J1:J2 at x[22:21] to I2:I1, which involves I=J^~S. */
5179 x
^= !(x
< 0) * (3 << 21);
5180 /* Append the final zero. */
5184 static int t16_setflags(DisasContext
*s
)
5186 return s
->condexec_mask
== 0;
5189 static int t16_push_list(DisasContext
*s
, int x
)
5191 return (x
& 0xff) | (x
& 0x100) << (14 - 8);
5194 static int t16_pop_list(DisasContext
*s
, int x
)
5196 return (x
& 0xff) | (x
& 0x100) << (15 - 8);
5200 * Include the generated decoders.
5203 #include "decode-a32.c.inc"
5204 #include "decode-a32-uncond.c.inc"
5205 #include "decode-t32.c.inc"
5206 #include "decode-t16.c.inc"
5208 static bool valid_cp(DisasContext
*s
, int cp
)
5211 * Return true if this coprocessor field indicates something
5212 * that's really a possible coprocessor.
5213 * For v7 and earlier, coprocessors 8..15 were reserved for Arm use,
5214 * and of those only cp14 and cp15 were used for registers.
5215 * cp10 and cp11 were used for VFP and Neon, whose decode is
5216 * dealt with elsewhere. With the advent of fp16, cp9 is also
5218 * For v8A and later, the encoding has been tightened so that
5219 * only cp14 and cp15 are valid, and other values aren't considered
5220 * to be in the coprocessor-instruction space at all. v8M still
5221 * permits coprocessors 0..7.
5223 if (arm_dc_feature(s
, ARM_FEATURE_V8
) &&
5224 !arm_dc_feature(s
, ARM_FEATURE_M
)) {
5227 return cp
< 8 || cp
>= 14;
5230 static bool trans_MCR(DisasContext
*s
, arg_MCR
*a
)
5232 if (!valid_cp(s
, a
->cp
)) {
5235 do_coproc_insn(s
, a
->cp
, false, a
->opc1
, a
->crn
, a
->crm
, a
->opc2
,
5240 static bool trans_MRC(DisasContext
*s
, arg_MRC
*a
)
5242 if (!valid_cp(s
, a
->cp
)) {
5245 do_coproc_insn(s
, a
->cp
, false, a
->opc1
, a
->crn
, a
->crm
, a
->opc2
,
5250 static bool trans_MCRR(DisasContext
*s
, arg_MCRR
*a
)
5252 if (!valid_cp(s
, a
->cp
)) {
5255 do_coproc_insn(s
, a
->cp
, true, a
->opc1
, 0, a
->crm
, 0,
5256 false, a
->rt
, a
->rt2
);
5260 static bool trans_MRRC(DisasContext
*s
, arg_MRRC
*a
)
5262 if (!valid_cp(s
, a
->cp
)) {
5265 do_coproc_insn(s
, a
->cp
, true, a
->opc1
, 0, a
->crm
, 0,
5266 true, a
->rt
, a
->rt2
);
5270 /* Helpers to swap operands for reverse-subtract. */
5271 static void gen_rsb(TCGv_i32 dst
, TCGv_i32 a
, TCGv_i32 b
)
5273 tcg_gen_sub_i32(dst
, b
, a
);
5276 static void gen_rsb_CC(TCGv_i32 dst
, TCGv_i32 a
, TCGv_i32 b
)
5278 gen_sub_CC(dst
, b
, a
);
5281 static void gen_rsc(TCGv_i32 dest
, TCGv_i32 a
, TCGv_i32 b
)
5283 gen_sub_carry(dest
, b
, a
);
5286 static void gen_rsc_CC(TCGv_i32 dest
, TCGv_i32 a
, TCGv_i32 b
)
5288 gen_sbc_CC(dest
, b
, a
);
5292 * Helpers for the data processing routines.
5294 * After the computation store the results back.
5295 * This may be suppressed altogether (STREG_NONE), require a runtime
5296 * check against the stack limits (STREG_SP_CHECK), or generate an
5297 * exception return. Oh, or store into a register.
5299 * Always return true, indicating success for a trans_* function.
5308 static bool store_reg_kind(DisasContext
*s
, int rd
,
5309 TCGv_i32 val
, StoreRegKind kind
)
5313 tcg_temp_free_i32(val
);
5316 /* See ALUWritePC: Interworking only from a32 mode. */
5318 store_reg(s
, rd
, val
);
5320 store_reg_bx(s
, rd
, val
);
5323 case STREG_SP_CHECK
:
5324 store_sp_checked(s
, val
);
5327 gen_exception_return(s
, val
);
5330 g_assert_not_reached();
5334 * Data Processing (register)
5336 * Operate, with set flags, one register source,
5337 * one immediate shifted register source, and a destination.
5339 static bool op_s_rrr_shi(DisasContext
*s
, arg_s_rrr_shi
*a
,
5340 void (*gen
)(TCGv_i32
, TCGv_i32
, TCGv_i32
),
5341 int logic_cc
, StoreRegKind kind
)
5343 TCGv_i32 tmp1
, tmp2
;
5345 tmp2
= load_reg(s
, a
->rm
);
5346 gen_arm_shift_im(tmp2
, a
->shty
, a
->shim
, logic_cc
);
5347 tmp1
= load_reg(s
, a
->rn
);
5349 gen(tmp1
, tmp1
, tmp2
);
5350 tcg_temp_free_i32(tmp2
);
5355 return store_reg_kind(s
, a
->rd
, tmp1
, kind
);
5358 static bool op_s_rxr_shi(DisasContext
*s
, arg_s_rrr_shi
*a
,
5359 void (*gen
)(TCGv_i32
, TCGv_i32
),
5360 int logic_cc
, StoreRegKind kind
)
5364 tmp
= load_reg(s
, a
->rm
);
5365 gen_arm_shift_im(tmp
, a
->shty
, a
->shim
, logic_cc
);
5371 return store_reg_kind(s
, a
->rd
, tmp
, kind
);
5375 * Data-processing (register-shifted register)
5377 * Operate, with set flags, one register source,
5378 * one register shifted register source, and a destination.
5380 static bool op_s_rrr_shr(DisasContext
*s
, arg_s_rrr_shr
*a
,
5381 void (*gen
)(TCGv_i32
, TCGv_i32
, TCGv_i32
),
5382 int logic_cc
, StoreRegKind kind
)
5384 TCGv_i32 tmp1
, tmp2
;
5386 tmp1
= load_reg(s
, a
->rs
);
5387 tmp2
= load_reg(s
, a
->rm
);
5388 gen_arm_shift_reg(tmp2
, a
->shty
, tmp1
, logic_cc
);
5389 tmp1
= load_reg(s
, a
->rn
);
5391 gen(tmp1
, tmp1
, tmp2
);
5392 tcg_temp_free_i32(tmp2
);
5397 return store_reg_kind(s
, a
->rd
, tmp1
, kind
);
5400 static bool op_s_rxr_shr(DisasContext
*s
, arg_s_rrr_shr
*a
,
5401 void (*gen
)(TCGv_i32
, TCGv_i32
),
5402 int logic_cc
, StoreRegKind kind
)
5404 TCGv_i32 tmp1
, tmp2
;
5406 tmp1
= load_reg(s
, a
->rs
);
5407 tmp2
= load_reg(s
, a
->rm
);
5408 gen_arm_shift_reg(tmp2
, a
->shty
, tmp1
, logic_cc
);
5414 return store_reg_kind(s
, a
->rd
, tmp2
, kind
);
5418 * Data-processing (immediate)
5420 * Operate, with set flags, one register source,
5421 * one rotated immediate, and a destination.
5423 * Note that logic_cc && a->rot setting CF based on the msb of the
5424 * immediate is the reason why we must pass in the unrotated form
5427 static bool op_s_rri_rot(DisasContext
*s
, arg_s_rri_rot
*a
,
5428 void (*gen
)(TCGv_i32
, TCGv_i32
, TCGv_i32
),
5429 int logic_cc
, StoreRegKind kind
)
5431 TCGv_i32 tmp1
, tmp2
;
5434 imm
= ror32(a
->imm
, a
->rot
);
5435 if (logic_cc
&& a
->rot
) {
5436 tcg_gen_movi_i32(cpu_CF
, imm
>> 31);
5438 tmp2
= tcg_const_i32(imm
);
5439 tmp1
= load_reg(s
, a
->rn
);
5441 gen(tmp1
, tmp1
, tmp2
);
5442 tcg_temp_free_i32(tmp2
);
5447 return store_reg_kind(s
, a
->rd
, tmp1
, kind
);
5450 static bool op_s_rxi_rot(DisasContext
*s
, arg_s_rri_rot
*a
,
5451 void (*gen
)(TCGv_i32
, TCGv_i32
),
5452 int logic_cc
, StoreRegKind kind
)
5457 imm
= ror32(a
->imm
, a
->rot
);
5458 if (logic_cc
&& a
->rot
) {
5459 tcg_gen_movi_i32(cpu_CF
, imm
>> 31);
5461 tmp
= tcg_const_i32(imm
);
5467 return store_reg_kind(s
, a
->rd
, tmp
, kind
);
5470 #define DO_ANY3(NAME, OP, L, K) \
5471 static bool trans_##NAME##_rrri(DisasContext *s, arg_s_rrr_shi *a) \
5472 { StoreRegKind k = (K); return op_s_rrr_shi(s, a, OP, L, k); } \
5473 static bool trans_##NAME##_rrrr(DisasContext *s, arg_s_rrr_shr *a) \
5474 { StoreRegKind k = (K); return op_s_rrr_shr(s, a, OP, L, k); } \
5475 static bool trans_##NAME##_rri(DisasContext *s, arg_s_rri_rot *a) \
5476 { StoreRegKind k = (K); return op_s_rri_rot(s, a, OP, L, k); }
5478 #define DO_ANY2(NAME, OP, L, K) \
5479 static bool trans_##NAME##_rxri(DisasContext *s, arg_s_rrr_shi *a) \
5480 { StoreRegKind k = (K); return op_s_rxr_shi(s, a, OP, L, k); } \
5481 static bool trans_##NAME##_rxrr(DisasContext *s, arg_s_rrr_shr *a) \
5482 { StoreRegKind k = (K); return op_s_rxr_shr(s, a, OP, L, k); } \
5483 static bool trans_##NAME##_rxi(DisasContext *s, arg_s_rri_rot *a) \
5484 { StoreRegKind k = (K); return op_s_rxi_rot(s, a, OP, L, k); }
5486 #define DO_CMP2(NAME, OP, L) \
5487 static bool trans_##NAME##_xrri(DisasContext *s, arg_s_rrr_shi *a) \
5488 { return op_s_rrr_shi(s, a, OP, L, STREG_NONE); } \
5489 static bool trans_##NAME##_xrrr(DisasContext *s, arg_s_rrr_shr *a) \
5490 { return op_s_rrr_shr(s, a, OP, L, STREG_NONE); } \
5491 static bool trans_##NAME##_xri(DisasContext *s, arg_s_rri_rot *a) \
5492 { return op_s_rri_rot(s, a, OP, L, STREG_NONE); }
5494 DO_ANY3(AND
, tcg_gen_and_i32
, a
->s
, STREG_NORMAL
)
5495 DO_ANY3(EOR
, tcg_gen_xor_i32
, a
->s
, STREG_NORMAL
)
5496 DO_ANY3(ORR
, tcg_gen_or_i32
, a
->s
, STREG_NORMAL
)
5497 DO_ANY3(BIC
, tcg_gen_andc_i32
, a
->s
, STREG_NORMAL
)
5499 DO_ANY3(RSB
, a
->s
? gen_rsb_CC
: gen_rsb
, false, STREG_NORMAL
)
5500 DO_ANY3(ADC
, a
->s
? gen_adc_CC
: gen_add_carry
, false, STREG_NORMAL
)
5501 DO_ANY3(SBC
, a
->s
? gen_sbc_CC
: gen_sub_carry
, false, STREG_NORMAL
)
5502 DO_ANY3(RSC
, a
->s
? gen_rsc_CC
: gen_rsc
, false, STREG_NORMAL
)
5504 DO_CMP2(TST
, tcg_gen_and_i32
, true)
5505 DO_CMP2(TEQ
, tcg_gen_xor_i32
, true)
5506 DO_CMP2(CMN
, gen_add_CC
, false)
5507 DO_CMP2(CMP
, gen_sub_CC
, false)
5509 DO_ANY3(ADD
, a
->s
? gen_add_CC
: tcg_gen_add_i32
, false,
5510 a
->rd
== 13 && a
->rn
== 13 ? STREG_SP_CHECK
: STREG_NORMAL
)
5513 * Note for the computation of StoreRegKind we return out of the
5514 * middle of the functions that are expanded by DO_ANY3, and that
5515 * we modify a->s via that parameter before it is used by OP.
5517 DO_ANY3(SUB
, a
->s
? gen_sub_CC
: tcg_gen_sub_i32
, false,
5519 StoreRegKind ret
= STREG_NORMAL
;
5520 if (a
->rd
== 15 && a
->s
) {
5522 * See ALUExceptionReturn:
5523 * In User mode, UNPREDICTABLE; we choose UNDEF.
5524 * In Hyp mode, UNDEFINED.
5526 if (IS_USER(s
) || s
->current_el
== 2) {
5527 unallocated_encoding(s
);
5530 /* There is no writeback of nzcv to PSTATE. */
5532 ret
= STREG_EXC_RET
;
5533 } else if (a
->rd
== 13 && a
->rn
== 13) {
5534 ret
= STREG_SP_CHECK
;
5539 DO_ANY2(MOV
, tcg_gen_mov_i32
, a
->s
,
5541 StoreRegKind ret
= STREG_NORMAL
;
5542 if (a
->rd
== 15 && a
->s
) {
5544 * See ALUExceptionReturn:
5545 * In User mode, UNPREDICTABLE; we choose UNDEF.
5546 * In Hyp mode, UNDEFINED.
5548 if (IS_USER(s
) || s
->current_el
== 2) {
5549 unallocated_encoding(s
);
5552 /* There is no writeback of nzcv to PSTATE. */
5554 ret
= STREG_EXC_RET
;
5555 } else if (a
->rd
== 13) {
5556 ret
= STREG_SP_CHECK
;
5561 DO_ANY2(MVN
, tcg_gen_not_i32
, a
->s
, STREG_NORMAL
)
5564 * ORN is only available with T32, so there is no register-shifted-register
5565 * form of the insn. Using the DO_ANY3 macro would create an unused function.
5567 static bool trans_ORN_rrri(DisasContext
*s
, arg_s_rrr_shi
*a
)
5569 return op_s_rrr_shi(s
, a
, tcg_gen_orc_i32
, a
->s
, STREG_NORMAL
);
5572 static bool trans_ORN_rri(DisasContext
*s
, arg_s_rri_rot
*a
)
5574 return op_s_rri_rot(s
, a
, tcg_gen_orc_i32
, a
->s
, STREG_NORMAL
);
5581 static bool trans_ADR(DisasContext
*s
, arg_ri
*a
)
5583 store_reg_bx(s
, a
->rd
, add_reg_for_lit(s
, 15, a
->imm
));
5587 static bool trans_MOVW(DisasContext
*s
, arg_MOVW
*a
)
5591 if (!ENABLE_ARCH_6T2
) {
5595 tmp
= tcg_const_i32(a
->imm
);
5596 store_reg(s
, a
->rd
, tmp
);
5600 static bool trans_MOVT(DisasContext
*s
, arg_MOVW
*a
)
5604 if (!ENABLE_ARCH_6T2
) {
5608 tmp
= load_reg(s
, a
->rd
);
5609 tcg_gen_ext16u_i32(tmp
, tmp
);
5610 tcg_gen_ori_i32(tmp
, tmp
, a
->imm
<< 16);
5611 store_reg(s
, a
->rd
, tmp
);
5616 * Multiply and multiply accumulate
5619 static bool op_mla(DisasContext
*s
, arg_s_rrrr
*a
, bool add
)
5623 t1
= load_reg(s
, a
->rn
);
5624 t2
= load_reg(s
, a
->rm
);
5625 tcg_gen_mul_i32(t1
, t1
, t2
);
5626 tcg_temp_free_i32(t2
);
5628 t2
= load_reg(s
, a
->ra
);
5629 tcg_gen_add_i32(t1
, t1
, t2
);
5630 tcg_temp_free_i32(t2
);
5635 store_reg(s
, a
->rd
, t1
);
5639 static bool trans_MUL(DisasContext
*s
, arg_MUL
*a
)
5641 return op_mla(s
, a
, false);
5644 static bool trans_MLA(DisasContext
*s
, arg_MLA
*a
)
5646 return op_mla(s
, a
, true);
5649 static bool trans_MLS(DisasContext
*s
, arg_MLS
*a
)
5653 if (!ENABLE_ARCH_6T2
) {
5656 t1
= load_reg(s
, a
->rn
);
5657 t2
= load_reg(s
, a
->rm
);
5658 tcg_gen_mul_i32(t1
, t1
, t2
);
5659 tcg_temp_free_i32(t2
);
5660 t2
= load_reg(s
, a
->ra
);
5661 tcg_gen_sub_i32(t1
, t2
, t1
);
5662 tcg_temp_free_i32(t2
);
5663 store_reg(s
, a
->rd
, t1
);
5667 static bool op_mlal(DisasContext
*s
, arg_s_rrrr
*a
, bool uns
, bool add
)
5669 TCGv_i32 t0
, t1
, t2
, t3
;
5671 t0
= load_reg(s
, a
->rm
);
5672 t1
= load_reg(s
, a
->rn
);
5674 tcg_gen_mulu2_i32(t0
, t1
, t0
, t1
);
5676 tcg_gen_muls2_i32(t0
, t1
, t0
, t1
);
5679 t2
= load_reg(s
, a
->ra
);
5680 t3
= load_reg(s
, a
->rd
);
5681 tcg_gen_add2_i32(t0
, t1
, t0
, t1
, t2
, t3
);
5682 tcg_temp_free_i32(t2
);
5683 tcg_temp_free_i32(t3
);
5686 gen_logicq_cc(t0
, t1
);
5688 store_reg(s
, a
->ra
, t0
);
5689 store_reg(s
, a
->rd
, t1
);
5693 static bool trans_UMULL(DisasContext
*s
, arg_UMULL
*a
)
5695 return op_mlal(s
, a
, true, false);
5698 static bool trans_SMULL(DisasContext
*s
, arg_SMULL
*a
)
5700 return op_mlal(s
, a
, false, false);
5703 static bool trans_UMLAL(DisasContext
*s
, arg_UMLAL
*a
)
5705 return op_mlal(s
, a
, true, true);
5708 static bool trans_SMLAL(DisasContext
*s
, arg_SMLAL
*a
)
5710 return op_mlal(s
, a
, false, true);
5713 static bool trans_UMAAL(DisasContext
*s
, arg_UMAAL
*a
)
5715 TCGv_i32 t0
, t1
, t2
, zero
;
5718 ? !arm_dc_feature(s
, ARM_FEATURE_THUMB_DSP
)
5723 t0
= load_reg(s
, a
->rm
);
5724 t1
= load_reg(s
, a
->rn
);
5725 tcg_gen_mulu2_i32(t0
, t1
, t0
, t1
);
5726 zero
= tcg_const_i32(0);
5727 t2
= load_reg(s
, a
->ra
);
5728 tcg_gen_add2_i32(t0
, t1
, t0
, t1
, t2
, zero
);
5729 tcg_temp_free_i32(t2
);
5730 t2
= load_reg(s
, a
->rd
);
5731 tcg_gen_add2_i32(t0
, t1
, t0
, t1
, t2
, zero
);
5732 tcg_temp_free_i32(t2
);
5733 tcg_temp_free_i32(zero
);
5734 store_reg(s
, a
->ra
, t0
);
5735 store_reg(s
, a
->rd
, t1
);
5740 * Saturating addition and subtraction
5743 static bool op_qaddsub(DisasContext
*s
, arg_rrr
*a
, bool add
, bool doub
)
5748 ? !arm_dc_feature(s
, ARM_FEATURE_THUMB_DSP
)
5749 : !ENABLE_ARCH_5TE
) {
5753 t0
= load_reg(s
, a
->rm
);
5754 t1
= load_reg(s
, a
->rn
);
5756 gen_helper_add_saturate(t1
, cpu_env
, t1
, t1
);
5759 gen_helper_add_saturate(t0
, cpu_env
, t0
, t1
);
5761 gen_helper_sub_saturate(t0
, cpu_env
, t0
, t1
);
5763 tcg_temp_free_i32(t1
);
5764 store_reg(s
, a
->rd
, t0
);
5768 #define DO_QADDSUB(NAME, ADD, DOUB) \
5769 static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
5771 return op_qaddsub(s, a, ADD, DOUB); \
5774 DO_QADDSUB(QADD
, true, false)
5775 DO_QADDSUB(QSUB
, false, false)
5776 DO_QADDSUB(QDADD
, true, true)
5777 DO_QADDSUB(QDSUB
, false, true)
5782 * Halfword multiply and multiply accumulate
5785 static bool op_smlaxxx(DisasContext
*s
, arg_rrrr
*a
,
5786 int add_long
, bool nt
, bool mt
)
5788 TCGv_i32 t0
, t1
, tl
, th
;
5791 ? !arm_dc_feature(s
, ARM_FEATURE_THUMB_DSP
)
5792 : !ENABLE_ARCH_5TE
) {
5796 t0
= load_reg(s
, a
->rn
);
5797 t1
= load_reg(s
, a
->rm
);
5798 gen_mulxy(t0
, t1
, nt
, mt
);
5799 tcg_temp_free_i32(t1
);
5803 store_reg(s
, a
->rd
, t0
);
5806 t1
= load_reg(s
, a
->ra
);
5807 gen_helper_add_setq(t0
, cpu_env
, t0
, t1
);
5808 tcg_temp_free_i32(t1
);
5809 store_reg(s
, a
->rd
, t0
);
5812 tl
= load_reg(s
, a
->ra
);
5813 th
= load_reg(s
, a
->rd
);
5814 /* Sign-extend the 32-bit product to 64 bits. */
5815 t1
= tcg_temp_new_i32();
5816 tcg_gen_sari_i32(t1
, t0
, 31);
5817 tcg_gen_add2_i32(tl
, th
, tl
, th
, t0
, t1
);
5818 tcg_temp_free_i32(t0
);
5819 tcg_temp_free_i32(t1
);
5820 store_reg(s
, a
->ra
, tl
);
5821 store_reg(s
, a
->rd
, th
);
5824 g_assert_not_reached();
5829 #define DO_SMLAX(NAME, add, nt, mt) \
5830 static bool trans_##NAME(DisasContext *s, arg_rrrr *a) \
5832 return op_smlaxxx(s, a, add, nt, mt); \
5835 DO_SMLAX(SMULBB
, 0, 0, 0)
5836 DO_SMLAX(SMULBT
, 0, 0, 1)
5837 DO_SMLAX(SMULTB
, 0, 1, 0)
5838 DO_SMLAX(SMULTT
, 0, 1, 1)
5840 DO_SMLAX(SMLABB
, 1, 0, 0)
5841 DO_SMLAX(SMLABT
, 1, 0, 1)
5842 DO_SMLAX(SMLATB
, 1, 1, 0)
5843 DO_SMLAX(SMLATT
, 1, 1, 1)
5845 DO_SMLAX(SMLALBB
, 2, 0, 0)
5846 DO_SMLAX(SMLALBT
, 2, 0, 1)
5847 DO_SMLAX(SMLALTB
, 2, 1, 0)
5848 DO_SMLAX(SMLALTT
, 2, 1, 1)
5852 static bool op_smlawx(DisasContext
*s
, arg_rrrr
*a
, bool add
, bool mt
)
5856 if (!ENABLE_ARCH_5TE
) {
5860 t0
= load_reg(s
, a
->rn
);
5861 t1
= load_reg(s
, a
->rm
);
5863 * Since the nominal result is product<47:16>, shift the 16-bit
5864 * input up by 16 bits, so that the result is at product<63:32>.
5867 tcg_gen_andi_i32(t1
, t1
, 0xffff0000);
5869 tcg_gen_shli_i32(t1
, t1
, 16);
5871 tcg_gen_muls2_i32(t0
, t1
, t0
, t1
);
5872 tcg_temp_free_i32(t0
);
5874 t0
= load_reg(s
, a
->ra
);
5875 gen_helper_add_setq(t1
, cpu_env
, t1
, t0
);
5876 tcg_temp_free_i32(t0
);
5878 store_reg(s
, a
->rd
, t1
);
5882 #define DO_SMLAWX(NAME, add, mt) \
5883 static bool trans_##NAME(DisasContext *s, arg_rrrr *a) \
5885 return op_smlawx(s, a, add, mt); \
5888 DO_SMLAWX(SMULWB
, 0, 0)
5889 DO_SMLAWX(SMULWT
, 0, 1)
5890 DO_SMLAWX(SMLAWB
, 1, 0)
5891 DO_SMLAWX(SMLAWT
, 1, 1)
5896 * MSR (immediate) and hints
5899 static bool trans_YIELD(DisasContext
*s
, arg_YIELD
*a
)
5902 * When running single-threaded TCG code, use the helper to ensure that
5903 * the next round-robin scheduled vCPU gets a crack. When running in
5904 * MTTCG we don't generate jumps to the helper as it won't affect the
5905 * scheduling of other vCPUs.
5907 if (!(tb_cflags(s
->base
.tb
) & CF_PARALLEL
)) {
5908 gen_set_pc_im(s
, s
->base
.pc_next
);
5909 s
->base
.is_jmp
= DISAS_YIELD
;
5914 static bool trans_WFE(DisasContext
*s
, arg_WFE
*a
)
5917 * When running single-threaded TCG code, use the helper to ensure that
5918 * the next round-robin scheduled vCPU gets a crack. In MTTCG mode we
5919 * just skip this instruction. Currently the SEV/SEVL instructions,
5920 * which are *one* of many ways to wake the CPU from WFE, are not
5921 * implemented so we can't sleep like WFI does.
5923 if (!(tb_cflags(s
->base
.tb
) & CF_PARALLEL
)) {
5924 gen_set_pc_im(s
, s
->base
.pc_next
);
5925 s
->base
.is_jmp
= DISAS_WFE
;
5930 static bool trans_WFI(DisasContext
*s
, arg_WFI
*a
)
5932 /* For WFI, halt the vCPU until an IRQ. */
5933 gen_set_pc_im(s
, s
->base
.pc_next
);
5934 s
->base
.is_jmp
= DISAS_WFI
;
5938 static bool trans_NOP(DisasContext
*s
, arg_NOP
*a
)
5943 static bool trans_MSR_imm(DisasContext
*s
, arg_MSR_imm
*a
)
5945 uint32_t val
= ror32(a
->imm
, a
->rot
* 2);
5946 uint32_t mask
= msr_mask(s
, a
->mask
, a
->r
);
5948 if (gen_set_psr_im(s
, mask
, a
->r
, val
)) {
5949 unallocated_encoding(s
);
5955 * Cyclic Redundancy Check
5958 static bool op_crc32(DisasContext
*s
, arg_rrr
*a
, bool c
, MemOp sz
)
5960 TCGv_i32 t1
, t2
, t3
;
5962 if (!dc_isar_feature(aa32_crc32
, s
)) {
5966 t1
= load_reg(s
, a
->rn
);
5967 t2
= load_reg(s
, a
->rm
);
5978 g_assert_not_reached();
5980 t3
= tcg_const_i32(1 << sz
);
5982 gen_helper_crc32c(t1
, t1
, t2
, t3
);
5984 gen_helper_crc32(t1
, t1
, t2
, t3
);
5986 tcg_temp_free_i32(t2
);
5987 tcg_temp_free_i32(t3
);
5988 store_reg(s
, a
->rd
, t1
);
5992 #define DO_CRC32(NAME, c, sz) \
5993 static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
5994 { return op_crc32(s, a, c, sz); }
5996 DO_CRC32(CRC32B
, false, MO_8
)
5997 DO_CRC32(CRC32H
, false, MO_16
)
5998 DO_CRC32(CRC32W
, false, MO_32
)
5999 DO_CRC32(CRC32CB
, true, MO_8
)
6000 DO_CRC32(CRC32CH
, true, MO_16
)
6001 DO_CRC32(CRC32CW
, true, MO_32
)
6006 * Miscellaneous instructions
6009 static bool trans_MRS_bank(DisasContext
*s
, arg_MRS_bank
*a
)
6011 if (arm_dc_feature(s
, ARM_FEATURE_M
)) {
6014 gen_mrs_banked(s
, a
->r
, a
->sysm
, a
->rd
);
6018 static bool trans_MSR_bank(DisasContext
*s
, arg_MSR_bank
*a
)
6020 if (arm_dc_feature(s
, ARM_FEATURE_M
)) {
6023 gen_msr_banked(s
, a
->r
, a
->sysm
, a
->rn
);
6027 static bool trans_MRS_reg(DisasContext
*s
, arg_MRS_reg
*a
)
6031 if (arm_dc_feature(s
, ARM_FEATURE_M
)) {
6036 unallocated_encoding(s
);
6039 tmp
= load_cpu_field(spsr
);
6041 tmp
= tcg_temp_new_i32();
6042 gen_helper_cpsr_read(tmp
, cpu_env
);
6044 store_reg(s
, a
->rd
, tmp
);
6048 static bool trans_MSR_reg(DisasContext
*s
, arg_MSR_reg
*a
)
6051 uint32_t mask
= msr_mask(s
, a
->mask
, a
->r
);
6053 if (arm_dc_feature(s
, ARM_FEATURE_M
)) {
6056 tmp
= load_reg(s
, a
->rn
);
6057 if (gen_set_psr(s
, mask
, a
->r
, tmp
)) {
6058 unallocated_encoding(s
);
6063 static bool trans_MRS_v7m(DisasContext
*s
, arg_MRS_v7m
*a
)
6067 if (!arm_dc_feature(s
, ARM_FEATURE_M
)) {
6070 tmp
= tcg_const_i32(a
->sysm
);
6071 gen_helper_v7m_mrs(tmp
, cpu_env
, tmp
);
6072 store_reg(s
, a
->rd
, tmp
);
6076 static bool trans_MSR_v7m(DisasContext
*s
, arg_MSR_v7m
*a
)
6080 if (!arm_dc_feature(s
, ARM_FEATURE_M
)) {
6083 addr
= tcg_const_i32((a
->mask
<< 10) | a
->sysm
);
6084 reg
= load_reg(s
, a
->rn
);
6085 gen_helper_v7m_msr(cpu_env
, addr
, reg
);
6086 tcg_temp_free_i32(addr
);
6087 tcg_temp_free_i32(reg
);
6088 /* If we wrote to CONTROL, the EL might have changed */
6089 gen_helper_rebuild_hflags_m32_newel(cpu_env
);
6094 static bool trans_BX(DisasContext
*s
, arg_BX
*a
)
6096 if (!ENABLE_ARCH_4T
) {
6099 gen_bx_excret(s
, load_reg(s
, a
->rm
));
6103 static bool trans_BXJ(DisasContext
*s
, arg_BXJ
*a
)
6105 if (!ENABLE_ARCH_5J
|| arm_dc_feature(s
, ARM_FEATURE_M
)) {
6108 /* Trivial implementation equivalent to bx. */
6109 gen_bx(s
, load_reg(s
, a
->rm
));
6113 static bool trans_BLX_r(DisasContext
*s
, arg_BLX_r
*a
)
6117 if (!ENABLE_ARCH_5
) {
6120 tmp
= load_reg(s
, a
->rm
);
6121 tcg_gen_movi_i32(cpu_R
[14], s
->base
.pc_next
| s
->thumb
);
6127 * BXNS/BLXNS: only exist for v8M with the security extensions,
6128 * and always UNDEF if NonSecure. We don't implement these in
6129 * the user-only mode either (in theory you can use them from
6130 * Secure User mode but they are too tied in to system emulation).
6132 static bool trans_BXNS(DisasContext
*s
, arg_BXNS
*a
)
6134 if (!s
->v8m_secure
|| IS_USER_ONLY
) {
6135 unallocated_encoding(s
);
6142 static bool trans_BLXNS(DisasContext
*s
, arg_BLXNS
*a
)
6144 if (!s
->v8m_secure
|| IS_USER_ONLY
) {
6145 unallocated_encoding(s
);
6147 gen_blxns(s
, a
->rm
);
6152 static bool trans_CLZ(DisasContext
*s
, arg_CLZ
*a
)
6156 if (!ENABLE_ARCH_5
) {
6159 tmp
= load_reg(s
, a
->rm
);
6160 tcg_gen_clzi_i32(tmp
, tmp
, 32);
6161 store_reg(s
, a
->rd
, tmp
);
6165 static bool trans_ERET(DisasContext
*s
, arg_ERET
*a
)
6169 if (!arm_dc_feature(s
, ARM_FEATURE_V7VE
)) {
6173 unallocated_encoding(s
);
6176 if (s
->current_el
== 2) {
6177 /* ERET from Hyp uses ELR_Hyp, not LR */
6178 tmp
= load_cpu_field(elr_el
[2]);
6180 tmp
= load_reg(s
, 14);
6182 gen_exception_return(s
, tmp
);
6186 static bool trans_HLT(DisasContext
*s
, arg_HLT
*a
)
6192 static bool trans_BKPT(DisasContext
*s
, arg_BKPT
*a
)
6194 if (!ENABLE_ARCH_5
) {
6197 if (arm_dc_feature(s
, ARM_FEATURE_M
) &&
6198 semihosting_enabled() &&
6199 #ifndef CONFIG_USER_ONLY
6203 gen_exception_internal_insn(s
, s
->pc_curr
, EXCP_SEMIHOST
);
6205 gen_exception_bkpt_insn(s
, syn_aa32_bkpt(a
->imm
, false));
6210 static bool trans_HVC(DisasContext
*s
, arg_HVC
*a
)
6212 if (!ENABLE_ARCH_7
|| arm_dc_feature(s
, ARM_FEATURE_M
)) {
6216 unallocated_encoding(s
);
6223 static bool trans_SMC(DisasContext
*s
, arg_SMC
*a
)
6225 if (!ENABLE_ARCH_6K
|| arm_dc_feature(s
, ARM_FEATURE_M
)) {
6229 unallocated_encoding(s
);
6236 static bool trans_SG(DisasContext
*s
, arg_SG
*a
)
6238 if (!arm_dc_feature(s
, ARM_FEATURE_M
) ||
6239 !arm_dc_feature(s
, ARM_FEATURE_V8
)) {
6244 * The bulk of the behaviour for this instruction is implemented
6245 * in v7m_handle_execute_nsc(), which deals with the insn when
6246 * it is executed by a CPU in non-secure state from memory
6247 * which is Secure & NonSecure-Callable.
6248 * Here we only need to handle the remaining cases:
6249 * * in NS memory (including the "security extension not
6250 * implemented" case) : NOP
6251 * * in S memory but CPU already secure (clear IT bits)
6252 * We know that the attribute for the memory this insn is
6253 * in must match the current CPU state, because otherwise
6254 * get_phys_addr_pmsav8 would have generated an exception.
6256 if (s
->v8m_secure
) {
6257 /* Like the IT insn, we don't need to generate any code */
6258 s
->condexec_cond
= 0;
6259 s
->condexec_mask
= 0;
6264 static bool trans_TT(DisasContext
*s
, arg_TT
*a
)
6268 if (!arm_dc_feature(s
, ARM_FEATURE_M
) ||
6269 !arm_dc_feature(s
, ARM_FEATURE_V8
)) {
6272 if (a
->rd
== 13 || a
->rd
== 15 || a
->rn
== 15) {
6273 /* We UNDEF for these UNPREDICTABLE cases */
6274 unallocated_encoding(s
);
6277 if (a
->A
&& !s
->v8m_secure
) {
6278 /* This case is UNDEFINED. */
6279 unallocated_encoding(s
);
6283 addr
= load_reg(s
, a
->rn
);
6284 tmp
= tcg_const_i32((a
->A
<< 1) | a
->T
);
6285 gen_helper_v7m_tt(tmp
, cpu_env
, addr
, tmp
);
6286 tcg_temp_free_i32(addr
);
6287 store_reg(s
, a
->rd
, tmp
);
6292 * Load/store register index
6295 static ISSInfo
make_issinfo(DisasContext
*s
, int rd
, bool p
, bool w
)
6299 /* ISS not valid if writeback */
6302 if (s
->base
.pc_next
- s
->pc_curr
== 2) {
6311 static TCGv_i32
op_addr_rr_pre(DisasContext
*s
, arg_ldst_rr
*a
)
6313 TCGv_i32 addr
= load_reg(s
, a
->rn
);
6315 if (s
->v8m_stackcheck
&& a
->rn
== 13 && a
->w
) {
6316 gen_helper_v8m_stackcheck(cpu_env
, addr
);
6320 TCGv_i32 ofs
= load_reg(s
, a
->rm
);
6321 gen_arm_shift_im(ofs
, a
->shtype
, a
->shimm
, 0);
6323 tcg_gen_add_i32(addr
, addr
, ofs
);
6325 tcg_gen_sub_i32(addr
, addr
, ofs
);
6327 tcg_temp_free_i32(ofs
);
6332 static void op_addr_rr_post(DisasContext
*s
, arg_ldst_rr
*a
,
6333 TCGv_i32 addr
, int address_offset
)
6336 TCGv_i32 ofs
= load_reg(s
, a
->rm
);
6337 gen_arm_shift_im(ofs
, a
->shtype
, a
->shimm
, 0);
6339 tcg_gen_add_i32(addr
, addr
, ofs
);
6341 tcg_gen_sub_i32(addr
, addr
, ofs
);
6343 tcg_temp_free_i32(ofs
);
6345 tcg_temp_free_i32(addr
);
6348 tcg_gen_addi_i32(addr
, addr
, address_offset
);
6349 store_reg(s
, a
->rn
, addr
);
6352 static bool op_load_rr(DisasContext
*s
, arg_ldst_rr
*a
,
6353 MemOp mop
, int mem_idx
)
6355 ISSInfo issinfo
= make_issinfo(s
, a
->rt
, a
->p
, a
->w
);
6358 addr
= op_addr_rr_pre(s
, a
);
6360 tmp
= tcg_temp_new_i32();
6361 gen_aa32_ld_i32(s
, tmp
, addr
, mem_idx
, mop
| s
->be_data
);
6362 disas_set_da_iss(s
, mop
, issinfo
);
6365 * Perform base writeback before the loaded value to
6366 * ensure correct behavior with overlapping index registers.
6368 op_addr_rr_post(s
, a
, addr
, 0);
6369 store_reg_from_load(s
, a
->rt
, tmp
);
6373 static bool op_store_rr(DisasContext
*s
, arg_ldst_rr
*a
,
6374 MemOp mop
, int mem_idx
)
6376 ISSInfo issinfo
= make_issinfo(s
, a
->rt
, a
->p
, a
->w
) | ISSIsWrite
;
6379 addr
= op_addr_rr_pre(s
, a
);
6381 tmp
= load_reg(s
, a
->rt
);
6382 gen_aa32_st_i32(s
, tmp
, addr
, mem_idx
, mop
| s
->be_data
);
6383 disas_set_da_iss(s
, mop
, issinfo
);
6384 tcg_temp_free_i32(tmp
);
6386 op_addr_rr_post(s
, a
, addr
, 0);
6390 static bool trans_LDRD_rr(DisasContext
*s
, arg_ldst_rr
*a
)
6392 int mem_idx
= get_mem_index(s
);
6395 if (!ENABLE_ARCH_5TE
) {
6399 unallocated_encoding(s
);
6402 addr
= op_addr_rr_pre(s
, a
);
6404 tmp
= tcg_temp_new_i32();
6405 gen_aa32_ld_i32(s
, tmp
, addr
, mem_idx
, MO_UL
| s
->be_data
);
6406 store_reg(s
, a
->rt
, tmp
);
6408 tcg_gen_addi_i32(addr
, addr
, 4);
6410 tmp
= tcg_temp_new_i32();
6411 gen_aa32_ld_i32(s
, tmp
, addr
, mem_idx
, MO_UL
| s
->be_data
);
6412 store_reg(s
, a
->rt
+ 1, tmp
);
6414 /* LDRD w/ base writeback is undefined if the registers overlap. */
6415 op_addr_rr_post(s
, a
, addr
, -4);
6419 static bool trans_STRD_rr(DisasContext
*s
, arg_ldst_rr
*a
)
6421 int mem_idx
= get_mem_index(s
);
6424 if (!ENABLE_ARCH_5TE
) {
6428 unallocated_encoding(s
);
6431 addr
= op_addr_rr_pre(s
, a
);
6433 tmp
= load_reg(s
, a
->rt
);
6434 gen_aa32_st_i32(s
, tmp
, addr
, mem_idx
, MO_UL
| s
->be_data
);
6435 tcg_temp_free_i32(tmp
);
6437 tcg_gen_addi_i32(addr
, addr
, 4);
6439 tmp
= load_reg(s
, a
->rt
+ 1);
6440 gen_aa32_st_i32(s
, tmp
, addr
, mem_idx
, MO_UL
| s
->be_data
);
6441 tcg_temp_free_i32(tmp
);
6443 op_addr_rr_post(s
, a
, addr
, -4);
6448 * Load/store immediate index
6451 static TCGv_i32
op_addr_ri_pre(DisasContext
*s
, arg_ldst_ri
*a
)
6459 if (s
->v8m_stackcheck
&& a
->rn
== 13 && a
->w
) {
6461 * Stackcheck. Here we know 'addr' is the current SP;
6462 * U is set if we're moving SP up, else down. It is
6463 * UNKNOWN whether the limit check triggers when SP starts
6464 * below the limit and ends up above it; we chose to do so.
6467 TCGv_i32 newsp
= tcg_temp_new_i32();
6468 tcg_gen_addi_i32(newsp
, cpu_R
[13], ofs
);
6469 gen_helper_v8m_stackcheck(cpu_env
, newsp
);
6470 tcg_temp_free_i32(newsp
);
6472 gen_helper_v8m_stackcheck(cpu_env
, cpu_R
[13]);
6476 return add_reg_for_lit(s
, a
->rn
, a
->p
? ofs
: 0);
6479 static void op_addr_ri_post(DisasContext
*s
, arg_ldst_ri
*a
,
6480 TCGv_i32 addr
, int address_offset
)
6484 address_offset
+= a
->imm
;
6486 address_offset
-= a
->imm
;
6489 tcg_temp_free_i32(addr
);
6492 tcg_gen_addi_i32(addr
, addr
, address_offset
);
6493 store_reg(s
, a
->rn
, addr
);
6496 static bool op_load_ri(DisasContext
*s
, arg_ldst_ri
*a
,
6497 MemOp mop
, int mem_idx
)
6499 ISSInfo issinfo
= make_issinfo(s
, a
->rt
, a
->p
, a
->w
);
6502 addr
= op_addr_ri_pre(s
, a
);
6504 tmp
= tcg_temp_new_i32();
6505 gen_aa32_ld_i32(s
, tmp
, addr
, mem_idx
, mop
| s
->be_data
);
6506 disas_set_da_iss(s
, mop
, issinfo
);
6509 * Perform base writeback before the loaded value to
6510 * ensure correct behavior with overlapping index registers.
6512 op_addr_ri_post(s
, a
, addr
, 0);
6513 store_reg_from_load(s
, a
->rt
, tmp
);
6517 static bool op_store_ri(DisasContext
*s
, arg_ldst_ri
*a
,
6518 MemOp mop
, int mem_idx
)
6520 ISSInfo issinfo
= make_issinfo(s
, a
->rt
, a
->p
, a
->w
) | ISSIsWrite
;
6523 addr
= op_addr_ri_pre(s
, a
);
6525 tmp
= load_reg(s
, a
->rt
);
6526 gen_aa32_st_i32(s
, tmp
, addr
, mem_idx
, mop
| s
->be_data
);
6527 disas_set_da_iss(s
, mop
, issinfo
);
6528 tcg_temp_free_i32(tmp
);
6530 op_addr_ri_post(s
, a
, addr
, 0);
6534 static bool op_ldrd_ri(DisasContext
*s
, arg_ldst_ri
*a
, int rt2
)
6536 int mem_idx
= get_mem_index(s
);
6539 addr
= op_addr_ri_pre(s
, a
);
6541 tmp
= tcg_temp_new_i32();
6542 gen_aa32_ld_i32(s
, tmp
, addr
, mem_idx
, MO_UL
| s
->be_data
);
6543 store_reg(s
, a
->rt
, tmp
);
6545 tcg_gen_addi_i32(addr
, addr
, 4);
6547 tmp
= tcg_temp_new_i32();
6548 gen_aa32_ld_i32(s
, tmp
, addr
, mem_idx
, MO_UL
| s
->be_data
);
6549 store_reg(s
, rt2
, tmp
);
6551 /* LDRD w/ base writeback is undefined if the registers overlap. */
6552 op_addr_ri_post(s
, a
, addr
, -4);
6556 static bool trans_LDRD_ri_a32(DisasContext
*s
, arg_ldst_ri
*a
)
6558 if (!ENABLE_ARCH_5TE
|| (a
->rt
& 1)) {
6561 return op_ldrd_ri(s
, a
, a
->rt
+ 1);
6564 static bool trans_LDRD_ri_t32(DisasContext
*s
, arg_ldst_ri2
*a
)
6567 .u
= a
->u
, .w
= a
->w
, .p
= a
->p
,
6568 .rn
= a
->rn
, .rt
= a
->rt
, .imm
= a
->imm
6570 return op_ldrd_ri(s
, &b
, a
->rt2
);
6573 static bool op_strd_ri(DisasContext
*s
, arg_ldst_ri
*a
, int rt2
)
6575 int mem_idx
= get_mem_index(s
);
6578 addr
= op_addr_ri_pre(s
, a
);
6580 tmp
= load_reg(s
, a
->rt
);
6581 gen_aa32_st_i32(s
, tmp
, addr
, mem_idx
, MO_UL
| s
->be_data
);
6582 tcg_temp_free_i32(tmp
);
6584 tcg_gen_addi_i32(addr
, addr
, 4);
6586 tmp
= load_reg(s
, rt2
);
6587 gen_aa32_st_i32(s
, tmp
, addr
, mem_idx
, MO_UL
| s
->be_data
);
6588 tcg_temp_free_i32(tmp
);
6590 op_addr_ri_post(s
, a
, addr
, -4);
6594 static bool trans_STRD_ri_a32(DisasContext
*s
, arg_ldst_ri
*a
)
6596 if (!ENABLE_ARCH_5TE
|| (a
->rt
& 1)) {
6599 return op_strd_ri(s
, a
, a
->rt
+ 1);
6602 static bool trans_STRD_ri_t32(DisasContext
*s
, arg_ldst_ri2
*a
)
6605 .u
= a
->u
, .w
= a
->w
, .p
= a
->p
,
6606 .rn
= a
->rn
, .rt
= a
->rt
, .imm
= a
->imm
6608 return op_strd_ri(s
, &b
, a
->rt2
);
6611 #define DO_LDST(NAME, WHICH, MEMOP) \
6612 static bool trans_##NAME##_ri(DisasContext *s, arg_ldst_ri *a) \
6614 return op_##WHICH##_ri(s, a, MEMOP, get_mem_index(s)); \
6616 static bool trans_##NAME##T_ri(DisasContext *s, arg_ldst_ri *a) \
6618 return op_##WHICH##_ri(s, a, MEMOP, get_a32_user_mem_index(s)); \
6620 static bool trans_##NAME##_rr(DisasContext *s, arg_ldst_rr *a) \
6622 return op_##WHICH##_rr(s, a, MEMOP, get_mem_index(s)); \
6624 static bool trans_##NAME##T_rr(DisasContext *s, arg_ldst_rr *a) \
6626 return op_##WHICH##_rr(s, a, MEMOP, get_a32_user_mem_index(s)); \
6629 DO_LDST(LDR
, load
, MO_UL
)
6630 DO_LDST(LDRB
, load
, MO_UB
)
6631 DO_LDST(LDRH
, load
, MO_UW
)
6632 DO_LDST(LDRSB
, load
, MO_SB
)
6633 DO_LDST(LDRSH
, load
, MO_SW
)
6635 DO_LDST(STR
, store
, MO_UL
)
6636 DO_LDST(STRB
, store
, MO_UB
)
6637 DO_LDST(STRH
, store
, MO_UW
)
6642 * Synchronization primitives
6645 static bool op_swp(DisasContext
*s
, arg_SWP
*a
, MemOp opc
)
6651 addr
= load_reg(s
, a
->rn
);
6652 taddr
= gen_aa32_addr(s
, addr
, opc
);
6653 tcg_temp_free_i32(addr
);
6655 tmp
= load_reg(s
, a
->rt2
);
6656 tcg_gen_atomic_xchg_i32(tmp
, taddr
, tmp
, get_mem_index(s
), opc
);
6657 tcg_temp_free(taddr
);
6659 store_reg(s
, a
->rt
, tmp
);
6663 static bool trans_SWP(DisasContext
*s
, arg_SWP
*a
)
6665 return op_swp(s
, a
, MO_UL
| MO_ALIGN
);
6668 static bool trans_SWPB(DisasContext
*s
, arg_SWP
*a
)
6670 return op_swp(s
, a
, MO_UB
);
6674 * Load/Store Exclusive and Load-Acquire/Store-Release
6677 static bool op_strex(DisasContext
*s
, arg_STREX
*a
, MemOp mop
, bool rel
)
6680 /* Some cases stopped being UNPREDICTABLE in v8A (but not v8M) */
6681 bool v8a
= ENABLE_ARCH_8
&& !arm_dc_feature(s
, ARM_FEATURE_M
);
6683 /* We UNDEF for these UNPREDICTABLE cases. */
6684 if (a
->rd
== 15 || a
->rn
== 15 || a
->rt
== 15
6685 || a
->rd
== a
->rn
|| a
->rd
== a
->rt
6686 || (!v8a
&& s
->thumb
&& (a
->rd
== 13 || a
->rt
== 13))
6690 || (!v8a
&& s
->thumb
&& a
->rt2
== 13)))) {
6691 unallocated_encoding(s
);
6696 tcg_gen_mb(TCG_MO_ALL
| TCG_BAR_STRL
);
6699 addr
= tcg_temp_local_new_i32();
6700 load_reg_var(s
, addr
, a
->rn
);
6701 tcg_gen_addi_i32(addr
, addr
, a
->imm
);
6703 gen_store_exclusive(s
, a
->rd
, a
->rt
, a
->rt2
, addr
, mop
);
6704 tcg_temp_free_i32(addr
);
6708 static bool trans_STREX(DisasContext
*s
, arg_STREX
*a
)
6710 if (!ENABLE_ARCH_6
) {
6713 return op_strex(s
, a
, MO_32
, false);
6716 static bool trans_STREXD_a32(DisasContext
*s
, arg_STREX
*a
)
6718 if (!ENABLE_ARCH_6K
) {
6721 /* We UNDEF for these UNPREDICTABLE cases. */
6723 unallocated_encoding(s
);
6727 return op_strex(s
, a
, MO_64
, false);
6730 static bool trans_STREXD_t32(DisasContext
*s
, arg_STREX
*a
)
6732 return op_strex(s
, a
, MO_64
, false);
6735 static bool trans_STREXB(DisasContext
*s
, arg_STREX
*a
)
6737 if (s
->thumb
? !ENABLE_ARCH_7
: !ENABLE_ARCH_6K
) {
6740 return op_strex(s
, a
, MO_8
, false);
6743 static bool trans_STREXH(DisasContext
*s
, arg_STREX
*a
)
6745 if (s
->thumb
? !ENABLE_ARCH_7
: !ENABLE_ARCH_6K
) {
6748 return op_strex(s
, a
, MO_16
, false);
6751 static bool trans_STLEX(DisasContext
*s
, arg_STREX
*a
)
6753 if (!ENABLE_ARCH_8
) {
6756 return op_strex(s
, a
, MO_32
, true);
6759 static bool trans_STLEXD_a32(DisasContext
*s
, arg_STREX
*a
)
6761 if (!ENABLE_ARCH_8
) {
6764 /* We UNDEF for these UNPREDICTABLE cases. */
6766 unallocated_encoding(s
);
6770 return op_strex(s
, a
, MO_64
, true);
6773 static bool trans_STLEXD_t32(DisasContext
*s
, arg_STREX
*a
)
6775 if (!ENABLE_ARCH_8
) {
6778 return op_strex(s
, a
, MO_64
, true);
6781 static bool trans_STLEXB(DisasContext
*s
, arg_STREX
*a
)
6783 if (!ENABLE_ARCH_8
) {
6786 return op_strex(s
, a
, MO_8
, true);
6789 static bool trans_STLEXH(DisasContext
*s
, arg_STREX
*a
)
6791 if (!ENABLE_ARCH_8
) {
6794 return op_strex(s
, a
, MO_16
, true);
6797 static bool op_stl(DisasContext
*s
, arg_STL
*a
, MemOp mop
)
6801 if (!ENABLE_ARCH_8
) {
6804 /* We UNDEF for these UNPREDICTABLE cases. */
6805 if (a
->rn
== 15 || a
->rt
== 15) {
6806 unallocated_encoding(s
);
6810 addr
= load_reg(s
, a
->rn
);
6811 tmp
= load_reg(s
, a
->rt
);
6812 tcg_gen_mb(TCG_MO_ALL
| TCG_BAR_STRL
);
6813 gen_aa32_st_i32(s
, tmp
, addr
, get_mem_index(s
), mop
| s
->be_data
);
6814 disas_set_da_iss(s
, mop
, a
->rt
| ISSIsAcqRel
| ISSIsWrite
);
6816 tcg_temp_free_i32(tmp
);
6817 tcg_temp_free_i32(addr
);
6821 static bool trans_STL(DisasContext
*s
, arg_STL
*a
)
6823 return op_stl(s
, a
, MO_UL
);
6826 static bool trans_STLB(DisasContext
*s
, arg_STL
*a
)
6828 return op_stl(s
, a
, MO_UB
);
6831 static bool trans_STLH(DisasContext
*s
, arg_STL
*a
)
6833 return op_stl(s
, a
, MO_UW
);
6836 static bool op_ldrex(DisasContext
*s
, arg_LDREX
*a
, MemOp mop
, bool acq
)
6839 /* Some cases stopped being UNPREDICTABLE in v8A (but not v8M) */
6840 bool v8a
= ENABLE_ARCH_8
&& !arm_dc_feature(s
, ARM_FEATURE_M
);
6842 /* We UNDEF for these UNPREDICTABLE cases. */
6843 if (a
->rn
== 15 || a
->rt
== 15
6844 || (!v8a
&& s
->thumb
&& a
->rt
== 13)
6846 && (a
->rt2
== 15 || a
->rt
== a
->rt2
6847 || (!v8a
&& s
->thumb
&& a
->rt2
== 13)))) {
6848 unallocated_encoding(s
);
6852 addr
= tcg_temp_local_new_i32();
6853 load_reg_var(s
, addr
, a
->rn
);
6854 tcg_gen_addi_i32(addr
, addr
, a
->imm
);
6856 gen_load_exclusive(s
, a
->rt
, a
->rt2
, addr
, mop
);
6857 tcg_temp_free_i32(addr
);
6860 tcg_gen_mb(TCG_MO_ALL
| TCG_BAR_LDAQ
);
6865 static bool trans_LDREX(DisasContext
*s
, arg_LDREX
*a
)
6867 if (!ENABLE_ARCH_6
) {
6870 return op_ldrex(s
, a
, MO_32
, false);
6873 static bool trans_LDREXD_a32(DisasContext
*s
, arg_LDREX
*a
)
6875 if (!ENABLE_ARCH_6K
) {
6878 /* We UNDEF for these UNPREDICTABLE cases. */
6880 unallocated_encoding(s
);
6884 return op_ldrex(s
, a
, MO_64
, false);
6887 static bool trans_LDREXD_t32(DisasContext
*s
, arg_LDREX
*a
)
6889 return op_ldrex(s
, a
, MO_64
, false);
6892 static bool trans_LDREXB(DisasContext
*s
, arg_LDREX
*a
)
6894 if (s
->thumb
? !ENABLE_ARCH_7
: !ENABLE_ARCH_6K
) {
6897 return op_ldrex(s
, a
, MO_8
, false);
6900 static bool trans_LDREXH(DisasContext
*s
, arg_LDREX
*a
)
6902 if (s
->thumb
? !ENABLE_ARCH_7
: !ENABLE_ARCH_6K
) {
6905 return op_ldrex(s
, a
, MO_16
, false);
6908 static bool trans_LDAEX(DisasContext
*s
, arg_LDREX
*a
)
6910 if (!ENABLE_ARCH_8
) {
6913 return op_ldrex(s
, a
, MO_32
, true);
6916 static bool trans_LDAEXD_a32(DisasContext
*s
, arg_LDREX
*a
)
6918 if (!ENABLE_ARCH_8
) {
6921 /* We UNDEF for these UNPREDICTABLE cases. */
6923 unallocated_encoding(s
);
6927 return op_ldrex(s
, a
, MO_64
, true);
6930 static bool trans_LDAEXD_t32(DisasContext
*s
, arg_LDREX
*a
)
6932 if (!ENABLE_ARCH_8
) {
6935 return op_ldrex(s
, a
, MO_64
, true);
6938 static bool trans_LDAEXB(DisasContext
*s
, arg_LDREX
*a
)
6940 if (!ENABLE_ARCH_8
) {
6943 return op_ldrex(s
, a
, MO_8
, true);
6946 static bool trans_LDAEXH(DisasContext
*s
, arg_LDREX
*a
)
6948 if (!ENABLE_ARCH_8
) {
6951 return op_ldrex(s
, a
, MO_16
, true);
6954 static bool op_lda(DisasContext
*s
, arg_LDA
*a
, MemOp mop
)
6958 if (!ENABLE_ARCH_8
) {
6961 /* We UNDEF for these UNPREDICTABLE cases. */
6962 if (a
->rn
== 15 || a
->rt
== 15) {
6963 unallocated_encoding(s
);
6967 addr
= load_reg(s
, a
->rn
);
6968 tmp
= tcg_temp_new_i32();
6969 gen_aa32_ld_i32(s
, tmp
, addr
, get_mem_index(s
), mop
| s
->be_data
);
6970 disas_set_da_iss(s
, mop
, a
->rt
| ISSIsAcqRel
);
6971 tcg_temp_free_i32(addr
);
6973 store_reg(s
, a
->rt
, tmp
);
6974 tcg_gen_mb(TCG_MO_ALL
| TCG_BAR_STRL
);
6978 static bool trans_LDA(DisasContext
*s
, arg_LDA
*a
)
6980 return op_lda(s
, a
, MO_UL
);
6983 static bool trans_LDAB(DisasContext
*s
, arg_LDA
*a
)
6985 return op_lda(s
, a
, MO_UB
);
6988 static bool trans_LDAH(DisasContext
*s
, arg_LDA
*a
)
6990 return op_lda(s
, a
, MO_UW
);
6994 * Media instructions
6997 static bool trans_USADA8(DisasContext
*s
, arg_USADA8
*a
)
7001 if (!ENABLE_ARCH_6
) {
7005 t1
= load_reg(s
, a
->rn
);
7006 t2
= load_reg(s
, a
->rm
);
7007 gen_helper_usad8(t1
, t1
, t2
);
7008 tcg_temp_free_i32(t2
);
7010 t2
= load_reg(s
, a
->ra
);
7011 tcg_gen_add_i32(t1
, t1
, t2
);
7012 tcg_temp_free_i32(t2
);
7014 store_reg(s
, a
->rd
, t1
);
7018 static bool op_bfx(DisasContext
*s
, arg_UBFX
*a
, bool u
)
7021 int width
= a
->widthm1
+ 1;
7024 if (!ENABLE_ARCH_6T2
) {
7027 if (shift
+ width
> 32) {
7028 /* UNPREDICTABLE; we choose to UNDEF */
7029 unallocated_encoding(s
);
7033 tmp
= load_reg(s
, a
->rn
);
7035 tcg_gen_extract_i32(tmp
, tmp
, shift
, width
);
7037 tcg_gen_sextract_i32(tmp
, tmp
, shift
, width
);
7039 store_reg(s
, a
->rd
, tmp
);
7043 static bool trans_SBFX(DisasContext
*s
, arg_SBFX
*a
)
7045 return op_bfx(s
, a
, false);
7048 static bool trans_UBFX(DisasContext
*s
, arg_UBFX
*a
)
7050 return op_bfx(s
, a
, true);
7053 static bool trans_BFCI(DisasContext
*s
, arg_BFCI
*a
)
7056 int msb
= a
->msb
, lsb
= a
->lsb
;
7059 if (!ENABLE_ARCH_6T2
) {
7063 /* UNPREDICTABLE; we choose to UNDEF */
7064 unallocated_encoding(s
);
7068 width
= msb
+ 1 - lsb
;
7071 tmp
= tcg_const_i32(0);
7074 tmp
= load_reg(s
, a
->rn
);
7077 TCGv_i32 tmp2
= load_reg(s
, a
->rd
);
7078 tcg_gen_deposit_i32(tmp
, tmp2
, tmp
, lsb
, width
);
7079 tcg_temp_free_i32(tmp2
);
7081 store_reg(s
, a
->rd
, tmp
);
7085 static bool trans_UDF(DisasContext
*s
, arg_UDF
*a
)
7087 unallocated_encoding(s
);
7092 * Parallel addition and subtraction
7095 static bool op_par_addsub(DisasContext
*s
, arg_rrr
*a
,
7096 void (*gen
)(TCGv_i32
, TCGv_i32
, TCGv_i32
))
7101 ? !arm_dc_feature(s
, ARM_FEATURE_THUMB_DSP
)
7106 t0
= load_reg(s
, a
->rn
);
7107 t1
= load_reg(s
, a
->rm
);
7111 tcg_temp_free_i32(t1
);
7112 store_reg(s
, a
->rd
, t0
);
7116 static bool op_par_addsub_ge(DisasContext
*s
, arg_rrr
*a
,
7117 void (*gen
)(TCGv_i32
, TCGv_i32
,
7118 TCGv_i32
, TCGv_ptr
))
7124 ? !arm_dc_feature(s
, ARM_FEATURE_THUMB_DSP
)
7129 t0
= load_reg(s
, a
->rn
);
7130 t1
= load_reg(s
, a
->rm
);
7132 ge
= tcg_temp_new_ptr();
7133 tcg_gen_addi_ptr(ge
, cpu_env
, offsetof(CPUARMState
, GE
));
7134 gen(t0
, t0
, t1
, ge
);
7136 tcg_temp_free_ptr(ge
);
7137 tcg_temp_free_i32(t1
);
7138 store_reg(s
, a
->rd
, t0
);
7142 #define DO_PAR_ADDSUB(NAME, helper) \
7143 static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
7145 return op_par_addsub(s, a, helper); \
7148 #define DO_PAR_ADDSUB_GE(NAME, helper) \
7149 static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
7151 return op_par_addsub_ge(s, a, helper); \
7154 DO_PAR_ADDSUB_GE(SADD16
, gen_helper_sadd16
)
7155 DO_PAR_ADDSUB_GE(SASX
, gen_helper_saddsubx
)
7156 DO_PAR_ADDSUB_GE(SSAX
, gen_helper_ssubaddx
)
7157 DO_PAR_ADDSUB_GE(SSUB16
, gen_helper_ssub16
)
7158 DO_PAR_ADDSUB_GE(SADD8
, gen_helper_sadd8
)
7159 DO_PAR_ADDSUB_GE(SSUB8
, gen_helper_ssub8
)
7161 DO_PAR_ADDSUB_GE(UADD16
, gen_helper_uadd16
)
7162 DO_PAR_ADDSUB_GE(UASX
, gen_helper_uaddsubx
)
7163 DO_PAR_ADDSUB_GE(USAX
, gen_helper_usubaddx
)
7164 DO_PAR_ADDSUB_GE(USUB16
, gen_helper_usub16
)
7165 DO_PAR_ADDSUB_GE(UADD8
, gen_helper_uadd8
)
7166 DO_PAR_ADDSUB_GE(USUB8
, gen_helper_usub8
)
7168 DO_PAR_ADDSUB(QADD16
, gen_helper_qadd16
)
7169 DO_PAR_ADDSUB(QASX
, gen_helper_qaddsubx
)
7170 DO_PAR_ADDSUB(QSAX
, gen_helper_qsubaddx
)
7171 DO_PAR_ADDSUB(QSUB16
, gen_helper_qsub16
)
7172 DO_PAR_ADDSUB(QADD8
, gen_helper_qadd8
)
7173 DO_PAR_ADDSUB(QSUB8
, gen_helper_qsub8
)
7175 DO_PAR_ADDSUB(UQADD16
, gen_helper_uqadd16
)
7176 DO_PAR_ADDSUB(UQASX
, gen_helper_uqaddsubx
)
7177 DO_PAR_ADDSUB(UQSAX
, gen_helper_uqsubaddx
)
7178 DO_PAR_ADDSUB(UQSUB16
, gen_helper_uqsub16
)
7179 DO_PAR_ADDSUB(UQADD8
, gen_helper_uqadd8
)
7180 DO_PAR_ADDSUB(UQSUB8
, gen_helper_uqsub8
)
7182 DO_PAR_ADDSUB(SHADD16
, gen_helper_shadd16
)
7183 DO_PAR_ADDSUB(SHASX
, gen_helper_shaddsubx
)
7184 DO_PAR_ADDSUB(SHSAX
, gen_helper_shsubaddx
)
7185 DO_PAR_ADDSUB(SHSUB16
, gen_helper_shsub16
)
7186 DO_PAR_ADDSUB(SHADD8
, gen_helper_shadd8
)
7187 DO_PAR_ADDSUB(SHSUB8
, gen_helper_shsub8
)
7189 DO_PAR_ADDSUB(UHADD16
, gen_helper_uhadd16
)
7190 DO_PAR_ADDSUB(UHASX
, gen_helper_uhaddsubx
)
7191 DO_PAR_ADDSUB(UHSAX
, gen_helper_uhsubaddx
)
7192 DO_PAR_ADDSUB(UHSUB16
, gen_helper_uhsub16
)
7193 DO_PAR_ADDSUB(UHADD8
, gen_helper_uhadd8
)
7194 DO_PAR_ADDSUB(UHSUB8
, gen_helper_uhsub8
)
7196 #undef DO_PAR_ADDSUB
7197 #undef DO_PAR_ADDSUB_GE
7200 * Packing, unpacking, saturation, and reversal
7203 static bool trans_PKH(DisasContext
*s
, arg_PKH
*a
)
7209 ? !arm_dc_feature(s
, ARM_FEATURE_THUMB_DSP
)
7214 tn
= load_reg(s
, a
->rn
);
7215 tm
= load_reg(s
, a
->rm
);
7221 tcg_gen_sari_i32(tm
, tm
, shift
);
7222 tcg_gen_deposit_i32(tn
, tn
, tm
, 0, 16);
7225 tcg_gen_shli_i32(tm
, tm
, shift
);
7226 tcg_gen_deposit_i32(tn
, tm
, tn
, 0, 16);
7228 tcg_temp_free_i32(tm
);
7229 store_reg(s
, a
->rd
, tn
);
7233 static bool op_sat(DisasContext
*s
, arg_sat
*a
,
7234 void (*gen
)(TCGv_i32
, TCGv_env
, TCGv_i32
, TCGv_i32
))
7236 TCGv_i32 tmp
, satimm
;
7239 if (!ENABLE_ARCH_6
) {
7243 tmp
= load_reg(s
, a
->rn
);
7245 tcg_gen_sari_i32(tmp
, tmp
, shift
? shift
: 31);
7247 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7250 satimm
= tcg_const_i32(a
->satimm
);
7251 gen(tmp
, cpu_env
, tmp
, satimm
);
7252 tcg_temp_free_i32(satimm
);
7254 store_reg(s
, a
->rd
, tmp
);
7258 static bool trans_SSAT(DisasContext
*s
, arg_sat
*a
)
7260 return op_sat(s
, a
, gen_helper_ssat
);
7263 static bool trans_USAT(DisasContext
*s
, arg_sat
*a
)
7265 return op_sat(s
, a
, gen_helper_usat
);
7268 static bool trans_SSAT16(DisasContext
*s
, arg_sat
*a
)
7270 if (s
->thumb
&& !arm_dc_feature(s
, ARM_FEATURE_THUMB_DSP
)) {
7273 return op_sat(s
, a
, gen_helper_ssat16
);
7276 static bool trans_USAT16(DisasContext
*s
, arg_sat
*a
)
7278 if (s
->thumb
&& !arm_dc_feature(s
, ARM_FEATURE_THUMB_DSP
)) {
7281 return op_sat(s
, a
, gen_helper_usat16
);
7284 static bool op_xta(DisasContext
*s
, arg_rrr_rot
*a
,
7285 void (*gen_extract
)(TCGv_i32
, TCGv_i32
),
7286 void (*gen_add
)(TCGv_i32
, TCGv_i32
, TCGv_i32
))
7290 if (!ENABLE_ARCH_6
) {
7294 tmp
= load_reg(s
, a
->rm
);
7296 * TODO: In many cases we could do a shift instead of a rotate.
7297 * Combined with a simple extend, that becomes an extract.
7299 tcg_gen_rotri_i32(tmp
, tmp
, a
->rot
* 8);
7300 gen_extract(tmp
, tmp
);
7303 TCGv_i32 tmp2
= load_reg(s
, a
->rn
);
7304 gen_add(tmp
, tmp
, tmp2
);
7305 tcg_temp_free_i32(tmp2
);
7307 store_reg(s
, a
->rd
, tmp
);
7311 static bool trans_SXTAB(DisasContext
*s
, arg_rrr_rot
*a
)
7313 return op_xta(s
, a
, tcg_gen_ext8s_i32
, tcg_gen_add_i32
);
7316 static bool trans_SXTAH(DisasContext
*s
, arg_rrr_rot
*a
)
7318 return op_xta(s
, a
, tcg_gen_ext16s_i32
, tcg_gen_add_i32
);
7321 static bool trans_SXTAB16(DisasContext
*s
, arg_rrr_rot
*a
)
7323 if (s
->thumb
&& !arm_dc_feature(s
, ARM_FEATURE_THUMB_DSP
)) {
7326 return op_xta(s
, a
, gen_helper_sxtb16
, gen_add16
);
7329 static bool trans_UXTAB(DisasContext
*s
, arg_rrr_rot
*a
)
7331 return op_xta(s
, a
, tcg_gen_ext8u_i32
, tcg_gen_add_i32
);
7334 static bool trans_UXTAH(DisasContext
*s
, arg_rrr_rot
*a
)
7336 return op_xta(s
, a
, tcg_gen_ext16u_i32
, tcg_gen_add_i32
);
7339 static bool trans_UXTAB16(DisasContext
*s
, arg_rrr_rot
*a
)
7341 if (s
->thumb
&& !arm_dc_feature(s
, ARM_FEATURE_THUMB_DSP
)) {
7344 return op_xta(s
, a
, gen_helper_uxtb16
, gen_add16
);
7347 static bool trans_SEL(DisasContext
*s
, arg_rrr
*a
)
7349 TCGv_i32 t1
, t2
, t3
;
7352 ? !arm_dc_feature(s
, ARM_FEATURE_THUMB_DSP
)
7357 t1
= load_reg(s
, a
->rn
);
7358 t2
= load_reg(s
, a
->rm
);
7359 t3
= tcg_temp_new_i32();
7360 tcg_gen_ld_i32(t3
, cpu_env
, offsetof(CPUARMState
, GE
));
7361 gen_helper_sel_flags(t1
, t3
, t1
, t2
);
7362 tcg_temp_free_i32(t3
);
7363 tcg_temp_free_i32(t2
);
7364 store_reg(s
, a
->rd
, t1
);
7368 static bool op_rr(DisasContext
*s
, arg_rr
*a
,
7369 void (*gen
)(TCGv_i32
, TCGv_i32
))
7373 tmp
= load_reg(s
, a
->rm
);
7375 store_reg(s
, a
->rd
, tmp
);
7379 static bool trans_REV(DisasContext
*s
, arg_rr
*a
)
7381 if (!ENABLE_ARCH_6
) {
7384 return op_rr(s
, a
, tcg_gen_bswap32_i32
);
7387 static bool trans_REV16(DisasContext
*s
, arg_rr
*a
)
7389 if (!ENABLE_ARCH_6
) {
7392 return op_rr(s
, a
, gen_rev16
);
7395 static bool trans_REVSH(DisasContext
*s
, arg_rr
*a
)
7397 if (!ENABLE_ARCH_6
) {
7400 return op_rr(s
, a
, gen_revsh
);
7403 static bool trans_RBIT(DisasContext
*s
, arg_rr
*a
)
7405 if (!ENABLE_ARCH_6T2
) {
7408 return op_rr(s
, a
, gen_helper_rbit
);
7412 * Signed multiply, signed and unsigned divide
7415 static bool op_smlad(DisasContext
*s
, arg_rrrr
*a
, bool m_swap
, bool sub
)
7419 if (!ENABLE_ARCH_6
) {
7423 t1
= load_reg(s
, a
->rn
);
7424 t2
= load_reg(s
, a
->rm
);
7426 gen_swap_half(t2
, t2
);
7428 gen_smul_dual(t1
, t2
);
7431 /* This subtraction cannot overflow. */
7432 tcg_gen_sub_i32(t1
, t1
, t2
);
7435 * This addition cannot overflow 32 bits; however it may
7436 * overflow considered as a signed operation, in which case
7437 * we must set the Q flag.
7439 gen_helper_add_setq(t1
, cpu_env
, t1
, t2
);
7441 tcg_temp_free_i32(t2
);
7444 t2
= load_reg(s
, a
->ra
);
7445 gen_helper_add_setq(t1
, cpu_env
, t1
, t2
);
7446 tcg_temp_free_i32(t2
);
7448 store_reg(s
, a
->rd
, t1
);
7452 static bool trans_SMLAD(DisasContext
*s
, arg_rrrr
*a
)
7454 return op_smlad(s
, a
, false, false);
7457 static bool trans_SMLADX(DisasContext
*s
, arg_rrrr
*a
)
7459 return op_smlad(s
, a
, true, false);
7462 static bool trans_SMLSD(DisasContext
*s
, arg_rrrr
*a
)
7464 return op_smlad(s
, a
, false, true);
7467 static bool trans_SMLSDX(DisasContext
*s
, arg_rrrr
*a
)
7469 return op_smlad(s
, a
, true, true);
7472 static bool op_smlald(DisasContext
*s
, arg_rrrr
*a
, bool m_swap
, bool sub
)
7477 if (!ENABLE_ARCH_6
) {
7481 t1
= load_reg(s
, a
->rn
);
7482 t2
= load_reg(s
, a
->rm
);
7484 gen_swap_half(t2
, t2
);
7486 gen_smul_dual(t1
, t2
);
7488 l1
= tcg_temp_new_i64();
7489 l2
= tcg_temp_new_i64();
7490 tcg_gen_ext_i32_i64(l1
, t1
);
7491 tcg_gen_ext_i32_i64(l2
, t2
);
7492 tcg_temp_free_i32(t1
);
7493 tcg_temp_free_i32(t2
);
7496 tcg_gen_sub_i64(l1
, l1
, l2
);
7498 tcg_gen_add_i64(l1
, l1
, l2
);
7500 tcg_temp_free_i64(l2
);
7502 gen_addq(s
, l1
, a
->ra
, a
->rd
);
7503 gen_storeq_reg(s
, a
->ra
, a
->rd
, l1
);
7504 tcg_temp_free_i64(l1
);
7508 static bool trans_SMLALD(DisasContext
*s
, arg_rrrr
*a
)
7510 return op_smlald(s
, a
, false, false);
7513 static bool trans_SMLALDX(DisasContext
*s
, arg_rrrr
*a
)
7515 return op_smlald(s
, a
, true, false);
7518 static bool trans_SMLSLD(DisasContext
*s
, arg_rrrr
*a
)
7520 return op_smlald(s
, a
, false, true);
7523 static bool trans_SMLSLDX(DisasContext
*s
, arg_rrrr
*a
)
7525 return op_smlald(s
, a
, true, true);
7528 static bool op_smmla(DisasContext
*s
, arg_rrrr
*a
, bool round
, bool sub
)
7533 ? !arm_dc_feature(s
, ARM_FEATURE_THUMB_DSP
)
7538 t1
= load_reg(s
, a
->rn
);
7539 t2
= load_reg(s
, a
->rm
);
7540 tcg_gen_muls2_i32(t2
, t1
, t1
, t2
);
7543 TCGv_i32 t3
= load_reg(s
, a
->ra
);
7546 * For SMMLS, we need a 64-bit subtract. Borrow caused by
7547 * a non-zero multiplicand lowpart, and the correct result
7548 * lowpart for rounding.
7550 TCGv_i32 zero
= tcg_const_i32(0);
7551 tcg_gen_sub2_i32(t2
, t1
, zero
, t3
, t2
, t1
);
7552 tcg_temp_free_i32(zero
);
7554 tcg_gen_add_i32(t1
, t1
, t3
);
7556 tcg_temp_free_i32(t3
);
7560 * Adding 0x80000000 to the 64-bit quantity means that we have
7561 * carry in to the high word when the low word has the msb set.
7563 tcg_gen_shri_i32(t2
, t2
, 31);
7564 tcg_gen_add_i32(t1
, t1
, t2
);
7566 tcg_temp_free_i32(t2
);
7567 store_reg(s
, a
->rd
, t1
);
7571 static bool trans_SMMLA(DisasContext
*s
, arg_rrrr
*a
)
7573 return op_smmla(s
, a
, false, false);
7576 static bool trans_SMMLAR(DisasContext
*s
, arg_rrrr
*a
)
7578 return op_smmla(s
, a
, true, false);
7581 static bool trans_SMMLS(DisasContext
*s
, arg_rrrr
*a
)
7583 return op_smmla(s
, a
, false, true);
7586 static bool trans_SMMLSR(DisasContext
*s
, arg_rrrr
*a
)
7588 return op_smmla(s
, a
, true, true);
7591 static bool op_div(DisasContext
*s
, arg_rrr
*a
, bool u
)
7596 ? !dc_isar_feature(aa32_thumb_div
, s
)
7597 : !dc_isar_feature(aa32_arm_div
, s
)) {
7601 t1
= load_reg(s
, a
->rn
);
7602 t2
= load_reg(s
, a
->rm
);
7604 gen_helper_udiv(t1
, t1
, t2
);
7606 gen_helper_sdiv(t1
, t1
, t2
);
7608 tcg_temp_free_i32(t2
);
7609 store_reg(s
, a
->rd
, t1
);
7613 static bool trans_SDIV(DisasContext
*s
, arg_rrr
*a
)
7615 return op_div(s
, a
, false);
7618 static bool trans_UDIV(DisasContext
*s
, arg_rrr
*a
)
7620 return op_div(s
, a
, true);
7624 * Block data transfer
7627 static TCGv_i32
op_addr_block_pre(DisasContext
*s
, arg_ldst_block
*a
, int n
)
7629 TCGv_i32 addr
= load_reg(s
, a
->rn
);
7634 tcg_gen_addi_i32(addr
, addr
, 4);
7637 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
7639 } else if (!a
->i
&& n
!= 1) {
7640 /* post decrement */
7641 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
7644 if (s
->v8m_stackcheck
&& a
->rn
== 13 && a
->w
) {
7646 * If the writeback is incrementing SP rather than
7647 * decrementing it, and the initial SP is below the
7648 * stack limit but the final written-back SP would
7649 * be above, then then we must not perform any memory
7650 * accesses, but it is IMPDEF whether we generate
7651 * an exception. We choose to do so in this case.
7652 * At this point 'addr' is the lowest address, so
7653 * either the original SP (if incrementing) or our
7654 * final SP (if decrementing), so that's what we check.
7656 gen_helper_v8m_stackcheck(cpu_env
, addr
);
7662 static void op_addr_block_post(DisasContext
*s
, arg_ldst_block
*a
,
7663 TCGv_i32 addr
, int n
)
7669 /* post increment */
7670 tcg_gen_addi_i32(addr
, addr
, 4);
7672 /* post decrement */
7673 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
7675 } else if (!a
->i
&& n
!= 1) {
7677 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
7679 store_reg(s
, a
->rn
, addr
);
7681 tcg_temp_free_i32(addr
);
7685 static bool op_stm(DisasContext
*s
, arg_ldst_block
*a
, int min_n
)
7687 int i
, j
, n
, list
, mem_idx
;
7689 TCGv_i32 addr
, tmp
, tmp2
;
7694 /* Only usable in supervisor mode. */
7695 unallocated_encoding(s
);
7702 if (n
< min_n
|| a
->rn
== 15) {
7703 unallocated_encoding(s
);
7707 addr
= op_addr_block_pre(s
, a
, n
);
7708 mem_idx
= get_mem_index(s
);
7710 for (i
= j
= 0; i
< 16; i
++) {
7711 if (!(list
& (1 << i
))) {
7715 if (user
&& i
!= 15) {
7716 tmp
= tcg_temp_new_i32();
7717 tmp2
= tcg_const_i32(i
);
7718 gen_helper_get_user_reg(tmp
, cpu_env
, tmp2
);
7719 tcg_temp_free_i32(tmp2
);
7721 tmp
= load_reg(s
, i
);
7723 gen_aa32_st32(s
, tmp
, addr
, mem_idx
);
7724 tcg_temp_free_i32(tmp
);
7726 /* No need to add after the last transfer. */
7728 tcg_gen_addi_i32(addr
, addr
, 4);
7732 op_addr_block_post(s
, a
, addr
, n
);
7736 static bool trans_STM(DisasContext
*s
, arg_ldst_block
*a
)
7738 /* BitCount(list) < 1 is UNPREDICTABLE */
7739 return op_stm(s
, a
, 1);
7742 static bool trans_STM_t32(DisasContext
*s
, arg_ldst_block
*a
)
7744 /* Writeback register in register list is UNPREDICTABLE for T32. */
7745 if (a
->w
&& (a
->list
& (1 << a
->rn
))) {
7746 unallocated_encoding(s
);
7749 /* BitCount(list) < 2 is UNPREDICTABLE */
7750 return op_stm(s
, a
, 2);
7753 static bool do_ldm(DisasContext
*s
, arg_ldst_block
*a
, int min_n
)
7755 int i
, j
, n
, list
, mem_idx
;
7758 bool exc_return
= false;
7759 TCGv_i32 addr
, tmp
, tmp2
, loaded_var
;
7762 /* LDM (user), LDM (exception return) */
7764 /* Only usable in supervisor mode. */
7765 unallocated_encoding(s
);
7768 if (extract32(a
->list
, 15, 1)) {
7772 /* LDM (user) does not allow writeback. */
7774 unallocated_encoding(s
);
7782 if (n
< min_n
|| a
->rn
== 15) {
7783 unallocated_encoding(s
);
7787 addr
= op_addr_block_pre(s
, a
, n
);
7788 mem_idx
= get_mem_index(s
);
7789 loaded_base
= false;
7792 for (i
= j
= 0; i
< 16; i
++) {
7793 if (!(list
& (1 << i
))) {
7797 tmp
= tcg_temp_new_i32();
7798 gen_aa32_ld32u(s
, tmp
, addr
, mem_idx
);
7800 tmp2
= tcg_const_i32(i
);
7801 gen_helper_set_user_reg(cpu_env
, tmp2
, tmp
);
7802 tcg_temp_free_i32(tmp2
);
7803 tcg_temp_free_i32(tmp
);
7804 } else if (i
== a
->rn
) {
7807 } else if (i
== 15 && exc_return
) {
7808 store_pc_exc_ret(s
, tmp
);
7810 store_reg_from_load(s
, i
, tmp
);
7813 /* No need to add after the last transfer. */
7815 tcg_gen_addi_i32(addr
, addr
, 4);
7819 op_addr_block_post(s
, a
, addr
, n
);
7822 /* Note that we reject base == pc above. */
7823 store_reg(s
, a
->rn
, loaded_var
);
7827 /* Restore CPSR from SPSR. */
7828 tmp
= load_cpu_field(spsr
);
7829 if (tb_cflags(s
->base
.tb
) & CF_USE_ICOUNT
) {
7832 gen_helper_cpsr_write_eret(cpu_env
, tmp
);
7833 tcg_temp_free_i32(tmp
);
7834 /* Must exit loop to check un-masked IRQs */
7835 s
->base
.is_jmp
= DISAS_EXIT
;
7840 static bool trans_LDM_a32(DisasContext
*s
, arg_ldst_block
*a
)
7843 * Writeback register in register list is UNPREDICTABLE
7844 * for ArchVersion() >= 7. Prior to v7, A32 would write
7845 * an UNKNOWN value to the base register.
7847 if (ENABLE_ARCH_7
&& a
->w
&& (a
->list
& (1 << a
->rn
))) {
7848 unallocated_encoding(s
);
7851 /* BitCount(list) < 1 is UNPREDICTABLE */
7852 return do_ldm(s
, a
, 1);
7855 static bool trans_LDM_t32(DisasContext
*s
, arg_ldst_block
*a
)
7857 /* Writeback register in register list is UNPREDICTABLE for T32. */
7858 if (a
->w
&& (a
->list
& (1 << a
->rn
))) {
7859 unallocated_encoding(s
);
7862 /* BitCount(list) < 2 is UNPREDICTABLE */
7863 return do_ldm(s
, a
, 2);
7866 static bool trans_LDM_t16(DisasContext
*s
, arg_ldst_block
*a
)
7868 /* Writeback is conditional on the base register not being loaded. */
7869 a
->w
= !(a
->list
& (1 << a
->rn
));
7870 /* BitCount(list) < 1 is UNPREDICTABLE */
7871 return do_ldm(s
, a
, 1);
7875 * Branch, branch with link
7878 static bool trans_B(DisasContext
*s
, arg_i
*a
)
7880 gen_jmp(s
, read_pc(s
) + a
->imm
);
7884 static bool trans_B_cond_thumb(DisasContext
*s
, arg_ci
*a
)
7886 /* This has cond from encoding, required to be outside IT block. */
7887 if (a
->cond
>= 0xe) {
7890 if (s
->condexec_mask
) {
7891 unallocated_encoding(s
);
7894 arm_skip_unless(s
, a
->cond
);
7895 gen_jmp(s
, read_pc(s
) + a
->imm
);
7899 static bool trans_BL(DisasContext
*s
, arg_i
*a
)
7901 tcg_gen_movi_i32(cpu_R
[14], s
->base
.pc_next
| s
->thumb
);
7902 gen_jmp(s
, read_pc(s
) + a
->imm
);
7906 static bool trans_BLX_i(DisasContext
*s
, arg_BLX_i
*a
)
7910 /* For A32, ARM_FEATURE_V5 is checked near the start of the uncond block. */
7911 if (s
->thumb
&& (a
->imm
& 2)) {
7914 tcg_gen_movi_i32(cpu_R
[14], s
->base
.pc_next
| s
->thumb
);
7915 tmp
= tcg_const_i32(!s
->thumb
);
7916 store_cpu_field(tmp
, thumb
);
7917 gen_jmp(s
, (read_pc(s
) & ~3) + a
->imm
);
7921 static bool trans_BL_BLX_prefix(DisasContext
*s
, arg_BL_BLX_prefix
*a
)
7923 assert(!arm_dc_feature(s
, ARM_FEATURE_THUMB2
));
7924 tcg_gen_movi_i32(cpu_R
[14], read_pc(s
) + (a
->imm
<< 12));
7928 static bool trans_BL_suffix(DisasContext
*s
, arg_BL_suffix
*a
)
7930 TCGv_i32 tmp
= tcg_temp_new_i32();
7932 assert(!arm_dc_feature(s
, ARM_FEATURE_THUMB2
));
7933 tcg_gen_addi_i32(tmp
, cpu_R
[14], (a
->imm
<< 1) | 1);
7934 tcg_gen_movi_i32(cpu_R
[14], s
->base
.pc_next
| 1);
7939 static bool trans_BLX_suffix(DisasContext
*s
, arg_BLX_suffix
*a
)
7943 assert(!arm_dc_feature(s
, ARM_FEATURE_THUMB2
));
7944 if (!ENABLE_ARCH_5
) {
7947 tmp
= tcg_temp_new_i32();
7948 tcg_gen_addi_i32(tmp
, cpu_R
[14], a
->imm
<< 1);
7949 tcg_gen_andi_i32(tmp
, tmp
, 0xfffffffc);
7950 tcg_gen_movi_i32(cpu_R
[14], s
->base
.pc_next
| 1);
7955 static bool op_tbranch(DisasContext
*s
, arg_tbranch
*a
, bool half
)
7959 tmp
= load_reg(s
, a
->rm
);
7961 tcg_gen_add_i32(tmp
, tmp
, tmp
);
7963 addr
= load_reg(s
, a
->rn
);
7964 tcg_gen_add_i32(addr
, addr
, tmp
);
7966 gen_aa32_ld_i32(s
, tmp
, addr
, get_mem_index(s
),
7967 half
? MO_UW
| s
->be_data
: MO_UB
);
7968 tcg_temp_free_i32(addr
);
7970 tcg_gen_add_i32(tmp
, tmp
, tmp
);
7971 tcg_gen_addi_i32(tmp
, tmp
, read_pc(s
));
7972 store_reg(s
, 15, tmp
);
7976 static bool trans_TBB(DisasContext
*s
, arg_tbranch
*a
)
7978 return op_tbranch(s
, a
, false);
7981 static bool trans_TBH(DisasContext
*s
, arg_tbranch
*a
)
7983 return op_tbranch(s
, a
, true);
7986 static bool trans_CBZ(DisasContext
*s
, arg_CBZ
*a
)
7988 TCGv_i32 tmp
= load_reg(s
, a
->rn
);
7990 arm_gen_condlabel(s
);
7991 tcg_gen_brcondi_i32(a
->nz
? TCG_COND_EQ
: TCG_COND_NE
,
7992 tmp
, 0, s
->condlabel
);
7993 tcg_temp_free_i32(tmp
);
7994 gen_jmp(s
, read_pc(s
) + a
->imm
);
7999 * Supervisor call - both T32 & A32 come here so we need to check
8000 * which mode we are in when checking for semihosting.
8003 static bool trans_SVC(DisasContext
*s
, arg_SVC
*a
)
8005 const uint32_t semihost_imm
= s
->thumb
? 0xab : 0x123456;
8007 if (!arm_dc_feature(s
, ARM_FEATURE_M
) && semihosting_enabled() &&
8008 #ifndef CONFIG_USER_ONLY
8011 (a
->imm
== semihost_imm
)) {
8012 gen_exception_internal_insn(s
, s
->pc_curr
, EXCP_SEMIHOST
);
8014 gen_set_pc_im(s
, s
->base
.pc_next
);
8015 s
->svc_imm
= a
->imm
;
8016 s
->base
.is_jmp
= DISAS_SWI
;
8022 * Unconditional system instructions
8025 static bool trans_RFE(DisasContext
*s
, arg_RFE
*a
)
8027 static const int8_t pre_offset
[4] = {
8028 /* DA */ -4, /* IA */ 0, /* DB */ -8, /* IB */ 4
8030 static const int8_t post_offset
[4] = {
8031 /* DA */ -8, /* IA */ 4, /* DB */ -4, /* IB */ 0
8033 TCGv_i32 addr
, t1
, t2
;
8035 if (!ENABLE_ARCH_6
|| arm_dc_feature(s
, ARM_FEATURE_M
)) {
8039 unallocated_encoding(s
);
8043 addr
= load_reg(s
, a
->rn
);
8044 tcg_gen_addi_i32(addr
, addr
, pre_offset
[a
->pu
]);
8046 /* Load PC into tmp and CPSR into tmp2. */
8047 t1
= tcg_temp_new_i32();
8048 gen_aa32_ld32u(s
, t1
, addr
, get_mem_index(s
));
8049 tcg_gen_addi_i32(addr
, addr
, 4);
8050 t2
= tcg_temp_new_i32();
8051 gen_aa32_ld32u(s
, t2
, addr
, get_mem_index(s
));
8054 /* Base writeback. */
8055 tcg_gen_addi_i32(addr
, addr
, post_offset
[a
->pu
]);
8056 store_reg(s
, a
->rn
, addr
);
8058 tcg_temp_free_i32(addr
);
8064 static bool trans_SRS(DisasContext
*s
, arg_SRS
*a
)
8066 if (!ENABLE_ARCH_6
|| arm_dc_feature(s
, ARM_FEATURE_M
)) {
8069 gen_srs(s
, a
->mode
, a
->pu
, a
->w
);
8073 static bool trans_CPS(DisasContext
*s
, arg_CPS
*a
)
8077 if (!ENABLE_ARCH_6
|| arm_dc_feature(s
, ARM_FEATURE_M
)) {
8081 /* Implemented as NOP in user mode. */
8084 /* TODO: There are quite a lot of UNPREDICTABLE argument combinations. */
8106 gen_set_psr_im(s
, mask
, 0, val
);
8111 static bool trans_CPS_v7m(DisasContext
*s
, arg_CPS_v7m
*a
)
8113 TCGv_i32 tmp
, addr
, el
;
8115 if (!arm_dc_feature(s
, ARM_FEATURE_M
)) {
8119 /* Implemented as NOP in user mode. */
8123 tmp
= tcg_const_i32(a
->im
);
8126 addr
= tcg_const_i32(19);
8127 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8128 tcg_temp_free_i32(addr
);
8132 addr
= tcg_const_i32(16);
8133 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8134 tcg_temp_free_i32(addr
);
8136 el
= tcg_const_i32(s
->current_el
);
8137 gen_helper_rebuild_hflags_m32(cpu_env
, el
);
8138 tcg_temp_free_i32(el
);
8139 tcg_temp_free_i32(tmp
);
8145 * Clear-Exclusive, Barriers
8148 static bool trans_CLREX(DisasContext
*s
, arg_CLREX
*a
)
8151 ? !ENABLE_ARCH_7
&& !arm_dc_feature(s
, ARM_FEATURE_M
)
8152 : !ENABLE_ARCH_6K
) {
8159 static bool trans_DSB(DisasContext
*s
, arg_DSB
*a
)
8161 if (!ENABLE_ARCH_7
&& !arm_dc_feature(s
, ARM_FEATURE_M
)) {
8164 tcg_gen_mb(TCG_MO_ALL
| TCG_BAR_SC
);
8168 static bool trans_DMB(DisasContext
*s
, arg_DMB
*a
)
8170 return trans_DSB(s
, NULL
);
8173 static bool trans_ISB(DisasContext
*s
, arg_ISB
*a
)
8175 if (!ENABLE_ARCH_7
&& !arm_dc_feature(s
, ARM_FEATURE_M
)) {
8179 * We need to break the TB after this insn to execute
8180 * self-modifying code correctly and also to take
8181 * any pending interrupts immediately.
8183 gen_goto_tb(s
, 0, s
->base
.pc_next
);
8187 static bool trans_SB(DisasContext
*s
, arg_SB
*a
)
8189 if (!dc_isar_feature(aa32_sb
, s
)) {
8193 * TODO: There is no speculation barrier opcode
8194 * for TCG; MB and end the TB instead.
8196 tcg_gen_mb(TCG_MO_ALL
| TCG_BAR_SC
);
8197 gen_goto_tb(s
, 0, s
->base
.pc_next
);
8201 static bool trans_SETEND(DisasContext
*s
, arg_SETEND
*a
)
8203 if (!ENABLE_ARCH_6
) {
8206 if (a
->E
!= (s
->be_data
== MO_BE
)) {
8207 gen_helper_setend(cpu_env
);
8208 s
->base
.is_jmp
= DISAS_UPDATE_EXIT
;
8214 * Preload instructions
8215 * All are nops, contingent on the appropriate arch level.
8218 static bool trans_PLD(DisasContext
*s
, arg_PLD
*a
)
8220 return ENABLE_ARCH_5TE
;
8223 static bool trans_PLDW(DisasContext
*s
, arg_PLD
*a
)
8225 return arm_dc_feature(s
, ARM_FEATURE_V7MP
);
8228 static bool trans_PLI(DisasContext
*s
, arg_PLD
*a
)
8230 return ENABLE_ARCH_7
;
8237 static bool trans_IT(DisasContext
*s
, arg_IT
*a
)
8239 int cond_mask
= a
->cond_mask
;
8242 * No actual code generated for this insn, just setup state.
8244 * Combinations of firstcond and mask which set up an 0b1111
8245 * condition are UNPREDICTABLE; we take the CONSTRAINED
8246 * UNPREDICTABLE choice to treat 0b1111 the same as 0b1110,
8247 * i.e. both meaning "execute always".
8249 s
->condexec_cond
= (cond_mask
>> 4) & 0xe;
8250 s
->condexec_mask
= cond_mask
& 0x1f;
8258 static void disas_arm_insn(DisasContext
*s
, unsigned int insn
)
8260 unsigned int cond
= insn
>> 28;
8262 /* M variants do not implement ARM mode; this must raise the INVSTATE
8263 * UsageFault exception.
8265 if (arm_dc_feature(s
, ARM_FEATURE_M
)) {
8266 gen_exception_insn(s
, s
->pc_curr
, EXCP_INVSTATE
, syn_uncategorized(),
8267 default_exception_el(s
));
8272 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
8273 * choose to UNDEF. In ARMv5 and above the space is used
8274 * for miscellaneous unconditional instructions.
8276 if (!arm_dc_feature(s
, ARM_FEATURE_V5
)) {
8277 unallocated_encoding(s
);
8281 /* Unconditional instructions. */
8282 /* TODO: Perhaps merge these into one decodetree output file. */
8283 if (disas_a32_uncond(s
, insn
) ||
8284 disas_vfp_uncond(s
, insn
) ||
8285 disas_neon_dp(s
, insn
) ||
8286 disas_neon_ls(s
, insn
) ||
8287 disas_neon_shared(s
, insn
)) {
8290 /* fall back to legacy decoder */
8292 if ((insn
& 0x0e000f00) == 0x0c000100) {
8293 if (arm_dc_feature(s
, ARM_FEATURE_IWMMXT
)) {
8294 /* iWMMXt register transfer. */
8295 if (extract32(s
->c15_cpar
, 1, 1)) {
8296 if (!disas_iwmmxt_insn(s
, insn
)) {
8305 /* if not always execute, we generate a conditional jump to
8307 arm_skip_unless(s
, cond
);
8310 /* TODO: Perhaps merge these into one decodetree output file. */
8311 if (disas_a32(s
, insn
) ||
8312 disas_vfp(s
, insn
)) {
8315 /* fall back to legacy decoder */
8316 /* TODO: convert xscale/iwmmxt decoder to decodetree ?? */
8317 if (arm_dc_feature(s
, ARM_FEATURE_XSCALE
)) {
8318 if (((insn
& 0x0c000e00) == 0x0c000000)
8319 && ((insn
& 0x03000000) != 0x03000000)) {
8320 /* Coprocessor insn, coprocessor 0 or 1 */
8321 disas_xscale_insn(s
, insn
);
8327 unallocated_encoding(s
);
8330 static bool thumb_insn_is_16bit(DisasContext
*s
, uint32_t pc
, uint32_t insn
)
8333 * Return true if this is a 16 bit instruction. We must be precise
8334 * about this (matching the decode).
8336 if ((insn
>> 11) < 0x1d) {
8337 /* Definitely a 16-bit instruction */
8341 /* Top five bits 0b11101 / 0b11110 / 0b11111 : this is the
8342 * first half of a 32-bit Thumb insn. Thumb-1 cores might
8343 * end up actually treating this as two 16-bit insns, though,
8344 * if it's half of a bl/blx pair that might span a page boundary.
8346 if (arm_dc_feature(s
, ARM_FEATURE_THUMB2
) ||
8347 arm_dc_feature(s
, ARM_FEATURE_M
)) {
8348 /* Thumb2 cores (including all M profile ones) always treat
8349 * 32-bit insns as 32-bit.
8354 if ((insn
>> 11) == 0x1e && pc
- s
->page_start
< TARGET_PAGE_SIZE
- 3) {
8355 /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix, and the suffix
8356 * is not on the next page; we merge this into a 32-bit
8361 /* 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF);
8362 * 0b1111_1xxx_xxxx_xxxx : BL suffix;
8363 * 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix on the end of a page
8364 * -- handle as single 16 bit insn
8369 /* Translate a 32-bit thumb instruction. */
8370 static void disas_thumb2_insn(DisasContext
*s
, uint32_t insn
)
8373 * ARMv6-M supports a limited subset of Thumb2 instructions.
8374 * Other Thumb1 architectures allow only 32-bit
8375 * combined BL/BLX prefix and suffix.
8377 if (arm_dc_feature(s
, ARM_FEATURE_M
) &&
8378 !arm_dc_feature(s
, ARM_FEATURE_V7
)) {
8381 static const uint32_t armv6m_insn
[] = {0xf3808000 /* msr */,
8382 0xf3b08040 /* dsb */,
8383 0xf3b08050 /* dmb */,
8384 0xf3b08060 /* isb */,
8385 0xf3e08000 /* mrs */,
8386 0xf000d000 /* bl */};
8387 static const uint32_t armv6m_mask
[] = {0xffe0d000,
8394 for (i
= 0; i
< ARRAY_SIZE(armv6m_insn
); i
++) {
8395 if ((insn
& armv6m_mask
[i
]) == armv6m_insn
[i
]) {
8403 } else if ((insn
& 0xf800e800) != 0xf000e800) {
8404 if (!arm_dc_feature(s
, ARM_FEATURE_THUMB2
)) {
8405 unallocated_encoding(s
);
8410 if (arm_dc_feature(s
, ARM_FEATURE_M
)) {
8412 * NOCP takes precedence over any UNDEF for (almost) the
8413 * entire wide range of coprocessor-space encodings, so check
8414 * for it first before proceeding to actually decode eg VFP
8415 * insns. This decode also handles the few insns which are
8416 * in copro space but do not have NOCP checks (eg VLLDM, VLSTM).
8418 if (disas_m_nocp(s
, insn
)) {
8423 if ((insn
& 0xef000000) == 0xef000000) {
8425 * T32 encodings 0b111p_1111_qqqq_qqqq_qqqq_qqqq_qqqq_qqqq
8427 * A32 encodings 0b1111_001p_qqqq_qqqq_qqqq_qqqq_qqqq_qqqq
8429 uint32_t a32_insn
= (insn
& 0xe2ffffff) |
8430 ((insn
& (1 << 28)) >> 4) | (1 << 28);
8432 if (disas_neon_dp(s
, a32_insn
)) {
8437 if ((insn
& 0xff100000) == 0xf9000000) {
8439 * T32 encodings 0b1111_1001_ppp0_qqqq_qqqq_qqqq_qqqq_qqqq
8441 * A32 encodings 0b1111_0100_ppp0_qqqq_qqqq_qqqq_qqqq_qqqq
8443 uint32_t a32_insn
= (insn
& 0x00ffffff) | 0xf4000000;
8445 if (disas_neon_ls(s
, a32_insn
)) {
8451 * TODO: Perhaps merge these into one decodetree output file.
8452 * Note disas_vfp is written for a32 with cond field in the
8453 * top nibble. The t32 encoding requires 0xe in the top nibble.
8455 if (disas_t32(s
, insn
) ||
8456 disas_vfp_uncond(s
, insn
) ||
8457 disas_neon_shared(s
, insn
) ||
8458 ((insn
>> 28) == 0xe && disas_vfp(s
, insn
))) {
8463 unallocated_encoding(s
);
8466 static void disas_thumb_insn(DisasContext
*s
, uint32_t insn
)
8468 if (!disas_t16(s
, insn
)) {
8469 unallocated_encoding(s
);
8473 static bool insn_crosses_page(CPUARMState
*env
, DisasContext
*s
)
8475 /* Return true if the insn at dc->base.pc_next might cross a page boundary.
8476 * (False positives are OK, false negatives are not.)
8477 * We know this is a Thumb insn, and our caller ensures we are
8478 * only called if dc->base.pc_next is less than 4 bytes from the page
8479 * boundary, so we cross the page if the first 16 bits indicate
8480 * that this is a 32 bit insn.
8482 uint16_t insn
= arm_lduw_code(env
, s
->base
.pc_next
, s
->sctlr_b
);
8484 return !thumb_insn_is_16bit(s
, s
->base
.pc_next
, insn
);
8487 static void arm_tr_init_disas_context(DisasContextBase
*dcbase
, CPUState
*cs
)
8489 DisasContext
*dc
= container_of(dcbase
, DisasContext
, base
);
8490 CPUARMState
*env
= cs
->env_ptr
;
8491 ARMCPU
*cpu
= env_archcpu(env
);
8492 uint32_t tb_flags
= dc
->base
.tb
->flags
;
8493 uint32_t condexec
, core_mmu_idx
;
8495 dc
->isar
= &cpu
->isar
;
8499 /* If we are coming from secure EL0 in a system with a 32-bit EL3, then
8500 * there is no secure EL1, so we route exceptions to EL3.
8502 dc
->secure_routed_to_el3
= arm_feature(env
, ARM_FEATURE_EL3
) &&
8503 !arm_el_is_aa64(env
, 3);
8504 dc
->thumb
= FIELD_EX32(tb_flags
, TBFLAG_AM32
, THUMB
);
8505 dc
->be_data
= FIELD_EX32(tb_flags
, TBFLAG_ANY
, BE_DATA
) ? MO_BE
: MO_LE
;
8506 condexec
= FIELD_EX32(tb_flags
, TBFLAG_AM32
, CONDEXEC
);
8507 dc
->condexec_mask
= (condexec
& 0xf) << 1;
8508 dc
->condexec_cond
= condexec
>> 4;
8510 core_mmu_idx
= FIELD_EX32(tb_flags
, TBFLAG_ANY
, MMUIDX
);
8511 dc
->mmu_idx
= core_to_arm_mmu_idx(env
, core_mmu_idx
);
8512 dc
->current_el
= arm_mmu_idx_to_el(dc
->mmu_idx
);
8513 #if !defined(CONFIG_USER_ONLY)
8514 dc
->user
= (dc
->current_el
== 0);
8516 dc
->fp_excp_el
= FIELD_EX32(tb_flags
, TBFLAG_ANY
, FPEXC_EL
);
8518 if (arm_feature(env
, ARM_FEATURE_M
)) {
8519 dc
->vfp_enabled
= 1;
8520 dc
->be_data
= MO_TE
;
8521 dc
->v7m_handler_mode
= FIELD_EX32(tb_flags
, TBFLAG_M32
, HANDLER
);
8522 dc
->v8m_secure
= arm_feature(env
, ARM_FEATURE_M_SECURITY
) &&
8523 regime_is_secure(env
, dc
->mmu_idx
);
8524 dc
->v8m_stackcheck
= FIELD_EX32(tb_flags
, TBFLAG_M32
, STACKCHECK
);
8525 dc
->v8m_fpccr_s_wrong
=
8526 FIELD_EX32(tb_flags
, TBFLAG_M32
, FPCCR_S_WRONG
);
8527 dc
->v7m_new_fp_ctxt_needed
=
8528 FIELD_EX32(tb_flags
, TBFLAG_M32
, NEW_FP_CTXT_NEEDED
);
8529 dc
->v7m_lspact
= FIELD_EX32(tb_flags
, TBFLAG_M32
, LSPACT
);
8532 FIELD_EX32(tb_flags
, TBFLAG_ANY
, BE_DATA
) ? MO_BE
: MO_LE
;
8533 dc
->debug_target_el
=
8534 FIELD_EX32(tb_flags
, TBFLAG_ANY
, DEBUG_TARGET_EL
);
8535 dc
->sctlr_b
= FIELD_EX32(tb_flags
, TBFLAG_A32
, SCTLR_B
);
8536 dc
->hstr_active
= FIELD_EX32(tb_flags
, TBFLAG_A32
, HSTR_ACTIVE
);
8537 dc
->ns
= FIELD_EX32(tb_flags
, TBFLAG_A32
, NS
);
8538 dc
->vfp_enabled
= FIELD_EX32(tb_flags
, TBFLAG_A32
, VFPEN
);
8539 if (arm_feature(env
, ARM_FEATURE_XSCALE
)) {
8540 dc
->c15_cpar
= FIELD_EX32(tb_flags
, TBFLAG_A32
, XSCALE_CPAR
);
8542 dc
->vec_len
= FIELD_EX32(tb_flags
, TBFLAG_A32
, VECLEN
);
8543 dc
->vec_stride
= FIELD_EX32(tb_flags
, TBFLAG_A32
, VECSTRIDE
);
8546 dc
->cp_regs
= cpu
->cp_regs
;
8547 dc
->features
= env
->features
;
8549 /* Single step state. The code-generation logic here is:
8551 * generate code with no special handling for single-stepping (except
8552 * that anything that can make us go to SS_ACTIVE == 1 must end the TB;
8553 * this happens anyway because those changes are all system register or
8555 * SS_ACTIVE == 1, PSTATE.SS == 1: (active-not-pending)
8556 * emit code for one insn
8557 * emit code to clear PSTATE.SS
8558 * emit code to generate software step exception for completed step
8559 * end TB (as usual for having generated an exception)
8560 * SS_ACTIVE == 1, PSTATE.SS == 0: (active-pending)
8561 * emit code to generate a software step exception
8564 dc
->ss_active
= FIELD_EX32(tb_flags
, TBFLAG_ANY
, SS_ACTIVE
);
8565 dc
->pstate_ss
= FIELD_EX32(tb_flags
, TBFLAG_ANY
, PSTATE_SS
);
8566 dc
->is_ldex
= false;
8568 dc
->page_start
= dc
->base
.pc_first
& TARGET_PAGE_MASK
;
8570 /* If architectural single step active, limit to 1. */
8571 if (is_singlestepping(dc
)) {
8572 dc
->base
.max_insns
= 1;
8575 /* ARM is a fixed-length ISA. Bound the number of insns to execute
8576 to those left on the page. */
8578 int bound
= -(dc
->base
.pc_first
| TARGET_PAGE_MASK
) / 4;
8579 dc
->base
.max_insns
= MIN(dc
->base
.max_insns
, bound
);
8582 cpu_V0
= tcg_temp_new_i64();
8583 cpu_V1
= tcg_temp_new_i64();
8584 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8585 cpu_M0
= tcg_temp_new_i64();
8588 static void arm_tr_tb_start(DisasContextBase
*dcbase
, CPUState
*cpu
)
8590 DisasContext
*dc
= container_of(dcbase
, DisasContext
, base
);
8592 /* A note on handling of the condexec (IT) bits:
8594 * We want to avoid the overhead of having to write the updated condexec
8595 * bits back to the CPUARMState for every instruction in an IT block. So:
8596 * (1) if the condexec bits are not already zero then we write
8597 * zero back into the CPUARMState now. This avoids complications trying
8598 * to do it at the end of the block. (For example if we don't do this
8599 * it's hard to identify whether we can safely skip writing condexec
8600 * at the end of the TB, which we definitely want to do for the case
8601 * where a TB doesn't do anything with the IT state at all.)
8602 * (2) if we are going to leave the TB then we call gen_set_condexec()
8603 * which will write the correct value into CPUARMState if zero is wrong.
8604 * This is done both for leaving the TB at the end, and for leaving
8605 * it because of an exception we know will happen, which is done in
8606 * gen_exception_insn(). The latter is necessary because we need to
8607 * leave the TB with the PC/IT state just prior to execution of the
8608 * instruction which caused the exception.
8609 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
8610 * then the CPUARMState will be wrong and we need to reset it.
8611 * This is handled in the same way as restoration of the
8612 * PC in these situations; we save the value of the condexec bits
8613 * for each PC via tcg_gen_insn_start(), and restore_state_to_opc()
8614 * then uses this to restore them after an exception.
8616 * Note that there are no instructions which can read the condexec
8617 * bits, and none which can write non-static values to them, so
8618 * we don't need to care about whether CPUARMState is correct in the
8622 /* Reset the conditional execution bits immediately. This avoids
8623 complications trying to do it at the end of the block. */
8624 if (dc
->condexec_mask
|| dc
->condexec_cond
) {
8625 TCGv_i32 tmp
= tcg_temp_new_i32();
8626 tcg_gen_movi_i32(tmp
, 0);
8627 store_cpu_field(tmp
, condexec_bits
);
8631 static void arm_tr_insn_start(DisasContextBase
*dcbase
, CPUState
*cpu
)
8633 DisasContext
*dc
= container_of(dcbase
, DisasContext
, base
);
8635 tcg_gen_insn_start(dc
->base
.pc_next
,
8636 (dc
->condexec_cond
<< 4) | (dc
->condexec_mask
>> 1),
8638 dc
->insn_start
= tcg_last_op();
8641 static bool arm_tr_breakpoint_check(DisasContextBase
*dcbase
, CPUState
*cpu
,
8642 const CPUBreakpoint
*bp
)
8644 DisasContext
*dc
= container_of(dcbase
, DisasContext
, base
);
8646 if (bp
->flags
& BP_CPU
) {
8647 gen_set_condexec(dc
);
8648 gen_set_pc_im(dc
, dc
->base
.pc_next
);
8649 gen_helper_check_breakpoints(cpu_env
);
8650 /* End the TB early; it's likely not going to be executed */
8651 dc
->base
.is_jmp
= DISAS_TOO_MANY
;
8653 gen_exception_internal_insn(dc
, dc
->base
.pc_next
, EXCP_DEBUG
);
8654 /* The address covered by the breakpoint must be
8655 included in [tb->pc, tb->pc + tb->size) in order
8656 to for it to be properly cleared -- thus we
8657 increment the PC here so that the logic setting
8658 tb->size below does the right thing. */
8659 /* TODO: Advance PC by correct instruction length to
8660 * avoid disassembler error messages */
8661 dc
->base
.pc_next
+= 2;
8662 dc
->base
.is_jmp
= DISAS_NORETURN
;
8668 static bool arm_pre_translate_insn(DisasContext
*dc
)
8670 #ifdef CONFIG_USER_ONLY
8671 /* Intercept jump to the magic kernel page. */
8672 if (dc
->base
.pc_next
>= 0xffff0000) {
8673 /* We always get here via a jump, so know we are not in a
8674 conditional execution block. */
8675 gen_exception_internal(EXCP_KERNEL_TRAP
);
8676 dc
->base
.is_jmp
= DISAS_NORETURN
;
8681 if (dc
->ss_active
&& !dc
->pstate_ss
) {
8682 /* Singlestep state is Active-pending.
8683 * If we're in this state at the start of a TB then either
8684 * a) we just took an exception to an EL which is being debugged
8685 * and this is the first insn in the exception handler
8686 * b) debug exceptions were masked and we just unmasked them
8687 * without changing EL (eg by clearing PSTATE.D)
8688 * In either case we're going to take a swstep exception in the
8689 * "did not step an insn" case, and so the syndrome ISV and EX
8690 * bits should be zero.
8692 assert(dc
->base
.num_insns
== 1);
8693 gen_swstep_exception(dc
, 0, 0);
8694 dc
->base
.is_jmp
= DISAS_NORETURN
;
8701 static void arm_post_translate_insn(DisasContext
*dc
)
8703 if (dc
->condjmp
&& !dc
->base
.is_jmp
) {
8704 gen_set_label(dc
->condlabel
);
8707 translator_loop_temp_check(&dc
->base
);
8710 static void arm_tr_translate_insn(DisasContextBase
*dcbase
, CPUState
*cpu
)
8712 DisasContext
*dc
= container_of(dcbase
, DisasContext
, base
);
8713 CPUARMState
*env
= cpu
->env_ptr
;
8716 if (arm_pre_translate_insn(dc
)) {
8720 dc
->pc_curr
= dc
->base
.pc_next
;
8721 insn
= arm_ldl_code(env
, dc
->base
.pc_next
, dc
->sctlr_b
);
8723 dc
->base
.pc_next
+= 4;
8724 disas_arm_insn(dc
, insn
);
8726 arm_post_translate_insn(dc
);
8728 /* ARM is a fixed-length ISA. We performed the cross-page check
8729 in init_disas_context by adjusting max_insns. */
8732 static bool thumb_insn_is_unconditional(DisasContext
*s
, uint32_t insn
)
8734 /* Return true if this Thumb insn is always unconditional,
8735 * even inside an IT block. This is true of only a very few
8736 * instructions: BKPT, HLT, and SG.
8738 * A larger class of instructions are UNPREDICTABLE if used
8739 * inside an IT block; we do not need to detect those here, because
8740 * what we do by default (perform the cc check and update the IT
8741 * bits state machine) is a permitted CONSTRAINED UNPREDICTABLE
8742 * choice for those situations.
8744 * insn is either a 16-bit or a 32-bit instruction; the two are
8745 * distinguishable because for the 16-bit case the top 16 bits
8746 * are zeroes, and that isn't a valid 32-bit encoding.
8748 if ((insn
& 0xffffff00) == 0xbe00) {
8753 if ((insn
& 0xffffffc0) == 0xba80 && arm_dc_feature(s
, ARM_FEATURE_V8
) &&
8754 !arm_dc_feature(s
, ARM_FEATURE_M
)) {
8755 /* HLT: v8A only. This is unconditional even when it is going to
8756 * UNDEF; see the v8A ARM ARM DDI0487B.a H3.3.
8757 * For v7 cores this was a plain old undefined encoding and so
8758 * honours its cc check. (We might be using the encoding as
8759 * a semihosting trap, but we don't change the cc check behaviour
8760 * on that account, because a debugger connected to a real v7A
8761 * core and emulating semihosting traps by catching the UNDEF
8762 * exception would also only see cases where the cc check passed.
8763 * No guest code should be trying to do a HLT semihosting trap
8764 * in an IT block anyway.
8769 if (insn
== 0xe97fe97f && arm_dc_feature(s
, ARM_FEATURE_V8
) &&
8770 arm_dc_feature(s
, ARM_FEATURE_M
)) {
8778 static void thumb_tr_translate_insn(DisasContextBase
*dcbase
, CPUState
*cpu
)
8780 DisasContext
*dc
= container_of(dcbase
, DisasContext
, base
);
8781 CPUARMState
*env
= cpu
->env_ptr
;
8785 if (arm_pre_translate_insn(dc
)) {
8789 dc
->pc_curr
= dc
->base
.pc_next
;
8790 insn
= arm_lduw_code(env
, dc
->base
.pc_next
, dc
->sctlr_b
);
8791 is_16bit
= thumb_insn_is_16bit(dc
, dc
->base
.pc_next
, insn
);
8792 dc
->base
.pc_next
+= 2;
8794 uint32_t insn2
= arm_lduw_code(env
, dc
->base
.pc_next
, dc
->sctlr_b
);
8796 insn
= insn
<< 16 | insn2
;
8797 dc
->base
.pc_next
+= 2;
8801 if (dc
->condexec_mask
&& !thumb_insn_is_unconditional(dc
, insn
)) {
8802 uint32_t cond
= dc
->condexec_cond
;
8805 * Conditionally skip the insn. Note that both 0xe and 0xf mean
8806 * "always"; 0xf is not "never".
8809 arm_skip_unless(dc
, cond
);
8814 disas_thumb_insn(dc
, insn
);
8816 disas_thumb2_insn(dc
, insn
);
8819 /* Advance the Thumb condexec condition. */
8820 if (dc
->condexec_mask
) {
8821 dc
->condexec_cond
= ((dc
->condexec_cond
& 0xe) |
8822 ((dc
->condexec_mask
>> 4) & 1));
8823 dc
->condexec_mask
= (dc
->condexec_mask
<< 1) & 0x1f;
8824 if (dc
->condexec_mask
== 0) {
8825 dc
->condexec_cond
= 0;
8829 arm_post_translate_insn(dc
);
8831 /* Thumb is a variable-length ISA. Stop translation when the next insn
8832 * will touch a new page. This ensures that prefetch aborts occur at
8835 * We want to stop the TB if the next insn starts in a new page,
8836 * or if it spans between this page and the next. This means that
8837 * if we're looking at the last halfword in the page we need to
8838 * see if it's a 16-bit Thumb insn (which will fit in this TB)
8839 * or a 32-bit Thumb insn (which won't).
8840 * This is to avoid generating a silly TB with a single 16-bit insn
8841 * in it at the end of this page (which would execute correctly
8842 * but isn't very efficient).
8844 if (dc
->base
.is_jmp
== DISAS_NEXT
8845 && (dc
->base
.pc_next
- dc
->page_start
>= TARGET_PAGE_SIZE
8846 || (dc
->base
.pc_next
- dc
->page_start
>= TARGET_PAGE_SIZE
- 3
8847 && insn_crosses_page(env
, dc
)))) {
8848 dc
->base
.is_jmp
= DISAS_TOO_MANY
;
8852 static void arm_tr_tb_stop(DisasContextBase
*dcbase
, CPUState
*cpu
)
8854 DisasContext
*dc
= container_of(dcbase
, DisasContext
, base
);
8856 if (tb_cflags(dc
->base
.tb
) & CF_LAST_IO
&& dc
->condjmp
) {
8857 /* FIXME: This can theoretically happen with self-modifying code. */
8858 cpu_abort(cpu
, "IO on conditional branch instruction");
8861 /* At this stage dc->condjmp will only be set when the skipped
8862 instruction was a conditional branch or trap, and the PC has
8863 already been written. */
8864 gen_set_condexec(dc
);
8865 if (dc
->base
.is_jmp
== DISAS_BX_EXCRET
) {
8866 /* Exception return branches need some special case code at the
8867 * end of the TB, which is complex enough that it has to
8868 * handle the single-step vs not and the condition-failed
8869 * insn codepath itself.
8871 gen_bx_excret_final_code(dc
);
8872 } else if (unlikely(is_singlestepping(dc
))) {
8873 /* Unconditional and "condition passed" instruction codepath. */
8874 switch (dc
->base
.is_jmp
) {
8877 gen_exception(EXCP_SWI
, syn_aa32_svc(dc
->svc_imm
, dc
->thumb
),
8878 default_exception_el(dc
));
8882 gen_exception(EXCP_HVC
, syn_aa32_hvc(dc
->svc_imm
), 2);
8886 gen_exception(EXCP_SMC
, syn_aa32_smc(), 3);
8889 case DISAS_TOO_MANY
:
8890 case DISAS_UPDATE_EXIT
:
8891 case DISAS_UPDATE_NOCHAIN
:
8892 gen_set_pc_im(dc
, dc
->base
.pc_next
);
8895 /* FIXME: Single stepping a WFI insn will not halt the CPU. */
8896 gen_singlestep_exception(dc
);
8898 case DISAS_NORETURN
:
8902 /* While branches must always occur at the end of an IT block,
8903 there are a few other things that can cause us to terminate
8904 the TB in the middle of an IT block:
8905 - Exception generating instructions (bkpt, swi, undefined).
8907 - Hardware watchpoints.
8908 Hardware breakpoints have already been handled and skip this code.
8910 switch(dc
->base
.is_jmp
) {
8912 case DISAS_TOO_MANY
:
8913 gen_goto_tb(dc
, 1, dc
->base
.pc_next
);
8915 case DISAS_UPDATE_NOCHAIN
:
8916 gen_set_pc_im(dc
, dc
->base
.pc_next
);
8921 case DISAS_UPDATE_EXIT
:
8922 gen_set_pc_im(dc
, dc
->base
.pc_next
);
8925 /* indicate that the hash table must be used to find the next TB */
8926 tcg_gen_exit_tb(NULL
, 0);
8928 case DISAS_NORETURN
:
8929 /* nothing more to generate */
8933 TCGv_i32 tmp
= tcg_const_i32((dc
->thumb
&&
8934 !(dc
->insn
& (1U << 31))) ? 2 : 4);
8936 gen_helper_wfi(cpu_env
, tmp
);
8937 tcg_temp_free_i32(tmp
);
8938 /* The helper doesn't necessarily throw an exception, but we
8939 * must go back to the main loop to check for interrupts anyway.
8941 tcg_gen_exit_tb(NULL
, 0);
8945 gen_helper_wfe(cpu_env
);
8948 gen_helper_yield(cpu_env
);
8951 gen_exception(EXCP_SWI
, syn_aa32_svc(dc
->svc_imm
, dc
->thumb
),
8952 default_exception_el(dc
));
8955 gen_exception(EXCP_HVC
, syn_aa32_hvc(dc
->svc_imm
), 2);
8958 gen_exception(EXCP_SMC
, syn_aa32_smc(), 3);
8964 /* "Condition failed" instruction codepath for the branch/trap insn */
8965 gen_set_label(dc
->condlabel
);
8966 gen_set_condexec(dc
);
8967 if (unlikely(is_singlestepping(dc
))) {
8968 gen_set_pc_im(dc
, dc
->base
.pc_next
);
8969 gen_singlestep_exception(dc
);
8971 gen_goto_tb(dc
, 1, dc
->base
.pc_next
);
8976 static void arm_tr_disas_log(const DisasContextBase
*dcbase
, CPUState
*cpu
)
8978 DisasContext
*dc
= container_of(dcbase
, DisasContext
, base
);
8980 qemu_log("IN: %s\n", lookup_symbol(dc
->base
.pc_first
));
8981 log_target_disas(cpu
, dc
->base
.pc_first
, dc
->base
.tb
->size
);
8984 static const TranslatorOps arm_translator_ops
= {
8985 .init_disas_context
= arm_tr_init_disas_context
,
8986 .tb_start
= arm_tr_tb_start
,
8987 .insn_start
= arm_tr_insn_start
,
8988 .breakpoint_check
= arm_tr_breakpoint_check
,
8989 .translate_insn
= arm_tr_translate_insn
,
8990 .tb_stop
= arm_tr_tb_stop
,
8991 .disas_log
= arm_tr_disas_log
,
8994 static const TranslatorOps thumb_translator_ops
= {
8995 .init_disas_context
= arm_tr_init_disas_context
,
8996 .tb_start
= arm_tr_tb_start
,
8997 .insn_start
= arm_tr_insn_start
,
8998 .breakpoint_check
= arm_tr_breakpoint_check
,
8999 .translate_insn
= thumb_tr_translate_insn
,
9000 .tb_stop
= arm_tr_tb_stop
,
9001 .disas_log
= arm_tr_disas_log
,
9004 /* generate intermediate code for basic block 'tb'. */
9005 void gen_intermediate_code(CPUState
*cpu
, TranslationBlock
*tb
, int max_insns
)
9007 DisasContext dc
= { };
9008 const TranslatorOps
*ops
= &arm_translator_ops
;
9010 if (FIELD_EX32(tb
->flags
, TBFLAG_AM32
, THUMB
)) {
9011 ops
= &thumb_translator_ops
;
9013 #ifdef TARGET_AARCH64
9014 if (FIELD_EX32(tb
->flags
, TBFLAG_ANY
, AARCH64_STATE
)) {
9015 ops
= &aarch64_translator_ops
;
9019 translator_loop(ops
, &dc
.base
, cpu
, tb
, max_insns
);
9022 void restore_state_to_opc(CPUARMState
*env
, TranslationBlock
*tb
,
9027 env
->condexec_bits
= 0;
9028 env
->exception
.syndrome
= data
[2] << ARM_INSN_START_WORD2_SHIFT
;
9030 env
->regs
[15] = data
[0];
9031 env
->condexec_bits
= data
[1];
9032 env
->exception
.syndrome
= data
[2] << ARM_INSN_START_WORD2_SHIFT
;