[SOFT386]
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Tue, 17 Sep 2013 23:02:22 +0000 (23:02 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Tue, 17 Sep 2013 23:02:22 +0000 (23:02 +0000)
- 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
lib/soft386/common.c
lib/soft386/common.h
lib/soft386/common.inl [new file with mode: 0644]
lib/soft386/opcodes.c
lib/soft386/soft386.c

index 70f2971..50e23a2 100644 (file)
@@ -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;
 };
 
index 00045f5..385fd5e 100644 (file)
 // #define _INC_WINDOWS
 #include <windef.h>
 
-#include <soft386.h>
-#include "common.h"
-
 // #define NDEBUG
 #include <debug.h>
 
-/* PRIVATE FUNCTIONS **********************************************************/
+#include <soft386.h>
+#include "common.h"
 
-static
-inline
-INT
-Soft386GetCurrentPrivLevel(PSOFT386_STATE State)
-{
-    return GET_SEGMENT_RPL(State->SegmentRegs[SOFT386_REG_CS].Selector);
-}
+/* PRIVATE FUNCTIONS **********************************************************/
 
-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 */
index 9c3e818..8e16978 100644 (file)
 
 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
-);
-
-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
-);
+/* static */ FORCEINLINE
+INT
+Soft386GetCurrentPrivLevel(PSOFT386_STATE State)
+{
+    return GET_SEGMENT_RPL(State->SegmentRegs[SOFT386_REG_CS].Selector);
+}
 
-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 (file)
index 0000000..b09ea1f
--- /dev/null
@@ -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 <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* 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 */
index feda378..2120bb4 100644 (file)
 // #define _INC_WINDOWS
 #include <windef.h>
 
+// #define NDEBUG
+#include <debug.h>
+
 #include <soft386.h>
 #include "opcodes.h"
 #include "common.h"
 
-// #define NDEBUG
-#include <debug.h>
-
 /* PUBLIC VARIABLES ***********************************************************/
 
 SOFT386_OPCODE_HANDLER_PROC
index abe55dd..76c5f58 100644 (file)
 // #define _INC_WINDOWS
 #include <windef.h>
 
+// #define NDEBUG
+#include <debug.h>
+
 #include <soft386.h>
 #include "common.h"
 #include "opcodes.h"
 
-// #define NDEBUG
-#include <debug.h>
-
 /* DEFINES ********************************************************************/
 
 typedef enum