From 99dd92ffa09b515cade77d124f413ad834cbdd53 Mon Sep 17 00:00:00 2001 From: Aleksandar Andrejevic Date: Sun, 15 Sep 2013 18:02:41 +0000 Subject: [PATCH] [SOFT386] Implement LAHF, SAHF, LEA and PUSH imm16/32 svn path=/branches/ntvdm/; revision=60144 --- lib/soft386/opcodes.c | 120 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 110 insertions(+), 10 deletions(-) diff --git a/lib/soft386/opcodes.c b/lib/soft386/opcodes.c index 733f74fa9a6..9d3b9bb3592 100644 --- a/lib/soft386/opcodes.c +++ b/lib/soft386/opcodes.c @@ -3627,10 +3627,49 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeArpl) SOFT386_OPCODE_HANDLER(Soft386OpcodePushImm) { - // TODO: NOT IMPLEMENTED - UNIMPLEMENTED; + BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size; - return FALSE; + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x68); + + if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE) + { + /* The OPSIZE prefix toggles the size */ + Size = !Size; + } + else + { + /* Invalid prefix */ + Soft386Exception(State, SOFT386_EXCEPTION_UD); + return FALSE; + } + + if (Size) + { + ULONG Data; + + if (!Soft386FetchDword(State, &Data)) + { + /* Exception occurred */ + return FALSE; + } + + /* Call the internal API */ + return Soft386StackPush(State, Data); + } + else + { + USHORT Data; + + if (!Soft386FetchWord(State, &Data)) + { + /* Exception occurred */ + return FALSE; + } + + /* Call the internal API */ + return Soft386StackPush(State, Data); + } } SOFT386_OPCODE_HANDLER(Soft386OpcodeImulModrmImm) @@ -3645,6 +3684,9 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodePushByteImm) { UCHAR Data; + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x6A); + if (!Soft386FetchByte(State, &Data)) { /* Exception occurred */ @@ -3811,10 +3853,57 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeMovStoreSeg) SOFT386_OPCODE_HANDLER(Soft386OpcodeLea) { - // TODO: NOT IMPLEMENTED - UNIMPLEMENTED; + SOFT386_MOD_REG_RM ModRegRm; + BOOLEAN OperandSize, AddressSize; - return FALSE; + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x8D); + + OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size; + + if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE) + { + /* The ADSIZE prefix toggles the address size */ + AddressSize = !AddressSize; + } + + if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE) + { + /* The OPSIZE prefix toggles the operand size */ + OperandSize = !OperandSize; + } + + /* Get the operands */ + if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* The second operand must be memory */ + if (!ModRegRm.Memory) + { + /* Invalid */ + Soft386Exception(State, SOFT386_EXCEPTION_UD); + return FALSE; + } + + /* Write the address to the register */ + if (OperandSize) + { + return Soft386WriteModrmDwordOperands(State, + &ModRegRm, + TRUE, + ModRegRm.MemoryAddress); + } + else + { + return Soft386WriteModrmWordOperands(State, + &ModRegRm, + TRUE, + ModRegRm.MemoryAddress); + + } } SOFT386_OPCODE_HANDLER(Soft386OpcodeMovLoadSeg) @@ -3936,16 +4025,27 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodePopFlags) SOFT386_OPCODE_HANDLER(Soft386OpcodeSahf) { - // TODO: NOT IMPLEMENTED - UNIMPLEMENTED; + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x9E); + + /* Set the low-order byte of FLAGS to AH */ + State->Flags.Long &= 0xFFFFFF00; + State->Flags.Long |= State->GeneralRegs[SOFT386_REG_EAX].HighByte; + + /* Restore the reserved bits of FLAGS */ + State->Flags.AlwaysSet = TRUE; + State->Flags.Reserved0 = State->Flags.Reserved1 = FALSE; return FALSE; } SOFT386_OPCODE_HANDLER(Soft386OpcodeLahf) { - // TODO: NOT IMPLEMENTED - UNIMPLEMENTED; + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x9F); + + /* Set AH to the low-order byte of FLAGS */ + State->GeneralRegs[SOFT386_REG_EAX].HighByte = LOBYTE(State->Flags.Long); return FALSE; }