From d3a6556ea53eadfb0b17b5e165609727b0cd5efb Mon Sep 17 00:00:00 2001 From: Aleksandar Andrejevic Date: Thu, 19 Sep 2013 22:48:45 +0000 Subject: [PATCH] [SOFT386] Implement JECXZ, LOOP, LOOPZ and LOOPNZ. svn path=/branches/ntvdm/; revision=60226 --- lib/soft386/opcodes.c | 110 +++++++++++++++++++++++++++++++++--------- lib/soft386/opcodes.h | 2 - 2 files changed, 86 insertions(+), 26 deletions(-) diff --git a/lib/soft386/opcodes.c b/lib/soft386/opcodes.c index bc733caf9d0..7e139f0440b 100644 --- a/lib/soft386/opcodes.c +++ b/lib/soft386/opcodes.c @@ -248,8 +248,8 @@ Soft386OpcodeHandlers[SOFT386_NUM_OPCODE_HANDLERS] = NULL, // TODO: OPCODE 0xDD NOT SUPPORTED NULL, // TODO: OPCODE 0xDE NOT SUPPORTED NULL, // TODO: OPCODE 0xDF NOT SUPPORTED - Soft386OpcodeLoopnz, - Soft386OpcodeLoopz, + Soft386OpcodeLoop, + Soft386OpcodeLoop, Soft386OpcodeLoop, Soft386OpcodeJecxz, Soft386OpcodeInByte, @@ -4323,36 +4323,98 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeXlat) return FALSE; } -SOFT386_OPCODE_HANDLER(Soft386OpcodeLoopnz) -{ - // TODO: NOT IMPLEMENTED - UNIMPLEMENTED; - - return FALSE; -} - -SOFT386_OPCODE_HANDLER(Soft386OpcodeLoopz) -{ - // TODO: NOT IMPLEMENTED - UNIMPLEMENTED; - - return FALSE; -} - SOFT386_OPCODE_HANDLER(Soft386OpcodeLoop) { - // TODO: NOT IMPLEMENTED - UNIMPLEMENTED; + BOOLEAN Condition; + BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size; + CHAR Offset = 0; - return FALSE; + /* Make sure this is the right instruction */ + ASSERT((Opcode >= 0xE0) && (Opcode <= 0xE2)); + + if (State->PrefixFlags & SOFT386_PREFIX_LOCK) + { + /* Invalid prefix */ + Soft386Exception(State, SOFT386_EXCEPTION_UD); + return FALSE; + } + + if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE) + { + /* The OPSIZE prefix toggles the size */ + Size = !Size; + } + + if (Size) Condition = ((--State->GeneralRegs[SOFT386_REG_ECX].Long) == 0); + else Condition = ((--State->GeneralRegs[SOFT386_REG_ECX].LowWord) == 0); + + if (Opcode == 0xE0) + { + /* Additional rule for LOOPNZ */ + if (State->Flags.Zf) Condition = FALSE; + } + + if (Opcode == 0xE1) + { + /* Additional rule for LOOPZ */ + if (!State->Flags.Zf) Condition = FALSE; + } + + /* Fetch the offset */ + if (!Soft386FetchByte(State, (PUCHAR)&Offset)) + { + /* An exception occurred */ + return FALSE; + } + + if (Condition) + { + /* Move the instruction pointer */ + State->InstPtr.Long += Offset; + } + + return TRUE; } SOFT386_OPCODE_HANDLER(Soft386OpcodeJecxz) { - // TODO: NOT IMPLEMENTED - UNIMPLEMENTED; + BOOLEAN Condition; + BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size; + CHAR Offset = 0; - return FALSE; + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xE3); + + if (State->PrefixFlags & SOFT386_PREFIX_LOCK) + { + /* Invalid prefix */ + Soft386Exception(State, SOFT386_EXCEPTION_UD); + return FALSE; + } + + if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE) + { + /* The OPSIZE prefix toggles the size */ + Size = !Size; + } + + if (Size) Condition = (State->GeneralRegs[SOFT386_REG_ECX].Long == 0); + else Condition = (State->GeneralRegs[SOFT386_REG_ECX].LowWord == 0); + + /* Fetch the offset */ + if (!Soft386FetchByte(State, (PUCHAR)&Offset)) + { + /* An exception occurred */ + return FALSE; + } + + if (Condition) + { + /* Move the instruction pointer */ + State->InstPtr.Long += Offset; + } + + return TRUE; } SOFT386_OPCODE_HANDLER(Soft386OpcodeCall) diff --git a/lib/soft386/opcodes.h b/lib/soft386/opcodes.h index ecd72a8f602..85e71c689a9 100644 --- a/lib/soft386/opcodes.h +++ b/lib/soft386/opcodes.h @@ -130,8 +130,6 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeIret); SOFT386_OPCODE_HANDLER(Soft386OpcodeAam); SOFT386_OPCODE_HANDLER(Soft386OpcodeAad); SOFT386_OPCODE_HANDLER(Soft386OpcodeXlat); -SOFT386_OPCODE_HANDLER(Soft386OpcodeLoopnz); -SOFT386_OPCODE_HANDLER(Soft386OpcodeLoopz); SOFT386_OPCODE_HANDLER(Soft386OpcodeLoop); SOFT386_OPCODE_HANDLER(Soft386OpcodeJecxz); SOFT386_OPCODE_HANDLER(Soft386OpcodeCall);