summaryrefslogtreecommitdiff
path: root/target/hppa/translate.c
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2017-10-11 08:54:49 -0700
committerRichard Henderson <richard.henderson@linaro.org>2018-01-30 10:08:18 -0800
commitf49b3537cb28b98284f6ce893ef7240a3cacded3 (patch)
tree11ba5dc8cb901dfd3e26de1df3d6cbd90052ca80 /target/hppa/translate.c
parent7f221b0706f7ab8359cb9008650dc7370238839c (diff)
downloadqemu-f49b3537cb28b98284f6ce893ef7240a3cacded3.tar.gz
target/hppa: Implement rfi
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'target/hppa/translate.c')
-rw-r--r--target/hppa/translate.c30
1 files changed, 28 insertions, 2 deletions
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 8ca58f3df3..df0bb04907 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -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
};