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;
|
StackValue += (int16_t)m_Opcode.immediate;
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
#ifdef Interpreter_StackTest
|
||||||
if (m_Opcode.rt == 29 && m_Opcode.rs != 29)
|
if (m_Opcode.rt == 29 && m_Opcode.rs != 29)
|
||||||
{
|
{
|
||||||
|
@ -979,7 +987,16 @@ void R4300iOp::BGTZL()
|
||||||
|
|
||||||
void R4300iOp::DADDI()
|
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()
|
void R4300iOp::DADDIU()
|
||||||
|
@ -1499,7 +1516,15 @@ void R4300iOp::SPECIAL_DDIVU()
|
||||||
|
|
||||||
void R4300iOp::SPECIAL_ADD()
|
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()
|
void R4300iOp::SPECIAL_ADDU()
|
||||||
|
@ -1509,7 +1534,16 @@ void R4300iOp::SPECIAL_ADDU()
|
||||||
|
|
||||||
void R4300iOp::SPECIAL_SUB()
|
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()
|
void R4300iOp::SPECIAL_SUBU()
|
||||||
|
@ -1569,7 +1603,15 @@ void R4300iOp::SPECIAL_SLTU()
|
||||||
|
|
||||||
void R4300iOp::SPECIAL_DADD()
|
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()
|
void R4300iOp::SPECIAL_DADDU()
|
||||||
|
@ -1579,7 +1621,16 @@ void R4300iOp::SPECIAL_DADDU()
|
||||||
|
|
||||||
void R4300iOp::SPECIAL_DSUB()
|
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()
|
void R4300iOp::SPECIAL_DSUBU()
|
||||||
|
@ -2688,6 +2739,13 @@ void R4300iOp::GenerateAddressErrorException(uint32_t VAddr, bool FromRead)
|
||||||
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER);
|
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)
|
void R4300iOp::GenerateTLBReadException(uint32_t VAddr, const char * function)
|
||||||
{
|
{
|
||||||
if (bShowTLBMisses())
|
if (bShowTLBMisses())
|
||||||
|
|
|
@ -241,6 +241,7 @@ protected:
|
||||||
static Func Jump_CoP1_L[64];
|
static Func Jump_CoP1_L[64];
|
||||||
|
|
||||||
static void GenerateAddressErrorException(uint32_t VAddr, bool FromRead);
|
static void GenerateAddressErrorException(uint32_t VAddr, bool FromRead);
|
||||||
|
static void GenerateOverflowException(void);
|
||||||
static void GenerateTLBReadException(uint32_t VAddr, const char * function);
|
static void GenerateTLBReadException(uint32_t VAddr, const char * function);
|
||||||
static void GenerateTLBWriteException(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;
|
StackValue += (int16_t)m_Opcode.immediate;
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
#ifdef Interpreter_StackTest
|
||||||
if (m_Opcode.rt == 29 && m_Opcode.rs != 29)
|
if (m_Opcode.rt == 29 && m_Opcode.rs != 29)
|
||||||
{
|
{
|
||||||
|
@ -1001,7 +1009,15 @@ void R4300iOp32::SPECIAL_JALR()
|
||||||
|
|
||||||
void R4300iOp32::SPECIAL_ADD()
|
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()
|
void R4300iOp32::SPECIAL_ADDU()
|
||||||
|
@ -1011,7 +1027,16 @@ void R4300iOp32::SPECIAL_ADDU()
|
||||||
|
|
||||||
void R4300iOp32::SPECIAL_SUB()
|
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()
|
void R4300iOp32::SPECIAL_SUBU()
|
||||||
|
|
|
@ -367,6 +367,22 @@ bool CRegisters::DoIntrException(bool DelaySlot)
|
||||||
return true;
|
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)
|
void CRegisters::DoTLBReadMiss(bool DelaySlot, uint32_t BadVaddr)
|
||||||
{
|
{
|
||||||
CAUSE_REGISTER = EXC_RMISS;
|
CAUSE_REGISTER = EXC_RMISS;
|
||||||
|
|
|
@ -269,6 +269,7 @@ public:
|
||||||
void DoTrapException( bool DelaySlot );
|
void DoTrapException( bool DelaySlot );
|
||||||
void DoCopUnusableException( bool DelaySlot, int32_t Coprocessor );
|
void DoCopUnusableException( bool DelaySlot, int32_t Coprocessor );
|
||||||
bool DoIntrException( bool DelaySlot );
|
bool DoIntrException( bool DelaySlot );
|
||||||
|
void DoOverflowException(bool DelaySlot);
|
||||||
void DoTLBReadMiss(bool DelaySlot, uint32_t BadVaddr);
|
void DoTLBReadMiss(bool DelaySlot, uint32_t BadVaddr);
|
||||||
void DoTLBWriteMiss(bool DelaySlot, uint32_t BadVaddr);
|
void DoTLBWriteMiss(bool DelaySlot, uint32_t BadVaddr);
|
||||||
void DoSysCallException ( bool DelaySlot);
|
void DoSysCallException ( bool DelaySlot);
|
||||||
|
|
|
@ -19,6 +19,7 @@ struct CExitInfo
|
||||||
TLBReadMiss = 5,
|
TLBReadMiss = 5,
|
||||||
TLBWriteMiss = 6,
|
TLBWriteMiss = 6,
|
||||||
ExitResetRecompCode = 8,
|
ExitResetRecompCode = 8,
|
||||||
|
Exit_ExceptionOverflow,
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string Name;
|
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)
|
if (m_CompilePC + ((int16_t)m_Opcode.offset << 2) + 4 == m_CompilePC + 8)
|
||||||
{
|
{
|
||||||
|
m_PipelineStage = PIPELINE_STAGE_DO_DELAY_SLOT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2218,8 +2219,6 @@ void CX86RecompilerOps::JAL()
|
||||||
|
|
||||||
void CX86RecompilerOps::ADDI()
|
void CX86RecompilerOps::ADDI()
|
||||||
{
|
{
|
||||||
if (m_Opcode.rt == 0) { return; }
|
|
||||||
|
|
||||||
if (g_System->bFastSP() && m_Opcode.rs == 29 && m_Opcode.rt == 29)
|
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);
|
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 (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
|
else
|
||||||
{
|
{
|
||||||
Map_GPR_32bit(m_Opcode.rt, true, m_Opcode.rs);
|
ProtectGPR(m_Opcode.rt);
|
||||||
m_Assembler.AddConstToX86Reg(GetMipsRegMapLo(m_Opcode.rt), (int16_t)m_Opcode.immediate);
|
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)
|
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);
|
UnMap_GPR(m_Opcode.rs, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_Opcode.rs != 0)
|
if (m_Opcode.rt != 0)
|
||||||
{
|
{
|
||||||
UnMap_GPR(m_Opcode.rt, true);
|
UnMap_GPR(m_Opcode.rt, true);
|
||||||
}
|
}
|
||||||
|
@ -4523,13 +4541,6 @@ void CX86RecompilerOps::SPECIAL_DSLLV()
|
||||||
{
|
{
|
||||||
return;
|
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);
|
Map_TempReg(CX86Ops::x86_ECX, m_Opcode.rs, false);
|
||||||
m_Assembler.AndConstToX86Reg(CX86Ops::x86_ECX, 0x3F);
|
m_Assembler.AndConstToX86Reg(CX86Ops::x86_ECX, 0x3F);
|
||||||
Map_GPR_64bit(m_Opcode.rd, m_Opcode.rt);
|
Map_GPR_64bit(m_Opcode.rd, m_Opcode.rt);
|
||||||
|
@ -4591,12 +4602,6 @@ void CX86RecompilerOps::SPECIAL_DSRLV()
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (m_Opcode.rd == m_Opcode.rt)
|
|
||||||
{
|
|
||||||
CX86RecompilerOps::UnknownOpcode();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Map_TempReg(CX86Ops::x86_ECX, -1, false);
|
Map_TempReg(CX86Ops::x86_ECX, -1, false);
|
||||||
m_Assembler.MoveConstToX86reg(Shift, CX86Ops::x86_ECX);
|
m_Assembler.MoveConstToX86reg(Shift, CX86Ops::x86_ECX);
|
||||||
Map_GPR_64bit(m_Opcode.rd, m_Opcode.rt);
|
Map_GPR_64bit(m_Opcode.rd, m_Opcode.rt);
|
||||||
|
@ -4650,13 +4655,6 @@ void CX86RecompilerOps::SPECIAL_DSRAV()
|
||||||
{
|
{
|
||||||
return;
|
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);
|
Map_TempReg(CX86Ops::x86_ECX, m_Opcode.rs, false);
|
||||||
m_Assembler.AndConstToX86Reg(CX86Ops::x86_ECX, 0x3F);
|
m_Assembler.AndConstToX86Reg(CX86Ops::x86_ECX, 0x3F);
|
||||||
Map_GPR_64bit(m_Opcode.rd, m_Opcode.rt);
|
Map_GPR_64bit(m_Opcode.rd, m_Opcode.rt);
|
||||||
|
@ -5127,44 +5125,56 @@ void CX86RecompilerOps::SPECIAL_DDIVU()
|
||||||
|
|
||||||
void CX86RecompilerOps::SPECIAL_ADD()
|
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 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;
|
int source2 = m_Opcode.rd == m_Opcode.rt ? m_Opcode.rs : m_Opcode.rt;
|
||||||
|
|
||||||
if (IsConst(source1) && IsConst(source2))
|
if (IsConst(source1) && IsConst(source2))
|
||||||
{
|
{
|
||||||
uint32_t temp = GetMipsRegLo(source1) + GetMipsRegLo(source2);
|
int32_t Val1 = GetMipsRegLo(source1);
|
||||||
if (IsMapped(m_Opcode.rd))
|
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;
|
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))
|
if (IsConst(source2))
|
||||||
{
|
{
|
||||||
m_Assembler.AddConstToX86Reg(GetMipsRegMapLo(m_Opcode.rd), GetMipsRegLo(source2));
|
m_Assembler.AddConstToX86Reg(Reg, GetMipsRegLo(source2));
|
||||||
}
|
}
|
||||||
else if (IsKnown(source2) && IsMapped(source2))
|
else if (IsKnown(source2) && IsMapped(source2))
|
||||||
{
|
{
|
||||||
m_Assembler.AddX86RegToX86Reg(GetMipsRegMapLo(m_Opcode.rd), GetMipsRegMapLo(source2));
|
m_Assembler.AddX86RegToX86Reg(Reg, GetMipsRegMapLo(source2));
|
||||||
}
|
}
|
||||||
else
|
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)
|
if (g_System->bFastSP() && m_Opcode.rd == 29)
|
||||||
{
|
{
|
||||||
ResetMemoryStack();
|
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()
|
void CX86RecompilerOps::SPECIAL_ADDU()
|
||||||
|
@ -5210,44 +5220,49 @@ void CX86RecompilerOps::SPECIAL_ADDU()
|
||||||
|
|
||||||
void CX86RecompilerOps::SPECIAL_SUB()
|
void CX86RecompilerOps::SPECIAL_SUB()
|
||||||
{
|
{
|
||||||
if (m_Opcode.rd == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsConst(m_Opcode.rt) && IsConst(m_Opcode.rs))
|
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
|
else
|
||||||
{
|
{
|
||||||
if (m_Opcode.rd == m_Opcode.rt)
|
ProtectGPR(m_Opcode.rd);
|
||||||
{
|
CX86Ops::x86Reg Reg = Map_TempReg(CX86Ops::x86_Any, m_Opcode.rs, false);
|
||||||
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);
|
|
||||||
if (IsConst(m_Opcode.rt))
|
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))
|
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
|
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)
|
if (g_System->bFastSP() && m_Opcode.rd == 29)
|
||||||
|
@ -6597,33 +6612,36 @@ void CX86RecompilerOps::SPECIAL_SLTU()
|
||||||
|
|
||||||
void CX86RecompilerOps::SPECIAL_DADD()
|
void CX86RecompilerOps::SPECIAL_DADD()
|
||||||
{
|
{
|
||||||
if (m_Opcode.rd == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsConst(m_Opcode.rt) && IsConst(m_Opcode.rs))
|
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.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;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
else
|
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
|
else
|
||||||
|
@ -6631,23 +6649,35 @@ void CX86RecompilerOps::SPECIAL_DADD()
|
||||||
int source1 = m_Opcode.rd == m_Opcode.rt ? m_Opcode.rt : m_Opcode.rs;
|
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;
|
int source2 = m_Opcode.rd == m_Opcode.rt ? m_Opcode.rs : m_Opcode.rt;
|
||||||
|
|
||||||
if (IsMapped(source2)) { ProtectGPR(source2); }
|
ProtectGPR(source1);
|
||||||
Map_GPR_64bit(m_Opcode.rd, 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))
|
if (IsConst(source2))
|
||||||
{
|
{
|
||||||
m_Assembler.AddConstToX86Reg(GetMipsRegMapLo(m_Opcode.rd), GetMipsRegLo(source2));
|
m_Assembler.AddConstToX86Reg(RegLo, GetMipsRegLo(source2));
|
||||||
m_Assembler.AddConstToX86Reg(GetMipsRegMapHi(m_Opcode.rd), GetMipsRegHi(source2));
|
m_Assembler.AdcConstToX86Reg(RegHi, GetMipsRegHi(source2));
|
||||||
}
|
}
|
||||||
else if (IsMapped(source2))
|
else if (IsMapped(source2))
|
||||||
{
|
{
|
||||||
CX86Ops::x86Reg HiReg = Is64Bit(source2) ? GetMipsRegMapHi(source2) : Map_TempReg(CX86Ops::x86_Any, source2, true);
|
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.AddX86RegToX86Reg(RegLo, GetMipsRegMapLo(source2));
|
||||||
m_Assembler.AdcX86RegToX86Reg(GetMipsRegMapHi(m_Opcode.rd), HiReg);
|
m_Assembler.AdcX86RegToX86Reg(RegHi, HiReg);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_Assembler.AddVariableToX86reg(GetMipsRegMapLo(m_Opcode.rd), &_GPR[source2].W[0], CRegName::GPR_Lo[source2]);
|
m_Assembler.AddVariableToX86reg(RegLo, &_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.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()
|
void CX86RecompilerOps::SPECIAL_DSUB()
|
||||||
{
|
{
|
||||||
if (m_Opcode.rd == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsConst(m_Opcode.rt) && IsConst(m_Opcode.rs))
|
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);
|
||||||
UnMap_GPR(m_Opcode.rd, false);
|
int64_t sub = rs - rt;
|
||||||
}
|
|
||||||
|
|
||||||
m_RegWorkingSet.SetMipsReg(m_Opcode.rd,
|
if (((rs ^ rt) & (rs ^ sub)) & 0x8000000000000000)
|
||||||
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);
|
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp());
|
||||||
}
|
CompileExit(m_CompilePC, m_CompilePC, m_RegWorkingSet, CExitInfo::Exit_ExceptionOverflow, true, nullptr);
|
||||||
else if (GetMipsRegLo_S(m_Opcode.rd) >= 0 && GetMipsRegHi_S(m_Opcode.rd) == 0)
|
m_PipelineStage = PIPELINE_STAGE_END_BLOCK;
|
||||||
{
|
|
||||||
m_RegWorkingSet.SetMipsRegState(m_Opcode.rd, CRegInfo::STATE_CONST_32_SIGN);
|
|
||||||
}
|
}
|
||||||
else
|
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
|
else
|
||||||
{
|
{
|
||||||
if (m_Opcode.rd == m_Opcode.rt)
|
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;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsMapped(m_Opcode.rt)) { ProtectGPR(m_Opcode.rt); }
|
ProtectGPR(source1);
|
||||||
Map_GPR_64bit(m_Opcode.rd, m_Opcode.rs);
|
ProtectGPR(source2);
|
||||||
if (IsConst(m_Opcode.rt))
|
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.SubConstFromX86Reg(RegLo, GetMipsRegLo(source2));
|
||||||
m_Assembler.SbbConstFromX86Reg(GetMipsRegMapHi(m_Opcode.rd), GetMipsRegHi(m_Opcode.rt));
|
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);
|
CX86Ops::x86Reg HiReg = Is64Bit(source2) ? GetMipsRegMapHi(source2) : Map_TempReg(CX86Ops::x86_Any, source2, true);
|
||||||
m_Assembler.SubX86RegToX86Reg(GetMipsRegMapLo(m_Opcode.rd), GetMipsRegMapLo(m_Opcode.rt));
|
m_Assembler.SubX86RegToX86Reg(RegLo, GetMipsRegMapLo(source2));
|
||||||
m_Assembler.SbbX86RegToX86Reg(GetMipsRegMapHi(m_Opcode.rd), HiReg);
|
m_Assembler.SbbX86RegToX86Reg(RegHi, HiReg);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_Assembler.SubVariableFromX86reg(GetMipsRegMapLo(m_Opcode.rd), &_GPR[m_Opcode.rt].W[0], CRegName::GPR_Lo[m_Opcode.rt]);
|
m_Assembler.SubVariableFromX86reg(RegLo, &_GPR[source2].W[0], CRegName::GPR_Lo[source2]);
|
||||||
m_Assembler.SbbVariableFromX86reg(GetMipsRegMapHi(m_Opcode.rd), &_GPR[m_Opcode.rt].W[1], CRegName::GPR_Hi[m_Opcode.rt]);
|
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__);
|
m_Assembler.X86BreakPoint(__FILE__, __LINE__);
|
||||||
ExitCodeBlock();
|
ExitCodeBlock();
|
||||||
break;
|
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:
|
default:
|
||||||
WriteTrace(TraceRecompiler, TraceError, "How did you want to exit on reason (%d) ???", reason);
|
WriteTrace(TraceRecompiler, TraceError, "How did you want to exit on reason (%d) ???", reason);
|
||||||
g_Notify->BreakPoint(__FILE__, __LINE__);
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
||||||
|
|
|
@ -630,6 +630,13 @@ void CX86Ops::JsLabel32(const char *Label, uint32_t Value)
|
||||||
AddCode32(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)
|
void CX86Ops::JzLabel8(const char *Label, uint8_t Value)
|
||||||
{
|
{
|
||||||
CodeLog(" jz $%s", Label);
|
CodeLog(" jz $%s", Label);
|
||||||
|
|
|
@ -114,6 +114,7 @@ public:
|
||||||
void JnsLabel32(const char * Label, uint32_t Value);
|
void JnsLabel32(const char * Label, uint32_t Value);
|
||||||
void JnzLabel8(const char * Label, uint8_t Value);
|
void JnzLabel8(const char * Label, uint8_t Value);
|
||||||
void JnzLabel32(const char * Label, uint32_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 JsLabel32(const char * Label, uint32_t Value);
|
||||||
void JzLabel8(const char * Label, uint8_t Value);
|
void JzLabel8(const char * Label, uint8_t Value);
|
||||||
void JzLabel32(const char * Label, uint32_t Value);
|
void JzLabel32(const char * Label, uint32_t Value);
|
||||||
|
|
Loading…
Reference in New Issue