diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.cpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.cpp index 5b93c432..70027f11 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.cpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.cpp @@ -45,11 +45,11 @@ static clock_t emul_end_time = 0; void powerpc_cpu::set_register(int id, any_register const & value) { if (id >= powerpc_registers::GPR(0) && id <= powerpc_registers::GPR(31)) { - regs.gpr[id - powerpc_registers::GPR_BASE] = value.i; + gpr(id - powerpc_registers::GPR_BASE) = value.i; return; } if (id >= powerpc_registers::FPR(0) && id <= powerpc_registers::FPR(31)) { - regs.fpr[id - powerpc_registers::FPR_BASE] = value.d; + fpr(id - powerpc_registers::FPR_BASE) = value.d; return; } switch (id) { @@ -72,11 +72,11 @@ any_register powerpc_cpu::get_register(int id) { any_register value; if (id >= powerpc_registers::GPR(0) && id <= powerpc_registers::GPR(31)) { - value.i = regs.gpr[id - powerpc_registers::GPR_BASE]; + value.i = gpr(id - powerpc_registers::GPR_BASE); return value; } if (id >= powerpc_registers::FPR(0) && id <= powerpc_registers::FPR(31)) { - value.d = regs.fpr[id - powerpc_registers::FPR_BASE]; + value.d = fpr(id - powerpc_registers::FPR_BASE); return value; } switch (id) { diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp index 9178e5d8..475872c3 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp @@ -76,8 +76,10 @@ public: uint32 & gpr(int i) { return regs.gpr[i]; } uint32 gpr(int i) const { return regs.gpr[i]; } - double & fpr(int i) { return regs.fpr[i]; } - double fpr(int i) const { return regs.fpr[i]; } + double & fpr(int i) { return regs.fpr[i].d; } + double fpr(int i) const { return regs.fpr[i].d; } + uint64 & fpr_dw(int i) { return regs.fpr[i].j; } + uint64 fpr_dw(int i) const { return regs.fpr[i].j; } protected: 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 34a6c1db..fc84ff71 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-execute.cpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-execute.cpp @@ -603,27 +603,18 @@ 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; - any_register d; if (LD) { - if (DB) { - d.j = vm_read_memory_8(ea); - operand_fp_RD::set(this, opcode, d.d); - } - else { - d.i = vm_read_memory_4(ea); - operand_fp_RD::set(this, opcode, (double)d.f); - } + if (DB) + operand_fp_dw_RD::set(this, opcode, vm_read_memory_8(ea)); + else + operand_fp_dw_RD::set(this, opcode, vm_read_memory_4(ea)); } else { - if (DB) { - d.d = operand_fp_RS::get(this, opcode); - vm_write_memory_8(ea, d.j); - } - else { - d.f = (float)operand_fp_RS::get(this, opcode); - vm_write_memory_4(ea, d.i); - } + if (DB) + vm_write_memory_8(ea, operand_fp_dw_RS::get(this, opcode)); + else + vm_write_memory_4(ea, operand_fp_dw_RS::get(this, opcode)); } if (UP) diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-operands.hpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-operands.hpp index 1040071c..76921816 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-operands.hpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-operands.hpp @@ -79,6 +79,23 @@ struct output_fpr { template< class field > struct fpr_operand : input_fpr< field >, output_fpr< field > { }; +template< class field > +struct input_fpr_dw { + static inline uint64 get(powerpc_cpu * cpu, uint32 opcode) { + return cpu->fpr_dw(field::extract(opcode)); + } +}; + +template< class field > +struct output_fpr_dw { + static inline void set(powerpc_cpu * cpu, uint32 opcode, uint64 value) { + cpu->fpr_dw(field::extract(opcode)) = value; + } +}; + +template< class field > +struct fpr_dw_operand : input_fpr_dw< field >, output_fpr_dw< field > { }; + /** * Immediate operands **/ @@ -208,6 +225,11 @@ typedef fpr_operand operand_fp_RB; typedef fpr_operand operand_fp_RC; typedef fpr_operand operand_fp_RD; typedef fpr_operand operand_fp_RS; +typedef fpr_dw_operand operand_fp_dw_RA; +typedef fpr_dw_operand operand_fp_dw_RB; +typedef fpr_dw_operand operand_fp_dw_RC; +typedef fpr_dw_operand operand_fp_dw_RD; +typedef fpr_dw_operand operand_fp_dw_RS; typedef xer_operand operand_XER_CA; typedef xer_operand operand_XER_COUNT; typedef fpscr_operand operand_FPSCR_RN; diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-registers.hpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-registers.hpp index 4d206be8..1d8407cb 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-registers.hpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-registers.hpp @@ -344,6 +344,17 @@ powerpc_xer_register::set(uint32 xer) typedef basic_spcflags powerpc_spcflags; +/** + * Floating point register + **/ + +union powerpc_fpr { + uint64 j; + double d; +}; + + + /** * VEA Register Set **/ @@ -366,7 +377,7 @@ struct powerpc_registers static inline int FPR(int r) { return FPR_BASE + r; } uint32 gpr[32]; // General-Purpose Registers - double fpr[32]; // Floating-Point Registers + powerpc_fpr fpr[32]; // Floating-Point Registers powerpc_cr_register cr; // Condition Register uint32 fpscr; // Floating-Point Status and Control Register powerpc_xer_register xer; // XER Register (SPR 1)