Fix floating-point single precision load/store (VEX's jm-ppc-test -f)

This commit is contained in:
gbeauche 2006-07-04 04:21:02 +00:00
parent c071cd14f6
commit 635ee55a5d
3 changed files with 44 additions and 22 deletions

View File

@ -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

View File

@ -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)

View File

@ -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
**/