target-arm queue:

* avoid passing CPU env pointer around in A32/T32 decoders
  * split M profile exception masking out from A/R profile
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABCAAGBQJUWMZfAAoJEDwlJe0UNgze1i8QAIEw/1jsyUG8gzzRpO1iojXb
 9aCknR+mxxH7JZS+p0pYOp/3kOGroI2Z8O+yODmCT3Y/ltF+OYvryjktGhdayl98
 li3ycH9IgHzDG4HRlTUYnBYAw5qiPcTv9uqv9YdwMRIHRVLrt8rOLeMDKWllb7pe
 NBL6G2a1hlbncRYsHuy9jzPo0cz8DsyGJ/mgfbq58EBeb6/toGabzGkB9zf/4XA0
 bRjeRXBcc7l1ZqQ4bPa43XyMrPLtB7Qs0OjiZ1aGEnTSMdT4ssab6Dc93ZRHKgps
 mrJaN1zUvmTei3JYyITC3kEMXGWHV6zDvZwBWN/iQ941W2WSVjEr58eqECQbEjXg
 AXovsEvrNdnrKYMVvZQzo4MYSFTwW6nVsWx93w0z3/F+Lx4lVB1P4KOC29ifsox4
 5Tep+2Ei1aM9KawPN6+SSUeNLhCuzDwhcFqKhEM0hzq2ufapY9X7G21AaJOC+3Xe
 HUkvSZ7a80H4BAZ7nqpd29QXvEXiOPVASaaRgTsE4X7dsO/9xHmpLJWbr8M50lj5
 LcelUILJpfO+WwAiiY+c/l8TvmWVRkFmK9JevhQygmswXyT//1701C7XNr7eCYSB
 Ddl92J5HAPAT9iQW/22+JWt2rlJ3PRyeob9EovfiBxzdTKh3YOzHxno9iT63T6nF
 QLrJ/EPW5Bb6CmM/VdsF
 =jeuZ
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20141104' into staging

target-arm queue:
 * avoid passing CPU env pointer around in A32/T32 decoders
 * split M profile exception masking out from A/R profile

# gpg: Signature made Tue 04 Nov 2014 12:28:15 GMT using RSA key ID 14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"

* remotes/pmaydell/tags/pull-target-arm-20141104:
  target-arm: Correct condition for taking VIRQ and VFIQ
  target-arm: Separate out M profile cpu_exec_interrupt handling
  target-arm/translate.c: Don't pass CPUARMState * to disas_arm_insn()
  target-arm/translate.c: Don't pass CPUARMState around in the decoder
  target-arm/translate.c: Don't use IS_M()
  target-arm/translate.c: Use arm_dc_feature() rather than arm_feature()
  target-arm/translate.c: Use arm_dc_feature() in ENABLE_ARCH_ macros

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
master
Peter Maydell 2014-11-04 13:35:04 +00:00
commit 45da08fa8a
3 changed files with 197 additions and 152 deletions

View File

