This fixes 4627 vertices sample when executing 3 instructions in a batch.

We're on the right lines here, however, WWE Raw and all XDK samples regressed further, despite the above
improvement.

Stack corruption now happens for most software with while(true).

Perhaps there's an extra condition on sign-extension that we're not checking for?
This commit is contained in:
Luke Usher 2018-09-27 22:21:32 +01:00
parent ae572166f1
commit cd22ba6145
1 changed files with 57 additions and 7 deletions

View File

@ -725,6 +725,30 @@ inline bool EmuX86_HasFlag_ZF(LPEXCEPTION_POINTERS e)
// See http://x86.renejeschke.de/ for affected CPU flags per instruction
void SignExtend32(uint32_t& dest, size_t from)
{
int32_t signExtended = 0;
switch (from) {
case 8:
signExtended = (int8_t)dest;
break;
case 16:
signExtended = (int16_t)dest;
break;
default:
assert(false);
break;
}
#if 0
if ((uint32_t)signExtended != dest) {
DebugBreak();
}
#endif
dest = (uint32_t)signExtended;
}
// Keep opcode emulations alphabetically ordered :
bool EmuX86_Opcode_ADD(LPEXCEPTION_POINTERS e, _DInst& info)
@ -739,7 +763,10 @@ bool EmuX86_Opcode_ADD(LPEXCEPTION_POINTERS e, _DInst& info)
if (!EmuX86_Operand_Addr_ForReadWrite(e, info, 0, OUT opAddr))
return false;
const uint32_t dest = EmuX86_Addr_Read(opAddr);
uint32_t dest = EmuX86_Addr_Read(opAddr);
if (info.ops[0].size > info.ops[1].size) {
SignExtend32(dest, info.ops[1].size);
}
uint32_t result = 0;
uint32_t eflags = e->ContextRecord->EFlags;
@ -776,6 +803,10 @@ bool EmuX86_Opcode_AND(LPEXCEPTION_POINTERS e, _DInst& info)
uint32_t dest = EmuX86_Addr_Read(opAddr);
if (info.ops[0].size > info.ops[1].size) {
SignExtend32(src, info.ops[1].size);
}
uint32_t result = 0;
uint32_t eflags = e->ContextRecord->EFlags;
__asm {
@ -817,6 +848,10 @@ bool EmuX86_Opcode_CMP(LPEXCEPTION_POINTERS e, _DInst& info)
uint32_t dest = 0;
if (!EmuX86_Operand_Read(e, info, 0, &dest))
return false;
if (info.ops[0].size > info.ops[1].size) {
SignExtend32(src, info.ops[1].size);
}
uint32_t eflags = e->ContextRecord->EFlags;
__asm {
@ -845,7 +880,6 @@ bool EmuX86_Opcode_CMPXCHG(LPEXCEPTION_POINTERS e, _DInst& info)
if (!EmuX86_Operand_Read(e, info, 0, &dest))
return false;
uint32_t mask;
switch (info.ops[0].size) {
case 8: mask = 0xFF; break; // TODO : Needs test-case
@ -1143,7 +1177,7 @@ bool EmuX86_Opcode_NOT(LPEXCEPTION_POINTERS e, _DInst& info)
OperandAddress opAddr;
if (!EmuX86_Operand_Addr_ForReadWrite(e, info, 0, OUT opAddr))
return false;
uint32_t dest = EmuX86_Addr_Read(opAddr);
uint32_t result = 0;
uint32_t eflags = e->ContextRecord->EFlags;
@ -1180,7 +1214,10 @@ bool EmuX86_Opcode_OR(LPEXCEPTION_POINTERS e, _DInst& info)
if (!EmuX86_Operand_Addr_ForReadWrite(e, info, 0, OUT opAddr))
return false;
uint32_t dest = EmuX86_Addr_Read(opAddr);
uint32_t dest = EmuX86_Addr_Read(opAddr);
if (info.ops[0].size > info.ops[1].size) {
SignExtend32(src, info.ops[1].size);
}
uint32_t result = 0;
uint32_t eflags = e->ContextRecord->EFlags;
@ -1279,7 +1316,7 @@ bool EmuX86_Opcode_SAR(LPEXCEPTION_POINTERS e, _DInst& info)
return false;
uint32_t dest = EmuX86_Addr_Read(opAddr);
uint32_t result = 0;
uint32_t eflags = e->ContextRecord->EFlags;
uint8_t byteSrc = src;
@ -1318,6 +1355,10 @@ bool EmuX86_Opcode_SBB(LPEXCEPTION_POINTERS e, _DInst& info)
uint32_t dest = EmuX86_Addr_Read(opAddr);
if (info.ops[0].size > info.ops[1].size) {
SignExtend32(src, info.ops[1].size);
}
uint32_t result = 0;
uint32_t eflags = e->ContextRecord->EFlags;
__asm {
@ -1399,8 +1440,9 @@ bool EmuX86_Opcode_SHR(LPEXCEPTION_POINTERS e, _DInst& info)
if (!EmuX86_Operand_Addr_ForReadWrite(e, info, 0, OUT opAddr))
return false;
uint32_t dest = EmuX86_Addr_Read(opAddr);
uint32_t dest = EmuX86_Addr_Read(opAddr);
uint32_t result = 0;
uint32_t eflags = e->ContextRecord->EFlags;
uint8_t byteSrc = src;
@ -1444,6 +1486,10 @@ bool EmuX86_Opcode_SUB(LPEXCEPTION_POINTERS e, _DInst& info)
return false;
uint32_t dest = EmuX86_Addr_Read(opAddr);
if (info.ops[0].size > info.ops[1].size) {
SignExtend32(src, info.ops[1].size);
}
uint32_t result = 0;
uint32_t eflags = e->ContextRecord->EFlags;
@ -1509,6 +1555,10 @@ bool EmuX86_Opcode_XOR(LPEXCEPTION_POINTERS e, _DInst& info)
uint32_t dest = EmuX86_Addr_Read(opAddr);
if (info.ops[0].size > info.ops[1].size) {
SignExtend32(src, info.ops[1].size);
}
uint32_t result = 0;
uint32_t eflags = e->ContextRecord->EFlags;
__asm {
@ -2861,7 +2911,7 @@ bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e)
// Execute op-codes until we hit an unhandled instruction, or an error occurs
while (true)
//for (int x=0;x<1;x++)
//for (int x=0;x<3;x++)
{
if (!EmuX86_DecodeOpcode((uint8_t*)e->ContextRecord->Eip, info)) {
EmuLog(LOG_PREFIX, LOG_LEVEL::WARNING, "Error decoding opcode at 0x%08X", e->ContextRecord->Eip);