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