From a4fa55519d700735021dc035765de12f3987941c Mon Sep 17 00:00:00 2001 From: Luke Usher Date: Tue, 19 Sep 2017 11:07:48 +0100 Subject: [PATCH] Implement INC/DEC opcodes --- src/CxbxKrnl/EmuX86.cpp | 63 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/src/CxbxKrnl/EmuX86.cpp b/src/CxbxKrnl/EmuX86.cpp index 085c84165..6ffbba4ea 100644 --- a/src/CxbxKrnl/EmuX86.cpp +++ b/src/CxbxKrnl/EmuX86.cpp @@ -876,6 +876,60 @@ bool EmuX86_Opcode_CMPXCHG(LPEXCEPTION_POINTERS e, _DInst& info) return true; } +bool EmuX86_Opcode_DEC(LPEXCEPTION_POINTERS e, _DInst& info) +{ + uint32_t dest = 0; + if (!EmuX86_Operand_Read(e, info, 0, &dest)) + return false; + + // ADD Destination to src + uint64_t result = dest - 1; + + // Write result back + EmuX86_Operand_Write(e, info, 0, result); + + EmuX86_SetFlag(e, EMUX86_EFLAG_OF, (result >> 31) != (dest >> 31)); + // TODO: Figure out how to calculate this EmuX86_SetFlag(e, EMUX86_EFLAG_AF, 0); + + EmuX86_SetFlag(e, EMUX86_EFLAG_SF, result >> 31); + EmuX86_SetFlag(e, EMUX86_EFLAG_ZF, result == 0 ? 1 : 0); + // Set Parity flag, based on "Compute parity in parallel" method from + // http://graphics.stanford.edu/~seander/bithacks.html#ParityParallel + uint32_t v = 255 & dest; + v ^= v >> 4; + v &= 0xf; + EmuX86_SetFlag(e, EMUX86_EFLAG_PF, (0x6996 >> v) & 1); + + return true; +} + +bool EmuX86_Opcode_INC(LPEXCEPTION_POINTERS e, _DInst& info) +{ + uint32_t dest = 0; + if (!EmuX86_Operand_Read(e, info, 0, &dest)) + return false; + + // ADD Destination to src + uint64_t result = dest + 1; + + // Write result back + EmuX86_Operand_Write(e, info, 0, result); + + EmuX86_SetFlag(e, EMUX86_EFLAG_OF, (result >> 31) != (dest >> 31)); + // TODO: Figure out how to calculate this EmuX86_SetFlag(e, EMUX86_EFLAG_AF, 0); + + EmuX86_SetFlag(e, EMUX86_EFLAG_SF, result >> 31); + EmuX86_SetFlag(e, EMUX86_EFLAG_ZF, result == 0 ? 1 : 0); + // Set Parity flag, based on "Compute parity in parallel" method from + // http://graphics.stanford.edu/~seander/bithacks.html#ParityParallel + uint32_t v = 255 & dest; + v ^= v >> 4; + v &= 0xf; + EmuX86_SetFlag(e, EMUX86_EFLAG_PF, (0x6996 >> v) & 1); + + return true; +} + bool EmuX86_Opcode_OR(LPEXCEPTION_POINTERS e, _DInst& info) { // Read value from Source and Destination @@ -1152,11 +1206,20 @@ bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e) case I_CPUID: EmuX86_Opcode_CPUID(e, info); break; + case I_DEC: + if (EmuX86_Opcode_DEC(e, info)) + break; + + goto unimplemented_opcode; case I_IN: if (EmuX86_Opcode_IN(e, info)) break; goto unimplemented_opcode; + case I_INC: + if (EmuX86_Opcode_INC(e, info)) + break; + goto unimplemented_opcode; case I_INVD: // Flush internal caches; initiate flushing of external caches. // We can safely ignore this break;