Core: Add handling of overflow exception
This commit is contained in:
parent
0371c20d32
commit
18b9892bc7
|
@ -816,7 +816,15 @@ void R4300iOp::ADDI()
|
|||
StackValue += (int16_t)m_Opcode.immediate;
|
||||
}
|
||||
#endif
|
||||
_GPR[m_Opcode.rt].DW = (_GPR[m_Opcode.rs].W[0] + ((int16_t)m_Opcode.immediate));
|
||||
int32_t rs = _GPR[m_Opcode.rs].W[0];
|
||||
int32_t imm = (int16_t)m_Opcode.immediate;
|
||||
int32_t sum = rs + imm;
|
||||
if ((~(rs ^ imm) & (rs ^ sum)) & 0x80000000)
|
||||
{
|
||||
GenerateOverflowException();
|
||||
return;
|
||||
}
|
||||
_GPR[m_Opcode.rt].DW = sum;
|
||||
#ifdef Interpreter_StackTest
|
||||
if (m_Opcode.rt == 29 && m_Opcode.rs != 29)
|
||||
{
|
||||
|
@ -979,7 +987,16 @@ void R4300iOp::BGTZL()
|
|||
|
||||
void R4300iOp::DADDI()
|
||||
{
|
||||
_GPR[m_Opcode.rt].DW = _GPR[m_Opcode.rs].DW + (int64_t)((int16_t)m_Opcode.immediate);
|
||||
int64_t rs = _GPR[m_Opcode.rs].DW;
|
||||
int64_t imm = (int64_t)((int16_t)m_Opcode.immediate);
|
||||
int64_t sum = rs + imm;
|
||||
if ((~(rs ^ imm) & (rs ^ sum)) & 0x8000000000000000)
|
||||
{
|
||||
GenerateOverflowException();
|
||||
return;
|
||||
}
|
||||
_GPR[m_Opcode.rt].DW = sum;
|
||||
|
||||
}
|
||||
|
||||
void R4300iOp::DADDIU()
|
||||
|
@ -1499,7 +1516,15 @@ void R4300iOp::SPECIAL_DDIVU()
|
|||
|
||||
void R4300iOp::SPECIAL_ADD()
|
||||
{
|
||||
_GPR[m_Opcode.rd].DW = _GPR[m_Opcode.rs].W[0] + _GPR[m_Opcode.rt].W[0];
|
||||
int32_t rs = _GPR[m_Opcode.rs].W[0];
|
||||
int32_t rt = _GPR[m_Opcode.rt].W[0];
|
||||
int32_t sum = rs + rt;
|
||||
if ((~(rs ^ rt) & (rs ^ sum)) & 0x80000000)
|
||||
{
|
||||
GenerateOverflowException();
|
||||
return;
|
||||
}
|
||||
_GPR[m_Opcode.rd].DW = sum;
|
||||
}
|
||||
|
||||
void R4300iOp::SPECIAL_ADDU()
|
||||
|
@ -1509,7 +1534,16 @@ void R4300iOp::SPECIAL_ADDU()
|
|||
|
||||
void R4300iOp::SPECIAL_SUB()
|
||||
{
|
||||
_GPR[m_Opcode.rd].DW = _GPR[m_Opcode.rs].W[0] - _GPR[m_Opcode.rt].W[0];
|
||||
int32_t rs = _GPR[m_Opcode.rs].W[0];
|
||||
int32_t rt = _GPR[m_Opcode.rt].W[0];
|
||||
int32_t sub = rs - rt;
|
||||
|
||||
if (((rs ^ rt) & (rs ^ sub)) & 0x80000000)
|
||||
{
|
||||
GenerateOverflowException();
|
||||
return;
|
||||
}
|
||||
_GPR[m_Opcode.rd].DW = sub;
|
||||
}
|
||||
|
||||
void R4300iOp::SPECIAL_SUBU()
|
||||
|
@ -1569,7 +1603,15 @@ void R4300iOp::SPECIAL_SLTU()
|
|||
|
||||
void R4300iOp::SPECIAL_DADD()
|
||||
{
|
||||
_GPR[m_Opcode.rd].DW = _GPR[m_Opcode.rs].DW + _GPR[m_Opcode.rt].DW;
|
||||
int64_t rs = _GPR[m_Opcode.rs].DW;
|
||||
int64_t rt = _GPR[m_Opcode.rt].DW;
|
||||
int64_t sum = rs + rt;
|
||||
if ((~(rs ^ rt) & (rs ^ sum)) & 0x8000000000000000)
|
||||
{
|
||||
GenerateOverflowException();
|
||||
return;
|
||||
}
|
||||
_GPR[m_Opcode.rd].DW = sum;
|
||||
}
|
||||
|
||||
void R4300iOp::SPECIAL_DADDU()
|
||||
|
@ -1579,7 +1621,16 @@ void R4300iOp::SPECIAL_DADDU()
|
|||
|
||||
void R4300iOp::SPECIAL_DSUB()
|
||||
{
|
||||
_GPR[m_Opcode.rd].DW = _GPR[m_Opcode.rs].DW - _GPR[m_Opcode.rt].DW;
|
||||
int64_t rs = _GPR[m_Opcode.rs].DW;
|
||||
int64_t rt = _GPR[m_Opcode.rt].DW;
|
||||
int64_t sub = rs - rt;
|
||||
|
||||
if (((rs ^ rt) & (rs ^ sub)) & 0x8000000000000000)
|
||||
{
|
||||
GenerateOverflowException();
|
||||
return;
|
||||
}
|
||||
_GPR[m_Opcode.rd].DW = sub;
|
||||
}
|
||||
|
||||
void R4300iOp::SPECIAL_DSUBU()
|
||||
|
@ -2688,6 +2739,13 @@ void R4300iOp::GenerateAddressErrorException(uint32_t VAddr, bool FromRead)
|
|||
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER);
|
||||
}
|
||||
|
||||
void R4300iOp::GenerateOverflowException(void)
|
||||
{
|
||||
g_Reg->DoOverflowException(g_System->m_PipelineStage == PIPELINE_STAGE_JUMP);
|
||||
g_System->m_PipelineStage = PIPELINE_STAGE_JUMP;
|
||||
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER);
|
||||
}
|
||||
|
||||
void R4300iOp::GenerateTLBReadException(uint32_t VAddr, const char * function)
|
||||
{
|
||||
if (bShowTLBMisses())
|
||||
|
|
|
@ -241,6 +241,7 @@ protected:
|
|||
static Func Jump_CoP1_L[64];
|
||||
|
||||
static void GenerateAddressErrorException(uint32_t VAddr, bool FromRead);
|
||||
static void GenerateOverflowException(void);
|
||||
static void GenerateTLBReadException(uint32_t VAddr, const char * function);
|
||||
static void GenerateTLBWriteException(uint32_t VAddr, const char * function);
|
||||
|
||||
|
|
|
@ -715,7 +715,15 @@ void R4300iOp32::ADDI()
|
|||
StackValue += (int16_t)m_Opcode.immediate;
|
||||
}
|
||||
#endif
|
||||
_GPR[m_Opcode.rt].W[0] = (_GPR[m_Opcode.rs].W[0] + ((int16_t)m_Opcode.immediate));
|
||||
int32_t rs = _GPR[m_Opcode.rs].W[0];
|
||||
int32_t imm = (int16_t)m_Opcode.immediate;
|
||||
int32_t sum = rs + imm;
|
||||
if ((~(rs ^ imm) & (rs ^ sum)) & 0x80000000)
|
||||
{
|
||||
GenerateOverflowException();
|
||||
return;
|
||||
}
|
||||
_GPR[m_Opcode.rt].W[0] = sum;
|
||||
#ifdef Interpreter_StackTest
|
||||
if (m_Opcode.rt == 29 && m_Opcode.rs != 29)
|
||||
{
|
||||
|
@ -1001,7 +1009,15 @@ void R4300iOp32::SPECIAL_JALR()
|
|||
|
||||
void R4300iOp32::SPECIAL_ADD()
|
||||
{
|
||||
_GPR[m_Opcode.rd].W[0] = _GPR[m_Opcode.rs].W[0] + _GPR[m_Opcode.rt].W[0];
|
||||
int32_t rs = _GPR[m_Opcode.rs].W[0];
|
||||
int32_t rt = _GPR[m_Opcode.rt].W[0];
|
||||
int32_t sum = rs + rt;
|
||||
if ((~(rs ^ rt) & (rs ^ sum)) & 0x80000000)
|
||||
{
|
||||
GenerateOverflowException();
|
||||
return;
|
||||
}
|
||||
_GPR[m_Opcode.rd].W[0] = sum;
|
||||
}
|
||||
|
||||
void R4300iOp32::SPECIAL_ADDU()
|
||||
|
@ -1011,7 +1027,16 @@ void R4300iOp32::SPECIAL_ADDU()
|
|||
|
||||
void R4300iOp32::SPECIAL_SUB()
|
||||
{
|
||||
_GPR[m_Opcode.rd].W[0] = _GPR[m_Opcode.rs].W[0] - _GPR[m_Opcode.rt].W[0];
|
||||
int32_t rs = _GPR[m_Opcode.rs].W[0];
|
||||
int32_t rt = _GPR[m_Opcode.rt].W[0];
|
||||
int32_t sub = rs - rt;
|
||||
|
||||
if (((rs ^ rt) & (rs ^ sub)) & 0x80000000)
|
||||
{
|
||||
GenerateOverflowException();
|
||||
return;
|
||||
}
|
||||
_GPR[m_Opcode.rd].W[0] = sub;
|
||||
}
|
||||
|
||||
void R4300iOp32::SPECIAL_SUBU()
|
||||
|
|
|
@ -367,6 +367,22 @@ bool CRegisters::DoIntrException(bool DelaySlot)
|
|||
return true;
|
||||
}
|
||||
|
||||
void CRegisters::DoOverflowException(bool DelaySlot)
|
||||
{
|
||||
CAUSE_REGISTER = EXC_OV;
|
||||
if (DelaySlot)
|
||||
{
|
||||
CAUSE_REGISTER |= CAUSE_BD;
|
||||
EPC_REGISTER = m_PROGRAM_COUNTER - 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
EPC_REGISTER = m_PROGRAM_COUNTER;
|
||||
}
|
||||
m_PROGRAM_COUNTER = 0x80000180;
|
||||
STATUS_REGISTER |= STATUS_EXL;
|
||||
}
|
||||
|
||||
void CRegisters::DoTLBReadMiss(bool DelaySlot, uint32_t BadVaddr)
|
||||
{
|
||||
CAUSE_REGISTER = EXC_RMISS;
|
||||
|
|
|
@ -269,6 +269,7 @@ public:
|
|||
void DoTrapException( bool DelaySlot );
|
||||
void DoCopUnusableException( bool DelaySlot, int32_t Coprocessor );
|
||||
bool DoIntrException( bool DelaySlot );
|
||||
void DoOverflowException(bool DelaySlot);
|
||||
void DoTLBReadMiss(bool DelaySlot, uint32_t BadVaddr);
|
||||
void DoTLBWriteMiss(bool DelaySlot, uint32_t BadVaddr);
|
||||
void DoSysCallException ( bool DelaySlot);
|
||||
|
|
|
@ -19,6 +19,7 @@ struct CExitInfo
|
|||
TLBReadMiss = 5,
|
||||
TLBWriteMiss = 6,
|
||||
ExitResetRecompCode = 8,
|
||||
Exit_ExceptionOverflow,
|
||||
};
|
||||
|
||||
std::string Name;
|
||||
|
|
|
@ -473,6 +473,7 @@ void CX86RecompilerOps::Compile_Branch(RecompilerBranchCompare CompareType, bool
|
|||
}
|
||||
if (m_CompilePC + ((int16_t)m_Opcode.offset << 2) + 4 == m_CompilePC + 8)
|
||||
{
|
||||
m_PipelineStage = PIPELINE_STAGE_DO_DELAY_SLOT;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2218,8 +2219,6 @@ void CX86RecompilerOps::JAL()
|
|||
|
||||
void CX86RecompilerOps::ADDI()
|
||||
{
|
||||
if (m_Opcode.rt == 0) { return; }
|
||||
|
||||
if (g_System->bFastSP() && m_Opcode.rs == 29 && m_Opcode.rt == 29)
|
||||
{
|
||||
m_Assembler.AddConstToX86Reg(Map_MemoryStack(CX86Ops::x86_Any, true), (int16_t)m_Opcode.immediate);
|
||||
|
@ -2227,17 +2226,36 @@ void CX86RecompilerOps::ADDI()
|
|||
|
||||
if (IsConst(m_Opcode.rs))
|
||||
{
|
||||
if (IsMapped(m_Opcode.rt))
|
||||
int32_t rs = GetMipsRegLo(m_Opcode.rs);
|
||||
int32_t imm = (int16_t)m_Opcode.immediate;
|
||||
int32_t sum = rs + imm;
|
||||
if ((~(rs ^ imm) & (rs ^ sum)) & 0x80000000)
|
||||
{
|
||||
UnMap_GPR(m_Opcode.rt, false);
|
||||
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp());
|
||||
CompileExit(m_CompilePC, m_CompilePC, m_RegWorkingSet, CExitInfo::Exit_ExceptionOverflow, true, nullptr);
|
||||
m_PipelineStage = PIPELINE_STAGE_END_BLOCK;
|
||||
}
|
||||
else if (m_Opcode.rt != 0)
|
||||
{
|
||||
if (IsMapped(m_Opcode.rt))
|
||||
{
|
||||
UnMap_GPR(m_Opcode.rt, false);
|
||||
}
|
||||
m_RegWorkingSet.SetMipsRegLo(m_Opcode.rt, sum);
|
||||
m_RegWorkingSet.SetMipsRegState(m_Opcode.rt, CRegInfo::STATE_CONST_32_SIGN);
|
||||
}
|
||||
m_RegWorkingSet.SetMipsRegLo(m_Opcode.rt, GetMipsRegLo(m_Opcode.rs) + (int16_t)m_Opcode.immediate);
|
||||
m_RegWorkingSet.SetMipsRegState(m_Opcode.rt, CRegInfo::STATE_CONST_32_SIGN);
|
||||
}
|
||||
else
|
||||
{
|
||||
Map_GPR_32bit(m_Opcode.rt, true, m_Opcode.rs);
|
||||
m_Assembler.AddConstToX86Reg(GetMipsRegMapLo(m_Opcode.rt), (int16_t)m_Opcode.immediate);
|
||||
ProtectGPR(m_Opcode.rt);
|
||||
CX86Ops::x86Reg Reg = Map_TempReg(CX86Ops::x86_Any, m_Opcode.rs, false);
|
||||
m_Assembler.AddConstToX86Reg(Reg, (int16_t)m_Opcode.immediate);
|
||||
CompileExit(m_CompilePC, m_CompilePC, m_RegWorkingSet, CExitInfo::Exit_ExceptionOverflow, false, &CX86Ops::JoLabel32);
|
||||
if (m_Opcode.rt != 0)
|
||||
{
|
||||
Map_GPR_32bit(m_Opcode.rt, true, -1);
|
||||
m_Assembler.MoveX86RegToX86Reg(Reg, GetMipsRegMapLo(m_Opcode.rt));
|
||||
}
|
||||
}
|
||||
if (g_System->bFastSP() && m_Opcode.rt == 29 && m_Opcode.rs != 29)
|
||||
{
|
||||
|
@ -2619,7 +2637,7 @@ void CX86RecompilerOps::DADDI()
|
|||
UnMap_GPR(m_Opcode.rs, true);
|
||||
}
|
||||
|
||||
if (m_Opcode.rs != 0)
|
||||
if (m_Opcode.rt != 0)
|
||||
{
|
||||
UnMap_GPR(m_Opcode.rt, true);
|
||||
}
|
||||
|
@ -4523,13 +4541,6 @@ void CX86RecompilerOps::SPECIAL_DSLLV()
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsConst(m_Opcode.rs))
|
||||
{
|
||||
//uint32_t Shift = (GetMipsRegLo(m_Opcode.rs) & 0x3F);
|
||||
CX86RecompilerOps::UnknownOpcode();
|
||||
return;
|
||||
}
|
||||
Map_TempReg(CX86Ops::x86_ECX, m_Opcode.rs, false);
|
||||
m_Assembler.AndConstToX86Reg(CX86Ops::x86_ECX, 0x3F);
|
||||
Map_GPR_64bit(m_Opcode.rd, m_Opcode.rt);
|
||||
|
@ -4591,12 +4602,6 @@ void CX86RecompilerOps::SPECIAL_DSRLV()
|
|||
}
|
||||
return;
|
||||
}
|
||||
if (m_Opcode.rd == m_Opcode.rt)
|
||||
{
|
||||
CX86RecompilerOps::UnknownOpcode();
|
||||
return;
|
||||
}
|
||||
|
||||
Map_TempReg(CX86Ops::x86_ECX, -1, false);
|
||||
m_Assembler.MoveConstToX86reg(Shift, CX86Ops::x86_ECX);
|
||||
Map_GPR_64bit(m_Opcode.rd, m_Opcode.rt);
|
||||
|
@ -4650,13 +4655,6 @@ void CX86RecompilerOps::SPECIAL_DSRAV()
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsConst(m_Opcode.rs))
|
||||
{
|
||||
//uint32_t Shift = (GetMipsRegLo(m_Opcode.rs) & 0x3F);
|
||||
CX86RecompilerOps::UnknownOpcode();
|
||||
return;
|
||||
}
|
||||
Map_TempReg(CX86Ops::x86_ECX, m_Opcode.rs, false);
|
||||
m_Assembler.AndConstToX86Reg(CX86Ops::x86_ECX, 0x3F);
|
||||
Map_GPR_64bit(m_Opcode.rd, m_Opcode.rt);
|
||||
|
@ -5127,44 +5125,56 @@ void CX86RecompilerOps::SPECIAL_DDIVU()
|
|||
|
||||
void CX86RecompilerOps::SPECIAL_ADD()
|
||||
{
|
||||
if (m_Opcode.rd == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int source1 = m_Opcode.rd == m_Opcode.rt ? m_Opcode.rt : m_Opcode.rs;
|
||||
int source2 = m_Opcode.rd == m_Opcode.rt ? m_Opcode.rs : m_Opcode.rt;
|
||||
|
||||
if (IsConst(source1) && IsConst(source2))
|
||||
{
|
||||
uint32_t temp = GetMipsRegLo(source1) + GetMipsRegLo(source2);
|
||||
if (IsMapped(m_Opcode.rd))
|
||||
int32_t Val1 = GetMipsRegLo(source1);
|
||||
int32_t Val2 = GetMipsRegLo(source2);
|
||||
int32_t Sum = Val1 + Val2;
|
||||
if ((~(Val1 ^ Val2) & (Val1 ^ Sum)) & 0x80000000)
|
||||
{
|
||||
UnMap_GPR(m_Opcode.rd, false);
|
||||
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp());
|
||||
CompileExit(m_CompilePC, m_CompilePC, m_RegWorkingSet, CExitInfo::Exit_ExceptionOverflow, true, nullptr);
|
||||
m_PipelineStage = PIPELINE_STAGE_END_BLOCK;
|
||||
}
|
||||
else if (m_Opcode.rd != 0)
|
||||
{
|
||||
if (IsMapped(m_Opcode.rd))
|
||||
{
|
||||
UnMap_GPR(m_Opcode.rd, false);
|
||||
}
|
||||
m_RegWorkingSet.SetMipsRegLo(m_Opcode.rd, Sum);
|
||||
m_RegWorkingSet.SetMipsRegState(m_Opcode.rd, CRegInfo::STATE_CONST_32_SIGN);
|
||||
}
|
||||
|
||||
m_RegWorkingSet.SetMipsRegLo(m_Opcode.rd, temp);
|
||||
m_RegWorkingSet.SetMipsRegState(m_Opcode.rd, CRegInfo::STATE_CONST_32_SIGN);
|
||||
return;
|
||||
}
|
||||
|
||||
Map_GPR_32bit(m_Opcode.rd, true, source1);
|
||||
ProtectGPR(m_Opcode.rd);
|
||||
CX86Ops::x86Reg Reg = Map_TempReg(CX86Ops::x86_Any, source1, false);
|
||||
if (IsConst(source2))
|
||||
{
|
||||
m_Assembler.AddConstToX86Reg(GetMipsRegMapLo(m_Opcode.rd), GetMipsRegLo(source2));
|
||||
m_Assembler.AddConstToX86Reg(Reg, GetMipsRegLo(source2));
|
||||
}
|
||||
else if (IsKnown(source2) && IsMapped(source2))
|
||||
{
|
||||
m_Assembler.AddX86RegToX86Reg(GetMipsRegMapLo(m_Opcode.rd), GetMipsRegMapLo(source2));
|
||||
m_Assembler.AddX86RegToX86Reg(Reg, GetMipsRegMapLo(source2));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Assembler.AddVariableToX86reg(GetMipsRegMapLo(m_Opcode.rd), &_GPR[source2].W[0], CRegName::GPR_Lo[source2]);
|
||||
m_Assembler.AddVariableToX86reg(Reg, &_GPR[source2].W[0], CRegName::GPR_Lo[source2]);
|
||||
}
|
||||
if (g_System->bFastSP() && m_Opcode.rd == 29)
|
||||
{
|
||||
ResetMemoryStack();
|
||||
}
|
||||
CompileExit(m_CompilePC, m_CompilePC, m_RegWorkingSet, CExitInfo::Exit_ExceptionOverflow, false, &CX86Ops::JoLabel32);
|
||||
if (m_Opcode.rd != 0)
|
||||
{
|
||||
Map_GPR_32bit(m_Opcode.rd, true, -1);
|
||||
m_Assembler.MoveX86RegToX86Reg(Reg, GetMipsRegMapLo(m_Opcode.rd));
|
||||
}
|
||||
}
|
||||
|
||||
void CX86RecompilerOps::SPECIAL_ADDU()
|
||||
|
@ -5210,44 +5220,49 @@ void CX86RecompilerOps::SPECIAL_ADDU()
|
|||
|
||||
void CX86RecompilerOps::SPECIAL_SUB()
|
||||
{
|
||||
if (m_Opcode.rd == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsConst(m_Opcode.rt) && IsConst(m_Opcode.rs))
|
||||
{
|
||||
uint32_t temp = GetMipsRegLo(m_Opcode.rs) - GetMipsRegLo(m_Opcode.rt);
|
||||
int32_t rs = GetMipsRegLo(m_Opcode.rs);
|
||||
int32_t rt = GetMipsRegLo(m_Opcode.rt);
|
||||
int32_t sub = rs - rt;
|
||||
|
||||
if (IsMapped(m_Opcode.rd))
|
||||
if (((rs ^ rt) & (rs ^ sub)) & 0x80000000)
|
||||
{
|
||||
UnMap_GPR(m_Opcode.rd, false);
|
||||
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp());
|
||||
CompileExit(m_CompilePC, m_CompilePC, m_RegWorkingSet, CExitInfo::Exit_ExceptionOverflow, true, nullptr);
|
||||
m_PipelineStage = PIPELINE_STAGE_END_BLOCK;
|
||||
}
|
||||
else if (m_Opcode.rd != 0)
|
||||
{
|
||||
if (IsMapped(m_Opcode.rd))
|
||||
{
|
||||
UnMap_GPR(m_Opcode.rd, false);
|
||||
}
|
||||
m_RegWorkingSet.SetMipsRegLo(m_Opcode.rd, sub);
|
||||
m_RegWorkingSet.SetMipsRegState(m_Opcode.rd, CRegInfo::STATE_CONST_32_SIGN);
|
||||
}
|
||||
|
||||
m_RegWorkingSet.SetMipsRegLo(m_Opcode.rd, temp);
|
||||
m_RegWorkingSet.SetMipsRegState(m_Opcode.rd, CRegInfo::STATE_CONST_32_SIGN);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_Opcode.rd == m_Opcode.rt)
|
||||
{
|
||||
CX86Ops::x86Reg Reg = Map_TempReg(CX86Ops::x86_Any, m_Opcode.rt, false);
|
||||
Map_GPR_32bit(m_Opcode.rd, true, m_Opcode.rs);
|
||||
m_Assembler.SubX86RegToX86Reg(GetMipsRegMapLo(m_Opcode.rd), Reg);
|
||||
return;
|
||||
}
|
||||
Map_GPR_32bit(m_Opcode.rd, true, m_Opcode.rs);
|
||||
ProtectGPR(m_Opcode.rd);
|
||||
CX86Ops::x86Reg Reg = Map_TempReg(CX86Ops::x86_Any, m_Opcode.rs, false);
|
||||
if (IsConst(m_Opcode.rt))
|
||||
{
|
||||
m_Assembler.SubConstFromX86Reg(GetMipsRegMapLo(m_Opcode.rd), GetMipsRegLo(m_Opcode.rt));
|
||||
m_Assembler.SubConstFromX86Reg(Reg, GetMipsRegLo(m_Opcode.rt));
|
||||
}
|
||||
else if (IsMapped(m_Opcode.rt))
|
||||
{
|
||||
m_Assembler.SubX86RegToX86Reg(GetMipsRegMapLo(m_Opcode.rd), GetMipsRegMapLo(m_Opcode.rt));
|
||||
m_Assembler.SubX86RegToX86Reg(Reg, GetMipsRegMapLo(m_Opcode.rt));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Assembler.SubVariableFromX86reg(GetMipsRegMapLo(m_Opcode.rd), &_GPR[m_Opcode.rt].W[0], CRegName::GPR_Lo[m_Opcode.rt]);
|
||||
m_Assembler.SubVariableFromX86reg(Reg, &_GPR[m_Opcode.rt].W[0], CRegName::GPR_Lo[m_Opcode.rt]);
|
||||
}
|
||||
CompileExit(m_CompilePC, m_CompilePC, m_RegWorkingSet, CExitInfo::Exit_ExceptionOverflow, false, &CX86Ops::JoLabel32);
|
||||
if (m_Opcode.rd != 0)
|
||||
{
|
||||
Map_GPR_32bit(m_Opcode.rd, true, -1);
|
||||
m_Assembler.MoveX86RegToX86Reg(Reg, GetMipsRegMapLo(m_Opcode.rd));
|
||||
}
|
||||
}
|
||||
if (g_System->bFastSP() && m_Opcode.rd == 29)
|
||||
|
@ -6597,33 +6612,36 @@ void CX86RecompilerOps::SPECIAL_SLTU()
|
|||
|
||||
void CX86RecompilerOps::SPECIAL_DADD()
|
||||
{
|
||||
if (m_Opcode.rd == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsConst(m_Opcode.rt) && IsConst(m_Opcode.rs))
|
||||
{
|
||||
if (IsMapped(m_Opcode.rd))
|
||||
int64_t rs = Is64Bit(m_Opcode.rs) ? GetMipsReg(m_Opcode.rs) : (int64_t)GetMipsRegLo_S(m_Opcode.rs);
|
||||
int64_t rt = Is64Bit(m_Opcode.rt) ? GetMipsReg(m_Opcode.rt) : (int64_t)GetMipsRegLo_S(m_Opcode.rt);
|
||||
int64_t sum = rs + rt;
|
||||
if ((~(rs ^ rt) & (rs ^ sum)) & 0x8000000000000000)
|
||||
{
|
||||
UnMap_GPR(m_Opcode.rd, false);
|
||||
}
|
||||
|
||||
m_RegWorkingSet.SetMipsReg(m_Opcode.rd,
|
||||
Is64Bit(m_Opcode.rs) ? GetMipsReg(m_Opcode.rs) : (int64_t)GetMipsRegLo_S(m_Opcode.rs) +
|
||||
Is64Bit(m_Opcode.rt) ? GetMipsReg(m_Opcode.rt) : (int64_t)GetMipsRegLo_S(m_Opcode.rt)
|
||||
);
|
||||
if (GetMipsRegLo_S(m_Opcode.rd) < 0 && GetMipsRegHi_S(m_Opcode.rd) == -1)
|
||||
{
|
||||
m_RegWorkingSet.SetMipsRegState(m_Opcode.rd, CRegInfo::STATE_CONST_32_SIGN);
|
||||
}
|
||||
else if (GetMipsRegLo_S(m_Opcode.rd) >= 0 && GetMipsRegHi_S(m_Opcode.rd) == 0)
|
||||
{
|
||||
m_RegWorkingSet.SetMipsRegState(m_Opcode.rd, CRegInfo::STATE_CONST_32_SIGN);
|
||||
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp());
|
||||
CompileExit(m_CompilePC, m_CompilePC, m_RegWorkingSet, CExitInfo::Exit_ExceptionOverflow, true, nullptr);
|
||||
m_PipelineStage = PIPELINE_STAGE_END_BLOCK;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_RegWorkingSet.SetMipsRegState(m_Opcode.rd, CRegInfo::STATE_CONST_64);
|
||||
if (IsMapped(m_Opcode.rd))
|
||||
{
|
||||
UnMap_GPR(m_Opcode.rd, false);
|
||||
}
|
||||
m_RegWorkingSet.SetMipsReg(m_Opcode.rd, sum);
|
||||
if (GetMipsRegLo_S(m_Opcode.rd) < 0 && GetMipsRegHi_S(m_Opcode.rd) == -1)
|
||||
{
|
||||
m_RegWorkingSet.SetMipsRegState(m_Opcode.rd, CRegInfo::STATE_CONST_32_SIGN);
|
||||
}
|
||||
else if (GetMipsRegLo_S(m_Opcode.rd) >= 0 && GetMipsRegHi_S(m_Opcode.rd) == 0)
|
||||
{
|
||||
m_RegWorkingSet.SetMipsRegState(m_Opcode.rd, CRegInfo::STATE_CONST_32_SIGN);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_RegWorkingSet.SetMipsRegState(m_Opcode.rd, CRegInfo::STATE_CONST_64);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -6631,23 +6649,35 @@ void CX86RecompilerOps::SPECIAL_DADD()
|
|||
int source1 = m_Opcode.rd == m_Opcode.rt ? m_Opcode.rt : m_Opcode.rs;
|
||||
int source2 = m_Opcode.rd == m_Opcode.rt ? m_Opcode.rs : m_Opcode.rt;
|
||||
|
||||
if (IsMapped(source2)) { ProtectGPR(source2); }
|
||||
Map_GPR_64bit(m_Opcode.rd, source1);
|
||||
ProtectGPR(source1);
|
||||
ProtectGPR(source2);
|
||||
CX86Ops::x86Reg RegLo = Map_TempReg(CX86Ops::x86_Any, source1, false);
|
||||
CX86Ops::x86Reg RegHi = Map_TempReg(CX86Ops::x86_Any, source1, true);
|
||||
|
||||
if (IsConst(source2))
|
||||
{
|
||||
m_Assembler.AddConstToX86Reg(GetMipsRegMapLo(m_Opcode.rd), GetMipsRegLo(source2));
|
||||
m_Assembler.AddConstToX86Reg(GetMipsRegMapHi(m_Opcode.rd), GetMipsRegHi(source2));
|
||||
m_Assembler.AddConstToX86Reg(RegLo, GetMipsRegLo(source2));
|
||||
m_Assembler.AdcConstToX86Reg(RegHi, GetMipsRegHi(source2));
|
||||
}
|
||||
else if (IsMapped(source2))
|
||||
{
|
||||
CX86Ops::x86Reg HiReg = Is64Bit(source2) ? GetMipsRegMapHi(source2) : Map_TempReg(CX86Ops::x86_Any, source2, true);
|
||||
m_Assembler.AddX86RegToX86Reg(GetMipsRegMapLo(m_Opcode.rd), GetMipsRegMapLo(source2));
|
||||
m_Assembler.AdcX86RegToX86Reg(GetMipsRegMapHi(m_Opcode.rd), HiReg);
|
||||
m_Assembler.AddX86RegToX86Reg(RegLo, GetMipsRegMapLo(source2));
|
||||
m_Assembler.AdcX86RegToX86Reg(RegHi, HiReg);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Assembler.AddVariableToX86reg(GetMipsRegMapLo(m_Opcode.rd), &_GPR[source2].W[0], CRegName::GPR_Lo[source2]);
|
||||
m_Assembler.AdcVariableToX86reg(GetMipsRegMapHi(m_Opcode.rd), &_GPR[source2].W[1], CRegName::GPR_Hi[source2]);
|
||||
m_Assembler.AddVariableToX86reg(RegLo, &_GPR[source2].W[0], CRegName::GPR_Lo[source2]);
|
||||
m_Assembler.AdcVariableToX86reg(RegHi, &_GPR[source2].W[1], CRegName::GPR_Hi[source2]);
|
||||
}
|
||||
CompileExit(m_CompilePC, m_CompilePC, m_RegWorkingSet, CExitInfo::Exit_ExceptionOverflow, false, &CX86Ops::JoLabel32);
|
||||
if (m_Opcode.rd != 0)
|
||||
{
|
||||
UnProtectGPR(source1);
|
||||
UnProtectGPR(source2);
|
||||
Map_GPR_64bit(m_Opcode.rd, source1);
|
||||
m_Assembler.MoveX86RegToX86Reg(RegLo, GetMipsRegMapLo(m_Opcode.rd));
|
||||
m_Assembler.MoveX86RegToX86Reg(RegHi, GetMipsRegMapHi(m_Opcode.rd));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6716,64 +6746,73 @@ void CX86RecompilerOps::SPECIAL_DADDU()
|
|||
|
||||
void CX86RecompilerOps::SPECIAL_DSUB()
|
||||
{
|
||||
if (m_Opcode.rd == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsConst(m_Opcode.rt) && IsConst(m_Opcode.rs))
|
||||
{
|
||||
if (IsMapped(m_Opcode.rd))
|
||||
{
|
||||
UnMap_GPR(m_Opcode.rd, false);
|
||||
}
|
||||
int64_t rs = Is64Bit(m_Opcode.rs) ? GetMipsReg(m_Opcode.rs) : (int64_t)GetMipsRegLo_S(m_Opcode.rs);
|
||||
int64_t rt = Is64Bit(m_Opcode.rt) ? GetMipsReg(m_Opcode.rt) : (int64_t)GetMipsRegLo_S(m_Opcode.rt);
|
||||
int64_t sub = rs - rt;
|
||||
|
||||
m_RegWorkingSet.SetMipsReg(m_Opcode.rd,
|
||||
Is64Bit(m_Opcode.rs) ? GetMipsReg(m_Opcode.rs) : (int64_t)GetMipsRegLo_S(m_Opcode.rs) -
|
||||
Is64Bit(m_Opcode.rt) ? GetMipsReg(m_Opcode.rt) : (int64_t)GetMipsRegLo_S(m_Opcode.rt)
|
||||
);
|
||||
if (GetMipsRegLo_S(m_Opcode.rd) < 0 && GetMipsRegHi_S(m_Opcode.rd) == -1)
|
||||
if (((rs ^ rt) & (rs ^ sub)) & 0x8000000000000000)
|
||||
{
|
||||
m_RegWorkingSet.SetMipsRegState(m_Opcode.rd, CRegInfo::STATE_CONST_32_SIGN);
|
||||
}
|
||||
else if (GetMipsRegLo_S(m_Opcode.rd) >= 0 && GetMipsRegHi_S(m_Opcode.rd) == 0)
|
||||
{
|
||||
m_RegWorkingSet.SetMipsRegState(m_Opcode.rd, CRegInfo::STATE_CONST_32_SIGN);
|
||||
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp());
|
||||
CompileExit(m_CompilePC, m_CompilePC, m_RegWorkingSet, CExitInfo::Exit_ExceptionOverflow, true, nullptr);
|
||||
m_PipelineStage = PIPELINE_STAGE_END_BLOCK;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_RegWorkingSet.SetMipsRegState(m_Opcode.rd, CRegInfo::STATE_CONST_64);
|
||||
if (IsMapped(m_Opcode.rd))
|
||||
{
|
||||
UnMap_GPR(m_Opcode.rd, false);
|
||||
}
|
||||
m_RegWorkingSet.SetMipsReg(m_Opcode.rd, sub);
|
||||
if (GetMipsRegLo_S(m_Opcode.rd) < 0 && GetMipsRegHi_S(m_Opcode.rd) == -1)
|
||||
{
|
||||
m_RegWorkingSet.SetMipsRegState(m_Opcode.rd, CRegInfo::STATE_CONST_32_SIGN);
|
||||
}
|
||||
else if (GetMipsRegLo_S(m_Opcode.rd) >= 0 && GetMipsRegHi_S(m_Opcode.rd) == 0)
|
||||
{
|
||||
m_RegWorkingSet.SetMipsRegState(m_Opcode.rd, CRegInfo::STATE_CONST_32_SIGN);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_RegWorkingSet.SetMipsRegState(m_Opcode.rd, CRegInfo::STATE_CONST_64);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_Opcode.rd == m_Opcode.rt)
|
||||
{
|
||||
CX86Ops::x86Reg HiReg = Map_TempReg(CX86Ops::x86_Any, m_Opcode.rt, true);
|
||||
CX86Ops::x86Reg LoReg = Map_TempReg(CX86Ops::x86_Any, m_Opcode.rt, false);
|
||||
Map_GPR_64bit(m_Opcode.rd, m_Opcode.rs);
|
||||
m_Assembler.SubX86RegToX86Reg(GetMipsRegMapLo(m_Opcode.rd), LoReg);
|
||||
m_Assembler.SbbX86RegToX86Reg(GetMipsRegMapHi(m_Opcode.rd), HiReg);
|
||||
return;
|
||||
}
|
||||
int source1 = m_Opcode.rd == m_Opcode.rt ? m_Opcode.rt : m_Opcode.rs;
|
||||
int source2 = m_Opcode.rd == m_Opcode.rt ? m_Opcode.rs : m_Opcode.rt;
|
||||
|
||||
if (IsMapped(m_Opcode.rt)) { ProtectGPR(m_Opcode.rt); }
|
||||
Map_GPR_64bit(m_Opcode.rd, m_Opcode.rs);
|
||||
if (IsConst(m_Opcode.rt))
|
||||
ProtectGPR(source1);
|
||||
ProtectGPR(source2);
|
||||
CX86Ops::x86Reg RegLo = Map_TempReg(CX86Ops::x86_Any, source1, false);
|
||||
CX86Ops::x86Reg RegHi = Map_TempReg(CX86Ops::x86_Any, source1, true);
|
||||
|
||||
if (IsConst(source2))
|
||||
{
|
||||
m_Assembler.SubConstFromX86Reg(GetMipsRegMapLo(m_Opcode.rd), GetMipsRegLo(m_Opcode.rt));
|
||||
m_Assembler.SbbConstFromX86Reg(GetMipsRegMapHi(m_Opcode.rd), GetMipsRegHi(m_Opcode.rt));
|
||||
m_Assembler.SubConstFromX86Reg(RegLo, GetMipsRegLo(source2));
|
||||
m_Assembler.SbbConstFromX86Reg(RegHi, GetMipsRegHi(source2));
|
||||
}
|
||||
else if (IsMapped(m_Opcode.rt))
|
||||
else if (IsMapped(source2))
|
||||
{
|
||||
CX86Ops::x86Reg HiReg = Is64Bit(m_Opcode.rt) ? GetMipsRegMapHi(m_Opcode.rt) : Map_TempReg(CX86Ops::x86_Any, m_Opcode.rt, true);
|
||||
m_Assembler.SubX86RegToX86Reg(GetMipsRegMapLo(m_Opcode.rd), GetMipsRegMapLo(m_Opcode.rt));
|
||||
m_Assembler.SbbX86RegToX86Reg(GetMipsRegMapHi(m_Opcode.rd), HiReg);
|
||||
CX86Ops::x86Reg HiReg = Is64Bit(source2) ? GetMipsRegMapHi(source2) : Map_TempReg(CX86Ops::x86_Any, source2, true);
|
||||
m_Assembler.SubX86RegToX86Reg(RegLo, GetMipsRegMapLo(source2));
|
||||
m_Assembler.SbbX86RegToX86Reg(RegHi, HiReg);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Assembler.SubVariableFromX86reg(GetMipsRegMapLo(m_Opcode.rd), &_GPR[m_Opcode.rt].W[0], CRegName::GPR_Lo[m_Opcode.rt]);
|
||||
m_Assembler.SbbVariableFromX86reg(GetMipsRegMapHi(m_Opcode.rd), &_GPR[m_Opcode.rt].W[1], CRegName::GPR_Hi[m_Opcode.rt]);
|
||||
m_Assembler.SubVariableFromX86reg(RegLo, &_GPR[source2].W[0], CRegName::GPR_Lo[source2]);
|
||||
m_Assembler.SbbVariableFromX86reg(RegHi, &_GPR[source2].W[1], CRegName::GPR_Hi[source2]);
|
||||
}
|
||||
CompileExit(m_CompilePC, m_CompilePC, m_RegWorkingSet, CExitInfo::Exit_ExceptionOverflow, false, &CX86Ops::JoLabel32);
|
||||
if (m_Opcode.rd != 0)
|
||||
{
|
||||
UnProtectGPR(source1);
|
||||
UnProtectGPR(source2);
|
||||
Map_GPR_64bit(m_Opcode.rd, source1);
|
||||
m_Assembler.MoveX86RegToX86Reg(RegLo, GetMipsRegMapLo(m_Opcode.rd));
|
||||
m_Assembler.MoveX86RegToX86Reg(RegHi, GetMipsRegMapHi(m_Opcode.rd));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9513,6 +9552,11 @@ void CX86RecompilerOps::CompileExit(uint32_t JumpPC, uint32_t TargetPC, CRegInfo
|
|||
m_Assembler.X86BreakPoint(__FILE__, __LINE__);
|
||||
ExitCodeBlock();
|
||||
break;
|
||||
case CExitInfo::Exit_ExceptionOverflow:
|
||||
m_Assembler.PushImm32(m_PipelineStage == PIPELINE_STAGE_JUMP || m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT);
|
||||
m_Assembler.CallThis((uint32_t)g_Reg, AddressOf(&CRegisters::DoOverflowException), "CRegisters::DoOverflowException", 12);
|
||||
ExitCodeBlock();
|
||||
break;
|
||||
default:
|
||||
WriteTrace(TraceRecompiler, TraceError, "How did you want to exit on reason (%d) ???", reason);
|
||||
g_Notify->BreakPoint(__FILE__, __LINE__);
|
||||
|
|
|
@ -630,6 +630,13 @@ void CX86Ops::JsLabel32(const char *Label, uint32_t Value)
|
|||
AddCode32(Value);
|
||||
}
|
||||
|
||||
void CX86Ops::JoLabel32(const char *Label, uint32_t Value)
|
||||
{
|
||||
CodeLog(" jo $%s", Label);
|
||||
AddCode16(0x800F);
|
||||
AddCode32(Value);
|
||||
}
|
||||
|
||||
void CX86Ops::JzLabel8(const char *Label, uint8_t Value)
|
||||
{
|
||||
CodeLog(" jz $%s", Label);
|
||||
|
|
|
@ -114,6 +114,7 @@ public:
|
|||
void JnsLabel32(const char * Label, uint32_t Value);
|
||||
void JnzLabel8(const char * Label, uint8_t Value);
|
||||
void JnzLabel32(const char * Label, uint32_t Value);
|
||||
void JoLabel32(const char * Label, uint32_t Value);
|
||||
void JsLabel32(const char * Label, uint32_t Value);
|
||||
void JzLabel8(const char * Label, uint8_t Value);
|
||||
void JzLabel32(const char * Label, uint32_t Value);
|
||||
|
|
Loading…
Reference in New Issue