PowerPC floating-point registers are now an union of uint64 & double. This

eases FP load/stores.
This commit is contained in:
gbeauche 2003-11-04 15:03:15 +00:00
parent 8ddf749ed5
commit 30bd089279
5 changed files with 50 additions and 24 deletions

View File

@ -45,11 +45,11 @@ static clock_t emul_end_time = 0;
void powerpc_cpu::set_register(int id, any_register const & value) void powerpc_cpu::set_register(int id, any_register const & value)
{ {
if (id >= powerpc_registers::GPR(0) && id <= powerpc_registers::GPR(31)) { 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; return;
} }
if (id >= powerpc_registers::FPR(0) && id <= powerpc_registers::FPR(31)) { 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; return;
} }
switch (id) { switch (id) {
@ -72,11 +72,11 @@ any_register powerpc_cpu::get_register(int id)
{ {
any_register value; any_register value;
if (id >= powerpc_registers::GPR(0) && id <= powerpc_registers::GPR(31)) { 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; return value;
} }
if (id >= powerpc_registers::FPR(0) && id <= powerpc_registers::FPR(31)) { 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; return value;
} }
switch (id) { switch (id) {

View File

@ -76,8 +76,10 @@ public:
uint32 & gpr(int i) { return regs.gpr[i]; } uint32 & gpr(int i) { return regs.gpr[i]; }
uint32 gpr(int i) const { 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) { return regs.fpr[i].d; }
double fpr(int i) const { return regs.fpr[i]; } 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: protected:

View File

@ -603,27 +603,18 @@ void powerpc_cpu::execute_fp_loadstore(uint32 opcode)
const uint32 a = RA::get(this, opcode); const uint32 a = RA::get(this, opcode);
const uint32 b = RB::get(this, opcode); const uint32 b = RB::get(this, opcode);
const uint32 ea = a + b; const uint32 ea = a + b;
any_register d;
if (LD) { if (LD) {
if (DB) { if (DB)
d.j = vm_read_memory_8(ea); operand_fp_dw_RD::set(this, opcode, vm_read_memory_8(ea));
operand_fp_RD::set(this, opcode, d.d); else
} operand_fp_dw_RD::set(this, opcode, vm_read_memory_4(ea));
else {
d.i = vm_read_memory_4(ea);
operand_fp_RD::set(this, opcode, (double)d.f);
}
} }
else { else {
if (DB) { if (DB)
d.d = operand_fp_RS::get(this, opcode); vm_write_memory_8(ea, operand_fp_dw_RS::get(this, opcode));
vm_write_memory_8(ea, d.j); else
} vm_write_memory_4(ea, operand_fp_dw_RS::get(this, opcode));
else {
d.f = (float)operand_fp_RS::get(this, opcode);
vm_write_memory_4(ea, d.i);
}
} }
if (UP) if (UP)

View File

@ -79,6 +79,23 @@ struct output_fpr {
template< class field > template< class field >
struct fpr_operand : input_fpr< field >, output_fpr< 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 * 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<frC_field> operand_fp_RC;
typedef fpr_operand<frD_field> operand_fp_RD; typedef fpr_operand<frD_field> operand_fp_RD;
typedef fpr_operand<frS_field> operand_fp_RS; 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_CA_field> operand_XER_CA;
typedef xer_operand<XER_COUNT_field> operand_XER_COUNT; typedef xer_operand<XER_COUNT_field> operand_XER_COUNT;
typedef fpscr_operand<FPSCR_RN_field> operand_FPSCR_RN; typedef fpscr_operand<FPSCR_RN_field> operand_FPSCR_RN;

View File

@ -344,6 +344,17 @@ powerpc_xer_register::set(uint32 xer)
typedef basic_spcflags powerpc_spcflags; typedef basic_spcflags powerpc_spcflags;
/**
* Floating point register
**/
union powerpc_fpr {
uint64 j;
double d;
};
/** /**
* VEA Register Set * VEA Register Set
**/ **/
@ -366,7 +377,7 @@ struct powerpc_registers
static inline int FPR(int r) { return FPR_BASE + r; } static inline int FPR(int r) { return FPR_BASE + r; }
uint32 gpr[32]; // General-Purpose Registers 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 powerpc_cr_register cr; // Condition Register
uint32 fpscr; // Floating-Point Status and Control Register uint32 fpscr; // Floating-Point Status and Control Register
powerpc_xer_register xer; // XER Register (SPR 1) powerpc_xer_register xer; // XER Register (SPR 1)