Real hardware would use an external device to control the power. But for the moment let's invent an instruction in reserved space.
Suggested-by: Helge Deller <del...@gmx.de> Signed-off-by: Richard Henderson <richard.hender...@linaro.org> --- target/hppa/helper.h | 1 + target/hppa/op_helper.c | 7 +++++++ target/hppa/translate.c | 18 +++++++++++++++++- 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/target/hppa/helper.h b/target/hppa/helper.h index 1e733b7926..6e86c596fe 100644 --- a/target/hppa/helper.h +++ b/target/hppa/helper.h @@ -80,6 +80,7 @@ DEF_HELPER_FLAGS_4(fmpynfadd_d, TCG_CALL_NO_RWG, i64, env, i64, i64, i64) DEF_HELPER_FLAGS_0(read_interval_timer, TCG_CALL_NO_RWG, tr) #ifndef CONFIG_USER_ONLY +DEF_HELPER_1(shutdown, noreturn, env) DEF_HELPER_1(rfi, void, env) DEF_HELPER_1(rfi_r, void, env) DEF_HELPER_FLAGS_2(write_interval_timer, TCG_CALL_NO_RWG, void, env, tr) diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c index d270f94e31..88be2ebf24 100644 --- a/target/hppa/op_helper.c +++ b/target/hppa/op_helper.c @@ -22,6 +22,7 @@ #include "exec/exec-all.h" #include "exec/helper-proto.h" #include "exec/cpu_ldst.h" +#include "sysemu/sysemu.h" #include "qemu/timer.h" @@ -639,6 +640,12 @@ void HELPER(write_interval_timer)(CPUHPPAState *env, target_ureg val) timer_mod(cpu->alarm_timer, timeout); } +void HELPER(shutdown)(CPUHPPAState *env) +{ + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); + helper_excp(env, EXCP_HLT); +} + target_ureg HELPER(swap_system_mask)(CPUHPPAState *env, target_ureg nsm) { target_ulong psw = env->psw; diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 00a8c26afa..68f0b86c72 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -2293,6 +2293,14 @@ static DisasJumpType trans_rfi(DisasContext *ctx, uint32_t insn, /* Exit the TB to recognize new interrupts. */ return nullify_end(ctx, DISAS_NORETURN); } + +static DisasJumpType gen_hlt(DisasContext *ctx) +{ + CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); + nullify_over(ctx); + gen_helper_shutdown(cpu_env); + return nullify_end(ctx, DISAS_NORETURN); +} #endif /* !CONFIG_USER_ONLY */ static const DisasInsn table_system[] = { @@ -4510,7 +4518,15 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) case 0x15: /* unassigned */ case 0x1D: /* unassigned */ case 0x37: /* unassigned */ - case 0x3F: /* unassigned */ + break; + case 0x3F: +#ifndef CONFIG_USER_ONLY + /* Unassigned, but use as system-halt. */ + if (insn == 0xffffffff) { + return gen_hlt(ctx); + } +#endif + break; default: break; } -- 2.14.3