target/hppa: Implement rfi

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2017-10-11 08:54:49 -07:00
parent 7f221b0706
commit f49b3537cb
4 changed files with 55 additions and 2 deletions

View File

@ -178,6 +178,7 @@ struct CPUHPPAState {
target_ureg cr[32]; /* control registers */
target_ureg cr_back[2]; /* back of cr17/cr18 */
target_ureg shadow[7]; /* shadow registers */
/* Those resources are used only in QEMU core */
CPU_COMMON

View File

@ -78,5 +78,7 @@ DEF_HELPER_FLAGS_4(fmpyfadd_d, TCG_CALL_NO_RWG, i64, env, i64, i64, i64)
DEF_HELPER_FLAGS_4(fmpynfadd_d, TCG_CALL_NO_RWG, i64, env, i64, i64, i64)
#ifndef CONFIG_USER_ONLY
DEF_HELPER_1(rfi, void, env)
DEF_HELPER_1(rfi_r, void, env)
DEF_HELPER_FLAGS_2(swap_system_mask, TCG_CALL_NO_RWG, tr, env, tr)
#endif

View File

@ -614,4 +614,28 @@ target_ureg HELPER(swap_system_mask)(CPUHPPAState *env, target_ureg nsm)
env->psw = (psw & ~PSW_SM) | (nsm & PSW_SM);
return psw & PSW_SM;
}
void HELPER(rfi)(CPUHPPAState *env)
{
/* ??? On second reading this condition simply seems
to be undefined rather than a diagnosed trap. */
if (env->psw & (PSW_I | PSW_R | PSW_Q)) {
helper_excp(env, EXCP_ILL);
}
env->iaoq_f = env->cr[CR_IIAOQ];
env->iaoq_b = env->cr_back[1];
cpu_hppa_put_psw(env, env->cr[CR_IPSW]);
}
void HELPER(rfi_r)(CPUHPPAState *env)
{
env->gr[1] = env->shadow[0];
env->gr[8] = env->shadow[1];
env->gr[9] = env->shadow[2];
env->gr[16] = env->shadow[3];
env->gr[17] = env->shadow[4];
env->gr[24] = env->shadow[5];
env->gr[25] = env->shadow[6];
helper_rfi(env);
}
#endif

View File

@ -655,6 +655,10 @@ static DisasJumpType nullify_end(DisasContext *ctx, DisasJumpType status)
{
TCGLabel *null_lab = ctx->null_lab;
/* For NEXT, NORETURN, STALE, we can easily continue (or exit).
For UPDATED, we cannot update on the nullified path. */
assert(status != DISAS_IAQ_N_UPDATED);
if (likely(null_lab == NULL)) {
/* The current insn wasn't conditional or handled the condition
applied to it without a branch, so the (new) setting of
@ -676,8 +680,6 @@ static DisasJumpType nullify_end(DisasContext *ctx, DisasJumpType status)
gen_set_label(null_lab);
ctx->null_cond = cond_make_n();
}
assert(status != DISAS_NORETURN && status != DISAS_IAQ_N_UPDATED);
if (status == DISAS_NORETURN) {
status = DISAS_NEXT;
}
@ -2153,6 +2155,29 @@ static DisasJumpType trans_mtsm(DisasContext *ctx, uint32_t insn,
/* Exit the TB to recognize new interrupts. */
return nullify_end(ctx, DISAS_IAQ_N_STALE_EXIT);
}
static DisasJumpType trans_rfi(DisasContext *ctx, uint32_t insn,
const DisasInsn *di)
{
unsigned comp = extract32(insn, 5, 4);
CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
nullify_over(ctx);
if (comp == 5) {
gen_helper_rfi_r(cpu_env);
} else {
gen_helper_rfi(cpu_env);
}
if (ctx->base.singlestep_enabled) {
gen_excp_1(EXCP_DEBUG);
} else {
tcg_gen_exit_tb(0);
}
/* Exit the TB to recognize new interrupts. */
return nullify_end(ctx, DISAS_NORETURN);
}
#endif /* !CONFIG_USER_ONLY */
static const DisasInsn table_system[] = {
@ -2169,6 +2194,7 @@ static const DisasInsn table_system[] = {
{ 0x00000e60u, 0xfc00ffe0u, trans_rsm },
{ 0x00000d60u, 0xfc00ffe0u, trans_ssm },
{ 0x00001860u, 0xffe0ffffu, trans_mtsm },
{ 0x00000c00u, 0xfffffe1fu, trans_rfi },
#endif
};