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
|
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[] = {
|
static const ARMCPRegInfo v7_cp_reginfo[] = {
|
||||||
/* DBGDRAR, DBGDSAR: always RAZ since we don't implement memory mapped
|
/* DBGDRAR, DBGDSAR: always RAZ since we don't implement memory mapped
|
||||||
* debug components
|
* debug components
|
||||||
|
@ -74,6 +106,9 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
|
||||||
.access = PL0_R, .type = ARM_CP_CONST, .resetvalue = 0 },
|
.access = PL0_R, .type = ARM_CP_CONST, .resetvalue = 0 },
|
||||||
{ .name = "DBGDRAR", .cp = 14, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0,
|
{ .name = "DBGDRAR", .cp = 14, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0,
|
||||||
.access = PL0_R, .type = ARM_CP_CONST, .resetvalue = 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
|
REGINFO_SENTINEL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -129,8 +164,15 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||||
}
|
}
|
||||||
|
|
||||||
define_arm_cp_regs(cpu, cp_reginfo);
|
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)) {
|
if (arm_feature(env, ARM_FEATURE_V7)) {
|
||||||
define_arm_cp_regs(cpu, v7_cp_reginfo);
|
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)) {
|
if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
|
||||||
define_arm_cp_regs(cpu, t2ee_cp_reginfo);
|
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 */
|
/* cdp */
|
||||||
return 1;
|
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)) {
|
if (IS_USER(s) && !cp15_user_ok(env, insn)) {
|
||||||
return 1;
|
return 1;
|
||||||
|
|
Loading…
Reference in New Issue