From 432372c3b6085d7b7367788c5bd098ca4a38cd28 Mon Sep 17 00:00:00 2001 From: Aleksandar Andrejevic Date: Sat, 21 Sep 2013 18:44:59 +0000 Subject: [PATCH] [SOFT386] Implement the MOV AL/AX/EAX, off16/32 and MOV off16/32, AL/AX/EAX instructions. svn path=/branches/ntvdm/; revision=60289 --- lib/soft386/opcodes.c | 201 +++++++++++++++++++++++++++++++++++++++++- lib/soft386/opcodes.h | 4 + 2 files changed, 201 insertions(+), 4 deletions(-) diff --git a/lib/soft386/opcodes.c b/lib/soft386/opcodes.c index 13d0480aa6e..21e02be4188 100644 --- a/lib/soft386/opcodes.c +++ b/lib/soft386/opcodes.c @@ -184,10 +184,10 @@ Soft386OpcodeHandlers[SOFT386_NUM_OPCODE_HANDLERS] = Soft386OpcodePopFlags, Soft386OpcodeSahf, Soft386OpcodeLahf, - NULL, // TODO: OPCODE 0xA0 NOT SUPPORTED - NULL, // TODO: OPCODE 0xA1 NOT SUPPORTED - NULL, // TODO: OPCODE 0xA2 NOT SUPPORTED - NULL, // TODO: OPCODE 0xA3 NOT SUPPORTED + Soft386OpcodeMovAlOffset, + Soft386OpcodeMovEaxOffset, + Soft386OpcodeMovOffsetAl, + Soft386OpcodeMovOffsetEax, NULL, // TODO: OPCODE 0xA4 NOT SUPPORTED NULL, // TODO: OPCODE 0xA5 NOT SUPPORTED NULL, // TODO: OPCODE 0xA6 NOT SUPPORTED @@ -4639,3 +4639,196 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeJmpAbs) return FALSE; } + +SOFT386_OPCODE_HANDLER(Soft386OpcodeMovAlOffset) +{ + BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size; + ULONG Offset; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xA0); + + if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE) + { + /* The OPSIZE prefix toggles the size */ + Size = !Size; + } + + if (Size) + { + if (!Soft386FetchDword(State, &Offset)) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + USHORT WordOffset; + + if (!Soft386FetchWord(State, &WordOffset)) + { + /* Exception occurred */ + return FALSE; + } + + Offset = (ULONG)WordOffset; + } + + /* Read from memory */ + return Soft386ReadMemory(State, + (State->PrefixFlags & SOFT386_PREFIX_SEG) ? + State->SegmentOverride : SOFT386_REG_DS, + Offset, + FALSE, + &State->GeneralRegs[SOFT386_REG_EAX].LowByte, + sizeof(UCHAR)); +} + +SOFT386_OPCODE_HANDLER(Soft386OpcodeMovEaxOffset) +{ + BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xA1); + + if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE) + { + /* The OPSIZE prefix toggles the size */ + Size = !Size; + } + + if (Size) + { + ULONG Offset; + + if (!Soft386FetchDword(State, &Offset)) + { + /* Exception occurred */ + return FALSE; + } + + /* Read from memory */ + return Soft386ReadMemory(State, + (State->PrefixFlags & SOFT386_PREFIX_SEG) ? + State->SegmentOverride : SOFT386_REG_DS, + Offset, + FALSE, + &State->GeneralRegs[SOFT386_REG_EAX].Long, + sizeof(ULONG)); + } + else + { + USHORT Offset; + + if (!Soft386FetchWord(State, &Offset)) + { + /* Exception occurred */ + return FALSE; + } + + /* Read from memory */ + return Soft386ReadMemory(State, + (State->PrefixFlags & SOFT386_PREFIX_SEG) ? + State->SegmentOverride : SOFT386_REG_DS, + Offset, + FALSE, + &State->GeneralRegs[SOFT386_REG_EAX].LowWord, + sizeof(USHORT)); + } +} + +SOFT386_OPCODE_HANDLER(Soft386OpcodeMovOffsetAl) +{ + BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size; + ULONG Offset; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xA2); + + if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE) + { + /* The OPSIZE prefix toggles the size */ + Size = !Size; + } + + if (Size) + { + if (!Soft386FetchDword(State, &Offset)) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + USHORT WordOffset; + + if (!Soft386FetchWord(State, &WordOffset)) + { + /* Exception occurred */ + return FALSE; + } + + Offset = (ULONG)WordOffset; + } + + /* Write to memory */ + return Soft386WriteMemory(State, + (State->PrefixFlags & SOFT386_PREFIX_SEG) ? + State->SegmentOverride : SOFT386_REG_DS, + Offset, + &State->GeneralRegs[SOFT386_REG_EAX].LowByte, + sizeof(UCHAR)); +} + +SOFT386_OPCODE_HANDLER(Soft386OpcodeMovOffsetEax) +{ + BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xA3); + + if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE) + { + /* The OPSIZE prefix toggles the size */ + Size = !Size; + } + + if (Size) + { + ULONG Offset; + + if (!Soft386FetchDword(State, &Offset)) + { + /* Exception occurred */ + return FALSE; + } + + /* Write to memory */ + return Soft386WriteMemory(State, + (State->PrefixFlags & SOFT386_PREFIX_SEG) ? + State->SegmentOverride : SOFT386_REG_DS, + Offset, + &State->GeneralRegs[SOFT386_REG_EAX].Long, + sizeof(ULONG)); + } + else + { + USHORT Offset; + + if (!Soft386FetchWord(State, &Offset)) + { + /* Exception occurred */ + return FALSE; + } + + /* Write to memory */ + return Soft386WriteMemory(State, + (State->PrefixFlags & SOFT386_PREFIX_SEG) ? + State->SegmentOverride : SOFT386_REG_DS, + Offset, + &State->GeneralRegs[SOFT386_REG_EAX].LowWord, + sizeof(USHORT)); + } +} diff --git a/lib/soft386/opcodes.h b/lib/soft386/opcodes.h index fcc0fe4ac12..85143b87423 100644 --- a/lib/soft386/opcodes.h +++ b/lib/soft386/opcodes.h @@ -132,5 +132,9 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeJecxz); SOFT386_OPCODE_HANDLER(Soft386OpcodeCall); SOFT386_OPCODE_HANDLER(Soft386OpcodeJmp); SOFT386_OPCODE_HANDLER(Soft386OpcodeJmpAbs); +SOFT386_OPCODE_HANDLER(Soft386OpcodeMovAlOffset); +SOFT386_OPCODE_HANDLER(Soft386OpcodeMovEaxOffset); +SOFT386_OPCODE_HANDLER(Soft386OpcodeMovOffsetAl); +SOFT386_OPCODE_HANDLER(Soft386OpcodeMovOffsetEax); #endif // _OPCODES_H_