From 85f05060e45f47463286c220f0760243bb3d5a46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Tue, 17 Sep 2013 23:02:22 +0000 Subject: [PATCH] [SOFT386] - Put inlined functions in a .inl file, which gets included by the corresponding header file (i.e. fix MSVC builds). - Use enums types instead of "only" INTs... svn path=/branches/ntvdm/; revision=60193 --- include/reactos/libs/soft386/soft386.h | 22 +- lib/soft386/common.c | 964 +------------------------ lib/soft386/common.h | 158 +--- lib/soft386/common.inl | 955 ++++++++++++++++++++++++ lib/soft386/opcodes.c | 6 +- lib/soft386/soft386.c | 6 +- 6 files changed, 993 insertions(+), 1118 deletions(-) create mode 100644 lib/soft386/common.inl diff --git a/include/reactos/libs/soft386/soft386.h b/include/reactos/libs/soft386/soft386.h index 70f2971781d..50e23a22670 100644 --- a/include/reactos/libs/soft386/soft386.h +++ b/include/reactos/libs/soft386/soft386.h @@ -44,7 +44,7 @@ struct _SOFT386_STATE; typedef struct _SOFT386_STATE SOFT386_STATE, *PSOFT386_STATE; -enum _SOFT386_GEN_REGS +typedef enum _SOFT386_GEN_REGS { SOFT386_REG_EAX, SOFT386_REG_ECX, @@ -54,9 +54,9 @@ enum _SOFT386_GEN_REGS SOFT386_REG_EBP, SOFT386_REG_ESI, SOFT386_REG_EDI -}; +} SOFT386_GEN_REGS, *PSOFT386_GEN_REGS; -enum _SOFT386_SEG_REGS +typedef enum _SOFT386_SEG_REGS { SOFT386_REG_ES, SOFT386_REG_CS, @@ -64,9 +64,9 @@ enum _SOFT386_SEG_REGS SOFT386_REG_DS, SOFT386_REG_FS, SOFT386_REG_GS -}; +} SOFT386_SEG_REGS, *PSOFT386_SEG_REGS; -enum _SOFT386_CTRL_REGS +typedef enum _SOFT386_CTRL_REGS { SOFT386_REG_CR0, SOFT386_REG_CR1, @@ -76,9 +76,9 @@ enum _SOFT386_CTRL_REGS SOFT386_REG_CR5, SOFT386_REG_CR6, SOFT386_REG_CR7 -}; +} SOFT386_CTRL_REGS, *PSOFT386_CTRL_REGS; -enum _SOFT386_DBG_REGS +typedef enum _SOFT386_DBG_REGS { SOFT386_REG_DR0, SOFT386_REG_DR1, @@ -88,9 +88,9 @@ enum _SOFT386_DBG_REGS SOFT386_REG_DR5, SOFT386_REG_DR6, SOFT386_REG_DR7 -}; +} SOFT386_DBG_REGS, *PSOFT386_DBG_REGS; -enum _SOFT386_EXCEPTIONS +typedef enum _SOFT386_EXCEPTIONS { SOFT386_EXCEPTION_DE = 0x00, SOFT386_EXCEPTION_DB = 0x01, @@ -108,7 +108,7 @@ enum _SOFT386_EXCEPTIONS SOFT386_EXCEPTION_MF = 0x10, SOFT386_EXCEPTION_AC = 0x11, SOFT386_EXCEPTION_MC = 0x12 -}; +} SOFT386_EXCEPTIONS, *PSOFT386_EXCEPTIONS; typedef BOOLEAN @@ -303,7 +303,7 @@ struct _SOFT386_STATE ULONG DebugRegisters[SOFT386_NUM_DBG_REGS]; ULONG ExceptionCount; ULONG PrefixFlags; - INT SegmentOverride; + SOFT386_SEG_REGS SegmentOverride; BOOLEAN HardwareInt; }; diff --git a/lib/soft386/common.c b/lib/soft386/common.c index 00045f51ebb..385fd5ebd6e 100644 --- a/lib/soft386/common.c +++ b/lib/soft386/common.c @@ -12,24 +12,15 @@ // #define _INC_WINDOWS #include -#include -#include "common.h" - // #define NDEBUG #include +#include +#include "common.h" + /* PRIVATE FUNCTIONS **********************************************************/ -static -inline -INT -Soft386GetCurrentPrivLevel(PSOFT386_STATE State) -{ - return GET_SEGMENT_RPL(State->SegmentRegs[SOFT386_REG_CS].Selector); -} - -static -inline +static FORCEINLINE ULONG Soft386GetPageTableEntry(PSOFT386_STATE State, ULONG VirtualAddress) @@ -42,10 +33,9 @@ Soft386GetPageTableEntry(PSOFT386_STATE State, /* PUBLIC FUNCTIONS ***********************************************************/ -inline BOOLEAN Soft386ReadMemory(PSOFT386_STATE State, - INT SegmentReg, + SOFT386_SEG_REGS SegmentReg, ULONG Offset, BOOLEAN InstFetch, PVOID Buffer, @@ -184,10 +174,9 @@ Soft386ReadMemory(PSOFT386_STATE State, return TRUE; } -inline BOOLEAN Soft386WriteMemory(PSOFT386_STATE State, - INT SegmentReg, + SOFT386_SEG_REGS SegmentReg, ULONG Offset, PVOID Buffer, ULONG Size) @@ -321,334 +310,6 @@ Soft386WriteMemory(PSOFT386_STATE State, return TRUE; } -inline -BOOLEAN -Soft386StackPush(PSOFT386_STATE State, ULONG Value) -{ - BOOLEAN Size = State->SegmentRegs[SOFT386_REG_SS].Size; - - /* The OPSIZE prefix toggles the size */ - if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE) Size = !Size; - - if (Size) - { - /* 32-bit size */ - - /* Check if ESP is between 1 and 3 */ - if (State->GeneralRegs[SOFT386_REG_ESP].Long >= 1 - && State->GeneralRegs[SOFT386_REG_ESP].Long <= 3) - { - Soft386Exception(State, SOFT386_EXCEPTION_SS); - return FALSE; - } - - /* Subtract ESP by 4 */ - State->GeneralRegs[SOFT386_REG_ESP].Long -= 4; - - /* Store the value in SS:ESP */ - return Soft386WriteMemory(State, - SOFT386_REG_SS, - State->GeneralRegs[SOFT386_REG_ESP].Long, - &Value, - sizeof(ULONG)); - } - else - { - /* 16-bit size */ - USHORT ShortValue = LOWORD(Value); - - /* Check if SP is 1 */ - if (State->GeneralRegs[SOFT386_REG_ESP].Long == 1) - { - Soft386Exception(State, SOFT386_EXCEPTION_SS); - return FALSE; - } - - /* Subtract SP by 2 */ - State->GeneralRegs[SOFT386_REG_ESP].LowWord -= 2; - - /* Store the value in SS:SP */ - return Soft386WriteMemory(State, - SOFT386_REG_SS, - State->GeneralRegs[SOFT386_REG_ESP].LowWord, - &ShortValue, - sizeof(USHORT)); - } -} - -inline -BOOLEAN -Soft386StackPop(PSOFT386_STATE State, PULONG Value) -{ - ULONG LongValue; - USHORT ShortValue; - BOOLEAN Size = State->SegmentRegs[SOFT386_REG_SS].Size; - - /* The OPSIZE prefix toggles the size */ - if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE) Size = !Size; - - if (Size) - { - /* 32-bit size */ - - /* Check if ESP is 0xFFFFFFFF */ - if (State->GeneralRegs[SOFT386_REG_ESP].Long == 0xFFFFFFFF) - { - Soft386Exception(State, SOFT386_EXCEPTION_SS); - return FALSE; - } - - /* Read the value from SS:ESP */ - if (!Soft386ReadMemory(State, - SOFT386_REG_SS, - State->GeneralRegs[SOFT386_REG_ESP].Long, - FALSE, - &LongValue, - sizeof(LongValue))) - { - /* An exception occurred */ - return FALSE; - } - - /* Increment ESP by 4 */ - State->GeneralRegs[SOFT386_REG_ESP].Long += 4; - - /* Store the value in the result */ - *Value = LongValue; - } - else - { - /* 16-bit size */ - - /* Check if SP is 0xFFFF */ - if (State->GeneralRegs[SOFT386_REG_ESP].LowWord == 0xFFFF) - { - Soft386Exception(State, SOFT386_EXCEPTION_SS); - return FALSE; - } - - /* Read the value from SS:SP */ - if (!Soft386ReadMemory(State, - SOFT386_REG_SS, - State->GeneralRegs[SOFT386_REG_ESP].LowWord, - FALSE, - &ShortValue, - sizeof(ShortValue))) - { - /* An exception occurred */ - return FALSE; - } - - /* Increment SP by 2 */ - State->GeneralRegs[SOFT386_REG_ESP].Long += 2; - - /* Store the value in the result */ - *Value = ShortValue; - } - - return TRUE; -} - -inline -BOOLEAN -Soft386LoadSegment(PSOFT386_STATE State, INT Segment, USHORT Selector) -{ - PSOFT386_SEG_REG CachedDescriptor; - SOFT386_GDT_ENTRY GdtEntry; - - ASSERT(Segment < SOFT386_NUM_SEG_REGS); - - /* Get the cached descriptor */ - CachedDescriptor = &State->SegmentRegs[Segment]; - - /* Check for protected mode */ - if (State->ControlRegisters[SOFT386_REG_CR0] & SOFT386_CR0_PE) - { - /* Make sure the GDT contains the entry */ - if (GET_SEGMENT_INDEX(Selector) >= (State->Gdtr.Size + 1)) - { - Soft386Exception(State, SOFT386_EXCEPTION_GP); - return FALSE; - } - - /* Read the GDT */ - // FIXME: This code is only correct when paging is disabled!!! - if (State->MemReadCallback) - { - State->MemReadCallback(State, - State->Gdtr.Address - + GET_SEGMENT_INDEX(Selector), - &GdtEntry, - sizeof(GdtEntry)); - } - else - { - RtlMoveMemory(&GdtEntry, - (PVOID)(State->Gdtr.Address - + GET_SEGMENT_INDEX(Selector)), - sizeof(GdtEntry)); - } - - /* Check if we are loading SS */ - if (Segment == SOFT386_REG_SS) - { - if (GET_SEGMENT_INDEX(Selector) == 0) - { - Soft386Exception(State, SOFT386_EXCEPTION_GP); - return FALSE; - } - - if (GdtEntry.Executable || !GdtEntry.ReadWrite) - { - Soft386Exception(State, SOFT386_EXCEPTION_GP); - return FALSE; - } - - if ((GET_SEGMENT_RPL(Selector) != Soft386GetCurrentPrivLevel(State)) - || (GET_SEGMENT_RPL(Selector) != GdtEntry.Dpl)) - { - Soft386Exception(State, SOFT386_EXCEPTION_GP); - return FALSE; - } - - if (!GdtEntry.Present) - { - Soft386Exception(State, SOFT386_EXCEPTION_SS); - return FALSE; - } - } - else - { - if ((GET_SEGMENT_RPL(Selector) > GdtEntry.Dpl) - && (Soft386GetCurrentPrivLevel(State) > GdtEntry.Dpl)) - { - Soft386Exception(State, SOFT386_EXCEPTION_GP); - return FALSE; - } - - if (!GdtEntry.Present) - { - Soft386Exception(State, SOFT386_EXCEPTION_NP); - return FALSE; - } - } - - /* Update the cache entry */ - CachedDescriptor->Selector = Selector; - CachedDescriptor->Base = GdtEntry.Base | (GdtEntry.BaseHigh << 24); - CachedDescriptor->Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16); - CachedDescriptor->Accessed = GdtEntry.Accessed; - CachedDescriptor->ReadWrite = GdtEntry.ReadWrite; - CachedDescriptor->DirConf = GdtEntry.DirConf; - CachedDescriptor->Executable = GdtEntry.Executable; - CachedDescriptor->SystemType = GdtEntry.SystemType; - CachedDescriptor->Dpl = GdtEntry.Dpl; - CachedDescriptor->Present = GdtEntry.Present; - CachedDescriptor->Size = GdtEntry.Size; - - /* Check for page granularity */ - if (GdtEntry.Granularity) CachedDescriptor->Limit <<= 12; - } - else - { - /* Update the selector and base */ - CachedDescriptor->Selector = Selector; - CachedDescriptor->Base = Selector << 4; - } - - return TRUE; -} - -inline -BOOLEAN -Soft386FetchByte(PSOFT386_STATE State, PUCHAR Data) -{ - PSOFT386_SEG_REG CachedDescriptor; - - /* Get the cached descriptor of CS */ - CachedDescriptor = &State->SegmentRegs[SOFT386_REG_CS]; - - /* Read from memory */ - if (!Soft386ReadMemory(State, - SOFT386_REG_CS, - (CachedDescriptor->Size) ? State->InstPtr.Long - : State->InstPtr.LowWord, - TRUE, - Data, - sizeof(UCHAR))) - { - /* Exception occurred during instruction fetch */ - return FALSE; - } - - /* Advance the instruction pointer */ - if (CachedDescriptor->Size) State->InstPtr.Long++; - else State->InstPtr.LowWord++; - - return TRUE; -} - -inline -BOOLEAN -Soft386FetchWord(PSOFT386_STATE State, PUSHORT Data) -{ - PSOFT386_SEG_REG CachedDescriptor; - - /* Get the cached descriptor of CS */ - CachedDescriptor = &State->SegmentRegs[SOFT386_REG_CS]; - - /* Read from memory */ - // FIXME: Fix byte order on big-endian machines - if (!Soft386ReadMemory(State, - SOFT386_REG_CS, - (CachedDescriptor->Size) ? State->InstPtr.Long - : State->InstPtr.LowWord, - TRUE, - Data, - sizeof(USHORT))) - { - /* Exception occurred during instruction fetch */ - return FALSE; - } - - /* Advance the instruction pointer */ - if (CachedDescriptor->Size) State->InstPtr.Long += sizeof(USHORT); - else State->InstPtr.LowWord += sizeof(USHORT); - - return TRUE; -} - -inline -BOOLEAN -Soft386FetchDword(PSOFT386_STATE State, PULONG Data) -{ - PSOFT386_SEG_REG CachedDescriptor; - - /* Get the cached descriptor of CS */ - CachedDescriptor = &State->SegmentRegs[SOFT386_REG_CS]; - - /* Read from memory */ - // FIXME: Fix byte order on big-endian machines - if (!Soft386ReadMemory(State, - SOFT386_REG_CS, - (CachedDescriptor->Size) ? State->InstPtr.Long - : State->InstPtr.LowWord, - TRUE, - Data, - sizeof(ULONG))) - { - /* Exception occurred during instruction fetch */ - return FALSE; - } - - /* Advance the instruction pointer */ - if (CachedDescriptor->Size) State->InstPtr.Long += sizeof(ULONG); - else State->InstPtr.LowWord += sizeof(ULONG); - - return TRUE; -} - -inline BOOLEAN Soft386InterruptInternal(PSOFT386_STATE State, USHORT SegmentSelector, @@ -769,77 +430,11 @@ Soft386InterruptInternal(PSOFT386_STATE State, return TRUE; } -inline -BOOLEAN -Soft386GetIntVector(PSOFT386_STATE State, - UCHAR Number, - PSOFT386_IDT_ENTRY IdtEntry) -{ - ULONG FarPointer; - - /* Check for protected mode */ - if (State->ControlRegisters[SOFT386_REG_CR0] & SOFT386_CR0_PE) - { - /* Read from the IDT */ - // FIXME: This code is only correct when paging is disabled!!! - if (State->MemReadCallback) - { - State->MemReadCallback(State, - State->Idtr.Address - + Number * sizeof(*IdtEntry), - IdtEntry, - sizeof(*IdtEntry)); - } - else - { - RtlMoveMemory(IdtEntry, - (PVOID)(State->Idtr.Address - + Number * sizeof(*IdtEntry)), - sizeof(*IdtEntry)); - } - } - else - { - /* Read from the real-mode IVT */ - - /* Paging is always disabled in real mode */ - if (State->MemReadCallback) - { - State->MemReadCallback(State, - State->Idtr.Address - + Number * sizeof(FarPointer), - &FarPointer, - sizeof(FarPointer)); - } - else - { - RtlMoveMemory(IdtEntry, - (PVOID)(State->Idtr.Address - + Number * sizeof(FarPointer)), - sizeof(FarPointer)); - } - - /* Fill a fake IDT entry */ - IdtEntry->Offset = LOWORD(FarPointer); - IdtEntry->Selector = HIWORD(FarPointer); - IdtEntry->Zero = 0; - IdtEntry->Type = SOFT386_IDT_INT_GATE; - IdtEntry->Storage = FALSE; - IdtEntry->Dpl = 0; - IdtEntry->Present = TRUE; - IdtEntry->OffsetHigh = 0; - } - - /* - * Once paging support is implemented this function - * will not always return true - */ - return TRUE; -} - VOID FASTCALL -Soft386ExceptionWithErrorCode(PSOFT386_STATE State, INT ExceptionCode, ULONG ErrorCode) +Soft386ExceptionWithErrorCode(PSOFT386_STATE State, + INT ExceptionCode, + ULONG ErrorCode) { SOFT386_IDT_ENTRY IdtEntry; @@ -890,545 +485,4 @@ Soft386ExceptionWithErrorCode(PSOFT386_STATE State, INT ExceptionCode, ULONG Err } } -inline -VOID -Soft386Exception(PSOFT386_STATE State, INT ExceptionCode) -{ - /* Call the internal function */ - Soft386ExceptionWithErrorCode(State, ExceptionCode, 0); -} - -inline -BOOLEAN -Soft386CalculateParity(UCHAR Number) -{ - Number ^= Number >> 1; - Number ^= Number >> 2; - Number ^= Number >> 4; - return !(Number & 1); -} - -inline -BOOLEAN -Soft386ParseModRegRm(PSOFT386_STATE State, - BOOLEAN AddressSize, - PSOFT386_MOD_REG_RM ModRegRm) -{ - UCHAR ModRmByte, Mode, RegMem; - - /* Fetch the MOD REG R/M byte */ - if (!Soft386FetchByte(State, &ModRmByte)) - { - /* Exception occurred */ - return FALSE; - } - - /* Unpack the mode and R/M */ - Mode = ModRmByte >> 6; - RegMem = ModRmByte & 0x07; - - /* Set the register operand */ - ModRegRm->Register = (ModRmByte >> 3) & 0x07; - - /* Check the mode */ - if ((ModRmByte >> 6) == 3) - { - /* The second operand is also a register */ - ModRegRm->Memory = FALSE; - ModRegRm->SecondRegister = RegMem; - - /* Done parsing */ - return TRUE; - } - - /* The second operand is memory */ - ModRegRm->Memory = TRUE; - - if (AddressSize) - { - if (RegMem == SOFT386_REG_ESP) - { - UCHAR SibByte; - ULONG Scale, Index, Base; - - /* Fetch the SIB byte */ - if (!Soft386FetchByte(State, &SibByte)) - { - /* Exception occurred */ - return FALSE; - } - - /* Unpack the scale, index and base */ - Scale = 1 << (SibByte >> 6); - Index = (SibByte >> 3) & 0x07; - if (Index != SOFT386_REG_ESP) Index = State->GeneralRegs[Index].Long; - else Index = 0; - Base = State->GeneralRegs[SibByte & 0x07].Long; - - /* Calculate the address */ - ModRegRm->MemoryAddress = Base + Index * Scale; - } - else if (RegMem == SOFT386_REG_EBP) - { - if (Mode) ModRegRm->MemoryAddress = State->GeneralRegs[SOFT386_REG_EBP].Long; - else ModRegRm->MemoryAddress = 0; - } - else - { - /* Get the base from the register */ - ModRegRm->MemoryAddress = State->GeneralRegs[RegMem].Long; - } - - /* Check if there is no segment override */ - if (!(State->PrefixFlags & SOFT386_PREFIX_SEG)) - { - /* Check if the default segment should be SS */ - if ((RegMem == SOFT386_REG_EBP) && Mode) - { - /* Add a SS: prefix */ - State->PrefixFlags |= SOFT386_PREFIX_SEG; - State->SegmentOverride = SOFT386_REG_SS; - } - } - - if (Mode == 1) - { - CHAR Offset; - - /* Fetch the byte */ - if (!Soft386FetchByte(State, (PUCHAR)&Offset)) - { - /* Exception occurred */ - return FALSE; - } - - /* Add the signed offset to the address */ - ModRegRm->MemoryAddress += (LONG)Offset; - } - else if ((Mode == 2) || ((Mode == 0) && (RegMem == SOFT386_REG_EBP))) - { - LONG Offset; - - /* Fetch the dword */ - if (!Soft386FetchDword(State, (PULONG)&Offset)) - { - /* Exception occurred */ - return FALSE; - } - - /* Add the signed offset to the address */ - ModRegRm->MemoryAddress += Offset; - } - } - else - { - /* Check the operand */ - switch (RegMem) - { - case 0: - case 2: - { - /* (SS:)[BX + SI] */ - ModRegRm->MemoryAddress = State->GeneralRegs[SOFT386_REG_EBX].LowWord - + State->GeneralRegs[SOFT386_REG_ESI].LowWord; - - break; - } - - case 1: - case 3: - { - /* (SS:)[BX + DI] */ - ModRegRm->MemoryAddress = State->GeneralRegs[SOFT386_REG_EBX].LowWord - + State->GeneralRegs[SOFT386_REG_EDI].LowWord; - - break; - } - - case 4: - { - /* [SI] */ - ModRegRm->MemoryAddress = State->GeneralRegs[SOFT386_REG_ESI].LowWord; - - break; - } - - case 5: - { - /* [DI] */ - ModRegRm->MemoryAddress = State->GeneralRegs[SOFT386_REG_EDI].LowWord; - - break; - } - - case 6: - { - if (Mode) - { - /* [BP] */ - ModRegRm->MemoryAddress = State->GeneralRegs[SOFT386_REG_EBP].LowWord; - } - else - { - /* [constant] (added later) */ - ModRegRm->MemoryAddress = 0; - } - - break; - } - - case 7: - { - /* [BX] */ - ModRegRm->MemoryAddress = State->GeneralRegs[SOFT386_REG_EBX].LowWord; - - break; - } - } - - /* Check if there is no segment override */ - if (!(State->PrefixFlags & SOFT386_PREFIX_SEG)) - { - /* Check if the default segment should be SS */ - if ((RegMem == 2) || (RegMem == 3) || ((RegMem == 6) && Mode)) - { - /* Add a SS: prefix */ - State->PrefixFlags |= SOFT386_PREFIX_SEG; - State->SegmentOverride = SOFT386_REG_SS; - } - } - - if (Mode == 1) - { - CHAR Offset; - - /* Fetch the byte */ - if (!Soft386FetchByte(State, (PUCHAR)&Offset)) - { - /* Exception occurred */ - return FALSE; - } - - /* Add the signed offset to the address */ - ModRegRm->MemoryAddress += (LONG)Offset; - } - else if ((Mode == 2) || ((Mode == 0) && (RegMem == 6))) - { - SHORT Offset; - - /* Fetch the word */ - if (!Soft386FetchWord(State, (PUSHORT)&Offset)) - { - /* Exception occurred */ - return FALSE; - } - - /* Add the signed offset to the address */ - ModRegRm->MemoryAddress += (LONG)Offset; - } - } - - return TRUE; -} - -inline -BOOLEAN -Soft386ReadModrmByteOperands(PSOFT386_STATE State, - PSOFT386_MOD_REG_RM ModRegRm, - PUCHAR RegValue, - PUCHAR RmValue) -{ - INT Segment = SOFT386_REG_DS; - - /* Get the register value */ - if (ModRegRm->Register & 0x04) - { - /* AH, CH, DH, BH */ - *RegValue = State->GeneralRegs[ModRegRm->Register & 0x03].HighByte; - } - else - { - /* AL, CL, DL, BL */ - *RegValue = State->GeneralRegs[ModRegRm->Register & 0x03].LowByte; - } - - if (!ModRegRm->Memory) - { - /* Get the second register value */ - if (ModRegRm->SecondRegister & 0x04) - { - /* AH, CH, DH, BH */ - *RmValue = State->GeneralRegs[ModRegRm->SecondRegister & 0x03].HighByte; - } - else - { - /* AL, CL, DL, BL */ - *RmValue = State->GeneralRegs[ModRegRm->SecondRegister & 0x03].LowByte; - } - } - else - { - /* Check for the segment override */ - if (State->PrefixFlags & SOFT386_PREFIX_SEG) - { - /* Use the override segment instead */ - Segment = State->SegmentOverride; - } - - /* Read memory */ - if (!Soft386ReadMemory(State, - Segment, - ModRegRm->MemoryAddress, - FALSE, - RmValue, - sizeof(UCHAR))) - { - /* Exception occurred */ - return FALSE; - } - } - - return TRUE; -} - -inline -BOOLEAN -Soft386ReadModrmWordOperands(PSOFT386_STATE State, - PSOFT386_MOD_REG_RM ModRegRm, - PUSHORT RegValue, - PUSHORT RmValue) -{ - INT Segment = SOFT386_REG_DS; - - /* Get the register value */ - *RegValue = State->GeneralRegs[ModRegRm->Register].LowWord; - - if (!ModRegRm->Memory) - { - /* Get the second register value */ - *RmValue = State->GeneralRegs[ModRegRm->SecondRegister].LowWord; - } - else - { - /* Check for the segment override */ - if (State->PrefixFlags & SOFT386_PREFIX_SEG) - { - /* Use the override segment instead */ - Segment = State->SegmentOverride; - } - - /* Read memory */ - if (!Soft386ReadMemory(State, - Segment, - ModRegRm->MemoryAddress, - FALSE, - RmValue, - sizeof(USHORT))) - { - /* Exception occurred */ - return FALSE; - } - } - - return TRUE; -} - -inline -BOOLEAN -Soft386ReadModrmDwordOperands(PSOFT386_STATE State, - PSOFT386_MOD_REG_RM ModRegRm, - PULONG RegValue, - PULONG RmValue) -{ - INT Segment = SOFT386_REG_DS; - - /* Get the register value */ - *RegValue = State->GeneralRegs[ModRegRm->Register].Long; - - if (!ModRegRm->Memory) - { - /* Get the second register value */ - *RmValue = State->GeneralRegs[ModRegRm->SecondRegister].Long; - } - else - { - /* Check for the segment override */ - if (State->PrefixFlags & SOFT386_PREFIX_SEG) - { - /* Use the override segment instead */ - Segment = State->SegmentOverride; - } - - /* Read memory */ - if (!Soft386ReadMemory(State, - Segment, - ModRegRm->MemoryAddress, - FALSE, - RmValue, - sizeof(ULONG))) - { - /* Exception occurred */ - return FALSE; - } - } - - return TRUE; -} - -inline -BOOLEAN -Soft386WriteModrmByteOperands(PSOFT386_STATE State, - PSOFT386_MOD_REG_RM ModRegRm, - BOOLEAN WriteRegister, - UCHAR Value) -{ - INT Segment = SOFT386_REG_DS; - - if (WriteRegister) - { - /* Store the value in the register */ - if (ModRegRm->Register & 0x04) - { - /* AH, CH, DH, BH */ - State->GeneralRegs[ModRegRm->Register & 0x03].HighByte = Value; - } - else - { - /* AL, CL, DL, BL */ - State->GeneralRegs[ModRegRm->Register & 0x03].LowByte = Value; - } - } - else - { - if (!ModRegRm->Memory) - { - /* Store the value in the second register */ - if (ModRegRm->SecondRegister & 0x04) - { - /* AH, CH, DH, BH */ - State->GeneralRegs[ModRegRm->SecondRegister & 0x03].HighByte = Value; - } - else - { - /* AL, CL, DL, BL */ - State->GeneralRegs[ModRegRm->SecondRegister & 0x03].LowByte = Value; - } - } - else - { - /* Check for the segment override */ - if (State->PrefixFlags & SOFT386_PREFIX_SEG) - { - /* Use the override segment instead */ - Segment = State->SegmentOverride; - } - - /* Write memory */ - if (!Soft386WriteMemory(State, - Segment, - ModRegRm->MemoryAddress, - &Value, - sizeof(UCHAR))) - { - /* Exception occurred */ - return FALSE; - } - } - } - - return TRUE; -} - -inline -BOOLEAN -Soft386WriteModrmWordOperands(PSOFT386_STATE State, - PSOFT386_MOD_REG_RM ModRegRm, - BOOLEAN WriteRegister, - USHORT Value) -{ - INT Segment = SOFT386_REG_DS; - - if (WriteRegister) - { - /* Store the value in the register */ - State->GeneralRegs[ModRegRm->Register].LowWord = Value; - } - else - { - if (!ModRegRm->Memory) - { - /* Store the value in the second register */ - State->GeneralRegs[ModRegRm->SecondRegister].LowWord = Value; - } - else - { - /* Check for the segment override */ - if (State->PrefixFlags & SOFT386_PREFIX_SEG) - { - /* Use the override segment instead */ - Segment = State->SegmentOverride; - } - - /* Write memory */ - if (!Soft386WriteMemory(State, - Segment, - ModRegRm->MemoryAddress, - &Value, - sizeof(USHORT))) - { - /* Exception occurred */ - return FALSE; - } - } - } - - return TRUE; -} - -inline -BOOLEAN -Soft386WriteModrmDwordOperands(PSOFT386_STATE State, - PSOFT386_MOD_REG_RM ModRegRm, - BOOLEAN WriteRegister, - ULONG Value) -{ - INT Segment = SOFT386_REG_DS; - - if (WriteRegister) - { - /* Store the value in the register */ - State->GeneralRegs[ModRegRm->Register].Long = Value; - } - else - { - if (!ModRegRm->Memory) - { - /* Store the value in the second register */ - State->GeneralRegs[ModRegRm->SecondRegister].Long = Value; - } - else - { - /* Check for the segment override */ - if (State->PrefixFlags & SOFT386_PREFIX_SEG) - { - /* Use the override segment instead */ - Segment = State->SegmentOverride; - } - - /* Write memory */ - if (!Soft386WriteMemory(State, - Segment, - ModRegRm->MemoryAddress, - &Value, - sizeof(ULONG))) - { - /* Exception occurred */ - return FALSE; - } - } - } - - return TRUE; -} - /* EOF */ diff --git a/lib/soft386/common.h b/lib/soft386/common.h index 9c3e8189125..8e1697838a7 100644 --- a/lib/soft386/common.h +++ b/lib/soft386/common.h @@ -32,11 +32,11 @@ typedef struct _SOFT386_MOD_REG_RM { - INT Register; + SOFT386_GEN_REGS Register; BOOLEAN Memory; union { - INT SecondRegister; + SOFT386_GEN_REGS SecondRegister; ULONG MemoryAddress; }; } SOFT386_MOD_REG_RM, *PSOFT386_MOD_REG_RM; @@ -84,79 +84,27 @@ typedef union _SOFT386_PAGE_TABLE /* FUNCTIONS ******************************************************************/ -inline BOOLEAN Soft386ReadMemory ( PSOFT386_STATE State, - INT SegmentReg, + SOFT386_SEG_REGS SegmentReg, ULONG Offset, BOOLEAN InstFetch, PVOID Buffer, ULONG Size ); -inline BOOLEAN Soft386WriteMemory ( PSOFT386_STATE State, - INT SegmentReg, + SOFT386_SEG_REGS SegmentReg, ULONG Offset, PVOID Buffer, ULONG Size ); -inline -BOOLEAN -Soft386StackPush -( - PSOFT386_STATE State, - ULONG Value -); - -inline -BOOLEAN -Soft386StackPop -( - PSOFT386_STATE State, - PULONG Value -); - -inline -BOOLEAN -Soft386LoadSegment -( - PSOFT386_STATE State, - INT Segment, - USHORT Selector -); - -inline -BOOLEAN -Soft386FetchByte -( - PSOFT386_STATE State, - PUCHAR Data -); - -inline -BOOLEAN -Soft386FetchWord -( - PSOFT386_STATE State, - PUSHORT Data -); - -inline -BOOLEAN -Soft386FetchDword -( - PSOFT386_STATE State, - PULONG Data -); - -inline BOOLEAN Soft386InterruptInternal ( @@ -166,15 +114,6 @@ Soft386InterruptInternal BOOLEAN InterruptGate ); -inline -BOOLEAN -Soft386GetIntVector -( - PSOFT386_STATE State, - UCHAR Number, - PSOFT386_IDT_ENTRY IdtEntry -); - VOID FASTCALL Soft386ExceptionWithErrorCode @@ -184,89 +123,16 @@ Soft386ExceptionWithErrorCode ULONG ErrorCode ); -inline -VOID -Soft386Exception -( - PSOFT386_STATE State, - INT ExceptionCode -); +/* INLINED FUNCTIONS **********************************************************/ -inline -BOOLEAN -Soft386CalculateParity -( - UCHAR Number -); +/* static */ FORCEINLINE +INT +Soft386GetCurrentPrivLevel(PSOFT386_STATE State) +{ + return GET_SEGMENT_RPL(State->SegmentRegs[SOFT386_REG_CS].Selector); +} -inline -BOOLEAN -Soft386ParseModRegRm -( - PSOFT386_STATE State, - BOOLEAN AddressSize, - PSOFT386_MOD_REG_RM ModRegRm -); - -inline -BOOLEAN -Soft386ReadModrmByteOperands -( - PSOFT386_STATE State, - PSOFT386_MOD_REG_RM ModRegRm, - PUCHAR RegValue, - PUCHAR RmValue -); - -inline -BOOLEAN -Soft386ReadModrmWordOperands -( - PSOFT386_STATE State, - PSOFT386_MOD_REG_RM ModRegRm, - PUSHORT RegValue, - PUSHORT RmValue -); - -inline -BOOLEAN -Soft386ReadModrmDwordOperands -( - PSOFT386_STATE State, - PSOFT386_MOD_REG_RM ModRegRm, - PULONG RegValue, - PULONG RmValue -); - -inline -BOOLEAN -Soft386WriteModrmByteOperands -( - PSOFT386_STATE State, - PSOFT386_MOD_REG_RM ModRegRm, - BOOLEAN WriteRegister, - UCHAR Value -); - -inline -BOOLEAN -Soft386WriteModrmWordOperands -( - PSOFT386_STATE State, - PSOFT386_MOD_REG_RM ModRegRm, - BOOLEAN WriteRegister, - USHORT Value -); - -inline -BOOLEAN -Soft386WriteModrmDwordOperands -( - PSOFT386_STATE State, - PSOFT386_MOD_REG_RM ModRegRm, - BOOLEAN WriteRegister, - ULONG Value -); +#include "common.inl" #endif // _COMMON_H_ diff --git a/lib/soft386/common.inl b/lib/soft386/common.inl new file mode 100644 index 00000000000..b09ea1f6253 --- /dev/null +++ b/lib/soft386/common.inl @@ -0,0 +1,955 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: 386/486 CPU Emulation Library + * FILE: common.inl + * PURPOSE: Common functions used internally by Soft386 (inlined funtions). + * PROGRAMMERS: Aleksandar Andrejevic + */ + +/* PUBLIC FUNCTIONS ***********************************************************/ + +FORCEINLINE +VOID +Soft386Exception(PSOFT386_STATE State, + INT ExceptionCode) +{ + /* Call the internal function */ + Soft386ExceptionWithErrorCode(State, ExceptionCode, 0); +} + +FORCEINLINE +BOOLEAN +Soft386StackPush(PSOFT386_STATE State, + ULONG Value) +{ + BOOLEAN Size = State->SegmentRegs[SOFT386_REG_SS].Size; + + /* The OPSIZE prefix toggles the size */ + if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE) Size = !Size; + + if (Size) + { + /* 32-bit size */ + + /* Check if ESP is between 1 and 3 */ + if (State->GeneralRegs[SOFT386_REG_ESP].Long >= 1 + && State->GeneralRegs[SOFT386_REG_ESP].Long <= 3) + { + Soft386Exception(State, SOFT386_EXCEPTION_SS); + return FALSE; + } + + /* Subtract ESP by 4 */ + State->GeneralRegs[SOFT386_REG_ESP].Long -= 4; + + /* Store the value in SS:ESP */ + return Soft386WriteMemory(State, + SOFT386_REG_SS, + State->GeneralRegs[SOFT386_REG_ESP].Long, + &Value, + sizeof(ULONG)); + } + else + { + /* 16-bit size */ + USHORT ShortValue = LOWORD(Value); + + /* Check if SP is 1 */ + if (State->GeneralRegs[SOFT386_REG_ESP].Long == 1) + { + Soft386Exception(State, SOFT386_EXCEPTION_SS); + return FALSE; + } + + /* Subtract SP by 2 */ + State->GeneralRegs[SOFT386_REG_ESP].LowWord -= 2; + + /* Store the value in SS:SP */ + return Soft386WriteMemory(State, + SOFT386_REG_SS, + State->GeneralRegs[SOFT386_REG_ESP].LowWord, + &ShortValue, + sizeof(USHORT)); + } +} + +FORCEINLINE +BOOLEAN +Soft386StackPop(PSOFT386_STATE State, + PULONG Value) +{ + ULONG LongValue; + USHORT ShortValue; + BOOLEAN Size = State->SegmentRegs[SOFT386_REG_SS].Size; + + /* The OPSIZE prefix toggles the size */ + if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE) Size = !Size; + + if (Size) + { + /* 32-bit size */ + + /* Check if ESP is 0xFFFFFFFF */ + if (State->GeneralRegs[SOFT386_REG_ESP].Long == 0xFFFFFFFF) + { + Soft386Exception(State, SOFT386_EXCEPTION_SS); + return FALSE; + } + + /* Read the value from SS:ESP */ + if (!Soft386ReadMemory(State, + SOFT386_REG_SS, + State->GeneralRegs[SOFT386_REG_ESP].Long, + FALSE, + &LongValue, + sizeof(LongValue))) + { + /* An exception occurred */ + return FALSE; + } + + /* Increment ESP by 4 */ + State->GeneralRegs[SOFT386_REG_ESP].Long += 4; + + /* Store the value in the result */ + *Value = LongValue; + } + else + { + /* 16-bit size */ + + /* Check if SP is 0xFFFF */ + if (State->GeneralRegs[SOFT386_REG_ESP].LowWord == 0xFFFF) + { + Soft386Exception(State, SOFT386_EXCEPTION_SS); + return FALSE; + } + + /* Read the value from SS:SP */ + if (!Soft386ReadMemory(State, + SOFT386_REG_SS, + State->GeneralRegs[SOFT386_REG_ESP].LowWord, + FALSE, + &ShortValue, + sizeof(ShortValue))) + { + /* An exception occurred */ + return FALSE; + } + + /* Increment SP by 2 */ + State->GeneralRegs[SOFT386_REG_ESP].Long += 2; + + /* Store the value in the result */ + *Value = ShortValue; + } + + return TRUE; +} + +FORCEINLINE +BOOLEAN +Soft386LoadSegment(PSOFT386_STATE State, + INT Segment, + USHORT Selector) +{ + PSOFT386_SEG_REG CachedDescriptor; + SOFT386_GDT_ENTRY GdtEntry; + + ASSERT(Segment < SOFT386_NUM_SEG_REGS); + + /* Get the cached descriptor */ + CachedDescriptor = &State->SegmentRegs[Segment]; + + /* Check for protected mode */ + if (State->ControlRegisters[SOFT386_REG_CR0] & SOFT386_CR0_PE) + { + /* Make sure the GDT contains the entry */ + if (GET_SEGMENT_INDEX(Selector) >= (State->Gdtr.Size + 1)) + { + Soft386Exception(State, SOFT386_EXCEPTION_GP); + return FALSE; + } + + /* Read the GDT */ + // FIXME: This code is only correct when paging is disabled!!! + if (State->MemReadCallback) + { + State->MemReadCallback(State, + State->Gdtr.Address + + GET_SEGMENT_INDEX(Selector), + &GdtEntry, + sizeof(GdtEntry)); + } + else + { + RtlMoveMemory(&GdtEntry, + (PVOID)(State->Gdtr.Address + + GET_SEGMENT_INDEX(Selector)), + sizeof(GdtEntry)); + } + + /* Check if we are loading SS */ + if (Segment == SOFT386_REG_SS) + { + if (GET_SEGMENT_INDEX(Selector) == 0) + { + Soft386Exception(State, SOFT386_EXCEPTION_GP); + return FALSE; + } + + if (GdtEntry.Executable || !GdtEntry.ReadWrite) + { + Soft386Exception(State, SOFT386_EXCEPTION_GP); + return FALSE; + } + + if ((GET_SEGMENT_RPL(Selector) != Soft386GetCurrentPrivLevel(State)) + || (GET_SEGMENT_RPL(Selector) != GdtEntry.Dpl)) + { + Soft386Exception(State, SOFT386_EXCEPTION_GP); + return FALSE; + } + + if (!GdtEntry.Present) + { + Soft386Exception(State, SOFT386_EXCEPTION_SS); + return FALSE; + } + } + else + { + if ((GET_SEGMENT_RPL(Selector) > GdtEntry.Dpl) + && (Soft386GetCurrentPrivLevel(State) > GdtEntry.Dpl)) + { + Soft386Exception(State, SOFT386_EXCEPTION_GP); + return FALSE; + } + + if (!GdtEntry.Present) + { + Soft386Exception(State, SOFT386_EXCEPTION_NP); + return FALSE; + } + } + + /* Update the cache entry */ + CachedDescriptor->Selector = Selector; + CachedDescriptor->Base = GdtEntry.Base | (GdtEntry.BaseHigh << 24); + CachedDescriptor->Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16); + CachedDescriptor->Accessed = GdtEntry.Accessed; + CachedDescriptor->ReadWrite = GdtEntry.ReadWrite; + CachedDescriptor->DirConf = GdtEntry.DirConf; + CachedDescriptor->Executable = GdtEntry.Executable; + CachedDescriptor->SystemType = GdtEntry.SystemType; + CachedDescriptor->Dpl = GdtEntry.Dpl; + CachedDescriptor->Present = GdtEntry.Present; + CachedDescriptor->Size = GdtEntry.Size; + + /* Check for page granularity */ + if (GdtEntry.Granularity) CachedDescriptor->Limit <<= 12; + } + else + { + /* Update the selector and base */ + CachedDescriptor->Selector = Selector; + CachedDescriptor->Base = Selector << 4; + } + + return TRUE; +} + +FORCEINLINE +BOOLEAN +Soft386FetchByte(PSOFT386_STATE State, + PUCHAR Data) +{ + PSOFT386_SEG_REG CachedDescriptor; + + /* Get the cached descriptor of CS */ + CachedDescriptor = &State->SegmentRegs[SOFT386_REG_CS]; + + /* Read from memory */ + if (!Soft386ReadMemory(State, + SOFT386_REG_CS, + (CachedDescriptor->Size) ? State->InstPtr.Long + : State->InstPtr.LowWord, + TRUE, + Data, + sizeof(UCHAR))) + { + /* Exception occurred during instruction fetch */ + return FALSE; + } + + /* Advance the instruction pointer */ + if (CachedDescriptor->Size) State->InstPtr.Long++; + else State->InstPtr.LowWord++; + + return TRUE; +} + +FORCEINLINE +BOOLEAN +Soft386FetchWord(PSOFT386_STATE State, + PUSHORT Data) +{ + PSOFT386_SEG_REG CachedDescriptor; + + /* Get the cached descriptor of CS */ + CachedDescriptor = &State->SegmentRegs[SOFT386_REG_CS]; + + /* Read from memory */ + // FIXME: Fix byte order on big-endian machines + if (!Soft386ReadMemory(State, + SOFT386_REG_CS, + (CachedDescriptor->Size) ? State->InstPtr.Long + : State->InstPtr.LowWord, + TRUE, + Data, + sizeof(USHORT))) + { + /* Exception occurred during instruction fetch */ + return FALSE; + } + + /* Advance the instruction pointer */ + if (CachedDescriptor->Size) State->InstPtr.Long += sizeof(USHORT); + else State->InstPtr.LowWord += sizeof(USHORT); + + return TRUE; +} + +FORCEINLINE +BOOLEAN +Soft386FetchDword(PSOFT386_STATE State, + PULONG Data) +{ + PSOFT386_SEG_REG CachedDescriptor; + + /* Get the cached descriptor of CS */ + CachedDescriptor = &State->SegmentRegs[SOFT386_REG_CS]; + + /* Read from memory */ + // FIXME: Fix byte order on big-endian machines + if (!Soft386ReadMemory(State, + SOFT386_REG_CS, + (CachedDescriptor->Size) ? State->InstPtr.Long + : State->InstPtr.LowWord, + TRUE, + Data, + sizeof(ULONG))) + { + /* Exception occurred during instruction fetch */ + return FALSE; + } + + /* Advance the instruction pointer */ + if (CachedDescriptor->Size) State->InstPtr.Long += sizeof(ULONG); + else State->InstPtr.LowWord += sizeof(ULONG); + + return TRUE; +} + +FORCEINLINE +BOOLEAN +Soft386GetIntVector(PSOFT386_STATE State, + UCHAR Number, + PSOFT386_IDT_ENTRY IdtEntry) +{ + ULONG FarPointer; + + /* Check for protected mode */ + if (State->ControlRegisters[SOFT386_REG_CR0] & SOFT386_CR0_PE) + { + /* Read from the IDT */ + // FIXME: This code is only correct when paging is disabled!!! + if (State->MemReadCallback) + { + State->MemReadCallback(State, + State->Idtr.Address + + Number * sizeof(*IdtEntry), + IdtEntry, + sizeof(*IdtEntry)); + } + else + { + RtlMoveMemory(IdtEntry, + (PVOID)(State->Idtr.Address + + Number * sizeof(*IdtEntry)), + sizeof(*IdtEntry)); + } + } + else + { + /* Read from the real-mode IVT */ + + /* Paging is always disabled in real mode */ + if (State->MemReadCallback) + { + State->MemReadCallback(State, + State->Idtr.Address + + Number * sizeof(FarPointer), + &FarPointer, + sizeof(FarPointer)); + } + else + { + RtlMoveMemory(IdtEntry, + (PVOID)(State->Idtr.Address + + Number * sizeof(FarPointer)), + sizeof(FarPointer)); + } + + /* Fill a fake IDT entry */ + IdtEntry->Offset = LOWORD(FarPointer); + IdtEntry->Selector = HIWORD(FarPointer); + IdtEntry->Zero = 0; + IdtEntry->Type = SOFT386_IDT_INT_GATE; + IdtEntry->Storage = FALSE; + IdtEntry->Dpl = 0; + IdtEntry->Present = TRUE; + IdtEntry->OffsetHigh = 0; + } + + /* + * Once paging support is implemented this function + * will not always return true + */ + return TRUE; +} + +FORCEINLINE +BOOLEAN +Soft386CalculateParity(UCHAR Number) +{ + Number ^= Number >> 1; + Number ^= Number >> 2; + Number ^= Number >> 4; + return !(Number & 1); +} + +FORCEINLINE +BOOLEAN +Soft386ParseModRegRm(PSOFT386_STATE State, + BOOLEAN AddressSize, + PSOFT386_MOD_REG_RM ModRegRm) +{ + UCHAR ModRmByte, Mode, RegMem; + + /* Fetch the MOD REG R/M byte */ + if (!Soft386FetchByte(State, &ModRmByte)) + { + /* Exception occurred */ + return FALSE; + } + + /* Unpack the mode and R/M */ + Mode = ModRmByte >> 6; + RegMem = ModRmByte & 0x07; + + /* Set the register operand */ + ModRegRm->Register = (ModRmByte >> 3) & 0x07; + + /* Check the mode */ + if ((ModRmByte >> 6) == 3) + { + /* The second operand is also a register */ + ModRegRm->Memory = FALSE; + ModRegRm->SecondRegister = RegMem; + + /* Done parsing */ + return TRUE; + } + + /* The second operand is memory */ + ModRegRm->Memory = TRUE; + + if (AddressSize) + { + if (RegMem == SOFT386_REG_ESP) + { + UCHAR SibByte; + ULONG Scale, Index, Base; + + /* Fetch the SIB byte */ + if (!Soft386FetchByte(State, &SibByte)) + { + /* Exception occurred */ + return FALSE; + } + + /* Unpack the scale, index and base */ + Scale = 1 << (SibByte >> 6); + Index = (SibByte >> 3) & 0x07; + if (Index != SOFT386_REG_ESP) Index = State->GeneralRegs[Index].Long; + else Index = 0; + Base = State->GeneralRegs[SibByte & 0x07].Long; + + /* Calculate the address */ + ModRegRm->MemoryAddress = Base + Index * Scale; + } + else if (RegMem == SOFT386_REG_EBP) + { + if (Mode) ModRegRm->MemoryAddress = State->GeneralRegs[SOFT386_REG_EBP].Long; + else ModRegRm->MemoryAddress = 0; + } + else + { + /* Get the base from the register */ + ModRegRm->MemoryAddress = State->GeneralRegs[RegMem].Long; + } + + /* Check if there is no segment override */ + if (!(State->PrefixFlags & SOFT386_PREFIX_SEG)) + { + /* Check if the default segment should be SS */ + if ((RegMem == SOFT386_REG_EBP) && Mode) + { + /* Add a SS: prefix */ + State->PrefixFlags |= SOFT386_PREFIX_SEG; + State->SegmentOverride = SOFT386_REG_SS; + } + } + + if (Mode == 1) + { + CHAR Offset; + + /* Fetch the byte */ + if (!Soft386FetchByte(State, (PUCHAR)&Offset)) + { + /* Exception occurred */ + return FALSE; + } + + /* Add the signed offset to the address */ + ModRegRm->MemoryAddress += (LONG)Offset; + } + else if ((Mode == 2) || ((Mode == 0) && (RegMem == SOFT386_REG_EBP))) + { + LONG Offset; + + /* Fetch the dword */ + if (!Soft386FetchDword(State, (PULONG)&Offset)) + { + /* Exception occurred */ + return FALSE; + } + + /* Add the signed offset to the address */ + ModRegRm->MemoryAddress += Offset; + } + } + else + { + /* Check the operand */ + switch (RegMem) + { + case 0: + case 2: + { + /* (SS:)[BX + SI] */ + ModRegRm->MemoryAddress = State->GeneralRegs[SOFT386_REG_EBX].LowWord + + State->GeneralRegs[SOFT386_REG_ESI].LowWord; + + break; + } + + case 1: + case 3: + { + /* (SS:)[BX + DI] */ + ModRegRm->MemoryAddress = State->GeneralRegs[SOFT386_REG_EBX].LowWord + + State->GeneralRegs[SOFT386_REG_EDI].LowWord; + + break; + } + + case 4: + { + /* [SI] */ + ModRegRm->MemoryAddress = State->GeneralRegs[SOFT386_REG_ESI].LowWord; + + break; + } + + case 5: + { + /* [DI] */ + ModRegRm->MemoryAddress = State->GeneralRegs[SOFT386_REG_EDI].LowWord; + + break; + } + + case 6: + { + if (Mode) + { + /* [BP] */ + ModRegRm->MemoryAddress = State->GeneralRegs[SOFT386_REG_EBP].LowWord; + } + else + { + /* [constant] (added later) */ + ModRegRm->MemoryAddress = 0; + } + + break; + } + + case 7: + { + /* [BX] */ + ModRegRm->MemoryAddress = State->GeneralRegs[SOFT386_REG_EBX].LowWord; + + break; + } + } + + /* Check if there is no segment override */ + if (!(State->PrefixFlags & SOFT386_PREFIX_SEG)) + { + /* Check if the default segment should be SS */ + if ((RegMem == 2) || (RegMem == 3) || ((RegMem == 6) && Mode)) + { + /* Add a SS: prefix */ + State->PrefixFlags |= SOFT386_PREFIX_SEG; + State->SegmentOverride = SOFT386_REG_SS; + } + } + + if (Mode == 1) + { + CHAR Offset; + + /* Fetch the byte */ + if (!Soft386FetchByte(State, (PUCHAR)&Offset)) + { + /* Exception occurred */ + return FALSE; + } + + /* Add the signed offset to the address */ + ModRegRm->MemoryAddress += (LONG)Offset; + } + else if ((Mode == 2) || ((Mode == 0) && (RegMem == 6))) + { + SHORT Offset; + + /* Fetch the word */ + if (!Soft386FetchWord(State, (PUSHORT)&Offset)) + { + /* Exception occurred */ + return FALSE; + } + + /* Add the signed offset to the address */ + ModRegRm->MemoryAddress += (LONG)Offset; + } + } + + return TRUE; +} + +FORCEINLINE +BOOLEAN +Soft386ReadModrmByteOperands(PSOFT386_STATE State, + PSOFT386_MOD_REG_RM ModRegRm, + PUCHAR RegValue, + PUCHAR RmValue) +{ + SOFT386_SEG_REGS Segment = SOFT386_REG_DS; + + /* Get the register value */ + if (ModRegRm->Register & 0x04) + { + /* AH, CH, DH, BH */ + *RegValue = State->GeneralRegs[ModRegRm->Register & 0x03].HighByte; + } + else + { + /* AL, CL, DL, BL */ + *RegValue = State->GeneralRegs[ModRegRm->Register & 0x03].LowByte; + } + + if (!ModRegRm->Memory) + { + /* Get the second register value */ + if (ModRegRm->SecondRegister & 0x04) + { + /* AH, CH, DH, BH */ + *RmValue = State->GeneralRegs[ModRegRm->SecondRegister & 0x03].HighByte; + } + else + { + /* AL, CL, DL, BL */ + *RmValue = State->GeneralRegs[ModRegRm->SecondRegister & 0x03].LowByte; + } + } + else + { + /* Check for the segment override */ + if (State->PrefixFlags & SOFT386_PREFIX_SEG) + { + /* Use the override segment instead */ + Segment = State->SegmentOverride; + } + + /* Read memory */ + if (!Soft386ReadMemory(State, + Segment, + ModRegRm->MemoryAddress, + FALSE, + RmValue, + sizeof(UCHAR))) + { + /* Exception occurred */ + return FALSE; + } + } + + return TRUE; +} + +FORCEINLINE +BOOLEAN +Soft386ReadModrmWordOperands(PSOFT386_STATE State, + PSOFT386_MOD_REG_RM ModRegRm, + PUSHORT RegValue, + PUSHORT RmValue) +{ + SOFT386_SEG_REGS Segment = SOFT386_REG_DS; + + /* Get the register value */ + *RegValue = State->GeneralRegs[ModRegRm->Register].LowWord; + + if (!ModRegRm->Memory) + { + /* Get the second register value */ + *RmValue = State->GeneralRegs[ModRegRm->SecondRegister].LowWord; + } + else + { + /* Check for the segment override */ + if (State->PrefixFlags & SOFT386_PREFIX_SEG) + { + /* Use the override segment instead */ + Segment = State->SegmentOverride; + } + + /* Read memory */ + if (!Soft386ReadMemory(State, + Segment, + ModRegRm->MemoryAddress, + FALSE, + RmValue, + sizeof(USHORT))) + { + /* Exception occurred */ + return FALSE; + } + } + + return TRUE; +} + +FORCEINLINE +BOOLEAN +Soft386ReadModrmDwordOperands(PSOFT386_STATE State, + PSOFT386_MOD_REG_RM ModRegRm, + PULONG RegValue, + PULONG RmValue) +{ + SOFT386_SEG_REGS Segment = SOFT386_REG_DS; + + /* Get the register value */ + *RegValue = State->GeneralRegs[ModRegRm->Register].Long; + + if (!ModRegRm->Memory) + { + /* Get the second register value */ + *RmValue = State->GeneralRegs[ModRegRm->SecondRegister].Long; + } + else + { + /* Check for the segment override */ + if (State->PrefixFlags & SOFT386_PREFIX_SEG) + { + /* Use the override segment instead */ + Segment = State->SegmentOverride; + } + + /* Read memory */ + if (!Soft386ReadMemory(State, + Segment, + ModRegRm->MemoryAddress, + FALSE, + RmValue, + sizeof(ULONG))) + { + /* Exception occurred */ + return FALSE; + } + } + + return TRUE; +} + +FORCEINLINE +BOOLEAN +Soft386WriteModrmByteOperands(PSOFT386_STATE State, + PSOFT386_MOD_REG_RM ModRegRm, + BOOLEAN WriteRegister, + UCHAR Value) +{ + SOFT386_SEG_REGS Segment = SOFT386_REG_DS; + + if (WriteRegister) + { + /* Store the value in the register */ + if (ModRegRm->Register & 0x04) + { + /* AH, CH, DH, BH */ + State->GeneralRegs[ModRegRm->Register & 0x03].HighByte = Value; + } + else + { + /* AL, CL, DL, BL */ + State->GeneralRegs[ModRegRm->Register & 0x03].LowByte = Value; + } + } + else + { + if (!ModRegRm->Memory) + { + /* Store the value in the second register */ + if (ModRegRm->SecondRegister & 0x04) + { + /* AH, CH, DH, BH */ + State->GeneralRegs[ModRegRm->SecondRegister & 0x03].HighByte = Value; + } + else + { + /* AL, CL, DL, BL */ + State->GeneralRegs[ModRegRm->SecondRegister & 0x03].LowByte = Value; + } + } + else + { + /* Check for the segment override */ + if (State->PrefixFlags & SOFT386_PREFIX_SEG) + { + /* Use the override segment instead */ + Segment = State->SegmentOverride; + } + + /* Write memory */ + if (!Soft386WriteMemory(State, + Segment, + ModRegRm->MemoryAddress, + &Value, + sizeof(UCHAR))) + { + /* Exception occurred */ + return FALSE; + } + } + } + + return TRUE; +} + +FORCEINLINE +BOOLEAN +Soft386WriteModrmWordOperands(PSOFT386_STATE State, + PSOFT386_MOD_REG_RM ModRegRm, + BOOLEAN WriteRegister, + USHORT Value) +{ + SOFT386_SEG_REGS Segment = SOFT386_REG_DS; + + if (WriteRegister) + { + /* Store the value in the register */ + State->GeneralRegs[ModRegRm->Register].LowWord = Value; + } + else + { + if (!ModRegRm->Memory) + { + /* Store the value in the second register */ + State->GeneralRegs[ModRegRm->SecondRegister].LowWord = Value; + } + else + { + /* Check for the segment override */ + if (State->PrefixFlags & SOFT386_PREFIX_SEG) + { + /* Use the override segment instead */ + Segment = State->SegmentOverride; + } + + /* Write memory */ + if (!Soft386WriteMemory(State, + Segment, + ModRegRm->MemoryAddress, + &Value, + sizeof(USHORT))) + { + /* Exception occurred */ + return FALSE; + } + } + } + + return TRUE; +} + +FORCEINLINE +BOOLEAN +Soft386WriteModrmDwordOperands(PSOFT386_STATE State, + PSOFT386_MOD_REG_RM ModRegRm, + BOOLEAN WriteRegister, + ULONG Value) +{ + SOFT386_SEG_REGS Segment = SOFT386_REG_DS; + + if (WriteRegister) + { + /* Store the value in the register */ + State->GeneralRegs[ModRegRm->Register].Long = Value; + } + else + { + if (!ModRegRm->Memory) + { + /* Store the value in the second register */ + State->GeneralRegs[ModRegRm->SecondRegister].Long = Value; + } + else + { + /* Check for the segment override */ + if (State->PrefixFlags & SOFT386_PREFIX_SEG) + { + /* Use the override segment instead */ + Segment = State->SegmentOverride; + } + + /* Write memory */ + if (!Soft386WriteMemory(State, + Segment, + ModRegRm->MemoryAddress, + &Value, + sizeof(ULONG))) + { + /* Exception occurred */ + return FALSE; + } + } + } + + return TRUE; +} + +/* EOF */ diff --git a/lib/soft386/opcodes.c b/lib/soft386/opcodes.c index feda3787ec2..2120bb40b67 100644 --- a/lib/soft386/opcodes.c +++ b/lib/soft386/opcodes.c @@ -12,13 +12,13 @@ // #define _INC_WINDOWS #include +// #define NDEBUG +#include + #include #include "opcodes.h" #include "common.h" -// #define NDEBUG -#include - /* PUBLIC VARIABLES ***********************************************************/ SOFT386_OPCODE_HANDLER_PROC diff --git a/lib/soft386/soft386.c b/lib/soft386/soft386.c index abe55dd8271..76c5f58f7dc 100644 --- a/lib/soft386/soft386.c +++ b/lib/soft386/soft386.c @@ -12,13 +12,13 @@ // #define _INC_WINDOWS #include +// #define NDEBUG +#include + #include #include "common.h" #include "opcodes.h" -// #define NDEBUG -#include - /* DEFINES ********************************************************************/ typedef enum