mirror of
https://github.com/libretro/Play-.git
synced 2025-02-20 19:51:10 +00:00
git-svn-id: http://svn.purei.org/purei/trunk@47 b36208d7-6611-0410-8bec-b1987f11c4a2
This commit is contained in:
parent
4cdc061460
commit
763c8fa483
@ -1,7 +1,9 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include "COP_SCU.h"
|
||||
#include "MIPS.h"
|
||||
#include "CodeGen.h"
|
||||
|
||||
uint8 CCOP_SCU::m_nRT;
|
||||
uint8 CCOP_SCU::m_nRD;
|
||||
@ -95,16 +97,38 @@ void CCOP_SCU::CO()
|
||||
//18
|
||||
void CCOP_SCU::ERET()
|
||||
{
|
||||
//Remove exception mode
|
||||
m_pB->PushAddr(&m_pCtx->m_State.nCOP0[STATUS]);
|
||||
m_pB->AndImm(~0x00000002);
|
||||
m_pB->PullAddr(&m_pCtx->m_State.nCOP0[STATUS]);
|
||||
CCodeGen::Begin(m_pB);
|
||||
{
|
||||
CCodeGen::PushRel(offsetof(CMIPS, m_State.nCOP0[STATUS]));
|
||||
CCodeGen::PushCst(0x02);
|
||||
CCodeGen::And();
|
||||
|
||||
CCodeGen::PushCst(0x00);
|
||||
CCodeGen::Cmp(CCodeGen::CONDITION_EQ);
|
||||
|
||||
//Go back to normal execution
|
||||
m_pB->PushAddr(&m_pCtx->m_State.nCOP0[EPC]);
|
||||
m_pB->PullAddr(&m_pCtx->m_State.nPC);
|
||||
CCodeGen::BeginIfElse(false);
|
||||
{
|
||||
//EXL bit was set
|
||||
CCodeGen::PushRel(offsetof(CMIPS, m_State.nCOP0[EPC]));
|
||||
CCodeGen::PullRel(offsetof(CMIPS, m_State.nPC));
|
||||
}
|
||||
CCodeGen::BeginIfElseAlt();
|
||||
{
|
||||
//EXL bit wasn't set, we assume ERL was (unsafe)
|
||||
CCodeGen::PushRel(offsetof(CMIPS, m_State.nCOP0[ERROREPC]));
|
||||
CCodeGen::PullRel(offsetof(CMIPS, m_State.nPC));
|
||||
}
|
||||
CCodeGen::EndIf();
|
||||
|
||||
m_pB->SetProgramCounterChanged();
|
||||
//Clear both EXL and ERL bits
|
||||
CCodeGen::PushRel(offsetof(CMIPS, m_State.nCOP0[STATUS]));
|
||||
CCodeGen::PushCst(~0x06);
|
||||
CCodeGen::And();
|
||||
CCodeGen::PullRel(offsetof(CMIPS, m_State.nCOP0[STATUS]));
|
||||
|
||||
m_pB->SetProgramCounterChanged();
|
||||
}
|
||||
CCodeGen::End();
|
||||
}
|
||||
|
||||
//38
|
||||
|
@ -10,6 +10,7 @@ public:
|
||||
{
|
||||
STATUS = 0x0C,
|
||||
EPC = 0x0E,
|
||||
ERROREPC = 0x1E,
|
||||
};
|
||||
|
||||
CCOP_SCU(MIPS_REGSIZE);
|
||||
|
@ -120,10 +120,6 @@ void CCacheBlock::InsertProlog(CMIPS* pCtx)
|
||||
{
|
||||
//add [pCtx->m_State.nPC], 4
|
||||
StreamWrite(4, 0x83, (0x01 << 6) | (0x00 << 3) | (0x05), offsetof(CMIPS, m_State.nPC), 4);
|
||||
|
||||
// StreamWrite(2, 0x83, 0x00 | (0x00 << 3) | (0x05));
|
||||
// StreamWriteWord((uint32)((uint8*)(&pCtx->m_State.nPC) - (uint8*)0));
|
||||
// StreamWriteByte(4);
|
||||
}
|
||||
|
||||
void CCacheBlock::InsertEpilog(CMIPS* pCtx, bool nDelayJump)
|
||||
|
@ -80,7 +80,7 @@ long CCallStackWnd::OnNotify(WPARAM wParam, NMHDR* pHDR)
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void CCallStackWnd::RefreshLayout()
|
||||
|
@ -11,6 +11,29 @@ CArrayStack<uint32> CCodeGen::m_Shadow;
|
||||
CArrayStack<uint32> CCodeGen::m_IfStack;
|
||||
|
||||
bool CCodeGen::m_nRegisterAllocated[MAX_REGISTER];
|
||||
|
||||
#ifdef AMD64
|
||||
|
||||
unsigned int CCodeGen::m_nRegisterLookup[MAX_REGISTER] =
|
||||
{
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
12,
|
||||
13,
|
||||
14,
|
||||
15,
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
unsigned int CCodeGen::m_nRegisterLookup[MAX_REGISTER] =
|
||||
{
|
||||
0,
|
||||
@ -21,6 +44,8 @@ unsigned int CCodeGen::m_nRegisterLookup[MAX_REGISTER] =
|
||||
7,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
void CCodeGen::Begin(CCacheBlock* pBlock)
|
||||
{
|
||||
unsigned int i;
|
||||
@ -203,6 +228,27 @@ unsigned int CCodeGen::AllocateRegister(REGISTER_TYPE nPreference)
|
||||
}
|
||||
}
|
||||
}
|
||||
if(nPreference == REGISTER_SAVED)
|
||||
{
|
||||
for(unsigned int i = 0; i < MAX_REGISTER; i++)
|
||||
{
|
||||
if(i == 0) continue;
|
||||
if(i == 1) continue;
|
||||
if(i == 2) continue;
|
||||
#ifdef AMD64
|
||||
if(i == 8) continue;
|
||||
if(i == 9) continue;
|
||||
if(i == 10) continue;
|
||||
if(i == 11) continue;
|
||||
#endif
|
||||
if(!m_nRegisterAllocated[i])
|
||||
{
|
||||
m_nRegisterAllocated[i] = true;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
@ -221,24 +267,150 @@ void CCodeGen::LoadVariableInRegister(unsigned int nRegister, uint32 nVariable)
|
||||
|
||||
void CCodeGen::LoadRelativeInRegister(unsigned int nRegister, uint32 nOffset)
|
||||
{
|
||||
|
||||
#ifdef AMD64
|
||||
|
||||
if(m_nRegisterLookup[nRegister] > 7)
|
||||
{
|
||||
//REX byte
|
||||
m_pBlock->StreamWrite(1, 0x44);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//mov reg, [base + rel]
|
||||
m_pBlock->StreamWrite(1, 0x8B);
|
||||
WriteRelativeRm(nRegister, nOffset);
|
||||
WriteRelativeRmRegister(nRegister, nOffset);
|
||||
}
|
||||
|
||||
void CCodeGen::WriteRelativeRm(unsigned int nRegister, uint32 nOffset)
|
||||
void CCodeGen::LoadConstantInRegister(unsigned int nRegister, uint32 nConstant)
|
||||
{
|
||||
unsigned int nRegIndex;
|
||||
|
||||
nRegIndex = m_nRegisterLookup[nRegister];
|
||||
|
||||
#ifdef AMD64
|
||||
|
||||
if(nRegIndex > 7)
|
||||
{
|
||||
//REX byte
|
||||
m_pBlock->StreamWrite(1, 0x41);
|
||||
|
||||
nRegIndex &= 0x07;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//mov reg, nConstant
|
||||
m_pBlock->StreamWrite(1, 0xB8 | nRegIndex);
|
||||
m_pBlock->StreamWriteWord(nConstant);
|
||||
}
|
||||
|
||||
void CCodeGen::CopyRegister(unsigned int nDst, unsigned int nSrc)
|
||||
{
|
||||
unsigned int nRegIndex1, nRegIndex2;
|
||||
|
||||
nRegIndex1 = m_nRegisterLookup[nSrc];
|
||||
nRegIndex2 = m_nRegisterLookup[nDst];
|
||||
|
||||
#ifdef AMD64
|
||||
|
||||
bool nNeedRex;
|
||||
uint8 nRex;
|
||||
|
||||
nNeedRex = false;
|
||||
nRex = 0x40;
|
||||
|
||||
nNeedRex = (nRegIndex1 > 7) || (nRegIndex2 > 7);
|
||||
|
||||
if(nRegIndex1 > 7)
|
||||
{
|
||||
nRegIndex1 &= 0x07;
|
||||
nRex |= 0x04;
|
||||
}
|
||||
|
||||
if(nRegIndex2 > 7)
|
||||
{
|
||||
nRegIndex2 &= 0x07;
|
||||
nRex |= 0x01;
|
||||
}
|
||||
|
||||
if(nNeedRex)
|
||||
{
|
||||
m_pBlock->StreamWrite(1, nRex);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
m_pBlock->StreamWrite(2, 0x89, 0xC0 | (nRegIndex1 << 3) | (nRegIndex2));
|
||||
}
|
||||
|
||||
#ifdef AMD64
|
||||
|
||||
void CCodeGen::LoadRelativeInRegister64(unsigned int nRegister, uint32 nRelative)
|
||||
{
|
||||
unsigned int nRegIndex;
|
||||
uint8 nRex;
|
||||
|
||||
nRegIndex = m_nRegisterLookup[nRegister];
|
||||
nRex = 0x48;
|
||||
|
||||
if(nRegIndex > 7)
|
||||
{
|
||||
nRex |= 0x01;
|
||||
nRegIndex &= 0x07;
|
||||
}
|
||||
|
||||
//mov reg, nRelative
|
||||
m_pBlock->StreamWrite(2, nRex, 0x8B);
|
||||
WriteRelativeRmRegister(nRegister, nRelative);
|
||||
}
|
||||
|
||||
void CCodeGen::LoadConstantInRegister64(unsigned int nRegister, uint64 nConstant)
|
||||
{
|
||||
unsigned int nRegIndex;
|
||||
uint8 nRex;
|
||||
|
||||
nRegIndex = m_nRegisterLookup[nRegister];
|
||||
nRex = 0x48;
|
||||
|
||||
if(nRegIndex > 7)
|
||||
{
|
||||
nRex |= 0x01;
|
||||
nRegIndex &= 0x07;
|
||||
}
|
||||
|
||||
//mov reg, nConstant
|
||||
m_pBlock->StreamWrite(2, nRex, 0xB8 | nRegIndex);
|
||||
m_pBlock->StreamWriteWord((uint32)((nConstant >> 0) & 0xFFFFFFFF));
|
||||
m_pBlock->StreamWriteWord((uint32)((nConstant >> 32) & 0xFFFFFFFF));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void CCodeGen::WriteRelativeRm(unsigned int nIndex, uint32 nOffset)
|
||||
{
|
||||
if(nOffset <= 0x7F)
|
||||
{
|
||||
m_pBlock->StreamWrite(2, (0x01 << 6) | (nRegister << 3) | 0x05, (uint8)nOffset);
|
||||
m_pBlock->StreamWrite(2, (0x01 << 6) | (nIndex << 3) | 0x05, (uint8)nOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pBlock->StreamWrite(1, (0x02 << 6) | (nRegister << 3) | 0x05);
|
||||
m_pBlock->StreamWrite(1, (0x02 << 6) | (nIndex << 3) | 0x05);
|
||||
m_pBlock->StreamWriteWord(nOffset);
|
||||
}
|
||||
}
|
||||
|
||||
void CCodeGen::WriteRelativeRmRegister(unsigned int nRegister, uint32 nOffset)
|
||||
{
|
||||
WriteRelativeRm(m_nRegisterLookup[nRegister] & 0x07, nOffset);
|
||||
}
|
||||
|
||||
void CCodeGen::WriteRelativeRmFunction(unsigned int nFunction, uint32 nOffset)
|
||||
{
|
||||
WriteRelativeRm(nFunction, nOffset);
|
||||
}
|
||||
|
||||
void CCodeGen::PushVar(uint32* pValue)
|
||||
{
|
||||
m_Shadow.Push(*(uint32*)&pValue);
|
||||
@ -263,12 +435,46 @@ void CCodeGen::PushRel(size_t nOffset)
|
||||
m_Shadow.Push(RELATIVE);
|
||||
}
|
||||
|
||||
void CCodeGen::PushIdx(unsigned int nIndex)
|
||||
{
|
||||
uint32 nParam1, nParam2;
|
||||
|
||||
nIndex *= 2;
|
||||
|
||||
nParam1 = m_Shadow.GetAt(nIndex + 0);
|
||||
nParam2 = m_Shadow.GetAt(nIndex + 1);
|
||||
|
||||
m_Shadow.Push(nParam2);
|
||||
m_Shadow.Push(nParam1);
|
||||
}
|
||||
|
||||
void CCodeGen::PushTop()
|
||||
{
|
||||
PushIdx(0);
|
||||
}
|
||||
|
||||
void CCodeGen::PushReg(unsigned int nRegister)
|
||||
{
|
||||
m_Shadow.Push(nRegister);
|
||||
m_Shadow.Push(REGISTER);
|
||||
}
|
||||
|
||||
void CCodeGen::ReplaceRegisterInStack(unsigned int nDst, unsigned int nSrc)
|
||||
{
|
||||
for(unsigned int i = 0; i < m_Shadow.GetCount(); i += 2)
|
||||
{
|
||||
if(m_Shadow.GetAt(i + 0) == REGISTER)
|
||||
{
|
||||
unsigned int nRegister;
|
||||
nRegister = m_Shadow.GetAt(i + 1);
|
||||
if(nRegister == nSrc)
|
||||
{
|
||||
m_Shadow.SetAt(i + 1, nDst);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CCodeGen::PullVar(uint32* pValue)
|
||||
{
|
||||
if(m_Shadow.GetAt(0) == REGISTER)
|
||||
@ -345,7 +551,8 @@ void CCodeGen::PullRel(size_t nOffset)
|
||||
nRegister = m_Shadow.Pull();
|
||||
|
||||
//mov dword ptr[pValue], reg
|
||||
m_pBlock->StreamWrite(1, 0x89); WriteRelativeRm(nRegister, (uint32)nOffset);
|
||||
m_pBlock->StreamWrite(1, 0x89);
|
||||
WriteRelativeRmRegister(nRegister, (uint32)nOffset);
|
||||
|
||||
FreeRegister(nRegister);
|
||||
}
|
||||
@ -371,16 +578,39 @@ void CCodeGen::PullRel(size_t nOffset)
|
||||
}
|
||||
|
||||
//mov dword ptr[pValue], reg
|
||||
m_pBlock->StreamWrite(1, 0x89); WriteRelativeRm(nRegister, (uint32)nOffset);
|
||||
m_pBlock->StreamWrite(1, 0x89);
|
||||
WriteRelativeRmRegister(nRegister, (uint32)nOffset);
|
||||
|
||||
FreeRegister(nRegister);
|
||||
}
|
||||
else if(m_Shadow.GetAt(0) == RELATIVE)
|
||||
{
|
||||
uint32 nRelative, nRegister;
|
||||
|
||||
m_Shadow.Pull();
|
||||
nRelative = m_Shadow.Pull();
|
||||
|
||||
nRegister = AllocateRegister();
|
||||
|
||||
LoadRelativeInRegister(nRegister, nRelative);
|
||||
|
||||
m_Shadow.Push(nRegister);
|
||||
m_Shadow.Push(REGISTER);
|
||||
|
||||
PullRel(nOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
void CCodeGen::PullTop()
|
||||
{
|
||||
m_Shadow.Pull();
|
||||
m_Shadow.Pull();
|
||||
}
|
||||
|
||||
void CCodeGen::Add()
|
||||
{
|
||||
if((m_Shadow.GetAt(0) == CONSTANT) && (m_Shadow.GetAt(2) == VARIABLE))
|
||||
@ -642,6 +872,27 @@ void CCodeGen::And()
|
||||
|
||||
And();
|
||||
}
|
||||
else if((m_Shadow.GetAt(0) == CONSTANT) && (m_Shadow.GetAt(2) == RELATIVE))
|
||||
{
|
||||
uint32 nRelative, nConstant;
|
||||
unsigned int nRegister;
|
||||
|
||||
m_Shadow.Pull();
|
||||
nConstant = m_Shadow.Pull();
|
||||
m_Shadow.Pull();
|
||||
nRelative = m_Shadow.Pull();
|
||||
|
||||
nRegister = AllocateRegister();
|
||||
LoadRelativeInRegister(nRegister, nRelative);
|
||||
|
||||
m_Shadow.Push(nRegister);
|
||||
m_Shadow.Push(REGISTER);
|
||||
|
||||
m_Shadow.Push(nConstant);
|
||||
m_Shadow.Push(CONSTANT);
|
||||
|
||||
And();
|
||||
}
|
||||
else if((m_Shadow.GetAt(0) == VARIABLE) && (m_Shadow.GetAt(2) == VARIABLE))
|
||||
{
|
||||
uint32 nVariable1, nVariable2;
|
||||
@ -672,6 +923,36 @@ void CCodeGen::Call(void* pFunc, unsigned int nParamCount, bool nKeepRet)
|
||||
{
|
||||
uint32 nCallRegister;
|
||||
|
||||
#ifdef AMD64
|
||||
|
||||
unsigned int nParamReg[4] =
|
||||
{
|
||||
1,
|
||||
2,
|
||||
6,
|
||||
7,
|
||||
};
|
||||
|
||||
assert(nParamCount <= 4);
|
||||
assert(m_nRegisterAllocated[nParamReg[0]] == false);
|
||||
assert(m_nRegisterAllocated[nParamReg[1]] == false);
|
||||
assert(m_nRegisterAllocated[nParamReg[2]] == false);
|
||||
assert(m_nRegisterAllocated[nParamReg[3]] == false);
|
||||
|
||||
#endif
|
||||
|
||||
if(m_nRegisterAllocated[0])
|
||||
{
|
||||
//This register is going to be scrapped, gotta save it...
|
||||
unsigned int nSaveReg;
|
||||
|
||||
nSaveReg = AllocateRegister(REGISTER_SAVED);
|
||||
CopyRegister(nSaveReg, 0);
|
||||
ReplaceRegisterInStack(nSaveReg, 0);
|
||||
|
||||
FreeRegister(0);
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < nParamCount; i++)
|
||||
{
|
||||
if(m_Shadow.GetAt(0) == VARIABLE)
|
||||
@ -685,6 +966,27 @@ void CCodeGen::Call(void* pFunc, unsigned int nParamCount, bool nKeepRet)
|
||||
m_pBlock->StreamWrite(2, 0xFF, 0x35);
|
||||
m_pBlock->StreamWriteWord(nVariable);
|
||||
}
|
||||
else if(m_Shadow.GetAt(0) == RELATIVE)
|
||||
{
|
||||
uint32 nRelative;
|
||||
|
||||
m_Shadow.Pull();
|
||||
nRelative = m_Shadow.Pull();
|
||||
|
||||
#ifdef AMD64
|
||||
|
||||
LoadRelativeInRegister(nParamReg[nParamCount - 1 - i], nRelative);
|
||||
|
||||
#else
|
||||
|
||||
//push [nBase + nRel]
|
||||
m_pBlock->StreamWrite(1, 0xFF);
|
||||
WriteRelativeRmFunction(6, nRelative);
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
else if(m_Shadow.GetAt(0) == REGISTER)
|
||||
{
|
||||
uint32 nRegister;
|
||||
@ -697,8 +999,18 @@ void CCodeGen::Call(void* pFunc, unsigned int nParamCount, bool nKeepRet)
|
||||
FreeRegister(nRegister);
|
||||
}
|
||||
|
||||
#ifdef AMD64
|
||||
|
||||
//mov param_reg, reg
|
||||
CopyRegister(nParamReg[nParamCount - 1 - i], nRegister);
|
||||
|
||||
#else
|
||||
|
||||
//push reg
|
||||
m_pBlock->StreamWrite(1, 0x50 | m_nRegisterLookup[nRegister]);
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
else if((m_Shadow.GetAt(0) == REFERENCE) || (m_Shadow.GetAt(0) == CONSTANT))
|
||||
{
|
||||
@ -707,9 +1019,19 @@ void CCodeGen::Call(void* pFunc, unsigned int nParamCount, bool nKeepRet)
|
||||
m_Shadow.Pull();
|
||||
nNumber = m_Shadow.Pull();
|
||||
|
||||
#ifdef AMD64
|
||||
|
||||
//mov reg, nNumber
|
||||
LoadConstantInRegister(nParamReg[nParamCount - 1 - i], nNumber);
|
||||
|
||||
#else
|
||||
|
||||
//push nNumber
|
||||
m_pBlock->StreamWrite(1, 0x68);
|
||||
m_pBlock->StreamWriteWord(nNumber);
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -719,6 +1041,38 @@ void CCodeGen::Call(void* pFunc, unsigned int nParamCount, bool nKeepRet)
|
||||
|
||||
nCallRegister = AllocateRegister();
|
||||
|
||||
#ifdef AMD64
|
||||
|
||||
unsigned int nRegIndex;
|
||||
|
||||
if(nParamCount != 0)
|
||||
{
|
||||
//sub rsp, (nParams * 0x08)
|
||||
m_pBlock->StreamWrite(3, 0x83, 0xC0 | (0x05 << 3) | (0x04), nParamCount * 0x08);
|
||||
}
|
||||
|
||||
//mov reg, nFuncAddress
|
||||
LoadConstantInRegister64(nCallRegister, (uint64)((uint8*)pFunc - (uint8*)0));
|
||||
|
||||
//call reg
|
||||
nRegIndex = m_nRegisterLookup[nCallRegister];
|
||||
if(nRegIndex > 7)
|
||||
{
|
||||
//REX byte
|
||||
m_pBlock->StreamWrite(1, 0x41);
|
||||
nRegIndex &= 7;
|
||||
}
|
||||
|
||||
m_pBlock->StreamWrite(2, 0xFF, 0xD0 | (nRegIndex));
|
||||
|
||||
if(nParamCount != 0)
|
||||
{
|
||||
//add esp, 0x08
|
||||
m_pBlock->StreamWrite(3, 0x83, 0xC0 | (0x00 << 3) | (0x04), nParamCount * 0x08);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
//mov reg, pFunc
|
||||
m_pBlock->StreamWrite(1, 0xB8 | (m_nRegisterLookup[nCallRegister]));
|
||||
m_pBlock->StreamWriteWord((uint32)((uint8*)pFunc - (uint8*)0));
|
||||
@ -726,14 +1080,16 @@ void CCodeGen::Call(void* pFunc, unsigned int nParamCount, bool nKeepRet)
|
||||
//call reg
|
||||
m_pBlock->StreamWrite(2, 0xFF, 0xD0 | (m_nRegisterLookup[nCallRegister]));
|
||||
|
||||
FreeRegister(nCallRegister);
|
||||
|
||||
if(nParamCount != 0)
|
||||
{
|
||||
//add esp, nParams * 4;
|
||||
m_pBlock->StreamWrite(3, 0x83, 0xC4, nParamCount * 4);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
FreeRegister(nCallRegister);
|
||||
|
||||
if(nKeepRet)
|
||||
{
|
||||
assert(m_nRegisterAllocated[0] == false);
|
||||
@ -1285,7 +1641,8 @@ void CCodeGen::Xor()
|
||||
LoadRelativeInRegister(nRegister, nRelative1);
|
||||
|
||||
//xor reg, dword ptr[base + rel]
|
||||
m_pBlock->StreamWrite(1, 0x33); WriteRelativeRm(nRegister, nRelative2);
|
||||
m_pBlock->StreamWrite(1, 0x33);
|
||||
WriteRelativeRmRegister(nRegister, nRelative2);
|
||||
|
||||
m_Shadow.Push(nRegister);
|
||||
m_Shadow.Push(REGISTER);
|
||||
@ -1426,6 +1783,99 @@ void CCodeGen::Cmp64Lt(bool nSigned)
|
||||
m_Shadow.Push(nRegister);
|
||||
m_Shadow.Push(REGISTER);
|
||||
}
|
||||
else if(\
|
||||
(m_Shadow.GetAt(0) == RELATIVE) && \
|
||||
(m_Shadow.GetAt(2) == RELATIVE) && \
|
||||
(m_Shadow.GetAt(4) == RELATIVE) && \
|
||||
(m_Shadow.GetAt(6) == RELATIVE))
|
||||
{
|
||||
uint32 nRelative1, nRelative2, nRelative3, nRelative4;
|
||||
uint32 nRegister;
|
||||
unsigned int nJmpPos1, nJmpPos2;
|
||||
|
||||
m_Shadow.Pull();
|
||||
nRelative4 = m_Shadow.Pull();
|
||||
m_Shadow.Pull();
|
||||
nRelative3 = m_Shadow.Pull();
|
||||
m_Shadow.Pull();
|
||||
nRelative2 = m_Shadow.Pull();
|
||||
m_Shadow.Pull();
|
||||
nRelative1 = m_Shadow.Pull();
|
||||
|
||||
nRegister = AllocateRegister();
|
||||
assert(m_nRegisterLookup[nRegister] < 8);
|
||||
|
||||
#ifdef AMD64
|
||||
|
||||
if(((nRelative4 - nRelative3) == 4) && ((nRelative2 - nRelative1) == 4))
|
||||
{
|
||||
LoadRelativeInRegister64(nRegister, nRelative1);
|
||||
|
||||
//cmp reg, qword ptr[base + rel4]
|
||||
m_pBlock->StreamWrite(2, 0x48, 0x3B);
|
||||
WriteRelativeRmRegister(nRegister, nRelative3);
|
||||
|
||||
//setb/l reg[l]
|
||||
m_pBlock->StreamWrite(3, 0x0F, nSigned ? 0x9C : 0x92, 0xC0 | (0x00 << 3) | (m_nRegisterLookup[nRegister]));
|
||||
|
||||
//movzx reg, reg[l]
|
||||
m_pBlock->StreamWrite(3, 0x0F, 0xB6, 0xC0 | (m_nRegisterLookup[nRegister] << 3) | (m_nRegisterLookup[nRegister]));
|
||||
}
|
||||
else
|
||||
|
||||
#endif
|
||||
|
||||
{
|
||||
/////////////////////////////////////////
|
||||
//Check high order word if equal
|
||||
|
||||
//mov reg, dword ptr[base + rel2]
|
||||
LoadRelativeInRegister(nRegister, nRelative2);
|
||||
|
||||
//cmp reg, dword ptr[base + rel4]
|
||||
m_pBlock->StreamWrite(1, 0x3B);
|
||||
WriteRelativeRmRegister(nRegister, nRelative4);
|
||||
|
||||
//je +0x08
|
||||
m_pBlock->StreamWrite(2, 0x74, 0x08);
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
//If they aren't equal, this comparaison decides of result
|
||||
|
||||
//setb/l reg[l]
|
||||
m_pBlock->StreamWrite(3, 0x0F, nSigned ? 0x9C : 0x92, 0xC0 | (0x00 << 3) | (m_nRegisterLookup[nRegister]));
|
||||
|
||||
//movzx reg, reg[l]
|
||||
m_pBlock->StreamWrite(3, 0x0F, 0xB6, 0xC0 | (m_nRegisterLookup[nRegister] << 3) | (m_nRegisterLookup[nRegister]));
|
||||
|
||||
//jmp +?
|
||||
nJmpPos1 = m_pBlock->StreamGetSize() + 1;
|
||||
m_pBlock->StreamWrite(2, 0xEB, 0x00);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//If they are equal, next comparaison decides of result
|
||||
|
||||
//mov reg, dword ptr[base + rel1]
|
||||
LoadRelativeInRegister(nRegister, nRelative1);
|
||||
|
||||
//cmp reg, dword ptr[base + rel3]
|
||||
m_pBlock->StreamWrite(1, 0x3B);
|
||||
WriteRelativeRmRegister(nRegister, nRelative3);
|
||||
|
||||
//setb reg[l]
|
||||
m_pBlock->StreamWrite(3, 0x0F, 0x92, 0xC0 | (0x00 << 3) | (m_nRegisterLookup[nRegister]));
|
||||
|
||||
//movzx reg, reg[l]
|
||||
m_pBlock->StreamWrite(3, 0x0F, 0xB6, 0xC0 | (m_nRegisterLookup[nRegister] << 3) | (m_nRegisterLookup[nRegister]));
|
||||
|
||||
//Fix Jmp Offset
|
||||
nJmpPos2 = m_pBlock->StreamGetSize();
|
||||
m_pBlock->StreamWriteAt(nJmpPos1, (nJmpPos2 - nJmpPos1 - 1));
|
||||
}
|
||||
|
||||
m_Shadow.Push(nRegister);
|
||||
m_Shadow.Push(REGISTER);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
|
@ -37,9 +37,12 @@ public:
|
||||
static void PushCst(uint32);
|
||||
static void PushRef(void*);
|
||||
static void PushRel(size_t);
|
||||
static void PushTop();
|
||||
static void PushIdx(unsigned int);
|
||||
|
||||
static void PullVar(uint32*);
|
||||
static void PullRel(size_t);
|
||||
static void PullTop();
|
||||
|
||||
static void Add();
|
||||
static void Add64();
|
||||
@ -64,7 +67,11 @@ private:
|
||||
|
||||
enum MAX_REGISTER
|
||||
{
|
||||
#ifdef AMD64
|
||||
MAX_REGISTER = 14,
|
||||
#else
|
||||
MAX_REGISTER = 6,
|
||||
#endif
|
||||
};
|
||||
|
||||
enum REL_REGISTER
|
||||
@ -91,6 +98,7 @@ private:
|
||||
{
|
||||
REGISTER_NORMAL,
|
||||
REGISTER_HASLOW,
|
||||
REGISTER_SAVED,
|
||||
};
|
||||
|
||||
static unsigned int AllocateRegister(REGISTER_TYPE = REGISTER_NORMAL);
|
||||
@ -99,12 +107,22 @@ private:
|
||||
static bool RegisterHasNextUse(unsigned int);
|
||||
static void LoadVariableInRegister(unsigned int, uint32);
|
||||
static void LoadRelativeInRegister(unsigned int, uint32);
|
||||
static void LoadConstantInRegister(unsigned int, uint32);
|
||||
static void CopyRegister(unsigned int, unsigned int);
|
||||
#ifdef AMD64
|
||||
static void LoadRelativeInRegister64(unsigned int, uint32);
|
||||
static void LoadConstantInRegister64(unsigned int, uint64);
|
||||
#endif
|
||||
|
||||
static void WriteRelativeRm(unsigned int, uint32);
|
||||
static void WriteRelativeRmRegister(unsigned int, uint32);
|
||||
static void WriteRelativeRmFunction(unsigned int, uint32);
|
||||
|
||||
static bool IsTopRegCstPairCom();
|
||||
static void GetRegCstPairCom(unsigned int*, uint32*);
|
||||
|
||||
static void PushReg(unsigned int);
|
||||
static void ReplaceRegisterInStack(unsigned int, unsigned int);
|
||||
|
||||
static void Cmp64Eq();
|
||||
static void Cmp64Lt(bool);
|
||||
|
Binary file not shown.
@ -42,6 +42,7 @@ private:
|
||||
void StartShift64OpTest();
|
||||
void StartSplitLoadOpTest();
|
||||
void StartAddition64OpTest();
|
||||
void StartSetLessThanOpTest();
|
||||
void Resume();
|
||||
void StepCPU1();
|
||||
void FindValue();
|
||||
|
@ -229,7 +229,7 @@ void CDisAsm::FindCallers()
|
||||
for(i = 0; i < CPS2VM::RAMSIZE / 4; i++)
|
||||
{
|
||||
nVal = ((uint32*)CPS2VM::m_pRAM)[i];
|
||||
if((nVal & 0xFC000000) == 0x0C000000)
|
||||
if(((nVal & 0xFC000000) == 0x0C000000) || ((nVal & 0xFC000000) == 0x08000000))
|
||||
{
|
||||
nVal &= 0x3FFFFFF;
|
||||
nVal *= 4;
|
||||
|
@ -94,7 +94,8 @@ long CFunctionsView::OnNotify(WPARAM wParam, NMHDR* pH)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
long CFunctionsView::OnCommand(unsigned short nID, unsigned short nCmd, HWND hSender)
|
||||
|
@ -259,9 +259,6 @@ void CGSH_OpenGL::SetReadCircuitMatrix(int nWidth, int nHeight)
|
||||
{
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
// glOrtho(0, nWidth, nHeight, 0, 0, -1.0);
|
||||
// glOrtho(0, nWidth, nHeight, 0, -1.0, -65536.0);
|
||||
// glOrtho(0, nWidth, nHeight, 0, 0.01, 1000);
|
||||
|
||||
LinearZOrtho(0, nWidth, nHeight, 0);
|
||||
|
||||
@ -846,6 +843,7 @@ void CGSH_OpenGL::Prim_Sprite()
|
||||
}
|
||||
else if(!m_PrimitiveMode.nTexture)
|
||||
{
|
||||
/*
|
||||
//Humm? Would it be possible to have a gradient using those registers?
|
||||
glColor4ub(MulBy2Clamp(rgbaq[0].nR), MulBy2Clamp(rgbaq[0].nG), MulBy2Clamp(rgbaq[0].nB), MulBy2Clamp(rgbaq[0].nA));
|
||||
//glColor4ub(rgbaq[0].nR, rgbaq[0].nG, rgbaq[0].nB, rgbaq[0].nA);
|
||||
@ -858,6 +856,7 @@ void CGSH_OpenGL::Prim_Sprite()
|
||||
glVertex3d(nX1, nY2, nZ2);
|
||||
|
||||
glEnd();
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -118,6 +118,7 @@ unsigned int CGSH_OpenGL::LoadTexture(GSTEX0* pReg0, GSTEX1* pReg1, CLAMP* pClam
|
||||
//glTexImage2D(GL_TEXTURE_2D, 0, 4, nWidth, nHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_pRAM + nPointer);
|
||||
break;
|
||||
case PSMCT16:
|
||||
case PSMCT16S:
|
||||
((this)->*(m_pTexUploader_Psm16))(pReg0, &TexA);
|
||||
break;
|
||||
case PSMT8:
|
||||
|
@ -227,6 +227,13 @@ void CGSHandler::WritePrivRegister(uint32 nAddress, uint32 nData)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x1200008:
|
||||
W_REG(nAddress, nData, m_nDISPLAY1);
|
||||
if(nAddress & 0x04)
|
||||
{
|
||||
UpdateViewport();
|
||||
}
|
||||
break;
|
||||
case 0x1200009:
|
||||
W_REG(nAddress, nData, m_nDISPFB2);
|
||||
if(nAddress & 0x04)
|
||||
|
@ -82,6 +82,25 @@ void CCdvdfsv::Invoke593(uint32 nMethod, void* pArgs, uint32 nArgsSize, void* pR
|
||||
{
|
||||
switch(nMethod)
|
||||
{
|
||||
case 0x03:
|
||||
|
||||
assert(nRetSize >= 4);
|
||||
|
||||
Log("GetDiskType();\r\n");
|
||||
|
||||
//Returns PS2DVD for now.
|
||||
((uint32*)pRet)[0x00] = 0x14;
|
||||
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
assert(nRetSize >= 4);
|
||||
|
||||
Log("GetError();\r\n");
|
||||
|
||||
((uint32*)pRet)[0x00] = 0x00;
|
||||
break;
|
||||
|
||||
case 0x0C:
|
||||
//Status
|
||||
//Returns
|
||||
@ -141,6 +160,15 @@ void CCdvdfsv::Invoke595(uint32 nMethod, void* pArgs, uint32 nArgsSize, void* pR
|
||||
case 9:
|
||||
StreamCmd(pArgs, nArgsSize, pRet, nRetSize);
|
||||
break;
|
||||
case 0x0E:
|
||||
//DiskReady (returns 2 if ready, 6 if not ready)
|
||||
|
||||
assert(nRetSize >= 4);
|
||||
|
||||
Log("NDiskReady();\r\n");
|
||||
|
||||
((uint32*)pRet)[0x00] = 2;
|
||||
break;
|
||||
default:
|
||||
Log("Unknown method invoked (0x%0.8X, 0x%0.8X).\r\n", m_nID, nMethod);
|
||||
break;
|
||||
@ -205,7 +233,10 @@ void CCdvdfsv::Read(void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
CPS2VM::m_pCDROM0->ReadBlock(nSector + i, CPS2VM::m_pRAM + (nDstAddr + (i * 0x800)));
|
||||
}
|
||||
|
||||
((uint32*)pRet)[0] = 0;
|
||||
if(nRetSize >= 4)
|
||||
{
|
||||
((uint32*)pRet)[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CCdvdfsv::StreamCmd(void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include <stddef.h>
|
||||
#include "MA_EE.h"
|
||||
#include "CodeGen_VUI128.h"
|
||||
#include "MIPS.h"
|
||||
@ -91,27 +92,27 @@ void CMA_EE::LQ()
|
||||
//1F
|
||||
void CMA_EE::SQ()
|
||||
{
|
||||
ComputeMemAccessAddr();
|
||||
CCodeGen::Begin(m_pB);
|
||||
{
|
||||
ComputeMemAccessAddrEx();
|
||||
|
||||
//Write the words
|
||||
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
||||
m_pB->PushRef(m_pCtx);
|
||||
m_pB->Call(&CCacheBlock::SetWordProxy, 2, false);
|
||||
m_pB->AddImm(4);
|
||||
for(unsigned int i = 0; i < 4; i++)
|
||||
{
|
||||
CCodeGen::PushRef(m_pCtx);
|
||||
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[i]));
|
||||
CCodeGen::PushIdx(2);
|
||||
CCodeGen::Call(&CCacheBlock::SetWordProxy, 3, false);
|
||||
|
||||
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[1]);
|
||||
m_pB->PushRef(m_pCtx);
|
||||
m_pB->Call(&CCacheBlock::SetWordProxy, 2, false);
|
||||
m_pB->AddImm(4);
|
||||
if(i != 3)
|
||||
{
|
||||
CCodeGen::PushCst(4);
|
||||
CCodeGen::Add();
|
||||
}
|
||||
}
|
||||
|
||||
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[2]);
|
||||
m_pB->PushRef(m_pCtx);
|
||||
m_pB->Call(&CCacheBlock::SetWordProxy, 2, false);
|
||||
m_pB->AddImm(4);
|
||||
|
||||
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[3]);
|
||||
m_pB->PushRef(m_pCtx);
|
||||
m_pB->Call(&CCacheBlock::SetWordProxy, 3, false);
|
||||
CCodeGen::PullTop();
|
||||
}
|
||||
CCodeGen::End();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
|
@ -1894,19 +1894,19 @@ void CMA_MIPSIV::SLTU()
|
||||
{
|
||||
CCodeGen::Begin(m_pB);
|
||||
{
|
||||
CCodeGen::PushVar(&m_pCtx->m_State.nGPR[m_nRS].nV[0]);
|
||||
CCodeGen::PushVar(&m_pCtx->m_State.nGPR[m_nRS].nV[1]);
|
||||
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
||||
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[1]));
|
||||
|
||||
CCodeGen::PushVar(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
||||
CCodeGen::PushVar(&m_pCtx->m_State.nGPR[m_nRT].nV[1]);
|
||||
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
||||
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
||||
|
||||
CCodeGen::Cmp64(CCodeGen::CONDITION_BL);
|
||||
|
||||
CCodeGen::PullVar(&m_pCtx->m_State.nGPR[m_nRD].nV[0]);
|
||||
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
||||
|
||||
//Clear higher 32-bits
|
||||
CCodeGen::PushCst(0);
|
||||
CCodeGen::PullVar(&m_pCtx->m_State.nGPR[m_nRD].nV[1]);
|
||||
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[1]));
|
||||
}
|
||||
CCodeGen::End();
|
||||
}
|
||||
|
@ -263,6 +263,12 @@ void CMIPSAssembler::SLLV(unsigned int nRD, unsigned int nRT, unsigned int nRS)
|
||||
m_pPtr++;
|
||||
}
|
||||
|
||||
void CMIPSAssembler::SLTU(unsigned int nRD, unsigned int nRT, unsigned int nRS)
|
||||
{
|
||||
(*m_pPtr) = (nRS << 21) | (nRT << 16) | (nRD << 11) | 0x2B;
|
||||
m_pPtr++;
|
||||
}
|
||||
|
||||
void CMIPSAssembler::SRA(unsigned int nRD, unsigned int nRT, unsigned int nSA)
|
||||
{
|
||||
nSA &= 0x1F;
|
||||
|
@ -49,6 +49,7 @@ public:
|
||||
void SD(unsigned int, uint16, unsigned int);
|
||||
void SLL(unsigned int, unsigned int, unsigned int);
|
||||
void SLLV(unsigned int, unsigned int, unsigned int);
|
||||
void SLTU(unsigned int, unsigned int, unsigned int);
|
||||
void SRA(unsigned int, unsigned int, unsigned int);
|
||||
void SRAV(unsigned int, unsigned int, unsigned int);
|
||||
void SRL(unsigned int, unsigned int, unsigned int);
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include "MIPSInstructionFactory.h"
|
||||
#include "MIPS.h"
|
||||
#include "PtrMacro.h"
|
||||
@ -108,6 +109,36 @@ void CMIPSInstructionFactory::BranchLikely(bool nCondition)
|
||||
m_pB->SetDelayedJumpCheck();
|
||||
}
|
||||
|
||||
void CMIPSInstructionFactory::ComputeMemAccessAddrEx()
|
||||
{
|
||||
uint8 nRS;
|
||||
uint16 nImmediate;
|
||||
|
||||
nRS = (uint8) ((m_nOpcode >> 21) & 0x001F);
|
||||
nImmediate = (uint16)((m_nOpcode >> 0) & 0xFFFF);
|
||||
|
||||
//TODO: Compute the complete 64-bit address
|
||||
|
||||
//Translate the address
|
||||
|
||||
//Push context
|
||||
CCodeGen::PushRef(m_pCtx);
|
||||
|
||||
//Push high part
|
||||
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[nRS].nV[1]));
|
||||
|
||||
//Push low part of address
|
||||
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[nRS].nV[0]));
|
||||
if(nImmediate != 0)
|
||||
{
|
||||
CCodeGen::PushCst((int16)nImmediate);
|
||||
CCodeGen::Add();
|
||||
}
|
||||
|
||||
//Call
|
||||
CCodeGen::Call(m_pCtx->m_pAddrTranslator, 3, true);
|
||||
}
|
||||
|
||||
void CMIPSInstructionFactory::BranchEx(bool nCondition)
|
||||
{
|
||||
uint16 nImmediate;
|
||||
|
@ -25,6 +25,7 @@ protected:
|
||||
static void Branch(bool);
|
||||
static void BranchLikely(bool);
|
||||
|
||||
static void ComputeMemAccessAddrEx();
|
||||
static void BranchEx(bool);
|
||||
|
||||
static void Illegal();
|
||||
|
108
Source/PS2OS.cpp
108
Source/PS2OS.cpp
@ -1,4 +1,5 @@
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include "PS2OS.h"
|
||||
#include "PS2VM.h"
|
||||
#include "StdStream.h"
|
||||
@ -33,6 +34,10 @@
|
||||
// 0x1FC01000 0x1FC02000 DMAC Interrupt Handler
|
||||
// 0x1FC02000 0x1FC03000 GS Interrupt Handler
|
||||
// 0x1FC03000 0x1FC03100 Thread epilogue
|
||||
// 0x1FC03100 0x1FC03200 Wait Thread Proc
|
||||
|
||||
#define BIOS_ADDRESS_BASE 0x1FC00000
|
||||
#define BIOS_ADDRESS_WAITTHREADPROC 0x1FC03100
|
||||
|
||||
#define CONFIGPATH ".\\config\\"
|
||||
#define PATCHESPATH "patches.xml"
|
||||
@ -288,7 +293,7 @@ void CPS2OS::LoadELF(CStream* pStream, const char* sExecName)
|
||||
for(i = 0; i < 0x02000000 / 4; i++)
|
||||
{
|
||||
nVal = ((uint32*)CPS2VM::m_pRAM)[i];
|
||||
if((nVal & 0xFFFF) == 0x9FB8)
|
||||
if((nVal & 0xFFFF) == 0x9B70)
|
||||
{
|
||||
//if((nVal & 0xFC000000) != 0x0C000000)
|
||||
{
|
||||
@ -374,6 +379,8 @@ void CPS2OS::LoadExecutable()
|
||||
AssembleDmacHandler();
|
||||
AssembleIntcHandler();
|
||||
AssembleThreadEpilog();
|
||||
AssembleWaitThreadProc();
|
||||
CreateWaitThread();
|
||||
|
||||
#ifdef DEBUGGER_INCLUDED
|
||||
CPS2VM::m_EE.m_pAnalysis->Clear();
|
||||
@ -689,7 +696,7 @@ void CPS2OS::AssembleDmacHandler()
|
||||
Asm.ORI(CMIPS::T0, CMIPS::R0, 0x0001);
|
||||
Asm.SLLV(CMIPS::T0, CMIPS::T0, CMIPS::S0);
|
||||
Asm.AND(CMIPS::T0, CMIPS::T0, CMIPS::S1);
|
||||
Asm.BEQ(CMIPS::T0, CMIPS::R0, 0x0019);
|
||||
Asm.BEQ(CMIPS::T0, CMIPS::R0, 0x001A);
|
||||
Asm.NOP();
|
||||
|
||||
//Clear interrupt
|
||||
@ -709,18 +716,17 @@ void CPS2OS::AssembleDmacHandler()
|
||||
|
||||
//Check validity
|
||||
Asm.LW(CMIPS::T1, 0x0000, CMIPS::T0);
|
||||
Asm.BEQ(CMIPS::T1, CMIPS::R0, 0x0009);
|
||||
Asm.BEQ(CMIPS::T1, CMIPS::R0, 0x000A);
|
||||
Asm.NOP();
|
||||
|
||||
//Check if the channel is good one
|
||||
Asm.LW(CMIPS::T1, 0x0004, CMIPS::T0);
|
||||
Asm.BNE(CMIPS::S0, CMIPS::T1, 0x0006);
|
||||
Asm.BNE(CMIPS::S0, CMIPS::T1, 0x0007);
|
||||
Asm.NOP();
|
||||
|
||||
//Load the necessary stuff
|
||||
Asm.LW(CMIPS::T1, 0x0008, CMIPS::T0);
|
||||
//Asm.ADDU(CMIPS::A0, CMIPS::S0, CMIPS::R0);
|
||||
//Asm.LW(CMIPS::A0, 0x000C, CMIPS::T0);
|
||||
Asm.ADDU(CMIPS::A0, CMIPS::S0, CMIPS::R0);
|
||||
Asm.LW(CMIPS::A1, 0x000C, CMIPS::T0);
|
||||
Asm.LW(CMIPS::GP, 0x0010, CMIPS::T0);
|
||||
|
||||
@ -731,12 +737,12 @@ void CPS2OS::AssembleDmacHandler()
|
||||
//Increment handler counter and test
|
||||
Asm.ADDIU(CMIPS::S2, CMIPS::S2, 0x0001);
|
||||
Asm.ADDIU(CMIPS::T0, CMIPS::R0, MAX_DMACHANDLER - 1);
|
||||
Asm.BNE(CMIPS::S2, CMIPS::T0, 0xFFED);
|
||||
Asm.BNE(CMIPS::S2, CMIPS::T0, 0xFFEC);
|
||||
Asm.NOP();
|
||||
|
||||
//Decrement channel counter and test
|
||||
Asm.ADDIU(CMIPS::S0, CMIPS::S0, 0xFFFF);
|
||||
Asm.BGEZ(CMIPS::S0, 0xFFE1);
|
||||
Asm.BGEZ(CMIPS::S0, 0xFFE0);
|
||||
Asm.NOP();
|
||||
|
||||
//Epilogue
|
||||
@ -814,6 +820,17 @@ void CPS2OS::AssembleThreadEpilog()
|
||||
Asm.SYSCALL();
|
||||
}
|
||||
|
||||
void CPS2OS::AssembleWaitThreadProc()
|
||||
{
|
||||
CMIPSAssembler Asm((uint32*)&CPS2VM::m_pBIOS[BIOS_ADDRESS_WAITTHREADPROC - BIOS_ADDRESS_BASE]);
|
||||
|
||||
Asm.ADDIU(CMIPS::V1, CMIPS::R0, 0x03);
|
||||
Asm.SYSCALL();
|
||||
|
||||
Asm.BEQ(CMIPS::R0, CMIPS::R0, 0xFFFD);
|
||||
Asm.NOP();
|
||||
}
|
||||
|
||||
uint32* CPS2OS::GetCustomSyscallTable()
|
||||
{
|
||||
return (uint32*)&CPS2VM::m_pRAM[0x00010000];
|
||||
@ -899,6 +916,54 @@ uint32 CPS2OS::GetNextReadyThread()
|
||||
THREAD* pThread;
|
||||
unsigned int nID;
|
||||
|
||||
unsigned int nRand, nCount;
|
||||
srand((unsigned int)time(NULL));
|
||||
nRand = rand();
|
||||
|
||||
nCount = 0;
|
||||
for(unsigned int i = 1; i < MAX_THREAD; i++)
|
||||
{
|
||||
if(i == GetCurrentThreadId()) continue;
|
||||
pThread = GetThread(i);
|
||||
if(pThread->nValid != 1) continue;
|
||||
if(pThread->nStatus != THREAD_RUNNING) continue;
|
||||
nCount++;
|
||||
}
|
||||
|
||||
|
||||
if(nCount == 0)
|
||||
{
|
||||
nID = GetCurrentThreadId();
|
||||
|
||||
pThread = GetThread(nID);
|
||||
if(pThread->nStatus != THREAD_RUNNING)
|
||||
{
|
||||
//Now, now, everyone is waiting for something...
|
||||
nID = 0;
|
||||
}
|
||||
|
||||
return nID;
|
||||
}
|
||||
|
||||
nRand %= nCount;
|
||||
|
||||
nCount = 0;
|
||||
for(unsigned int i = 1; i < MAX_THREAD; i++)
|
||||
{
|
||||
if(i == GetCurrentThreadId()) continue;
|
||||
pThread = GetThread(i);
|
||||
if(pThread->nValid != 1) continue;
|
||||
if(pThread->nStatus != THREAD_RUNNING) continue;
|
||||
if(nRand == nCount)
|
||||
{
|
||||
nID = i;
|
||||
break;
|
||||
}
|
||||
nCount++;
|
||||
}
|
||||
|
||||
return nID;
|
||||
/*
|
||||
for(itThread = m_pThreadSchedule->Begin(); !itThread.IsEnd(); itThread++)
|
||||
{
|
||||
nID = itThread.GetValue();
|
||||
@ -907,6 +972,7 @@ uint32 CPS2OS::GetNextReadyThread()
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if(itThread.IsEnd())
|
||||
{
|
||||
//Deadlock or something here
|
||||
@ -918,6 +984,17 @@ uint32 CPS2OS::GetNextReadyThread()
|
||||
m_pThreadSchedule->Insert(nID, pThread->nPriority);
|
||||
|
||||
return nID;
|
||||
*/
|
||||
}
|
||||
|
||||
void CPS2OS::CreateWaitThread()
|
||||
{
|
||||
THREAD* pThread;
|
||||
|
||||
pThread = GetThread(0);
|
||||
pThread->nValid = 1;
|
||||
pThread->nEPC = BIOS_ADDRESS_WAITTHREADPROC;
|
||||
pThread->nStatus = THREAD_ZOMBIE;
|
||||
}
|
||||
|
||||
uint32 CPS2OS::GetNextAvailableSemaphoreId()
|
||||
@ -1514,12 +1591,15 @@ void CPS2OS::sc_SleepThread()
|
||||
}
|
||||
|
||||
//33
|
||||
//34
|
||||
void CPS2OS::sc_WakeupThread()
|
||||
{
|
||||
THREAD* pThread;
|
||||
uint32 nID;
|
||||
bool nInt;
|
||||
|
||||
nID = m_pCtx->m_State.nGPR[SC_PARAM0].nV[0];
|
||||
nInt = m_pCtx->m_State.nGPR[3].nV[0] == 0x34;
|
||||
|
||||
pThread = GetThread(nID);
|
||||
|
||||
@ -1554,7 +1634,7 @@ void CPS2OS::sc_RFU060()
|
||||
|
||||
//Set up the main thread
|
||||
|
||||
pThread = GetThread(0);
|
||||
pThread = GetThread(1);
|
||||
|
||||
pThread->nValid = 0x01;
|
||||
pThread->nStatus = THREAD_RUNNING;
|
||||
@ -1565,7 +1645,7 @@ void CPS2OS::sc_RFU060()
|
||||
nStackAddr -= STACKRES;
|
||||
pThread->nContextPtr = nStackAddr;
|
||||
|
||||
SetCurrentThreadId(0);
|
||||
SetCurrentThreadId(1);
|
||||
|
||||
m_pCtx->m_State.nGPR[SC_RETURN].nV[0] = nStackAddr;
|
||||
m_pCtx->m_State.nGPR[SC_RETURN].nV[1] = 0;
|
||||
@ -2130,6 +2210,10 @@ void CPS2OS::DisassembleSysCall(uint8 nFunc)
|
||||
printf("PS2OS: WakeupThread(id = %i);\r\n", \
|
||||
m_pCtx->m_State.nGPR[SC_PARAM0].nV[0]);
|
||||
break;
|
||||
case 0x34:
|
||||
printf("PS2OS: iWakeupThread(id = %i);\r\n", \
|
||||
m_pCtx->m_State.nGPR[SC_PARAM0].nV[0]);
|
||||
break;
|
||||
case 0x3C:
|
||||
printf("PS2OS: RFU060(gp = 0x%0.8X, stack = 0x%0.8X, stack_size = 0x%0.8X, args = 0x%0.8X, root_func = 0x%0.8X);\r\n", \
|
||||
m_pCtx->m_State.nGPR[SC_PARAM0].nV[0], \
|
||||
@ -2248,7 +2332,7 @@ void (*CPS2OS::m_pSysCall[0x80])() =
|
||||
//0x28
|
||||
sc_Unhandled, sc_ChangeThreadPriority, sc_Unhandled, sc_RotateThreadReadyQueue, sc_Unhandled, sc_Unhandled, sc_Unhandled, sc_GetThreadId,
|
||||
//0x30
|
||||
sc_ReferThreadStatus, sc_Unhandled, sc_SleepThread, sc_WakeupThread, sc_Unhandled, sc_Unhandled, sc_Unhandled, sc_Unhandled,
|
||||
sc_ReferThreadStatus, sc_Unhandled, sc_SleepThread, sc_WakeupThread, sc_WakeupThread, sc_Unhandled, sc_Unhandled, sc_Unhandled,
|
||||
//0x38
|
||||
sc_Unhandled, sc_Unhandled, sc_Unhandled, sc_Unhandled, sc_RFU060, sc_RFU061, sc_EndOfHeap, sc_Unhandled,
|
||||
//0x40
|
||||
@ -2326,7 +2410,7 @@ unsigned int CPS2OS::CRoundRibbon::Insert(uint32 nValue, uint32 nWeight)
|
||||
continue;
|
||||
}
|
||||
|
||||
if(pNode->nWeight < pNext->nWeight)
|
||||
if(pNode->nWeight > pNext->nWeight)
|
||||
{
|
||||
pNext = NULL;
|
||||
continue;
|
||||
|
@ -208,9 +208,11 @@ private:
|
||||
static void AssembleDmacHandler();
|
||||
static void AssembleIntcHandler();
|
||||
static void AssembleThreadEpilog();
|
||||
static void AssembleWaitThreadProc();
|
||||
|
||||
static uint32* GetCustomSyscallTable();
|
||||
|
||||
static void CreateWaitThread();
|
||||
static uint32 GetCurrentThreadId();
|
||||
static void SetCurrentThreadId(uint32);
|
||||
static uint32 GetNextAvailableThreadId();
|
||||
|
@ -82,6 +82,7 @@ BEGIN
|
||||
MENUITEM "Shift Operations Test", ID_VM_TEST_SHIFT
|
||||
MENUITEM "Split Load Operations Test", ID_VM_TEST_SPLITLOAD
|
||||
MENUITEM "64-bit Addition Operations Test", ID_VM_TEST_ADD64
|
||||
MENUITEM "SLT Operations Test", ID_VM_TEST_SLT
|
||||
END
|
||||
END
|
||||
POPUP "&View"
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "IOP_DbcMan.h"
|
||||
#include "IOP_LibSD.h"
|
||||
#include "IOP_Cdvdfsv.h"
|
||||
#include "IOP_Dummy.h"
|
||||
|
||||
#define CMD_RECVADDR 0x00001000
|
||||
#define RPC_RECVADDR 0xDEADBEEF
|
||||
@ -47,6 +48,7 @@ void CSIF::Reset()
|
||||
//Create modules that have multiple RPC IDs
|
||||
m_pPadMan = new IOP::CPadMan();
|
||||
|
||||
m_Module.Insert(new IOP::CDummy, IOP::CDummy::MODULE_ID);
|
||||
m_Module.Insert(new IOP::CFileIO, IOP::CFileIO::MODULE_ID);
|
||||
m_Module.Insert(new IOP::CSysMem, IOP::CSysMem::MODULE_ID);
|
||||
m_Module.Insert(new IOP::CLoadFile, IOP::CLoadFile::MODULE_ID);
|
||||
|
@ -439,7 +439,8 @@ uint32 CVIF::CVPU1::ExecuteCommand(CODE nCommand, uint32 nAddress, uint32 nSize)
|
||||
return 0;
|
||||
break;
|
||||
case 0x50:
|
||||
//DIRECT
|
||||
case 0x51:
|
||||
//DIRECT/DIRECTHL
|
||||
return Cmd_DIRECT(nCommand, nAddress, nSize);
|
||||
break;
|
||||
default:
|
||||
@ -450,6 +451,8 @@ uint32 CVIF::CVPU1::ExecuteCommand(CODE nCommand, uint32 nAddress, uint32 nSize)
|
||||
|
||||
uint32 CVIF::CVPU1::Cmd_DIRECT(CODE nCommand, uint32 nAddress, uint32 nSize)
|
||||
{
|
||||
nSize = min(m_CODE.nIMM * 0x10, nSize);
|
||||
|
||||
CGIF::ProcessPacket(CPS2VM::m_pRAM, nAddress, nAddress + nSize);
|
||||
|
||||
m_CODE.nIMM -= (nSize / 0x10);
|
||||
|
@ -117,13 +117,15 @@
|
||||
#define ID_VM_DUMPINTCHANDLERS 40119
|
||||
#define ID_VIRTUALMACHINE_DUMPDMACHANDLERS 40120
|
||||
#define ID_VM_DUMPDMACHANDLERS 40121
|
||||
#define ID_ASSEMBLESTARTTEST_SLTOPERATIONSTEST 40122
|
||||
#define ID_VM_TEST_SLT 40123
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 113
|
||||
#define _APS_NEXT_COMMAND_VALUE 40122
|
||||
#define _APS_NEXT_COMMAND_VALUE 40124
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
|
@ -13,4 +13,10 @@
|
||||
<Patch Address="0x0029B8EC" Value="0x00000000" Description="Skips movies" />
|
||||
<Patch Address="0x0029B8F8" Value="0x00000000" Description="Skips movies" />
|
||||
</Executable>
|
||||
<Executable Name="SLPM_661.75;1">
|
||||
<Patch Address="0x009B47D0" Value="0x00000002" Description="Enable libcdvd tracing."/>
|
||||
<Patch Address="0x0042FD58" Value="0x24020001" />
|
||||
<Patch Address="0x00412CB4" Value="0x24020000" />
|
||||
<Patch Address="0x00417284" Value="0x00000000" />
|
||||
</Executable>
|
||||
</Patches>
|
||||
|
Loading…
x
Reference in New Issue
Block a user