mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-05 06:21:26 +12:00
Implement the FPSCR register.
This commit is contained in:
parent
6627cc9666
commit
a87de1b565
2 changed files with 55 additions and 57 deletions
|
@ -981,8 +981,10 @@ private:
|
||||||
|
|
||||||
void FSCRRD(u32 rt)
|
void FSCRRD(u32 rt)
|
||||||
{
|
{
|
||||||
// TODO (rarely used)
|
CPU.GPR[rt]._u32[3] = CPU.FPSCR._u32[3];
|
||||||
CPU.GPR[rt].clear();
|
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)
|
void FESD(u32 rt, u32 ra)
|
||||||
{
|
{
|
||||||
|
@ -998,12 +1000,10 @@ private:
|
||||||
}
|
}
|
||||||
void FSCRWR(u32 rt, u32 ra)
|
void FSCRWR(u32 rt, u32 ra)
|
||||||
{
|
{
|
||||||
// TODO (rarely used)
|
CPU.FPSCR._u32[3] = CPU.GPR[ra]._u32[3] & 0x00000F07;
|
||||||
if (CPU.GPR[ra]._u64[0] || CPU.GPR[ra]._u64[1])
|
CPU.FPSCR._u32[2] = CPU.GPR[ra]._u32[2] & 0x00003F07;
|
||||||
{
|
CPU.FPSCR._u32[1] = CPU.GPR[ra]._u32[1] & 0x00003F07;
|
||||||
LOG_ERROR(SPU, "FSCRWR(%d,%d): value = %s", rt, ra, CPU.GPR[ra].to_hex().c_str());
|
CPU.FPSCR._u32[0] = CPU.GPR[ra]._u32[0] & 0x00000F07;
|
||||||
UNIMPLEMENTED();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
void DFTSV(u32 rt, u32 ra, s32 i7)
|
void DFTSV(u32 rt, u32 ra, s32 i7)
|
||||||
{
|
{
|
||||||
|
|
|
@ -167,45 +167,49 @@ struct g_imm_table_struct
|
||||||
|
|
||||||
extern const g_imm_table_struct g_imm_table;
|
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
|
//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:
|
public:
|
||||||
u64 low;
|
u32 _u32[4];
|
||||||
u64 hi;
|
|
||||||
|
|
||||||
FPSCR() {}
|
SPU_FPSCR() {}
|
||||||
|
|
||||||
std::string ToString() const
|
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()
|
void Reset()
|
||||||
{
|
{
|
||||||
memset(this, 0, sizeof(*this));
|
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
|
//0 -> round even
|
||||||
//1 -> round towards zero (truncate)
|
//1 -> round towards zero (truncate)
|
||||||
//2 -> round towards positive inf
|
//2 -> round towards positive inf
|
||||||
//3 -> round towards neg inf
|
//3 -> round towards neg inf
|
||||||
void setSliceRounding(u8 slice, u8 roundTo)
|
void setSliceRounding(u8 slice, u8 roundTo)
|
||||||
{
|
{
|
||||||
u64 mask = roundTo;
|
int shift = 8 + 2*slice;
|
||||||
switch(slice)
|
//rounding is located in the left end of the FPSCR
|
||||||
{
|
this->_u32[3] = (this->_u32[3] & ~(3 << shift)) | (roundTo << shift);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
//Slice 0 or 1
|
//Slice 0 or 1
|
||||||
u8 checkSliceRounding(u8 slice) const
|
u8 checkSliceRounding(u8 slice) const
|
||||||
|
@ -213,10 +217,10 @@ public:
|
||||||
switch(slice)
|
switch(slice)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
return this->low >> 20 & 0x3;
|
return this->_u32[3] >> 8 & 0x3;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
return this->low >> 22 & 0x3;
|
return this->_u32[3] >> 10 & 0x3;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw fmt::Format("Unexpected slice value in FPSCR::checkSliceRounding(): %d", slice);
|
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)
|
//slice -> slice number (0-3)
|
||||||
//exception: 1 -> Overflow 2 -> Underflow 4-> Diff (could be IE^3 non compliant)
|
//exception: FPSCR_S* bitmask
|
||||||
void setSinglePrecisionExceptionFlags(u8 slice, u8 exception)
|
void setSinglePrecisionExceptionFlags(u8 slice, u32 exceptions)
|
||||||
{
|
{
|
||||||
u64 mask = exception;
|
_u32[slice] |= exceptions;
|
||||||
switch(slice)
|
}
|
||||||
{
|
|
||||||
case 0:
|
//Single-precision divide-by-zero flags (all 4 slices)
|
||||||
mask = mask << 29;
|
//slice -> slice number (0-3)
|
||||||
this->low = this->low & mask;
|
void setDivideByZeroFlag(u8 slice)
|
||||||
break;
|
{
|
||||||
case 1:
|
_u32[0] |= 1 << (8 + slice);
|
||||||
mask = mask << 61;
|
}
|
||||||
this->low = this->low & mask;
|
|
||||||
break;
|
//Double-precision exception flags
|
||||||
case 2:
|
//slice -> slice number (0-1)
|
||||||
mask = mask << 29;
|
//exception: FPSCR_D* bitmask
|
||||||
this->hi = this->hi & mask;
|
void setDoublePrecisionExceptionFlags(u8 slice, u32 exceptions)
|
||||||
break;
|
{
|
||||||
case 3:
|
_u32[1+slice] |= exceptions;
|
||||||
mask = mask << 61;
|
|
||||||
this->hi = this->hi & mask;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
union SPU_SNRConfig_hdr
|
union SPU_SNRConfig_hdr
|
||||||
|
@ -277,7 +275,7 @@ class SPUThread : public PPCThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
u128 GPR[128]; // General-Purpose Registers
|
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)
|
SPU_SNRConfig_hdr cfg; // Signal Notification Registers Configuration (OR-mode enabled: 0x1 for SNR1, 0x2 for SNR2)
|
||||||
|
|
||||||
u64 R_ADDR; // reservation address
|
u64 R_ADDR; // reservation address
|
||||||
|
@ -630,4 +628,4 @@ public:
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue