Implement the FPSCR register.

This commit is contained in:
Andrew Church 2015-01-19 03:17:51 +09:00
parent 6627cc9666
commit a87de1b565
2 changed files with 55 additions and 57 deletions

View File

@ -981,8 +981,10 @@ private:
void FSCRRD(u32 rt)
{
// TODO (rarely used)
CPU.GPR[rt].clear();
CPU.GPR[rt]._u32[3] = CPU.FPSCR._u32[3];
CPU.GPR[rt]._u32[2] = CPU.FPSCR._u32[2];
CPU.GPR[rt]._u32[1] = CPU.FPSCR._u32[1];
CPU.GPR[rt]._u32[0] = CPU.FPSCR._u32[0];
}
void FESD(u32 rt, u32 ra)
{
@ -998,12 +1000,10 @@ private:
}
void FSCRWR(u32 rt, u32 ra)
{
// TODO (rarely used)
if (CPU.GPR[ra]._u64[0] || CPU.GPR[ra]._u64[1])
{
LOG_ERROR(SPU, "FSCRWR(%d,%d): value = %s", rt, ra, CPU.GPR[ra].to_hex().c_str());
UNIMPLEMENTED();
}
CPU.FPSCR._u32[3] = CPU.GPR[ra]._u32[3] & 0x00000F07;
CPU.FPSCR._u32[2] = CPU.GPR[ra]._u32[2] & 0x00003F07;
CPU.FPSCR._u32[1] = CPU.GPR[ra]._u32[1] & 0x00003F07;
CPU.FPSCR._u32[0] = CPU.GPR[ra]._u32[0] & 0x00000F07;
}
void DFTSV(u32 rt, u32 ra, s32 i7)
{

View File

@ -167,45 +167,49 @@ struct g_imm_table_struct
extern const g_imm_table_struct g_imm_table;
//Floating point status and control register. Unsure if this is one of the GPRs or SPRs
enum FPSCR_EX
{
//Single-precision exceptions
FPSCR_SOVF = 1 << 2, //Overflow
FPSCR_SUNF = 1 << 1, //Underflow
FPSCR_SDIFF = 1 << 0, //Different (could be IEEE non-compliant)
//Double-precision exceptions
FPSCR_DOVF = 1 << 13, //Overflow
FPSCR_DUNF = 1 << 12, //Underflow
FPSCR_DINX = 1 << 11, //Inexact
FPSCR_DINV = 1 << 10, //Invalid operation
FPSCR_DNAN = 1 << 9, //NaN
FPSCR_DDENORM = 1 << 8, //Denormal
};
//Is 128 bits, but bits 0-19, 24-28, 32-49, 56-60, 64-81, 88-92, 96-115, 120-124 are unused
class FPSCR
class SPU_FPSCR
{
public:
u64 low;
u64 hi;
u32 _u32[4];
FPSCR() {}
SPU_FPSCR() {}
std::string ToString() const
{
return "FPSCR writer not yet implemented"; //fmt::Format("%08x%08x%08x%08x", _u32[3], _u32[2], _u32[1], _u32[0]);
return fmt::Format("%08x%08x%08x%08x", _u32[3], _u32[2], _u32[1], _u32[0]);
}
void Reset()
{
memset(this, 0, sizeof(*this));
}
//slice -> 0 - 1 (4 slices total, only two have rounding)
//slice -> 0 - 1 (double-precision slice index)
//NOTE: slices follow u128 indexing, i.e. slice 0 is RIGHT end of register!
//0 -> round even
//1 -> round towards zero (truncate)
//2 -> round towards positive inf
//3 -> round towards neg inf
void setSliceRounding(u8 slice, u8 roundTo)
{
u64 mask = roundTo;
switch(slice)
{
case 0:
mask = mask << 20;
break;
case 1:
mask = mask << 22;
break;
}
//rounding is located in the low end of the FPSCR
this->low = this->low & mask;
int shift = 8 + 2*slice;
//rounding is located in the left end of the FPSCR
this->_u32[3] = (this->_u32[3] & ~(3 << shift)) | (roundTo << shift);
}
//Slice 0 or 1
u8 checkSliceRounding(u8 slice) const
@ -213,10 +217,10 @@ public:
switch(slice)
{
case 0:
return this->low >> 20 & 0x3;
return this->_u32[3] >> 8 & 0x3;
case 1:
return this->low >> 22 & 0x3;
return this->_u32[3] >> 10 & 0x3;
default:
throw fmt::Format("Unexpected slice value in FPSCR::checkSliceRounding(): %d", slice);
@ -224,34 +228,28 @@ public:
}
}
//Single Precision Exception Flags (all 3 slices)
//Single-precision exception flags (all 4 slices)
//slice -> slice number (0-3)
//exception: 1 -> Overflow 2 -> Underflow 4-> Diff (could be IE^3 non compliant)
void setSinglePrecisionExceptionFlags(u8 slice, u8 exception)
//exception: FPSCR_S* bitmask
void setSinglePrecisionExceptionFlags(u8 slice, u32 exceptions)
{
u64 mask = exception;
switch(slice)
{
case 0:
mask = mask << 29;
this->low = this->low & mask;
break;
case 1:
mask = mask << 61;
this->low = this->low & mask;
break;
case 2:
mask = mask << 29;
this->hi = this->hi & mask;
break;
case 3:
mask = mask << 61;
this->hi = this->hi & mask;
break;
}
_u32[slice] |= exceptions;
}
//Single-precision divide-by-zero flags (all 4 slices)
//slice -> slice number (0-3)
void setDivideByZeroFlag(u8 slice)
{
_u32[0] |= 1 << (8 + slice);
}
//Double-precision exception flags
//slice -> slice number (0-1)
//exception: FPSCR_D* bitmask
void setDoublePrecisionExceptionFlags(u8 slice, u32 exceptions)
{
_u32[1+slice] |= exceptions;
}
};
union SPU_SNRConfig_hdr
@ -277,7 +275,7 @@ class SPUThread : public PPCThread
{
public:
u128 GPR[128]; // General-Purpose Registers
//FPSCR FPSCR;
SPU_FPSCR FPSCR;
SPU_SNRConfig_hdr cfg; // Signal Notification Registers Configuration (OR-mode enabled: 0x1 for SNR1, 0x2 for SNR2)
u64 R_ADDR; // reservation address
@ -630,4 +628,4 @@ public:
return *this;
}
};
};