From cd22ba61458f13f021ade6faa1278d54598919fc Mon Sep 17 00:00:00 2001 From: Luke Usher Date: Thu, 27 Sep 2018 22:21:32 +0100 Subject: [PATCH 1/2] 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? --- src/CxbxKrnl/EmuX86.cpp | 64 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 7 deletions(-) diff --git a/src/CxbxKrnl/EmuX86.cpp b/src/CxbxKrnl/EmuX86.cpp index cb6a7352c..01f119bc2 100644 --- a/src/CxbxKrnl/EmuX86.cpp +++ b/src/CxbxKrnl/EmuX86.cpp @@ -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); From 42aae20d8e405cf625e2f066d7a35bf250fd2e72 Mon Sep 17 00:00:00 2001 From: Luke Usher Date: Thu, 27 Sep 2018 22:31:18 +0100 Subject: [PATCH 2/2] Oops, we sign-extended the wrong value for ADD. This fixes 4627 graphics --- src/CxbxKrnl/EmuX86.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CxbxKrnl/EmuX86.cpp b/src/CxbxKrnl/EmuX86.cpp index 01f119bc2..c0f4390f9 100644 --- a/src/CxbxKrnl/EmuX86.cpp +++ b/src/CxbxKrnl/EmuX86.cpp @@ -765,7 +765,7 @@ bool EmuX86_Opcode_ADD(LPEXCEPTION_POINTERS e, _DInst& info) uint32_t dest = EmuX86_Addr_Read(opAddr); if (info.ops[0].size > info.ops[1].size) { - SignExtend32(dest, info.ops[1].size); + SignExtend32(src, info.ops[1].size); } uint32_t result = 0;