@ -203,15 +203,6 @@ bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
cc->do_interrupt(cs);
ret = true;
}
/* ARMv7-M interrupt return works by loading a magic value
into the PC. On real hardware the load causes the
return to occur. The qemu implementation performs the
jump normally, then does the exception return when the
CPU tries to execute code at the magic address.
This will cause the magic PC value to be pushed to
the stack if an interrupt occurred at the wrong time.
We avoid this by disabling interrupts when
pc contains a magic address. */
if (interrupt_request & CPU_INTERRUPT_HARD
&& arm_excp_unmasked(cs, EXCP_IRQ)) {
cs->exception_index = EXCP_IRQ;
@ -234,6 +225,42 @@ bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
return ret;
}
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
{
CPUClass *cc = CPU_GET_CLASS(cs);
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
bool ret = false;
if (interrupt_request & CPU_INTERRUPT_FIQ
&& !(env->daif & PSTATE_F)) {
cs->exception_index = EXCP_FIQ;
cc->do_interrupt(cs);
ret = true;
}
/* ARMv7-M interrupt return works by loading a magic value
* into the PC. On real hardware the load causes the
* return to occur. The qemu implementation performs the
* jump normally, then does the exception return when the
* CPU tries to execute code at the magic address.
* This will cause the magic PC value to be pushed to
* the stack if an interrupt occurred at the wrong time.
* We avoid this by disabling interrupts when
* pc contains a magic address.
*/
if (interrupt_request & CPU_INTERRUPT_HARD
&& !(env->daif & PSTATE_I)
&& (env->regs[15] < 0xfffffff0)) {
cs->exception_index = EXCP_IRQ;
cc->do_interrupt(cs);
ret = true;
}
return ret;
}
#endif
#ifndef CONFIG_USER_ONLY
static void arm_cpu_set_irq(void *opaque, int irq, int level)
{
@ -670,11 +697,13 @@ static void cortex_m3_initfn(Object *obj)
static void arm_v7m_class_init(ObjectClass *oc, void *data)
{
#ifndef CONFIG_USER_ONLY
CPUClass *cc = CPU_CLASS(oc);
#ifndef CONFIG_USER_ONLY
cc->do_interrupt = arm_v7m_cpu_do_interrupt;
#endif
cc->cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt;
}
static const ARMCPRegInfo cortexa8_cp_reginfo[] = {

View File

@ -1251,18 +1251,6 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx)
bool secure = false;
/* If in EL1/0, Physical IRQ routing to EL2 only happens from NS state. */
bool irq_can_hyp = !secure && cur_el < 2 && target_el == 2;
/* ARMv7-M interrupt return works by loading a magic value
* into the PC. On real hardware the load causes the
* return to occur. The qemu implementation performs the
* jump normally, then does the exception return when the
* CPU tries to execute code at the magic address.
* This will cause the magic PC value to be pushed to
* the stack if an interrupt occurred at the wrong time.
* We avoid this by disabling interrupts when
* pc contains a magic address.
*/
bool irq_unmasked = !(env->daif & PSTATE_I)
&& (!IS_M(env) || env->regs[15] < 0xfffffff0);
/* Don't take exceptions if they target a lower EL. */
if (cur_el > target_el) {
@ -1279,19 +1267,19 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx)
if (irq_can_hyp && (env->cp15.hcr_el2 & HCR_IMO)) {
return true;
}
return irq_unmasked;
return !(env->daif & PSTATE_I);
case EXCP_VFIQ:
if (!secure && !(env->cp15.hcr_el2 & HCR_FMO)) {
if (secure || !(env->cp15.hcr_el2 & HCR_FMO)) {
/* VFIQs are only taken when hypervized and non-secure. */
return false;
}
return !(env->daif & PSTATE_F);
case EXCP_VIRQ:
if (!secure && !(env->cp15.hcr_el2 & HCR_IMO)) {
if (secure || !(env->cp15.hcr_el2 & HCR_IMO)) {
/* VIRQs are only taken when hypervized and non-secure. */
return false;
}
return irq_unmasked;
return !(env->daif & PSTATE_I);
default:
g_assert_not_reached();
}

View File

@ -38,16 +38,16 @@
#include "trace-tcg.h"
#define ENABLE_ARCH_4T arm_feature(env, ARM_FEATURE_V4T)
#define ENABLE_ARCH_5 arm_feature(env, ARM_FEATURE_V5)
#define ENABLE_ARCH_4T arm_dc_feature(s, ARM_FEATURE_V4T)
#define ENABLE_ARCH_5 arm_dc_feature(s, ARM_FEATURE_V5)
/* currently all emulated v5 cores are also v5TE, so don't bother */
#define ENABLE_ARCH_5TE arm_feature(env, ARM_FEATURE_V5)
#define ENABLE_ARCH_5TE arm_dc_feature(s, ARM_FEATURE_V5)
#define ENABLE_ARCH_5J 0
#define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
#define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
#define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
#define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
#define ENABLE_ARCH_8 arm_feature(env, ARM_FEATURE_V8)
#define ENABLE_ARCH_6 arm_dc_feature(s, ARM_FEATURE_V6)
#define ENABLE_ARCH_6K arm_dc_feature(s, ARM_FEATURE_V6K)
#define ENABLE_ARCH_6T2 arm_dc_feature(s, ARM_FEATURE_THUMB2)
#define ENABLE_ARCH_7 arm_dc_feature(s, ARM_FEATURE_V7)
#define ENABLE_ARCH_8 arm_dc_feature(s, ARM_FEATURE_V8)
#define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
@ -834,8 +834,7 @@ static inline void gen_bx(DisasContext *s, TCGv_i32 var)
/* Variant of store_reg which uses branch&exchange logic when storing
to r15 in ARM architecture v7 and above. The source must be a temporary
and will be marked as dead. */
static inline void store_reg_bx(CPUARMState *env, DisasContext *s,
int reg, TCGv_i32 var)
static inline void store_reg_bx(DisasContext *s, int reg, TCGv_i32 var)
{
if (reg == 15 && ENABLE_ARCH_7) {
gen_bx(s, var);
@ -848,8 +847,7 @@ static inline void store_reg_bx(CPUARMState *env, DisasContext *s,
* to r15 in ARM architecture v5T and above. This is used for storing
* the results of a LDR/LDM/POP into r15, and corresponds to the cases
* in the ARM ARM which use the LoadWritePC() pseudocode function. */
static inline void store_reg_from_load(CPUARMState *env, DisasContext *s,
int reg, TCGv_i32 var)
static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
{
if (reg == 15 && ENABLE_ARCH_5) {
gen_bx(s, var);
@ -1541,7 +1539,7 @@ static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv_i32 dest)
/* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
(ie. an undefined instruction). */
static int disas_iwmmxt_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
{
int rd, wrd;
int rdhi, rdlo, rd0, rd1, i;
@ -2547,7 +2545,7 @@ static int disas_iwmmxt_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
/* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
(ie. an undefined instruction). */
static int disas_dsp_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
static int disas_dsp_insn(DisasContext *s, uint32_t insn)
{
int acc, rd0, rd1, rdhi, rdlo;
TCGv_i32 tmp, tmp2;
@ -2619,7 +2617,7 @@ static int disas_dsp_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
#define VFP_SREG(insn, bigbit, smallbit) \
((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
if (arm_feature(env, ARM_FEATURE_VFP3)) { \
if (arm_dc_feature(s, ARM_FEATURE_VFP3)) { \
reg = (((insn) >> (bigbit)) & 0x0f) \
| (((insn) >> ((smallbit) - 4)) & 0x10); \
} else { \
@ -2966,11 +2964,11 @@ static const uint8_t fp_decode_rm[] = {
FPROUNDING_NEGINF,
};
static int disas_vfp_v8_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
static int disas_vfp_v8_insn(DisasContext *s, uint32_t insn)
{
uint32_t rd, rn, rm, dp = extract32(insn, 8, 1);
if (!arm_feature(env, ARM_FEATURE_V8)) {
if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
return 1;
}
@ -3002,7 +3000,7 @@ static int disas_vfp_v8_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
/* Disassemble a VFP instruction. Returns nonzero if an error occurred
(ie. an undefined instruction). */
static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
static int disas_vfp_insn(DisasContext *s, uint32_t insn)
{
uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
int dp, veclen;
@ -3010,8 +3008,9 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
TCGv_i32 tmp;
TCGv_i32 tmp2;
if (!arm_feature(env, ARM_FEATURE_VFP))
if (!arm_dc_feature(s, ARM_FEATURE_VFP)) {
return 1;
}
/* FIXME: this access check should not take precedence over UNDEF
* for invalid encodings; we will generate incorrect syndrome information
@ -3038,7 +3037,7 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
/* Encodings with T=1 (Thumb) or unconditional (ARM):
* only used in v8 and above.
*/
return disas_vfp_v8_insn(env, s, insn);
return disas_vfp_v8_insn(s, insn);
}
dp = ((insn & 0xf00) == 0xb00);
@ -3055,8 +3054,9 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
if (insn & 0xf)
return 1;
if (insn & 0x00c00060
&& !arm_feature(env, ARM_FEATURE_NEON))
&& !arm_dc_feature(s, ARM_FEATURE_NEON)) {
return 1;
}
pass = (insn >> 21) & 1;
if (insn & (1 << 22)) {
@ -3151,8 +3151,9 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
VFP3 restricts all id registers to privileged
accesses. */
if (IS_USER(s)
&& arm_feature(env, ARM_FEATURE_VFP3))
&& arm_dc_feature(s, ARM_FEATURE_VFP3)) {
return 1;
}
tmp = load_cpu_field(vfp.xregs[rn]);
break;
case ARM_VFP_FPEXC:
@ -3164,8 +3165,9 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
case ARM_VFP_FPINST2:
/* Not present in VFP3. */
if (IS_USER(s)
|| arm_feature(env, ARM_FEATURE_VFP3))
|| arm_dc_feature(s, ARM_FEATURE_VFP3)) {
return 1;
}
tmp = load_cpu_field(vfp.xregs[rn]);
break;
case ARM_VFP_FPSCR:
@ -3178,15 +3180,16 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
}
break;
case ARM_VFP_MVFR2:
if (!arm_feature(env, ARM_FEATURE_V8)) {
if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
return 1;
}
/* fall through */
case ARM_VFP_MVFR0:
case ARM_VFP_MVFR1:
if (IS_USER(s)
|| !arm_feature(env, ARM_FEATURE_MVFR))
|| !arm_dc_feature(s, ARM_FEATURE_MVFR)) {
return 1;
}
tmp = load_cpu_field(vfp.xregs[rn]);
break;
default:
@ -3367,8 +3370,8 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
* UNPREDICTABLE if bit 8 is set prior to ARMv8
* (we choose to UNDEF)
*/
if ((dp && !arm_feature(env, ARM_FEATURE_V8)) ||
!arm_feature(env, ARM_FEATURE_VFP_FP16)) {
if ((dp && !arm_dc_feature(s, ARM_FEATURE_V8)) ||
!arm_dc_feature(s, ARM_FEATURE_VFP_FP16)) {
return 1;
}
if (!extract32(rn, 1, 1)) {
@ -3447,7 +3450,7 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
* correct : an input NaN should come out with its sign bit
* flipped if it is a negated-input.
*/
if (!arm_feature(env, ARM_FEATURE_VFP4)) {
if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
return 1;
}
if (dp) {
@ -3488,8 +3491,9 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
}
break;
case 14: /* fconst */
if (!arm_feature(env, ARM_FEATURE_VFP3))
return 1;
if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
return 1;
}
n = (insn << 12) & 0x80000000;
i = ((insn >> 12) & 0x70) | (insn & 0xf);
@ -3644,23 +3648,27 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
gen_vfp_sito(dp, 0);
break;
case 20: /* fshto */
if (!arm_feature(env, ARM_FEATURE_VFP3))
return 1;
if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
return 1;
}
gen_vfp_shto(dp, 16 - rm, 0);
break;
case 21: /* fslto */
if (!arm_feature(env, ARM_FEATURE_VFP3))
return 1;
if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
return 1;
}
gen_vfp_slto(dp, 32 - rm, 0);
break;
case 22: /* fuhto */
if (!arm_feature(env, ARM_FEATURE_VFP3))
return 1;
if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
return 1;
}
gen_vfp_uhto(dp, 16 - rm, 0);
break;
case 23: /* fulto */
if (!arm_feature(env, ARM_FEATURE_VFP3))
return 1;
if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
return 1;
}
gen_vfp_ulto(dp, 32 - rm, 0);
break;
case 24: /* ftoui */
@ -3676,23 +3684,27 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
gen_vfp_tosiz(dp, 0);
break;
case 28: /* ftosh */
if (!arm_feature(env, ARM_FEATURE_VFP3))
return 1;
if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
return 1;
}
gen_vfp_tosh(dp, 16 - rm, 0);
break;
case 29: /* ftosl */
if (!arm_feature(env, ARM_FEATURE_VFP3))
return 1;
if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
return 1;
}
gen_vfp_tosl(dp, 32 - rm, 0);
break;
case 30: /* ftouh */
if (!arm_feature(env, ARM_FEATURE_VFP3))
return 1;
if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
return 1;
}
gen_vfp_touh(dp, 16 - rm, 0);
break;
case 31: /* ftoul */
if (!arm_feature(env, ARM_FEATURE_VFP3))
return 1;
if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
return 1;
}
gen_vfp_toul(dp, 32 - rm, 0);
break;
default: /* undefined */
@ -3948,7 +3960,8 @@ static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
}
/* Return the mask of PSR bits set by a MSR instruction. */
static uint32_t msr_mask(CPUARMState *env, DisasContext *s, int flags, int spsr) {
static uint32_t msr_mask(DisasContext *s, int flags, int spsr)
{
uint32_t mask;
mask = 0;
@ -3963,14 +3976,18 @@ static uint32_t msr_mask(CPUARMState *env, DisasContext *s, int flags, int spsr)
/* Mask out undefined bits. */
mask &= ~CPSR_RESERVED;
if (!arm_feature(env, ARM_FEATURE_V4T))
if (!arm_dc_feature(s, ARM_FEATURE_V4T)) {
mask &= ~CPSR_T;
if (!arm_feature(env, ARM_FEATURE_V5))
}
if (!arm_dc_feature(s, ARM_FEATURE_V5)) {
mask &= ~CPSR_Q; /* V5TE in reality*/
if (!arm_feature(env, ARM_FEATURE_V6))
}
if (!arm_dc_feature(s, ARM_FEATURE_V6)) {
mask &= ~(CPSR_E | CPSR_GE);
if (!arm_feature(env, ARM_FEATURE_THUMB2))
}
if (!arm_dc_feature(s, ARM_FEATURE_THUMB2)) {
mask &= ~CPSR_IT;
}
/* Mask out execution state and reserved bits. */
if (!spsr) {
mask &= ~(CPSR_EXEC | CPSR_RESERVED);
@ -4294,7 +4311,7 @@ static struct {
/* Translate a NEON load/store element instruction. Return nonzero if the
instruction is invalid. */
static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
{
int rd, rn, rm;
int op;
@ -5036,7 +5053,7 @@ static const uint8_t neon_2rm_sizes[] = {
We process data in a mixture of 32-bit and 64-bit chunks.
Mostly we use 32-bit chunks so we can use normal scalar instructions. */
static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
{
int op;
int q;
@ -5092,7 +5109,7 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins
return 1;
}
if (!u) { /* SHA-1 */
if (!arm_feature(env, ARM_FEATURE_V8_SHA1)) {
if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA1)) {
return 1;
}
tmp = tcg_const_i32(rd);
@ -5102,7 +5119,7 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins
gen_helper_crypto_sha1_3reg(cpu_env, tmp, tmp2, tmp3, tmp4);
tcg_temp_free_i32(tmp4);
} else { /* SHA-256 */
if (!arm_feature(env, ARM_FEATURE_V8_SHA256) || size == 3) {
if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA256) || size == 3) {
return 1;
}
tmp = tcg_const_i32(rd);
@ -5237,7 +5254,7 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins
break;
case NEON_3R_FLOAT_MISC:
/* VMAXNM/VMINNM in ARMv8 */
if (u && !arm_feature(env, ARM_FEATURE_V8)) {
if (u && !arm_dc_feature(s, ARM_FEATURE_V8)) {
return 1;
}
break;
@ -5248,7 +5265,7 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins
}
break;
case NEON_3R_VFM:
if (!arm_feature(env, ARM_FEATURE_VFP4) || u) {
if (!arm_dc_feature(s, ARM_FEATURE_VFP4) || u) {
return 1;
}
break;
@ -6067,7 +6084,7 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins
if (op == 14 && size == 2) {
TCGv_i64 tcg_rn, tcg_rm, tcg_rd;
if (!arm_feature(env, ARM_FEATURE_V8_PMULL)) {
if (!arm_dc_feature(s, ARM_FEATURE_V8_PMULL)) {
return 1;
}
tcg_rn = tcg_temp_new_i64();
@ -6555,7 +6572,7 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins
}
break;
case NEON_2RM_VCVT_F16_F32:
if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
if (!arm_dc_feature(s, ARM_FEATURE_VFP_FP16) ||
q || (rm & 1)) {
return 1;
}
@ -6579,7 +6596,7 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins
tcg_temp_free_i32(tmp);
break;
case NEON_2RM_VCVT_F32_F16:
if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
if (!arm_dc_feature(s, ARM_FEATURE_VFP_FP16) ||
q || (rd & 1)) {
return 1;
}
@ -6603,7 +6620,7 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins
tcg_temp_free_i32(tmp3);
break;
case NEON_2RM_AESE: case NEON_2RM_AESMC:
if (!arm_feature(env, ARM_FEATURE_V8_AES)
if (!arm_dc_feature(s, ARM_FEATURE_V8_AES)
|| ((rm | rd) & 1)) {
return 1;
}
@ -6625,7 +6642,7 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins
tcg_temp_free_i32(tmp3);
break;
case NEON_2RM_SHA1H:
if (!arm_feature(env, ARM_FEATURE_V8_SHA1)
if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA1)
|| ((rm | rd) & 1)) {
return 1;
}
@ -6643,10 +6660,10 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins
}
/* bit 6 (q): set -> SHA256SU0, cleared -> SHA1SU1 */
if (q) {
if (!arm_feature(env, ARM_FEATURE_V8_SHA256)) {
if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA256)) {
return 1;
}
} else if (!arm_feature(env, ARM_FEATURE_V8_SHA1)) {
} else if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA1)) {
return 1;
}
tmp = tcg_const_i32(rd);
@ -7031,7 +7048,7 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins
return 0;
}
static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
static int disas_coproc_insn(DisasContext *s, uint32_t insn)
{
int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
const ARMCPRegInfo *ri;
@ -7039,14 +7056,14 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
cpnum = (insn >> 8) & 0xf;
/* First check for coprocessor space used for XScale/iwMMXt insns */
if (arm_feature(env, ARM_FEATURE_XSCALE) && (cpnum < 2)) {
if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cpnum < 2)) {
if (extract32(s->c15_cpar, cpnum, 1) == 0) {
return 1;
}
if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
return disas_iwmmxt_insn(env, s, insn);
} else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
return disas_dsp_insn(env, s, insn);
if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
return disas_iwmmxt_insn(s, insn);
} else if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) {
return disas_dsp_insn(s, insn);
}
return 1;
}
@ -7082,7 +7099,7 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
}
if (ri->accessfn ||
(arm_feature(env, ARM_FEATURE_XSCALE) && cpnum < 14)) {
(arm_dc_feature(s, ARM_FEATURE_XSCALE) && cpnum < 14)) {
/* Emit code to perform further access permissions checks at
* runtime; this may result in an exception.
* Note that on XScale all cp0..c13 registers do an access check
@ -7125,7 +7142,7 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
* in which case the syndrome information won't actually be
* guest visible.
*/
assert(!arm_feature(env, ARM_FEATURE_V8));
assert(!arm_dc_feature(s, ARM_FEATURE_V8));
syndrome = syn_uncategorized();
break;
}
@ -7543,21 +7560,19 @@ static void gen_srs(DisasContext *s,
tcg_temp_free_i32(addr);
}
static void disas_arm_insn(CPUARMState * env, DisasContext *s)
static void disas_arm_insn(DisasContext *s, unsigned int insn)
{
unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
unsigned int cond, val, op1, i, shift, rm, rs, rn, rd, sh;
TCGv_i32 tmp;
TCGv_i32 tmp2;
TCGv_i32 tmp3;
TCGv_i32 addr;
TCGv_i64 tmp64;
insn = arm_ldl_code(env, s->pc, s->bswap_code);
s->pc += 4;
/* M variants do not implement ARM mode. */
if (IS_M(env))
if (arm_dc_feature(s, ARM_FEATURE_M)) {
goto illegal_op;
}
cond = insn >> 28;
if (cond == 0xf){
/* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
@ -7569,25 +7584,29 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
/* Unconditional instructions. */
if (((insn >> 25) & 7) == 1) {
/* NEON Data processing. */
if (!arm_feature(env, ARM_FEATURE_NEON))
if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
goto illegal_op;
}
if (disas_neon_data_insn(env, s, insn))
if (disas_neon_data_insn(s, insn)) {
goto illegal_op;
}
return;
}
if ((insn & 0x0f100000) == 0x04000000) {
/* NEON load/store. */
if (!arm_feature(env, ARM_FEATURE_NEON))
if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
goto illegal_op;
}
if (disas_neon_ls_insn(env, s, insn))
if (disas_neon_ls_insn(s, insn)) {
goto illegal_op;
}
return;
}
if ((insn & 0x0f000e10) == 0x0e000a00) {
/* VFP. */
if (disas_vfp_insn(env, s, insn)) {
if (disas_vfp_insn(s, insn)) {
goto illegal_op;
}
return;
@ -7596,7 +7615,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
((insn & 0x0f30f010) == 0x0710f000)) {
if ((insn & (1 << 22)) == 0) {
/* PLDW; v7MP */
if (!arm_feature(env, ARM_FEATURE_V7MP)) {
if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
goto illegal_op;
}
}
@ -7611,7 +7630,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
}
if (((insn & 0x0f700000) == 0x04100000) ||
((insn & 0x0f700010) == 0x06100000)) {
if (!arm_feature(env, ARM_FEATURE_V7MP)) {
if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
goto illegal_op;
}
return; /* v7MP: Unallocated memory hint: must NOP */
@ -7708,10 +7727,10 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
gen_bx_im(s, val);
return;
} else if ((insn & 0x0e000f00) == 0x0c000100) {
if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
/* iWMMXt register transfer. */
if (extract32(s->c15_cpar, 1, 1)) {
if (!disas_iwmmxt_insn(env, s, insn)) {
if (!disas_iwmmxt_insn(s, insn)) {
return;
}
}
@ -7784,8 +7803,10 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
if (shift)
val = (val >> shift) | (val << (32 - shift));
i = ((insn & (1 << 22)) != 0);
if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
if (gen_set_psr_im(s, msr_mask(s, (insn >> 16) & 0xf, i),
i, val)) {
goto illegal_op;
}
}
}
} else if ((insn & 0x0f900000) == 0x01000000
@ -7800,7 +7821,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
/* PSR = reg */
tmp = load_reg(s, rm);
i = ((op1 & 2) != 0);
if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
if (gen_set_psr(s, msr_mask(s, (insn >> 16) & 0xf, i), i, tmp))
goto illegal_op;
} else {
/* reg = PSR */
@ -7864,7 +7885,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
* op1 == 3 is UNPREDICTABLE but handle as UNDEFINED.
* Bits 8, 10 and 11 should be zero.
*/
if (!arm_feature(env, ARM_FEATURE_CRC) || op1 == 0x3 ||
if (!arm_dc_feature(s, ARM_FEATURE_CRC) || op1 == 0x3 ||
(c & 0xd) != 0) {
goto illegal_op;
}
@ -8038,14 +8059,14 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
if (logic_cc) {
gen_logic_CC(tmp);
}
store_reg_bx(env, s, rd, tmp);
store_reg_bx(s, rd, tmp);
break;
case 0x01:
tcg_gen_xor_i32(tmp, tmp, tmp2);
if (logic_cc) {
gen_logic_CC(tmp);
}
store_reg_bx(env, s, rd, tmp);
store_reg_bx(s, rd, tmp);
break;
case 0x02:
if (set_cc && rd == 15) {
@ -8061,7 +8082,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
} else {
tcg_gen_sub_i32(tmp, tmp, tmp2);
}
store_reg_bx(env, s, rd, tmp);
store_reg_bx(s, rd, tmp);
}
break;
case 0x03:
@ -8070,7 +8091,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
} else {
tcg_gen_sub_i32(tmp, tmp2, tmp);
}
store_reg_bx(env, s, rd, tmp);
store_reg_bx(s, rd, tmp);
break;
case 0x04:
if (set_cc) {
@ -8078,7 +8099,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
} else {
tcg_gen_add_i32(tmp, tmp, tmp2);
}
store_reg_bx(env, s, rd, tmp);
store_reg_bx(s, rd, tmp);
break;
case 0x05:
if (set_cc) {
@ -8086,7 +8107,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
} else {
gen_add_carry(tmp, tmp, tmp2);
}
store_reg_bx(env, s, rd, tmp);
store_reg_bx(s, rd, tmp);
break;
case 0x06:
if (set_cc) {
@ -8094,7 +8115,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
} else {
gen_sub_carry(tmp, tmp, tmp2);
}
store_reg_bx(env, s, rd, tmp);
store_reg_bx(s, rd, tmp);
break;
case 0x07:
if (set_cc) {
@ -8102,7 +8123,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
} else {
gen_sub_carry(tmp, tmp2, tmp);
}
store_reg_bx(env, s, rd, tmp);
store_reg_bx(s, rd, tmp);
break;
case 0x08:
if (set_cc) {
@ -8135,7 +8156,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
if (logic_cc) {
gen_logic_CC(tmp);
}
store_reg_bx(env, s, rd, tmp);
store_reg_bx(s, rd, tmp);
break;
case 0x0d:
if (logic_cc && rd == 15) {
@ -8148,7 +8169,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
if (logic_cc) {
gen_logic_CC(tmp2);
}
store_reg_bx(env, s, rd, tmp2);
store_reg_bx(s, rd, tmp2);
}
break;
case 0x0e:
@ -8156,7 +8177,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
if (logic_cc) {
gen_logic_CC(tmp);
}
store_reg_bx(env, s, rd, tmp);
store_reg_bx(s, rd, tmp);
break;
default:
case 0x0f:
@ -8164,7 +8185,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
if (logic_cc) {
gen_logic_CC(tmp2);
}
store_reg_bx(env, s, rd, tmp2);
store_reg_bx(s, rd, tmp2);
break;
}
if (op1 != 0x0f && op1 != 0x0d) {
@ -8673,7 +8694,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
case 1:
case 3:
/* SDIV, UDIV */
if (!arm_feature(env, ARM_FEATURE_ARM_DIV)) {
if (!arm_dc_feature(s, ARM_FEATURE_ARM_DIV)) {
goto illegal_op;
}
if (((insn >> 5) & 7) || (rd != 15)) {
@ -8802,7 +8823,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
}
if (insn & (1 << 20)) {
/* Complete the load. */
store_reg_from_load(env, s, rd, tmp);
store_reg_from_load(s, rd, tmp);
}
break;
case 0x08:
@ -8865,7 +8886,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
loaded_var = tmp;
loaded_base = 1;
} else {
store_reg_from_load(env, s, i, tmp);
store_reg_from_load(s, i, tmp);
}
} else {
/* store */
@ -8948,10 +8969,10 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
case 0xe:
if (((insn >> 8) & 0xe) == 10) {
/* VFP. */
if (disas_vfp_insn(env, s, insn)) {
if (disas_vfp_insn(s, insn)) {
goto illegal_op;
}
} else if (disas_coproc_insn(env, s, insn)) {
} else if (disas_coproc_insn(s, insn)) {
/* Coprocessor. */
goto illegal_op;
}
@ -9069,8 +9090,8 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
int conds;
int logic_cc;
if (!(arm_feature(env, ARM_FEATURE_THUMB2)
|| arm_feature (env, ARM_FEATURE_M))) {
if (!(arm_dc_feature(s, ARM_FEATURE_THUMB2)
|| arm_dc_feature(s, ARM_FEATURE_M))) {
/* Thumb-1 cores may need to treat bl and blx as a pair of
16-bit instructions to get correct prefetch abort behavior. */
insn = insn_hw1;
@ -9280,7 +9301,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
/* Load/store multiple, RFE, SRS. */
if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
/* RFE, SRS: not available in user mode or on M profile */
if (IS_USER(s) || IS_M(env)) {
if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
goto illegal_op;
}
if (insn & (1 << 20)) {
@ -9432,7 +9453,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
if (logic_cc)
gen_logic_CC(tmp);
store_reg_bx(env, s, rd, tmp);
store_reg_bx(s, rd, tmp);
break;
case 1: /* Sign/zero extend. */
tmp = load_reg(s, rm);
@ -9523,7 +9544,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
uint32_t sz = op & 0x3;
uint32_t c = op & 0x8;
if (!arm_feature(env, ARM_FEATURE_CRC)) {
if (!arm_dc_feature(s, ARM_FEATURE_CRC)) {
goto illegal_op;
}
@ -9651,7 +9672,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
tmp2 = load_reg(s, rm);
if ((op & 0x50) == 0x10) {
/* sdiv, udiv */
if (!arm_feature(env, ARM_FEATURE_THUMB_DIV)) {
if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DIV)) {
goto illegal_op;
}
if (op & 0x20)
@ -9714,17 +9735,19 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
if (((insn >> 24) & 3) == 3) {
/* Translate into the equivalent ARM encoding. */
insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
if (disas_neon_data_insn(env, s, insn))
if (disas_neon_data_insn(s, insn)) {
goto illegal_op;
}
} else if (((insn >> 8) & 0xe) == 10) {
if (disas_vfp_insn(env, s, insn)) {
if (disas_vfp_insn(s, insn)) {
goto illegal_op;
}
} else {
if (insn & (1 << 28))
goto illegal_op;
if (disas_coproc_insn (env, s, insn))
if (disas_coproc_insn(s, insn)) {
goto illegal_op;
}
}
break;
case 8: case 9: case 10: case 11:
@ -9784,7 +9807,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
op = (insn >> 20) & 7;
switch (op) {
case 0: /* msr cpsr. */
if (IS_M(env)) {
if (arm_dc_feature(s, ARM_FEATURE_M)) {
tmp = load_reg(s, rn);
addr = tcg_const_i32(insn & 0xff);
gen_helper_v7m_msr(cpu_env, addr, tmp);
@ -9795,11 +9818,12 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
}
/* fall through */
case 1: /* msr spsr. */
if (IS_M(env))
if (arm_dc_feature(s, ARM_FEATURE_M)) {
goto illegal_op;
}
tmp = load_reg(s, rn);
if (gen_set_psr(s,
msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
msr_mask(s, (insn >> 8) & 0xf, op == 1),
op == 1, tmp))
goto illegal_op;
break;
@ -9864,7 +9888,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
break;
case 6: /* mrs cpsr. */
tmp = tcg_temp_new_i32();
if (IS_M(env)) {
if (arm_dc_feature(s, ARM_FEATURE_M)) {
addr = tcg_const_i32(insn & 0xff);
gen_helper_v7m_mrs(tmp, cpu_env, addr);
tcg_temp_free_i32(addr);
@ -9875,8 +9899,9 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
break;
case 7: /* mrs spsr. */
/* Not accessible in user mode. */
if (IS_USER(s) || IS_M(env))
if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
goto illegal_op;
}
tmp = load_cpu_field(spsr);
store_reg(s, rd, tmp);
break;
@ -10064,8 +10089,9 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
int writeback = 0;
int memidx;
if ((insn & 0x01100000) == 0x01000000) {
if (disas_neon_ls_insn(env, s, insn))
if (disas_neon_ls_insn(s, insn)) {
goto illegal_op;
}
break;
}
op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
@ -10761,7 +10787,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
store_reg(s, 13, addr);
/* set the new PC value */
if ((insn & 0x0900) == 0x0900) {
store_reg_from_load(env, s, 15, tmp);
store_reg_from_load(s, 15, tmp);
}
break;
@ -10831,7 +10857,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
if (IS_USER(s)) {
break;
}
if (IS_M(env)) {
if (arm_dc_feature(s, ARM_FEATURE_M)) {
tmp = tcg_const_i32((insn & (1 << 4)) != 0);
/* FAULTMASK */
if (insn & 1) {
@ -11103,7 +11129,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
break;
}
#else
if (dc->pc >= 0xfffffff0 && IS_M(env)) {
if (dc->pc >= 0xfffffff0 && arm_dc_feature(dc, ARM_FEATURE_M)) {
/* We always get here via a jump, so know we are not in a
conditional execution block. */
gen_exception_internal(EXCP_EXCEPTION_EXIT);
@ -11170,7 +11196,9 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
}
}
} else {
disas_arm_insn(env, dc);
unsigned int insn = arm_ldl_code(env, dc->pc, dc->bswap_code);
dc->pc += 4;
disas_arm_insn(dc, insn);
}
if (dc->condjmp && !dc->is_jmp) {