From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1L9SOY-0007m4-UF for qemu-devel@nongnu.org; Sun, 07 Dec 2008 17:46:34 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1L9SOY-0007lf-2T for qemu-devel@nongnu.org; Sun, 07 Dec 2008 17:46:34 -0500 Received: from [199.232.76.173] (port=43741 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1L9SOX-0007lc-SV for qemu-devel@nongnu.org; Sun, 07 Dec 2008 17:46:33 -0500 Received: from savannah.gnu.org ([199.232.41.3]:55590 helo=sv.gnu.org) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1L9SOX-0002O0-FX for qemu-devel@nongnu.org; Sun, 07 Dec 2008 17:46:33 -0500 Received: from cvs.savannah.gnu.org ([199.232.41.69]) by sv.gnu.org with esmtp (Exim 4.63) (envelope-from ) id 1L9SOW-0007Gg-TY for qemu-devel@nongnu.org; Sun, 07 Dec 2008 22:46:33 +0000 Received: from aurel32 by cvs.savannah.gnu.org with local (Exim 4.63) (envelope-from ) id 1L9SOW-0007Ga-Fp for qemu-devel@nongnu.org; Sun, 07 Dec 2008 22:46:32 +0000 MIME-Version: 1.0 Errors-To: aurel32 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Aurelien Jarno Message-Id: Date: Sun, 07 Dec 2008 22:46:32 +0000 Subject: [Qemu-devel] [5937] SH4: Implement FD bit Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Revision: 5937 http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=5937 Author: aurel32 Date: 2008-12-07 22:46:31 +0000 (Sun, 07 Dec 2008) Log Message: ----------- SH4: Implement FD bit SH4 manual say that if a floating point instruction is executed while FD bit in the status register is 1, an exception should be raised. QEMU presently does not do that, so the kernel does not initialize FP state for any thread, nor does it save/restore FP state. The most apparent consequence is that while recent gcc/libc expect double-precision mode to be set by kernel, they run in single-precision mode, and all FP code produces wrong values. This patch fixes this. It also fixes a couple of places where PC was not updated before handling an exception, although both those places deal with invalid instruction and don't lead to any user-visible bugs. (Vladimir Prus) Modified Paths: -------------- trunk/target-sh4/cpu.h trunk/target-sh4/helper.h trunk/target-sh4/op_helper.c trunk/target-sh4/translate.c Modified: trunk/target-sh4/cpu.h =================================================================== --- trunk/target-sh4/cpu.h 2008-12-07 20:35:00 UTC (rev 5936) +++ trunk/target-sh4/cpu.h 2008-12-07 22:46:31 UTC (rev 5937) @@ -279,7 +279,8 @@ *flags = (env->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL | DELAY_SLOT_TRUE | DELAY_SLOT_CLEARME)) /* Bits 0- 3 */ | (env->fpscr & (FPSCR_FR | FPSCR_SZ | FPSCR_PR)) /* Bits 19-21 */ - | (env->sr & (SR_MD | SR_RB)); /* Bits 29-30 */ + | (env->sr & (SR_MD | SR_RB)) /* Bits 29-30 */ + | (env->sr & SR_FD); /* Bit 15 */ } #endif /* _CPU_SH4_H */ Modified: trunk/target-sh4/helper.h =================================================================== --- trunk/target-sh4/helper.h 2008-12-07 20:35:00 UTC (rev 5936) +++ trunk/target-sh4/helper.h 2008-12-07 22:46:31 UTC (rev 5937) @@ -3,6 +3,8 @@ DEF_HELPER_0(ldtlb, void) DEF_HELPER_0(raise_illegal_instruction, void) DEF_HELPER_0(raise_slot_illegal_instruction, void) +DEF_HELPER_0(raise_fpu_disable, void) +DEF_HELPER_0(raise_slot_fpu_disable, void) DEF_HELPER_0(debug, void) DEF_HELPER_1(sleep, void, i32) DEF_HELPER_1(trapa, void, i32) Modified: trunk/target-sh4/op_helper.c =================================================================== --- trunk/target-sh4/op_helper.c 2008-12-07 20:35:00 UTC (rev 5936) +++ trunk/target-sh4/op_helper.c 2008-12-07 22:46:31 UTC (rev 5937) @@ -89,6 +89,18 @@ cpu_loop_exit(); } +void helper_raise_fpu_disable(void) +{ + env->exception_index = 0x800; + cpu_loop_exit(); +} + +void helper_raise_slot_fpu_disable(void) +{ + env->exception_index = 0x820; + cpu_loop_exit(); +} + void helper_debug(void) { env->exception_index = EXCP_DEBUG; Modified: trunk/target-sh4/translate.c =================================================================== --- trunk/target-sh4/translate.c 2008-12-07 20:35:00 UTC (rev 5936) +++ trunk/target-sh4/translate.c 2008-12-07 22:46:31 UTC (rev 5937) @@ -447,17 +447,35 @@ #define DREG(x) FREG(x) /* Assumes lsb of (x) is always 0 */ #define CHECK_NOT_DELAY_SLOT \ - if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) \ - {gen_helper_raise_slot_illegal_instruction(); ctx->bstate = BS_EXCP; \ - return;} + if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) \ + { \ + tcg_gen_movi_i32(cpu_pc, ctx->pc-2); \ + gen_helper_raise_slot_illegal_instruction(); \ + ctx->bstate = BS_EXCP; \ + return; \ + } #define CHECK_PRIVILEGED \ if (IS_USER(ctx)) { \ + tcg_gen_movi_i32(cpu_pc, ctx->pc); \ gen_helper_raise_illegal_instruction(); \ ctx->bstate = BS_EXCP; \ return; \ } +#define CHECK_FPU_ENABLED \ + if (ctx->flags & SR_FD) { \ + if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \ + tcg_gen_movi_i32(cpu_pc, ctx->pc-2); \ + gen_helper_raise_slot_fpu_disable(); \ + } else { \ + tcg_gen_movi_i32(cpu_pc, ctx->pc); \ + gen_helper_raise_fpu_disable(); \ + } \ + ctx->bstate = BS_EXCP; \ + return; \ + } + static void _decode_opc(DisasContext * ctx) { #if 0 @@ -1454,12 +1472,14 @@ LDST(mach, 0x400a, 0x4006, 0x000a, 0x4002, {}) LDST(macl, 0x401a, 0x4016, 0x001a, 0x4012, {}) LDST(pr, 0x402a, 0x4026, 0x002a, 0x4022, {}) - LDST(fpul, 0x405a, 0x4056, 0x005a, 0x4052, {}) + LDST(fpul, 0x405a, 0x4056, 0x005a, 0x4052, {CHECK_FPU_ENABLED}) case 0x406a: /* lds Rm,FPSCR */ + CHECK_FPU_ENABLED gen_helper_ld_fpscr(REG(B11_8)); ctx->bstate = BS_STOP; return; case 0x4066: /* lds.l @Rm+,FPSCR */ + CHECK_FPU_ENABLED { TCGv addr = tcg_temp_new(); tcg_gen_qemu_ld32s(addr, REG(B11_8), ctx->memidx); @@ -1470,9 +1490,11 @@ } return; case 0x006a: /* sts FPSCR,Rn */ + CHECK_FPU_ENABLED tcg_gen_andi_i32(REG(B11_8), cpu_fpscr, 0x003fffff); return; case 0x4062: /* sts FPSCR,@-Rn */ + CHECK_FPU_ENABLED { TCGv addr, val; val = tcg_temp_new();