@@ -20,8 +20,27 @@
#include "cpu.h"
#include "exception.h"
-void QEMU_NORETURN raise_exception(OpenRISCCPU *cpu, uint32_t excp)
+void QEMU_NORETURN do_raise_exception(OpenRISCCPU *cpu,
+ uint32_t exception,
+ uintptr_t pc)
{
- cpu->env.exception_index = excp;
+ TranslationBlock *tb;
+
+ /* openrisc cpu has fifteen exceptions */
+ if (exception < 0xe)
+ qemu_log("%s: %d\n", __func__, exception);
+
+ cpu->env.exception_index = exception;
+
+ if (pc) {
+ /* now we have a real cpu fault */
+ tb = tb_find_pc(pc);
+ if (tb) {
+ /* the PC is inside the translated code. It means that we have
+ a virtual CPU fault */
+ cpu_restore_state(tb, &cpu->env, pc);
+ }
+ }
+
cpu_loop_exit(&cpu->env);
}
@@ -23,6 +23,7 @@
#include "cpu.h"
#include "qemu-common.h"
-void QEMU_NORETURN raise_exception(OpenRISCCPU *cpu, uint32_t excp);
-
+void QEMU_NORETURN do_raise_exception(OpenRISCCPU *cpu,
+ uint32_t exception,
+ uintptr_t pc);
#endif /* QEMU_OPENRISC_EXCP_H */
@@ -25,5 +25,5 @@ void HELPER(exception)(CPUOpenRISCState *env, uint32_t excp)
{
OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
- raise_exception(cpu, excp);
+ do_raise_exception(cpu, excp, 0);
}
@@ -51,17 +51,21 @@ static inline uint32_t ieee_ex_to_openrisc(OpenRISCCPU *cpu, int fexcp)
return ret;
}
-static inline void update_fpcsr(OpenRISCCPU *cpu)
+static inline void update_fpcsr(OpenRISCCPU *cpu, uintptr_t pc)
{
int tmp = ieee_ex_to_openrisc(cpu,
get_float_exception_flags(&cpu->env.fp_status));
SET_FP_CAUSE(cpu->env.fpcsr, tmp);
- if ((GET_FP_ENABLE(cpu->env.fpcsr) & tmp) &&
- (cpu->env.fpcsr & FPCSR_FPEE)) {
- helper_exception(&cpu->env, EXCP_FPE);
- } else {
- UPDATE_FP_FLAGS(cpu->env.fpcsr, tmp);
+ if (tmp) {
+ set_float_exception_flags(0, &cpu->env.fp_status);
+
+ if ((GET_FP_ENABLE(cpu->env.fpcsr) & tmp) &&
+ (cpu->env.fpcsr & FPCSR_FPEE)) {
+ do_raise_exception(cpu, EXCP_FPE, pc);
+ } else {
+ UPDATE_FP_FLAGS(cpu->env.fpcsr, tmp);
+ }
}
}
@@ -72,7 +76,7 @@ uint64_t HELPER(itofd)(CPUOpenRISCState *env, uint64_t val)
set_float_exception_flags(0, &cpu->env.fp_status);
itofd = int32_to_float64(val, &cpu->env.fp_status);
- update_fpcsr(cpu);
+ update_fpcsr(cpu, GETPC());
return itofd;
}
@@ -84,7 +88,7 @@ uint32_t HELPER(itofs)(CPUOpenRISCState *env, uint32_t val)
set_float_exception_flags(0, &cpu->env.fp_status);
itofs = int32_to_float32(val, &cpu->env.fp_status);
- update_fpcsr(cpu);
+ update_fpcsr(cpu, GETPC());
return itofs;
}
@@ -96,7 +100,7 @@ uint64_t HELPER(ftoid)(CPUOpenRISCState *env, uint64_t val)
set_float_exception_flags(0, &cpu->env.fp_status);
ftoid = float32_to_int64(val, &cpu->env.fp_status);
- update_fpcsr(cpu);
+ update_fpcsr(cpu, GETPC());
return ftoid;
}
@@ -108,7 +112,7 @@ uint32_t HELPER(ftois)(CPUOpenRISCState *env, uint32_t val)
set_float_exception_flags(0, &cpu->env.fp_status);
ftois = float32_to_int32(val, &cpu->env.fp_status);
- update_fpcsr(cpu);
+ update_fpcsr(cpu, GETPC());
return ftois;
}
@@ -123,7 +127,7 @@ uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \
OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); \
set_float_exception_flags(0, &cpu->env.fp_status); \
result = float64_ ## name(fdt0, fdt1, &cpu->env.fp_status); \
- update_fpcsr(cpu); \
+ update_fpcsr(cpu, GETPC()); \
return result; \
} \
\
@@ -134,7 +138,7 @@ uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env, \
OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); \
set_float_exception_flags(0, &cpu->env.fp_status); \
result = float32_ ## name(fdt0, fdt1, &cpu->env.fp_status); \
- update_fpcsr(cpu); \
+ update_fpcsr(cpu, GETPC()); \
return result; \
} \
@@ -163,7 +167,7 @@ uint64_t helper_float_ ## name1 ## name2 ## _d(CPUOpenRISCState *env, \
result = float64_ ## name2(result, temp, &cpu->env.fp_status); \
val1 = result >> 32; \
val2 = (uint32_t) (result & 0xffffffff); \
- update_fpcsr(cpu); \
+ update_fpcsr(cpu, GETPC()); \
cpu->env.fpmaddlo = val2; \
cpu->env.fpmaddhi = val1; \
return 0; \
@@ -183,7 +187,7 @@ uint32_t helper_float_ ## name1 ## name2 ## _s(CPUOpenRISCState *env, \
result = float64_ ## name2(result, temp, &cpu->env.fp_status); \
val1 = result >> 32; \
val2 = (uint32_t) (result & 0xffffffff); \
- update_fpcsr(cpu); \
+ update_fpcsr(cpu, GETPC()); \
cpu->env.fpmaddlo = val2; \
cpu->env.fpmaddhi = val1; \
return 0; \
@@ -201,7 +205,7 @@ uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \
OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); \
set_float_exception_flags(0, &cpu->env.fp_status); \
res = float64_ ## name(fdt0, fdt1, &cpu->env.fp_status); \
- update_fpcsr(cpu); \
+ update_fpcsr(cpu, GETPC()); \
return res; \
} \
\
@@ -212,7 +216,7 @@ uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env, \
OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); \
set_float_exception_flags(0, &cpu->env.fp_status); \
res = float32_ ## name(fdt0, fdt1, &cpu->env.fp_status); \
- update_fpcsr(cpu); \
+ update_fpcsr(cpu, GETPC()); \
return res; \
}
@@ -230,7 +234,7 @@ uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \
OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); \
set_float_exception_flags(0, &cpu->env.fp_status); \
res = !float64_eq_quiet(fdt0, fdt1, &cpu->env.fp_status); \
- update_fpcsr(cpu); \
+ update_fpcsr(cpu, GETPC()); \
return res; \
} \
\
@@ -241,7 +245,7 @@ uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env, \
OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); \
set_float_exception_flags(0, &cpu->env.fp_status); \
res = !float32_eq_quiet(fdt0, fdt1, &cpu->env.fp_status); \
- update_fpcsr(cpu); \
+ update_fpcsr(cpu, GETPC()); \
return res; \
}
@@ -256,7 +260,7 @@ uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \
OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); \
set_float_exception_flags(0, &cpu->env.fp_status); \
res = !float64_le(fdt0, fdt1, &cpu->env.fp_status); \
- update_fpcsr(cpu); \
+ update_fpcsr(cpu, GETPC()); \
return res; \
} \
\
@@ -267,7 +271,7 @@ uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env, \
OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); \
set_float_exception_flags(0, &cpu->env.fp_status); \
res = !float32_le(fdt0, fdt1, &cpu->env.fp_status); \
- update_fpcsr(cpu); \
+ update_fpcsr(cpu, GETPC()); \
return res; \
}
FLOAT_CMPGT(gt)
@@ -281,7 +285,7 @@ uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \
OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); \
set_float_exception_flags(0, &cpu->env.fp_status); \
res = !float64_lt(fdt0, fdt1, &cpu->env.fp_status); \
- update_fpcsr(cpu); \
+ update_fpcsr(cpu, GETPC()); \
return res; \
} \
\
@@ -292,7 +296,7 @@ uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env, \
OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); \
set_float_exception_flags(0, &cpu->env.fp_status); \
res = !float32_lt(fdt0, fdt1, &cpu->env.fp_status); \
- update_fpcsr(cpu); \
+ update_fpcsr(cpu, GETPC()); \
return res; \
}
@@ -72,7 +72,7 @@ uint32_t HELPER(mul32)(CPUOpenRISCState *env,
cpu->env.sr |= (SR_OV | SR_CY);
if (cpu->env.sr & SR_OVE) {
- raise_exception(cpu, EXCP_RANGE);
+ do_raise_exception(cpu, EXCP_RANGE, GETPC());
}
return result;
@@ -19,6 +19,7 @@
*/
#include "cpu.h"
+#include "exception.h"
#ifndef CONFIG_USER_ONLY
#include "softmmu_exec.h"
@@ -39,25 +40,13 @@
void tlb_fill(CPUOpenRISCState *env, target_ulong addr, int is_write,
int mmu_idx, uintptr_t retaddr)
{
- TranslationBlock *tb;
- unsigned long pc;
int ret;
+ OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env));
ret = cpu_openrisc_handle_mmu_fault(env, addr, is_write, mmu_idx);
if (ret) {
- if (retaddr) {
- /* now we have a real cpu fault. */
- pc = (unsigned long)retaddr;
- tb = tb_find_pc(pc);
- if (tb) {
- /* the PC is inside the translated code. It means that we
- have a virtual CPU fault. */
- cpu_restore_state(tb, env, pc);
- }
- }
- /* Raise Exception. */
- cpu_loop_exit(env);
+ do_raise_exception(cpu, env->exception_index, retaddr);
}
}
#endif
From: Feng Gao <gf91597@gmail.com> This patch complete target-openrisc floating point exception. When float exception, the right PC can be saved, so exception handler could do proper processing, and back to the right address letting the program continue. The patch I have tested it ok. --- target-openrisc/exception.c | 23 +++++++++++++++-- target-openrisc/exception.h | 5 ++-- target-openrisc/exception_helper.c | 2 +- target-openrisc/fpu_helper.c | 48 +++++++++++++++++++----------------- target-openrisc/int_helper.c | 2 +- target-openrisc/mmu_helper.c | 17 +++---------- 6 files changed, 55 insertions(+), 42 deletions(-)