aboutsummaryrefslogtreecommitdiff
path: root/target/openrisc/sys_helper.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2016-04-05 11:41:48 -0700
committerRichard Henderson <rth@twiddle.net>2017-02-14 08:15:00 +1100
commit24c328521b19aff2559118809ddf0522d6dfaaea (patch)
treed8bd63c5a682fbc3aeb9d019195059928c482477 /target/openrisc/sys_helper.c
parenta8000cb480c8cfb612b039bf0382c41b9d6c7d45 (diff)
target/openrisc: Tidy ppc/npc implementation
The NPC SPR is really only supposed to be used for FPGA debugging. It contains the same contents as PC, unless one plays games. Follow the or1ksim implementation in flushing delayed branch state when it is changed. The PPC SPR need not be updated every instruction, merely when we exit the TB or attempt to read its contents. Signed-off-by: Richard Henderson <rth@twiddle.net>
Diffstat (limited to 'target/openrisc/sys_helper.c')
-rw-r--r--target/openrisc/sys_helper.c44
1 files changed, 16 insertions, 28 deletions
diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c
index 9841a5bb27..0968901426 100644
--- a/target/openrisc/sys_helper.c
+++ b/target/openrisc/sys_helper.c
@@ -29,11 +29,10 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
target_ulong ra, target_ulong rb, target_ulong offset)
{
#ifndef CONFIG_USER_ONLY
- int spr = (ra | offset);
- int idx;
-
OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
CPUState *cs = CPU(cpu);
+ int spr = (ra | offset);
+ int idx;
switch (spr) {
case TO_SPR(0, 0): /* VR */
@@ -41,7 +40,14 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
break;
case TO_SPR(0, 16): /* NPC */
- env->npc = rb;
+ cpu_restore_state(cs, GETPC());
+ /* ??? Mirror or1ksim in not trashing delayed branch state
+ when "jumping" to the current instruction. */
+ if (env->pc != rb) {
+ env->pc = rb;
+ env->flags = 0;
+ cpu_loop_exit(cs);
+ }
break;
case TO_SPR(0, 17): /* SR */
@@ -170,7 +176,6 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
cpu_openrisc_timer_update(cpu);
break;
default:
-
break;
}
#endif
@@ -180,11 +185,11 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
target_ulong rd, target_ulong ra, uint32_t offset)
{
#ifndef CONFIG_USER_ONLY
+ OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
+ CPUState *cs = CPU(cpu);
int spr = (ra | offset);
int idx;
- OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
-
switch (spr) {
case TO_SPR(0, 0): /* VR */
return env->vr & SPR_VR;
@@ -201,13 +206,15 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
case TO_SPR(0, 4): /* IMMUCFGR */
return env->immucfgr;
- case TO_SPR(0, 16): /* NPC */
- return env->npc;
+ case TO_SPR(0, 16): /* NPC (equals PC) */
+ cpu_restore_state(cs, GETPC());
+ return env->pc;
case TO_SPR(0, 17): /* SR */
return cpu_get_sr(env);
case TO_SPR(0, 18): /* PPC */
+ cpu_restore_state(cs, GETPC());
return env->ppc;
case TO_SPR(0, 32): /* EPCR */
@@ -276,25 +283,6 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
}
#endif
-/*If we later need to add tracepoints (or debug printfs) for the return
-value, it may be useful to structure the code like this:
-
-target_ulong ret = 0;
-
-switch() {
-case x:
- ret = y;
- break;
-case z:
- ret = 42;
- break;
-...
-}
-
-later something like trace_spr_read(ret);
-
-return ret;*/
-
/* for rd is passed in, if rd unchanged, just keep it back. */
return rd;
}