From 635ee55a5ddb7371c8af4d9195a288415cc973fa Mon Sep 17 00:00:00 2001 From: gbeauche <> Date: Tue, 4 Jul 2006 04:21:02 +0000 Subject: [PATCH] Fix floating-point single precision load/store (VEX's jm-ppc-test -f) --- .../kpx_cpu/src/cpu/ppc/ppc-dyngen-ops.cpp | 12 ++----- .../src/kpx_cpu/src/cpu/ppc/ppc-execute.cpp | 21 +++++------- .../src/kpx_cpu/src/cpu/ppc/ppc-execute.hpp | 33 +++++++++++++++++++ 3 files changed, 44 insertions(+), 22 deletions(-) diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen-ops.cpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen-ops.cpp index 75557572..0932eb6b 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen-ops.cpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen-ops.cpp @@ -237,19 +237,11 @@ DEFINE_REG(31); #endif #ifndef do_load_single -#define do_load_single(REG, EA) do { \ - any_register *x = (any_register *)&FD; \ - x->i = vm_read_memory_4(EA); \ - REG = (double)x->f; \ -} while (0) +#define do_load_single(REG, EA) REG##_dw = fp_load_single_convert(vm_read_memory_4(EA)) #endif #ifndef do_store_single -#define do_store_single(REG, EA) do { \ - any_register *x = (any_register *)&FD; \ - x->f = (float)REG; \ - vm_write_memory_4(EA, x->i); \ -} while (0) +#define do_store_single(REG, EA) vm_write_memory_4(EA, fp_store_single_convert(REG##_dw)) #endif #ifndef do_load_double diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-execute.cpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-execute.cpp index f5176acc..82fa9a36 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-execute.cpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-execute.cpp @@ -616,24 +616,21 @@ void powerpc_cpu::execute_fp_loadstore(uint32 opcode) const uint32 a = RA::get(this, opcode); const uint32 b = RB::get(this, opcode); const uint32 ea = a + b; + uint64 v; if (LD) { if (DB) - operand_fp_dw_RD::set(this, opcode, vm_read_memory_8(ea)); - else { - any_register x; - x.i = vm_read_memory_4(ea); - operand_fp_RD::set(this, opcode, (double)x.f); - } + v = vm_read_memory_8(ea); + else + v = fp_load_single_convert(vm_read_memory_4(ea)); + operand_fp_dw_RD::set(this, opcode, v); } else { + v = operand_fp_dw_RS::get(this, opcode); if (DB) - vm_write_memory_8(ea, operand_fp_dw_RS::get(this, opcode)); - else { - any_register x; - x.f = (float)operand_fp_RS::get(this, opcode); - vm_write_memory_4(ea, x.i); - } + vm_write_memory_8(ea, v); + else + vm_write_memory_4(ea, fp_store_single_convert(v)); } if (UP) diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-execute.hpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-execute.hpp index 158d6ead..7aa689c0 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-execute.hpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-execute.hpp @@ -191,6 +191,39 @@ DEFINE_HELPER(do_execute_divide, (uint32 RA, uint32 RB)) RETURN(RD); } +/** + * FP load/store + **/ + +// C.6 Floating-Point Load Instructions +static inline uint64 fp_load_single_convert(uint32 v) +{ + // XXX we currently use the native floating-point capabilities + any_register x; + x.i = v; + x.d = (double)x.f; + return x.j; +} + +// C.7 Floating-Point Store Instructions +static inline uint32 fp_store_single_convert(uint64 v) +{ + int exp = (v >> 52) & 0x7ff; + if (exp < 874 || exp > 896) { + // No denormalization required (or "undefined" behaviour) + // WORD[0 - 1] = frS[0 - 1] + // WORD[2 - 31] = frS[5 - 34] + return (uint32)(((v >> 32) & 0xc0000000) | ((v >> 29) & 0x3fffffff)); + } + + // Handle denormalization (874 <= frS[1 - 11] <= 896 + // XXX we currently use the native floating-point capabilities + any_register x; + x.j = v; + x.f = (float)x.d; + return x.i; +} + /** * FP classification **/