From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1L9SPa-00086d-Rs for qemu-devel@nongnu.org; Sun, 07 Dec 2008 17:47:38 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1L9SPZ-00086O-Tf for qemu-devel@nongnu.org; Sun, 07 Dec 2008 17:47:38 -0500 Received: from [199.232.76.173] (port=43757 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1L9SPZ-00086L-L0 for qemu-devel@nongnu.org; Sun, 07 Dec 2008 17:47:37 -0500 Received: from hall.aurel32.net ([88.191.82.174]:55240) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1L9SPY-0002Yu-Eq for qemu-devel@nongnu.org; Sun, 07 Dec 2008 17:47:37 -0500 Received: from volta.aurel32.net ([2002:52e8:2fb:1:21e:8cff:feb0:693b]) by hall.aurel32.net with esmtpsa (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.63) (envelope-from ) id 1L9SPX-0007sa-3a for qemu-devel@nongnu.org; Sun, 07 Dec 2008 23:47:35 +0100 Received: from aurel32 by volta.aurel32.net with local (Exim 4.69) (envelope-from ) id 1L9SPW-0000WK-Ap for qemu-devel@nongnu.org; Sun, 07 Dec 2008 23:47:34 +0100 Date: Sun, 7 Dec 2008 23:47:34 +0100 From: Aurelien Jarno Subject: Re: [Qemu-devel] SH4: Implement FD bit Message-ID: <20081207224734.GD3591@volta.aurel32.net> References: <200812012022.02276.vladimir@codesourcery.com> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-15 Content-Disposition: inline In-Reply-To: <200812012022.02276.vladimir@codesourcery.com> 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 On Mon, Dec 01, 2008 at 08:22:02PM +0300, Vladimir Prus wrote: > > 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. > > - Volodya Thanks, applied. > commit 0cbaa15c2db2168937fa154d5f1f625497392552 > Author: Vladimir Prus > Date: Mon Dec 1 19:28:32 2008 +0300 > > SH: Implement FD bit > > * target-sh4/cpu.h (cpu_get_tb_cpu_state): Include SR's FD bit in > the flags. > * target-sh4/helper.h (raise_fpu_disable, raise_slot_fpu_disable): > New helpers. > * targets-sh4/op_helper.c (helper_raise_fpu_disable) > (helper_raise_slot_fpu_disable): New. > * target-sh4/translate.c (CHECK_NOT_DELAY_SLOT, CHECK_PRIVILEGED): > Set PC to the right value. > (CHECK_FPU_ENABLED): New. > (_decode_opc): Use CHECK_FPU_ENABLED for FP instructions. > > diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h > index aae9b42..e6c658e 100644 > --- a/target-sh4/cpu.h > +++ b/target-sh4/cpu.h > @@ -294,6 +294,7 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc, > | 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_FD) /* Bit 15 */ > | (env->store_requests ? TB_FLAG_PENDING_MOVCA : 0); /* Bit 4 */ > } > > diff --git a/target-sh4/helper.h b/target-sh4/helper.h > index c3f6393..d995688 100644 > --- a/target-sh4/helper.h > +++ b/target-sh4/helper.h > @@ -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) > diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c > index c18d67c..b4982b0 100644 > --- a/target-sh4/op_helper.c > +++ b/target-sh4/op_helper.c > @@ -89,6 +89,18 @@ void helper_raise_slot_illegal_instruction(void) > 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; > diff --git a/target-sh4/translate.c b/target-sh4/translate.c > index 80c0f30..d11a738 100644 > --- a/target-sh4/translate.c > +++ b/target-sh4/translate.c > @@ -457,17 +457,36 @@ static inline void gen_store_fpr64 (TCGv_i64 t, int reg) > #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) > { > /* This code tries to make movcal emulation sufficiently > @@ -504,6 +523,13 @@ static void _decode_opc(DisasContext * ctx) > } > } > > + /* The 0xfffd instruction is underfined, so we don't want to > + raise fpu disable exception on it. */ > + if (((ctx->opcode & 0xf000) == 0xf000) > + && (ctx->opcode != 0xfffd)) > + { > + CHECK_FPU_ENABLED > + } > #if 0 > fprintf(stderr, "Translating opcode 0x%04x\n", ctx->opcode); > #endif > @@ -1498,12 +1524,14 @@ static void _decode_opc(DisasContext * ctx) > 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); > @@ -1514,9 +1542,11 @@ static void _decode_opc(DisasContext * ctx) > } > 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(); -- .''`. Aurelien Jarno | GPG: 1024D/F1BCDB73 : :' : Debian developer | Electrical Engineer `. `' aurel32@debian.org | aurelien@aurel32.net `- people.debian.org/~aurel32 | www.aurel32.net