mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-12-25 02:29:49 +00:00
PowerPC floating-point registers are now an union of uint64 & double. This
eases FP load/stores.
This commit is contained in:
parent
8ddf749ed5
commit
30bd089279
@ -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) {
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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<frB_field> operand_fp_RB;
|
||||
typedef fpr_operand<frC_field> operand_fp_RC;
|
||||
typedef fpr_operand<frD_field> operand_fp_RD;
|
||||
typedef fpr_operand<frS_field> operand_fp_RS;
|
||||
typedef fpr_dw_operand<frA_field> operand_fp_dw_RA;
|
||||
typedef fpr_dw_operand<frB_field> operand_fp_dw_RB;
|
||||
typedef fpr_dw_operand<frC_field> operand_fp_dw_RC;
|
||||
typedef fpr_dw_operand<frD_field> operand_fp_dw_RD;
|
||||
typedef fpr_dw_operand<frS_field> operand_fp_dw_RS;
|
||||
typedef xer_operand<XER_CA_field> operand_XER_CA;
|
||||
typedef xer_operand<XER_COUNT_field> operand_XER_COUNT;
|
||||
typedef fpscr_operand<FPSCR_RN_field> operand_FPSCR_RN;
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user