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>
master
Peter Maydell 2012-06-20 11:57:11 +00:00
parent c326b9796f
commit 7d57f40877
2 changed files with 42 additions and 51 deletions

View File

@ -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);

View File

@ -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;