Add OpenRisc fpu excepiton. When an exception raised, CPU can save right PC.
Signed-off-by: Feng Gao <gf91...@gmail.com> --- target-openrisc/exception.c | 31 +++++++++++++++++++++-- target-openrisc/exception.h | 8 ++++-- 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, 66 insertions(+), 42 deletions(-) diff --git a/target-openrisc/exception.c b/target-openrisc/exception.c index 58e53c6..39966a7 100644 --- a/target-openrisc/exception.c +++ b/target-openrisc/exception.c @@ -20,8 +20,35 @@ #include "cpu.h" #include "exception.h" -void QEMU_NORETURN raise_exception(OpenRISCCPU *cpu, uint32_t excp) +void QEMU_NORETURN do_raise_exception_err(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); } + +void QEMU_NORETURN do_raise_exception(OpenRISCCPU *cpu, + uint32_t exception, + uintptr_t pc) +{ + do_raise_exception_err(cpu, exception, pc); +} + diff --git a/target-openrisc/exception.h b/target-openrisc/exception.h index 4b64430..4d1928e 100644 --- a/target-openrisc/exception.h +++ b/target-openrisc/exception.h @@ -23,6 +23,10 @@ #include "cpu.h" #include "qemu-common.h" -void QEMU_NORETURN raise_exception(OpenRISCCPU *cpu, uint32_t excp); - +void QEMU_NORETURN do_raise_exception_err(OpenRISCCPU *cpu, + uint32_t exception, + uintptr_t pc); +void QEMU_NORETURN do_raise_exception(OpenRISCCPU *cpu, + uint32_t exception, + uintptr_t pc); #endif /* QEMU_OPENRISC_EXCP_H */ diff --git a/target-openrisc/exception_helper.c b/target-openrisc/exception_helper.c index dab4148..15b9c1f 100644 --- a/target-openrisc/exception_helper.c +++ b/target-openrisc/exception_helper.c @@ -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); } diff --git a/target-openrisc/fpu_helper.c b/target-openrisc/fpu_helper.c index b184d5e..c2890d5 100644 --- a/target-openrisc/fpu_helper.c +++ b/target-openrisc/fpu_helper.c @@ -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; \ } diff --git a/target-openrisc/int_helper.c b/target-openrisc/int_helper.c index 2fdfd27..46ec978 100644 --- a/target-openrisc/int_helper.c +++ b/target-openrisc/int_helper.c @@ -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; diff --git a/target-openrisc/mmu_helper.c b/target-openrisc/mmu_helper.c index 59ed371..8b687c0 100644 --- a/target-openrisc/mmu_helper.c +++ b/target-openrisc/mmu_helper.c @@ -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_err(cpu, env->exception_index, retaddr); } } #endif -- 1.7.10.4