git-svn-id: http://svn.purei.org/purei/trunk@47 b36208d7-6611-0410-8bec-b1987f11c4a2

This commit is contained in:
jpd002 2006-06-26 09:31:14 +00:00
parent 4cdc061460
commit 763c8fa483
27 changed files with 735 additions and 66 deletions

View File

@ -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

View File

@ -10,6 +10,7 @@ public:
{
STATUS = 0x0C,
EPC = 0x0E,
ERROREPC = 0x1E,
};
CCOP_SCU(MIPS_REGSIZE);

View File

@ -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)

View File

@ -80,7 +80,7 @@ long CCallStackWnd::OnNotify(WPARAM wParam, NMHDR* pHDR)
break;
}
return TRUE;
return FALSE;
}
void CCallStackWnd::RefreshLayout()

View File

@ -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);

View File

@ -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.

View File

@ -42,6 +42,7 @@ private:
void StartShift64OpTest();
void StartSplitLoadOpTest();
void StartAddition64OpTest();
void StartSetLessThanOpTest();
void Resume();
void StepCPU1();
void FindValue();

View File

@ -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;

View File

@ -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)

View File

@ -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
{

View File

@ -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:

View File

@ -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)

View File

@ -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)

View File

@ -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();
}
//////////////////////////////////////////////////

View File

@ -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();
}

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -25,6 +25,7 @@ protected:
static void Branch(bool);
static void BranchLikely(bool);
static void ComputeMemAccessAddrEx();
static void BranchEx(bool);
static void Illegal();

View File

@ -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;

View File

@ -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();

View File

@ -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"

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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>