Began implementing X86 interpreter fallback for instructions Direct Code execution fails on

Began setting up LLE structure for NV2A
This commit is contained in:
Luke Usher 2016-10-07 10:55:44 +01:00
parent 0b07ff8600
commit 514cce2f6e
4 changed files with 1364 additions and 13 deletions

View File

@ -179,6 +179,7 @@
<ClInclude Include="..\..\src\CxbxKrnl\HLEDataBase.h" />
<ClInclude Include="..\..\src\CxbxKrnl\HLEIntercept.h" />
<ClInclude Include="..\..\src\Common\Win32\Mutex.h" />
<ClInclude Include="..\..\src\CxbxKrnl\nv2a_int.h" />
<ClInclude Include="..\..\src\CxbxKrnl\OOVPA.h" />
<ClInclude Include="..\..\src\CxbxKrnl\ResourceTracker.h" />
<ClInclude Include="..\..\src\Common\Win32\XBController.h" />

View File

@ -39,9 +39,41 @@
#include "CxbxKrnl.h"
#include "Emu.h"
#include "EmuNV2A.h"
#include "nv2a_int.h"
uint32_t EmuNV2A_PMC_Read32(uint32_t addr)
{
switch (addr) {
default:
EmuWarning("EmuNV2A_PMC_Read32: Unknown Read Address %08X", addr);
}
return 0;
}
uint32_t EmuNV2A_PBUS_Read32(uint32_t addr)
{
switch (addr) {
case NV_PBUS_PCI_NV_0:
return 0x10de; // PCI_VENDOR_ID_NVIDIA
break;
default:
EmuWarning("EmuNV2A_PBUS_Read32: Unknown Read Address %08X", addr);
}
return 0;
}
uint32_t EmuNV2A_Read32(uint32_t addr)
{
if (addr <= 0x1000) {
return EmuNV2A_PMC_Read32(addr);
}
else if (addr <= 0x2000) {
return EmuNV2A_PBUS_Read32(addr - 0x1000);
}
EmuWarning("EmuNV2A_Read32: Unknown Read Address %08X", addr);
return 0;
}

View File

@ -61,43 +61,109 @@ void EmuX86_Write32(uint32_t addr, uint32_t value)
EmuWarning("EmuX86_Write32: Unknown Write Address %08X", addr);
}
bool EmuX86_DecodeMemoryOperand(uint32_t* output, LPEXCEPTION_POINTERS e, Zydis::OperandInfo& operand)
{
uint32_t base = 0;
uint32_t index = 0;
switch (operand.base) {
case Zydis::Register::EAX:
base = e->ContextRecord->Eax;
break;
case Zydis::Register::EBX:
base = e->ContextRecord->Ebx;
break;
case Zydis::Register::ECX:
base = e->ContextRecord->Ecx;
break;
case Zydis::Register::EDX:
base = e->ContextRecord->Edx;
break;
case Zydis::Register::NONE:
break;
default:
return false;
}
switch (operand.index) {
case Zydis::Register::NONE:
break;
default:
return false;
}
*output = base + index + operand.lval.udword;
return true;
}
bool EmuX86_MOV(LPEXCEPTION_POINTERS e, Zydis::InstructionInfo& info)
{
if (info.operand[0].type == Zydis::OperandType::REGISTER && info.operand[1].type == Zydis::OperandType::MEMORY)
{
DWORD* pDstReg = nullptr;
uint32_t srcAddr = 0;
switch (info.operand[0].base) {
case Zydis::Register::EAX:
e->ContextRecord->Eax = EmuX86_Read32(info.operand[1].lval.udword);
return true;
pDstReg = &e->ContextRecord->Eax;
break;
case Zydis::Register::EBX:
e->ContextRecord->Ebx = EmuX86_Read32(info.operand[1].lval.udword);
return true;
pDstReg = &e->ContextRecord->Ebx;
break;
case Zydis::Register::ECX:
e->ContextRecord->Ebx = EmuX86_Read32(info.operand[1].lval.udword);
return true;
pDstReg = &e->ContextRecord->Ecx;
break;
case Zydis::Register::EDX:
pDstReg = &e->ContextRecord->Edx;
break;
default:
return false;
}
if (!EmuX86_DecodeMemoryOperand(&srcAddr, e, info.operand[1])) {
return false;
}
*pDstReg = EmuX86_Read32(srcAddr);
return true;
}
else if (info.operand[0].type == Zydis::OperandType::MEMORY && info.operand[1].type == Zydis::OperandType::REGISTER)
{
uint32_t addr = 0;
uint32_t value = 0;
if (!EmuX86_DecodeMemoryOperand(&addr, e, info.operand[0])) {
return false;
}
switch (info.operand[1].base) {
case Zydis::Register::EAX:
EmuX86_Write32(info.operand[1].lval.udword, e->ContextRecord->Eax);
return true;
value = e->ContextRecord->Eax;
break;
case Zydis::Register::EBX:
EmuX86_Write32(info.operand[1].lval.udword, e->ContextRecord->Ebx);
return true;
value = e->ContextRecord->Ebx;
break;
case Zydis::Register::ECX:
EmuX86_Write32(info.operand[1].lval.udword, e->ContextRecord->Ecx);
return true;
value = e->ContextRecord->Ecx;
break;
case Zydis::Register::EDX:
value = e->ContextRecord->Edx;
break;
default:
return false;
}
EmuX86_Write32(addr, value);
return true;
}
else if (info.operand[0].type == Zydis::OperandType::MEMORY && info.operand[1].type == Zydis::OperandType::IMMEDIATE)
{
EmuX86_Write32(info.operand[0].lval.udword, info.operand[1].lval.udword);
uint32_t addr = 0;
if (!EmuX86_DecodeMemoryOperand(&addr, e, info.operand[1])) {
return false;
}
EmuX86_Write32(addr, info.operand[1].lval.udword);
return true;
}
}

1252
src/CxbxKrnl/nv2a_int.h Normal file

File diff suppressed because it is too large Load Diff