aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
Diffstat (limited to 'target')
-rw-r--r--target/hppa/cpu.c2
-rw-r--r--target/hppa/cpu.h5
-rw-r--r--target/hppa/helper.h1
-rw-r--r--target/hppa/insns.decode1
-rw-r--r--target/hppa/int_helper.c19
-rw-r--r--target/hppa/op_helper.c7
-rw-r--r--target/hppa/translate.c10
7 files changed, 42 insertions, 3 deletions
diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
index 23eb254..37b763f 100644
--- a/target/hppa/cpu.c
+++ b/target/hppa/cpu.c
@@ -62,7 +62,7 @@ static void hppa_cpu_synchronize_from_tb(CPUState *cs,
static bool hppa_cpu_has_work(CPUState *cs)
{
- return cs->interrupt_request & CPU_INTERRUPT_HARD;
+ return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
}
static void hppa_cpu_disas_set_info(CPUState *cs, disassemble_info *info)
diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index 45fd338..93c1195 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -69,6 +69,11 @@
#define EXCP_SYSCALL 30
#define EXCP_SYSCALL_LWS 31
+/* Emulated hardware TOC button */
+#define EXCP_TOC 32 /* TOC = Transfer of control (NMI) */
+
+#define CPU_INTERRUPT_NMI CPU_INTERRUPT_TGT_EXT_3 /* TOC */
+
/* Taken from Linux kernel: arch/parisc/include/asm/psw.h */
#define PSW_I 0x00000001
#define PSW_D 0x00000002
diff --git a/target/hppa/helper.h b/target/hppa/helper.h
index 0a629ff..fe8a9ce 100644
--- a/target/hppa/helper.h
+++ b/target/hppa/helper.h
@@ -80,6 +80,7 @@ DEF_HELPER_FLAGS_0(read_interval_timer, TCG_CALL_NO_RWG, tr)
#ifndef CONFIG_USER_ONLY
DEF_HELPER_1(halt, noreturn, env)
DEF_HELPER_1(reset, noreturn, env)
+DEF_HELPER_1(getshadowregs, void, 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/insns.decode b/target/hppa/insns.decode
index d4eefc0..c7a7e99 100644
--- a/target/hppa/insns.decode
+++ b/target/hppa/insns.decode
@@ -111,6 +111,7 @@ rfi_r 000000 ----- ----- --- 01100101 00000
# They are allocated from the unassigned instruction space.
halt 1111 1111 1111 1101 1110 1010 1101 0000
reset 1111 1111 1111 1101 1110 1010 1101 0001
+getshadowregs 1111 1111 1111 1101 1110 1010 1101 0010
####
# Memory Management
diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c
index 13073ae..f599dcc 100644
--- a/target/hppa/int_helper.c
+++ b/target/hppa/int_helper.c
@@ -23,6 +23,7 @@
#include "cpu.h"
#include "exec/helper-proto.h"
#include "hw/core/cpu.h"
+#include "hw/hppa/hppa_hardware.h"
#ifndef CONFIG_USER_ONLY
static void eval_interrupt(HPPACPU *cpu)
@@ -181,7 +182,14 @@ void hppa_cpu_do_interrupt(CPUState *cs)
}
/* step 7 */
- env->iaoq_f = env->cr[CR_IVA] + 32 * i;
+ if (i == EXCP_TOC) {
+ env->iaoq_f = FIRMWARE_START;
+ /* help SeaBIOS and provide iaoq_b and iasq_back in shadow regs */
+ env->gr[24] = env->cr_back[0];
+ env->gr[25] = env->cr_back[1];
+ } else {
+ env->iaoq_f = env->cr[CR_IVA] + 32 * i;
+ }
env->iaoq_b = env->iaoq_f + 4;
env->iasq_f = 0;
env->iasq_b = 0;
@@ -219,6 +227,7 @@ void hppa_cpu_do_interrupt(CPUState *cs)
[EXCP_PER_INTERRUPT] = "performance monitor interrupt",
[EXCP_SYSCALL] = "syscall",
[EXCP_SYSCALL_LWS] = "syscall-lws",
+ [EXCP_TOC] = "TOC (transfer of control)",
};
static int count;
const char *name = NULL;
@@ -248,6 +257,14 @@ bool hppa_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
HPPACPU *cpu = HPPA_CPU(cs);
CPUHPPAState *env = &cpu->env;
+ if (interrupt_request & CPU_INTERRUPT_NMI) {
+ /* Raise TOC (NMI) interrupt */
+ cpu_reset_interrupt(cs, CPU_INTERRUPT_NMI);
+ cs->exception_index = EXCP_TOC;
+ hppa_cpu_do_interrupt(cs);
+ return true;
+ }
+
/* If interrupts are requested and enabled, raise them. */
if ((env->psw & PSW_I) && (interrupt_request & CPU_INTERRUPT_HARD)) {
cs->exception_index = EXCP_EXT_INTERRUPT;
diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c
index 1b86557..b0dec4e 100644
--- a/target/hppa/op_helper.c
+++ b/target/hppa/op_helper.c
@@ -694,7 +694,7 @@ void HELPER(rfi)(CPUHPPAState *env)
cpu_hppa_put_psw(env, env->cr[CR_IPSW]);
}
-void HELPER(rfi_r)(CPUHPPAState *env)
+void HELPER(getshadowregs)(CPUHPPAState *env)
{
env->gr[1] = env->shadow[0];
env->gr[8] = env->shadow[1];
@@ -703,6 +703,11 @@ void HELPER(rfi_r)(CPUHPPAState *env)
env->gr[17] = env->shadow[4];
env->gr[24] = env->shadow[5];
env->gr[25] = env->shadow[6];
+}
+
+void HELPER(rfi_r)(CPUHPPAState *env)
+{
+ helper_getshadowregs(env);
helper_rfi(env);
}
#endif
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index c619559..5c0b1eb 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -2393,6 +2393,16 @@ static bool trans_reset(DisasContext *ctx, arg_reset *a)
#endif
}
+static bool trans_getshadowregs(DisasContext *ctx, arg_getshadowregs *a)
+{
+ CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
+#ifndef CONFIG_USER_ONLY
+ nullify_over(ctx);
+ gen_helper_getshadowregs(cpu_env);
+ return nullify_end(ctx);
+#endif
+}
+
static bool trans_nop_addrx(DisasContext *ctx, arg_ldst *a)
{
if (a->m) {