mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-23 14:25:37 +00:00
PGXP: Make mult/div compute results instead of parameters
Lets us call it from the recompiler.
This commit is contained in:
parent
33a5617ea3
commit
a722fd6b53
|
@ -827,7 +827,7 @@ restart_instruction:
|
||||||
g_state.regs.lo = Truncate32(result);
|
g_state.regs.lo = Truncate32(result);
|
||||||
|
|
||||||
if constexpr (pgxp_mode >= PGXPMode::CPU)
|
if constexpr (pgxp_mode >= PGXPMode::CPU)
|
||||||
PGXP::CPU_MULT(inst.bits, g_state.regs.hi, g_state.regs.lo, lhs, rhs);
|
PGXP::CPU_MULT(inst.bits, lhs, rhs);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -838,7 +838,7 @@ restart_instruction:
|
||||||
const u64 result = ZeroExtend64(lhs) * ZeroExtend64(rhs);
|
const u64 result = ZeroExtend64(lhs) * ZeroExtend64(rhs);
|
||||||
|
|
||||||
if constexpr (pgxp_mode >= PGXPMode::CPU)
|
if constexpr (pgxp_mode >= PGXPMode::CPU)
|
||||||
PGXP::CPU_MULTU(inst.bits, g_state.regs.hi, g_state.regs.lo, lhs, rhs);
|
PGXP::CPU_MULTU(inst.bits, lhs, rhs);
|
||||||
|
|
||||||
g_state.regs.hi = Truncate32(result >> 32);
|
g_state.regs.hi = Truncate32(result >> 32);
|
||||||
g_state.regs.lo = Truncate32(result);
|
g_state.regs.lo = Truncate32(result);
|
||||||
|
@ -869,7 +869,7 @@ restart_instruction:
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (pgxp_mode >= PGXPMode::CPU)
|
if constexpr (pgxp_mode >= PGXPMode::CPU)
|
||||||
PGXP::CPU_DIV(inst.bits, g_state.regs.hi, g_state.regs.lo, num, denom);
|
PGXP::CPU_DIV(inst.bits, num, denom);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -891,7 +891,7 @@ restart_instruction:
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (pgxp_mode >= PGXPMode::CPU)
|
if constexpr (pgxp_mode >= PGXPMode::CPU)
|
||||||
PGXP::CPU_DIVU(inst.bits, g_state.regs.hi, g_state.regs.lo, num, denom);
|
PGXP::CPU_DIVU(inst.bits, num, denom);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -183,28 +183,28 @@ void MakeValid(PGXP_value* pV, u32 psxV)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Validate(PGXP_value* pV, u32 psxV)
|
void ALWAYS_INLINE_RELEASE Validate(PGXP_value* pV, u32 psxV)
|
||||||
{
|
{
|
||||||
// assume pV is not NULL
|
// assume pV is not NULL
|
||||||
pV->flags &= (pV->value == psxV) ? ALL : INV_VALID_ALL;
|
pV->flags &= (pV->value == psxV) ? ALL : INV_VALID_ALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MaskValidate(PGXP_value* pV, u32 psxV, u32 mask, u32 validMask)
|
void ALWAYS_INLINE_RELEASE MaskValidate(PGXP_value* pV, u32 psxV, u32 mask, u32 validMask)
|
||||||
{
|
{
|
||||||
// assume pV is not NULL
|
// assume pV is not NULL
|
||||||
pV->flags &= ((pV->value & mask) == (psxV & mask)) ? ALL : (ALL ^ (validMask));
|
pV->flags &= ((pV->value & mask) == (psxV & mask)) ? ALL : (ALL ^ (validMask));
|
||||||
}
|
}
|
||||||
|
|
||||||
double f16Sign(double in)
|
double ALWAYS_INLINE_RELEASE f16Sign(double in)
|
||||||
{
|
{
|
||||||
u32 s = (u32)(in * (double)((u32)1 << 16));
|
u32 s = (u32)(in * (double)((u32)1 << 16));
|
||||||
return ((double)*((s32*)&s)) / (double)((s32)1 << 16);
|
return ((double)*((s32*)&s)) / (double)((s32)1 << 16);
|
||||||
}
|
}
|
||||||
double f16Unsign(double in)
|
double ALWAYS_INLINE_RELEASE f16Unsign(double in)
|
||||||
{
|
{
|
||||||
return (in >= 0) ? in : ((double)in + (double)USHRT_MAX + 1);
|
return (in >= 0) ? in : ((double)in + (double)USHRT_MAX + 1);
|
||||||
}
|
}
|
||||||
double f16Overflow(double in)
|
double ALWAYS_INLINE_RELEASE f16Overflow(double in)
|
||||||
{
|
{
|
||||||
double out = 0;
|
double out = 0;
|
||||||
s64 v = ((s64)in) >> 16;
|
s64 v = ((s64)in) >> 16;
|
||||||
|
@ -1310,7 +1310,7 @@ void CPU_SLTU(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal)
|
||||||
// Register mult/div
|
// Register mult/div
|
||||||
////////////////////////////////////
|
////////////////////////////////////
|
||||||
|
|
||||||
void CPU_MULT(u32 instr, u32 hiVal, u32 loVal, u32 rsVal, u32 rtVal)
|
void CPU_MULT(u32 instr, u32 rsVal, u32 rtVal)
|
||||||
{
|
{
|
||||||
// Hi/Lo = Rs * Rt (signed)
|
// Hi/Lo = Rs * Rt (signed)
|
||||||
Validate(&CPU_reg[rs(instr)], rsVal);
|
Validate(&CPU_reg[rs(instr)], rsVal);
|
||||||
|
@ -1352,11 +1352,13 @@ void CPU_MULT(u32 instr, u32 hiVal, u32 loVal, u32 rsVal, u32 rtVal)
|
||||||
CPU_Hi.x = (float)f16Sign(hx);
|
CPU_Hi.x = (float)f16Sign(hx);
|
||||||
CPU_Hi.y = (float)f16Sign(hy);
|
CPU_Hi.y = (float)f16Sign(hy);
|
||||||
|
|
||||||
CPU_Lo.value = loVal;
|
// compute PSX value
|
||||||
CPU_Hi.value = hiVal;
|
const u64 result = static_cast<u64>(static_cast<s64>(SignExtend64(rsVal)) * static_cast<s64>(SignExtend64(rtVal)));
|
||||||
|
CPU_Hi.value = Truncate32(result >> 32);
|
||||||
|
CPU_Lo.value = Truncate32(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPU_MULTU(u32 instr, u32 hiVal, u32 loVal, u32 rsVal, u32 rtVal)
|
void CPU_MULTU(u32 instr, u32 rsVal, u32 rtVal)
|
||||||
{
|
{
|
||||||
// Hi/Lo = Rs * Rt (unsigned)
|
// Hi/Lo = Rs * Rt (unsigned)
|
||||||
Validate(&CPU_reg[rs(instr)], rsVal);
|
Validate(&CPU_reg[rs(instr)], rsVal);
|
||||||
|
@ -1398,11 +1400,13 @@ void CPU_MULTU(u32 instr, u32 hiVal, u32 loVal, u32 rsVal, u32 rtVal)
|
||||||
CPU_Hi.x = (float)f16Sign(hx);
|
CPU_Hi.x = (float)f16Sign(hx);
|
||||||
CPU_Hi.y = (float)f16Sign(hy);
|
CPU_Hi.y = (float)f16Sign(hy);
|
||||||
|
|
||||||
CPU_Lo.value = loVal;
|
// compute PSX value
|
||||||
CPU_Hi.value = hiVal;
|
const u64 result = ZeroExtend64(rsVal) * ZeroExtend64(rtVal);
|
||||||
|
CPU_Hi.value = Truncate32(result >> 32);
|
||||||
|
CPU_Lo.value = Truncate32(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPU_DIV(u32 instr, u32 hiVal, u32 loVal, u32 rsVal, u32 rtVal)
|
void CPU_DIV(u32 instr, u32 rsVal, u32 rtVal)
|
||||||
{
|
{
|
||||||
// Lo = Rs / Rt (signed)
|
// Lo = Rs / Rt (signed)
|
||||||
// Hi = Rs % Rt (signed)
|
// Hi = Rs % Rt (signed)
|
||||||
|
@ -1431,11 +1435,27 @@ void CPU_DIV(u32 instr, u32 hiVal, u32 loVal, u32 rsVal, u32 rtVal)
|
||||||
CPU_Hi.y = (float)f16Sign(f16Overflow(hi));
|
CPU_Hi.y = (float)f16Sign(f16Overflow(hi));
|
||||||
CPU_Hi.x = (float)f16Sign(hi);
|
CPU_Hi.x = (float)f16Sign(hi);
|
||||||
|
|
||||||
CPU_Lo.value = loVal;
|
// compute PSX value
|
||||||
CPU_Hi.value = hiVal;
|
if (static_cast<s32>(rtVal) == 0)
|
||||||
|
{
|
||||||
|
// divide by zero
|
||||||
|
CPU_Lo.value = (static_cast<s32>(rsVal) >= 0) ? UINT32_C(0xFFFFFFFF) : UINT32_C(1);
|
||||||
|
CPU_Hi.value = static_cast<u32>(static_cast<s32>(rsVal));
|
||||||
|
}
|
||||||
|
else if (rsVal == UINT32_C(0x80000000) && static_cast<s32>(rtVal) == -1)
|
||||||
|
{
|
||||||
|
// unrepresentable
|
||||||
|
CPU_Lo.value = UINT32_C(0x80000000);
|
||||||
|
CPU_Hi.value = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CPU_Lo.value = static_cast<u32>(static_cast<s32>(rsVal) / static_cast<s32>(rtVal));
|
||||||
|
CPU_Hi.value = static_cast<u32>(static_cast<s32>(rsVal) % static_cast<s32>(rtVal));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPU_DIVU(u32 instr, u32 hiVal, u32 loVal, u32 rsVal, u32 rtVal)
|
void CPU_DIVU(u32 instr, u32 rsVal, u32 rtVal)
|
||||||
{
|
{
|
||||||
// Lo = Rs / Rt (unsigned)
|
// Lo = Rs / Rt (unsigned)
|
||||||
// Hi = Rs % Rt (unsigned)
|
// Hi = Rs % Rt (unsigned)
|
||||||
|
@ -1464,8 +1484,17 @@ void CPU_DIVU(u32 instr, u32 hiVal, u32 loVal, u32 rsVal, u32 rtVal)
|
||||||
CPU_Hi.y = (float)f16Sign(f16Overflow(hi));
|
CPU_Hi.y = (float)f16Sign(f16Overflow(hi));
|
||||||
CPU_Hi.x = (float)f16Sign(hi);
|
CPU_Hi.x = (float)f16Sign(hi);
|
||||||
|
|
||||||
CPU_Lo.value = loVal;
|
if (rtVal == 0)
|
||||||
CPU_Hi.value = hiVal;
|
{
|
||||||
|
// divide by zero
|
||||||
|
CPU_Lo.value = UINT32_C(0xFFFFFFFF);
|
||||||
|
CPU_Hi.value = rsVal;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CPU_Lo.value = rsVal / rtVal;
|
||||||
|
CPU_Hi.value = rsVal % rtVal;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////
|
////////////////////////////////////
|
||||||
|
|
|
@ -76,10 +76,10 @@ void CPU_SLT(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal);
|
||||||
void CPU_SLTU(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal);
|
void CPU_SLTU(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal);
|
||||||
|
|
||||||
// Register mult/div
|
// Register mult/div
|
||||||
void CPU_MULT(u32 instr, u32 hiVal, u32 loVal, u32 rsVal, u32 rtVal);
|
void CPU_MULT(u32 instr, u32 rsVal, u32 rtVal);
|
||||||
void CPU_MULTU(u32 instr, u32 hiVal, u32 loVal, u32 rsVal, u32 rtVal);
|
void CPU_MULTU(u32 instr, u32 rsVal, u32 rtVal);
|
||||||
void CPU_DIV(u32 instr, u32 hiVal, u32 loVal, u32 rsVal, u32 rtVal);
|
void CPU_DIV(u32 instr, u32 rsVal, u32 rtVal);
|
||||||
void CPU_DIVU(u32 instr, u32 hiVal, u32 loVal, u32 rsVal, u32 rtVal);
|
void CPU_DIVU(u32 instr, u32 rsVal, u32 rtVal);
|
||||||
|
|
||||||
// Shift operations (sa)
|
// Shift operations (sa)
|
||||||
void CPU_SLL(u32 instr, u32 rdVal, u32 rtVal);
|
void CPU_SLL(u32 instr, u32 rdVal, u32 rtVal);
|
||||||
|
|
Loading…
Reference in a new issue