From patchwork Thu Dec 6 23:53:31 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Feng@gaofeng-K43SM.localdomain, Gao@gaofeng-K43SM.localdomain X-Patchwork-Id: 204422 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 6A1F42C00C6 for ; Fri, 7 Dec 2012 19:23:04 +1100 (EST) Received: from localhost ([::1]:45320 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TgtD2-0003WW-R8 for incoming@patchwork.ozlabs.org; Fri, 07 Dec 2012 03:23:00 -0500 Received: from eggs.gnu.org ([208.118.235.92]:56961) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Tgm1m-0005Ud-Lw for qemu-devel@nongnu.org; Thu, 06 Dec 2012 19:42:59 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Tgm1h-0007FN-8a for qemu-devel@nongnu.org; Thu, 06 Dec 2012 19:42:54 -0500 Received: from [114.247.222.194] (port=55487 helo=gaofeng-K43SM.localdomain) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Tgm1g-0007FE-Dm for qemu-devel@nongnu.org; Thu, 06 Dec 2012 19:42:49 -0500 Received: by gaofeng-K43SM.localdomain (Postfix, from userid 1000) id C38FA3219DF; Fri, 7 Dec 2012 07:53:33 +0800 (CST) From: Feng@gaofeng-K43SM.localdomain, Gao@gaofeng-K43SM.localdomain To: qemu-devel@nongnu.org Date: Fri, 7 Dec 2012 07:53:31 +0800 Message-Id: <1354838011-5937-1-git-send-email-gf91597@gmail.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 114.247.222.194 X-Mailman-Approved-At: Fri, 07 Dec 2012 03:22:31 -0500 Cc: Feng Gao Subject: [Qemu-devel] [PATCH_v3] add target-openrisc floating point exception X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Feng Gao 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(-) diff --git a/target-openrisc/exception.c b/target-openrisc/exception.c index 58e53c6..0377c43 100644 --- a/target-openrisc/exception.c +++ b/target-openrisc/exception.c @@ -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); } diff --git a/target-openrisc/exception.h b/target-openrisc/exception.h index 4b64430..b3cb687 100644 --- a/target-openrisc/exception.h +++ b/target-openrisc/exception.h @@ -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 */ 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..d7507db 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(cpu, env->exception_index, retaddr); } } #endif