mirror of https://gitee.com/openkylin/qemu.git
target-arm: Convert WFI/barriers special cases to cp_reginfo
Convert the various WFI and barrier instruction special cases to use cp_reginfo infrastructure. Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
c326b9796f
commit
7d57f40877
|
@ -66,6 +66,38 @@ static const ARMCPRegInfo cp_reginfo[] = {
|
|||
REGINFO_SENTINEL
|
||||
};
|
||||
|
||||
static const ARMCPRegInfo not_v6_cp_reginfo[] = {
|
||||
/* Not all pre-v6 cores implemented this WFI, so this is slightly
|
||||
* over-broad.
|
||||
*/
|
||||
{ .name = "WFI_v5", .cp = 15, .crn = 7, .crm = 8, .opc1 = 0, .opc2 = 2,
|
||||
.access = PL1_W, .type = ARM_CP_WFI },
|
||||
REGINFO_SENTINEL
|
||||
};
|
||||
|
||||
static const ARMCPRegInfo not_v7_cp_reginfo[] = {
|
||||
/* Standard v6 WFI (also used in some pre-v6 cores); not in v7 (which
|
||||
* is UNPREDICTABLE; we choose to NOP as most implementations do).
|
||||
*/
|
||||
{ .name = "WFI_v6", .cp = 15, .crn = 7, .crm = 0, .opc1 = 0, .opc2 = 4,
|
||||
.access = PL1_W, .type = ARM_CP_WFI },
|
||||
REGINFO_SENTINEL
|
||||
};
|
||||
|
||||
static const ARMCPRegInfo v6_cp_reginfo[] = {
|
||||
/* prefetch by MVA in v6, NOP in v7 */
|
||||
{ .name = "MVA_prefetch",
|
||||
.cp = 15, .crn = 7, .crm = 13, .opc1 = 0, .opc2 = 1,
|
||||
.access = PL1_W, .type = ARM_CP_NOP },
|
||||
{ .name = "ISB", .cp = 15, .crn = 7, .crm = 5, .opc1 = 0, .opc2 = 4,
|
||||
.access = PL0_W, .type = ARM_CP_NOP },
|
||||
{ .name = "ISB", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 4,
|
||||
.access = PL0_W, .type = ARM_CP_NOP },
|
||||
{ .name = "ISB", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 5,
|
||||
.access = PL0_W, .type = ARM_CP_NOP },
|
||||
REGINFO_SENTINEL
|
||||
};
|
||||
|
||||
static const ARMCPRegInfo v7_cp_reginfo[] = {
|
||||
/* DBGDRAR, DBGDSAR: always RAZ since we don't implement memory mapped
|
||||
* debug components
|
||||
|
@ -74,6 +106,9 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
|
|||
.access = PL0_R, .type = ARM_CP_CONST, .resetvalue = 0 },
|
||||
{ .name = "DBGDRAR", .cp = 14, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0,
|
||||
.access = PL0_R, .type = ARM_CP_CONST, .resetvalue = 0 },
|
||||
/* the old v6 WFI, UNPREDICTABLE in v7 but we choose to NOP */
|
||||
{ .name = "NOP", .cp = 15, .crn = 7, .crm = 0, .opc1 = 0, .opc2 = 4,
|
||||
.access = PL1_W, .type = ARM_CP_NOP },
|
||||
REGINFO_SENTINEL
|
||||
};
|
||||
|
||||
|
@ -129,8 +164,15 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
|||
}
|
||||
|
||||
define_arm_cp_regs(cpu, cp_reginfo);
|
||||
if (arm_feature(env, ARM_FEATURE_V6)) {
|
||||
define_arm_cp_regs(cpu, v6_cp_reginfo);
|
||||
} else {
|
||||
define_arm_cp_regs(cpu, not_v6_cp_reginfo);
|
||||
}
|
||||
if (arm_feature(env, ARM_FEATURE_V7)) {
|
||||
define_arm_cp_regs(cpu, v7_cp_reginfo);
|
||||
} else {
|
||||
define_arm_cp_regs(cpu, not_v7_cp_reginfo);
|
||||
}
|
||||
if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
|
||||
define_arm_cp_regs(cpu, t2ee_cp_reginfo);
|
||||
|
|
|
@ -2541,57 +2541,6 @@ static int disas_cp15_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
|
|||
/* cdp */
|
||||
return 1;
|
||||
}
|
||||
/* We special case a number of cp15 instructions which were used
|
||||
* for things which are real instructions in ARMv7. This allows
|
||||
* them to work in linux-user mode which doesn't provide functional
|
||||
* get_cp15/set_cp15 helpers, and is more efficient anyway.
|
||||
*/
|
||||
switch ((insn & 0x0fff0fff)) {
|
||||
case 0x0e070f90:
|
||||
/* 0,c7,c0,4: Standard v6 WFI (also used in some pre-v6 cores).
|
||||
* In v7, this must NOP.
|
||||
*/
|
||||
if (IS_USER(s)) {
|
||||
return 1;
|
||||
}
|
||||
if (!arm_feature(env, ARM_FEATURE_V7)) {
|
||||
/* Wait for interrupt. */
|
||||
gen_set_pc_im(s->pc);
|
||||
s->is_jmp = DISAS_WFI;
|
||||
}
|
||||
return 0;
|
||||
case 0x0e070f58:
|
||||
/* 0,c7,c8,2: Not all pre-v6 cores implemented this WFI,
|
||||
* so this is slightly over-broad.
|
||||
*/
|
||||
if (!IS_USER(s) && !arm_feature(env, ARM_FEATURE_V6)) {
|
||||
/* Wait for interrupt. */
|
||||
gen_set_pc_im(s->pc);
|
||||
s->is_jmp = DISAS_WFI;
|
||||
return 0;
|
||||
}
|
||||
/* Otherwise continue to handle via helper function.
|
||||
* In particular, on v7 and some v6 cores this is one of
|
||||
* the VA-PA registers.
|
||||
*/
|
||||
break;
|
||||
case 0x0e070f3d:
|
||||
/* 0,c7,c13,1: prefetch-by-MVA in v6, NOP in v7 */
|
||||
if (arm_feature(env, ARM_FEATURE_V6)) {
|
||||
return IS_USER(s) ? 1 : 0;
|
||||
}
|
||||
break;
|
||||
case 0x0e070f95: /* 0,c7,c5,4 : ISB */
|
||||
case 0x0e070f9a: /* 0,c7,c10,4: DSB */
|
||||
case 0x0e070fba: /* 0,c7,c10,5: DMB */
|
||||
/* Barriers in both v6 and v7 */
|
||||
if (arm_feature(env, ARM_FEATURE_V6)) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (IS_USER(s) && !cp15_user_ok(env, insn)) {
|
||||
return 1;
|
||||
|
|
Loading…
Reference in New Issue