mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-12-25 17:29:19 +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)
|
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) {
|
||||||
|
@ -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:
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user