From b78a6cb2122f18d9a71351e72265a52d16b3021e Mon Sep 17 00:00:00 2001 From: Aleksandar Andrejevic Date: Sun, 15 Sep 2013 18:26:25 +0000 Subject: [PATCH] [SOFT386] Implement the direct relative near call (CALL rel16/32) instruction. svn path=/branches/ntvdm/; revision=60147 --- lib/soft386/opcodes.c | 56 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 3 deletions(-) diff --git a/lib/soft386/opcodes.c b/lib/soft386/opcodes.c index c9fcd5f94aa..5fbc14df1bf 100644 --- a/lib/soft386/opcodes.c +++ b/lib/soft386/opcodes.c @@ -4204,10 +4204,60 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeJecxz) SOFT386_OPCODE_HANDLER(Soft386OpcodeCall) { - // TODO: NOT IMPLEMENTED - UNIMPLEMENTED; + BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size; - return FALSE; + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xE8); + + if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE) + { + /* The OPSIZE prefix toggles the size */ + Size = !Size; + } + else if (State->PrefixFlags != 0) + { + /* Invalid prefix */ + Soft386Exception(State, SOFT386_EXCEPTION_UD); + return FALSE; + } + + /* Push the current value of the instruction pointer */ + if (!Soft386StackPush(State, State->InstPtr.Long)) + { + /* Exception occurred */ + return FALSE; + } + + if (Size) + { + LONG Offset = 0; + + /* Fetch the offset */ + if (!Soft386FetchDword(State, (PULONG)&Offset)) + { + /* An exception occurred */ + return FALSE; + } + + /* Move the instruction pointer */ + State->InstPtr.Long += Offset; + } + else + { + SHORT Offset = 0; + + /* Fetch the offset */ + if (!Soft386FetchWord(State, (PUSHORT)&Offset)) + { + /* An exception occurred */ + return FALSE; + } + + /* Move the instruction pointer */ + State->InstPtr.LowWord += Offset; + } + + return TRUE; } SOFT386_OPCODE_HANDLER(Soft386OpcodeJmp)