diff options
Diffstat (limited to 'target/openrisc')
-rw-r--r-- | target/openrisc/cpu.c | 1 | ||||
-rw-r--r-- | target/openrisc/cpu.h | 2 | ||||
-rw-r--r-- | target/openrisc/fpu_helper.c | 13 | ||||
-rw-r--r-- | target/openrisc/machine.c | 11 | ||||
-rw-r--r-- | target/openrisc/sys_helper.c | 16 |
5 files changed, 38 insertions, 5 deletions
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c index b931605e62..f96a69e278 100644 --- a/target/openrisc/cpu.c +++ b/target/openrisc/cpu.c @@ -55,6 +55,7 @@ static void openrisc_cpu_reset(CPUState *s) cpu->env.sr = SR_FO | SR_SM; cpu->env.lock_addr = -1; s->exception_index = -1; + cpu_set_fpcsr(&cpu->env, 0); #ifndef CONFIG_USER_ONLY cpu->env.picmr = 0x00000000; diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h index 71c5959828..0ad02eab79 100644 --- a/target/openrisc/cpu.h +++ b/target/openrisc/cpu.h @@ -413,6 +413,8 @@ static inline void cpu_set_sr(CPUOpenRISCState *env, uint32_t val) env->sr = (val & ~(SR_F | SR_CY | SR_OV)) | SR_FO; } +void cpu_set_fpcsr(CPUOpenRISCState *env, uint32_t val); + #define CPU_INTERRUPT_TIMER CPU_INTERRUPT_TGT_INT_0 #endif /* OPENRISC_CPU_H */ diff --git a/target/openrisc/fpu_helper.c b/target/openrisc/fpu_helper.c index 7bcef9dc53..59e1413279 100644 --- a/target/openrisc/fpu_helper.c +++ b/target/openrisc/fpu_helper.c @@ -61,6 +61,19 @@ void HELPER(update_fpcsr)(CPUOpenRISCState *env) } } +void cpu_set_fpcsr(CPUOpenRISCState *env, uint32_t val) +{ + static const int rm_to_sf[] = { + float_round_nearest_even, + float_round_to_zero, + float_round_up, + float_round_down + }; + + env->fpcsr = val & 0x7ff; + set_float_rounding_mode(rm_to_sf[extract32(val, 1, 2)], &env->fp_status); +} + uint64_t HELPER(itofd)(CPUOpenRISCState *env, uint64_t val) { return int64_to_float64(val, &env->fp_status); diff --git a/target/openrisc/machine.c b/target/openrisc/machine.c index 0a96404dc6..b92985d99b 100644 --- a/target/openrisc/machine.c +++ b/target/openrisc/machine.c @@ -121,10 +121,21 @@ static const VMStateDescription vmstate_env = { } }; +static int cpu_post_load(void *opaque, int version_id) +{ + OpenRISCCPU *cpu = opaque; + CPUOpenRISCState *env = &cpu->env; + + /* Update env->fp_status to match env->fpcsr. */ + cpu_set_fpcsr(env, env->fpcsr); + return 0; +} + const VMStateDescription vmstate_openrisc_cpu = { .name = "cpu", .version_id = 1, .minimum_version_id = 1, + .post_load = cpu_post_load, .fields = (VMStateField[]) { VMSTATE_CPU(), VMSTATE_STRUCT(env, OpenRISCCPU, 1, vmstate_env, CPUOpenRISCState), diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c index cf8e637b08..d9fe6c5948 100644 --- a/target/openrisc/sys_helper.c +++ b/target/openrisc/sys_helper.c @@ -37,8 +37,10 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb) CPUState *cs = env_cpu(env); target_ulong mr; int idx; +#endif switch (spr) { +#ifndef CONFIG_USER_ONLY case TO_SPR(0, 11): /* EVBAR */ env->evbar = rb; break; @@ -179,10 +181,12 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb) } cpu_openrisc_timer_update(cpu); break; - default: +#endif + + case TO_SPR(0, 20): /* FPCSR */ + cpu_set_fpcsr(env, rb); break; } -#endif } target_ulong HELPER(mfspr)(CPUOpenRISCState *env, target_ulong rd, @@ -193,8 +197,10 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, target_ulong rd, OpenRISCCPU *cpu = env_archcpu(env); CPUState *cs = env_cpu(env); int idx; +#endif switch (spr) { +#ifndef CONFIG_USER_ONLY case TO_SPR(0, 0): /* VR */ return env->vr; @@ -303,11 +309,11 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, target_ulong rd, case TO_SPR(10, 1): /* TTCR */ cpu_openrisc_count_update(cpu); return cpu_openrisc_count_get(cpu); +#endif - default: - break; + case TO_SPR(0, 20): /* FPCSR */ + return env->fpcsr; } -#endif /* for rd is passed in, if rd unchanged, just keep it back. */ return rd; |