* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#include "common.h"
+
/* PUBLIC FUNCTIONS ***********************************************************/
+FORCEINLINE
+INT
+Fast486GetCurrentPrivLevel(PFAST486_STATE State)
+{
+ /* Return the CPL, or 3 if we're in virtual 8086 mode */
+ return (!State->Flags.Vm) ? State->Cpl : 3;
+}
+
+FORCEINLINE
+ULONG
+Fast486GetPageTableEntry(PFAST486_STATE State,
+ ULONG VirtualAddress,
+ BOOLEAN MarkAsDirty)
+{
+ ULONG PdeIndex = GET_ADDR_PDE(VirtualAddress);
+ ULONG PteIndex = GET_ADDR_PTE(VirtualAddress);
+ FAST486_PAGE_DIR DirectoryEntry;
+ FAST486_PAGE_TABLE TableEntry;
+ ULONG PageDirectory = State->ControlRegisters[FAST486_REG_CR3];
+
+ if ((State->Tlb != NULL)
+ && (State->Tlb[VirtualAddress >> 12] != INVALID_TLB_FIELD))
+ {
+ /* Return the cached entry */
+ return State->Tlb[VirtualAddress >> 12];
+ }
+
+ /* Read the directory entry */
+ State->MemReadCallback(State,
+ PageDirectory + PdeIndex * sizeof(ULONG),
+ &DirectoryEntry.Value,
+ sizeof(DirectoryEntry));
+
+ /* Make sure it is present */
+ if (!DirectoryEntry.Present) return 0;
+
+ /* Was the directory entry accessed before? */
+ if (!DirectoryEntry.Accessed)
+ {
+ /* Well, it is now */
+ DirectoryEntry.Accessed = TRUE;
+
+ /* Write back the directory entry */
+ State->MemWriteCallback(State,
+ PageDirectory + PdeIndex * sizeof(ULONG),
+ &DirectoryEntry.Value,
+ sizeof(DirectoryEntry));
+ }
+
+ /* Read the table entry */
+ State->MemReadCallback(State,
+ (DirectoryEntry.TableAddress << 12)
+ + PteIndex * sizeof(ULONG),
+ &TableEntry.Value,
+ sizeof(TableEntry));
+
+ /* Make sure it is present */
+ if (!TableEntry.Present) return 0;
+
+ if (MarkAsDirty) TableEntry.Dirty = TRUE;
+
+ /* Was the table entry accessed before? */
+ if (!TableEntry.Accessed)
+ {
+ /* Well, it is now */
+ TableEntry.Accessed = TRUE;
+
+ /* Write back the table entry */
+ State->MemWriteCallback(State,
+ (DirectoryEntry.TableAddress << 12)
+ + PteIndex * sizeof(ULONG),
+ &TableEntry.Value,
+ sizeof(TableEntry));
+ }
+
+ /*
+ * The resulting permissions depend on the permissions
+ * in the page directory table too
+ */
+ TableEntry.Writeable &= DirectoryEntry.Writeable;
+ TableEntry.Usermode &= DirectoryEntry.Usermode;
+
+ if (State->Tlb != NULL)
+ {
+ /* Set the TLB entry */
+ State->Tlb[VirtualAddress >> 12] = TableEntry.Value;
+ }
+
+ /* Return the table entry */
+ return TableEntry.Value;
+}
+
+FORCEINLINE
+BOOLEAN
+Fast486ReadLinearMemory(PFAST486_STATE State,
+ ULONG LinearAddress,
+ PVOID Buffer,
+ ULONG Size)
+{
+ /* Check if paging is enabled */
+ if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PG)
+ {
+ ULONG Page;
+ FAST486_PAGE_TABLE TableEntry;
+ INT Cpl = Fast486GetCurrentPrivLevel(State);
+ ULONG BufferOffset = 0;
+
+ for (Page = PAGE_ALIGN(LinearAddress);
+ Page <= PAGE_ALIGN(LinearAddress + Size - 1);
+ Page += PAGE_SIZE)
+ {
+ ULONG PageOffset = 0, PageLength = PAGE_SIZE;
+
+ /* Get the table entry */
+ TableEntry.Value = Fast486GetPageTableEntry(State, Page, FALSE);
+
+ if (!TableEntry.Present || (!TableEntry.Usermode && (Cpl > 0)))
+ {
+ /* Exception */
+ Fast486ExceptionWithErrorCode(State,
+ FAST486_EXCEPTION_PF,
+ TableEntry.Value & 0x07);
+ return FALSE;
+ }
+
+ /* Check if this is the first page */
+ if (Page == PAGE_ALIGN(LinearAddress))
+ {
+ /* Start reading from the offset from the beginning of the page */
+ PageOffset = PAGE_OFFSET(LinearAddress);
+ PageLength -= PageOffset;
+ }
+
+ /* Check if this is the last page */
+ if (Page == PAGE_ALIGN(LinearAddress + Size - 1))
+ {
+ /* Read only a part of the page */
+ PageLength = PAGE_OFFSET(LinearAddress + Size - 1) - PageOffset + 1;
+ }
+
+ /* Read the memory */
+ State->MemReadCallback(State,
+ (TableEntry.Address << 12) | PageOffset,
+ (PVOID)((ULONG_PTR)Buffer + BufferOffset),
+ PageLength);
+
+ BufferOffset += PageLength;
+ }
+ }
+ else
+ {
+ /* Read the memory */
+ State->MemReadCallback(State, LinearAddress, Buffer, Size);
+ }
+
+ return TRUE;
+}
+
+FORCEINLINE
+BOOLEAN
+Fast486WriteLinearMemory(PFAST486_STATE State,
+ ULONG LinearAddress,
+ PVOID Buffer,
+ ULONG Size)
+{
+ /* Check if paging is enabled */
+ if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PG)
+ {
+ ULONG Page;
+ FAST486_PAGE_TABLE TableEntry;
+ INT Cpl = Fast486GetCurrentPrivLevel(State);
+ ULONG BufferOffset = 0;
+
+ for (Page = PAGE_ALIGN(LinearAddress);
+ Page <= PAGE_ALIGN(LinearAddress + Size - 1);
+ Page += PAGE_SIZE)
+ {
+ ULONG PageOffset = 0, PageLength = PAGE_SIZE;
+
+ /* Get the table entry */
+ TableEntry.Value = Fast486GetPageTableEntry(State, Page, TRUE);
+
+ if ((!TableEntry.Present || (!TableEntry.Usermode && (Cpl > 0)))
+ || ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_WP)
+ && !TableEntry.Writeable))
+ {
+ /* Exception */
+ Fast486ExceptionWithErrorCode(State,
+ FAST486_EXCEPTION_PF,
+ TableEntry.Value & 0x07);
+ return FALSE;
+ }
+
+ /* Check if this is the first page */
+ if (Page == PAGE_ALIGN(LinearAddress))
+ {
+ /* Start writing from the offset from the beginning of the page */
+ PageOffset = PAGE_OFFSET(LinearAddress);
+ PageLength -= PageOffset;
+ }
+
+ /* Check if this is the last page */
+ if (Page == PAGE_ALIGN(LinearAddress + Size - 1))
+ {
+ /* Write only a part of the page */
+ PageLength = PAGE_OFFSET(LinearAddress + Size - 1) - PageOffset + 1;
+ }
+
+ /* Write the memory */
+ State->MemWriteCallback(State,
+ (TableEntry.Address << 12) | PageOffset,
+ (PVOID)((ULONG_PTR)Buffer + BufferOffset),
+ PageLength);
+
+ BufferOffset += PageLength;
+ }
+ }
+ else
+ {
+ /* Write the memory */
+ State->MemWriteCallback(State, LinearAddress, Buffer, Size);
+ }
+
+ return TRUE;
+}
+
FORCEINLINE
VOID
Fast486Exception(PFAST486_STATE State,
Fast486StackPush(PFAST486_STATE State,
ULONG Value)
{
- BOOLEAN Size = State->SegmentRegs[FAST486_REG_SS].Size;
+ BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
/* The OPSIZE prefix toggles the size */
if (State->PrefixFlags & FAST486_PREFIX_OPSIZE) Size = !Size;
}
/* Subtract ESP by 4 */
- State->GeneralRegs[FAST486_REG_ESP].Long -= 4;
+ State->GeneralRegs[FAST486_REG_ESP].Long -= sizeof(ULONG);
/* Store the value in SS:ESP */
return Fast486WriteMemory(State,
USHORT ShortValue = LOWORD(Value);
/* Check if SP is 1 */
- if (State->GeneralRegs[FAST486_REG_ESP].Long == 1)
+ if (State->GeneralRegs[FAST486_REG_ESP].LowWord == 1)
{
Fast486Exception(State, FAST486_EXCEPTION_SS);
return FALSE;
}
/* Subtract SP by 2 */
- State->GeneralRegs[FAST486_REG_ESP].LowWord -= 2;
+ State->GeneralRegs[FAST486_REG_ESP].LowWord -= sizeof(USHORT);
/* Store the value in SS:SP */
return Fast486WriteMemory(State,
Fast486StackPop(PFAST486_STATE State,
PULONG Value)
{
- ULONG LongValue;
- USHORT ShortValue;
- BOOLEAN Size = State->SegmentRegs[FAST486_REG_SS].Size;
+ BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
/* The OPSIZE prefix toggles the size */
- if (State->PrefixFlags & FAST486_PREFIX_OPSIZE) Size = !Size;
+ TOGGLE_OPSIZE(Size);
if (Size)
{
/* 32-bit size */
+ ULONG LongValue;
/* Check if ESP is 0xFFFFFFFF */
if (State->GeneralRegs[FAST486_REG_ESP].Long == 0xFFFFFFFF)
}
/* Increment ESP by 4 */
- State->GeneralRegs[FAST486_REG_ESP].Long += 4;
+ State->GeneralRegs[FAST486_REG_ESP].Long += sizeof(ULONG);
/* Store the value in the result */
*Value = LongValue;
else
{
/* 16-bit size */
+ USHORT ShortValue;
/* Check if SP is 0xFFFF */
if (State->GeneralRegs[FAST486_REG_ESP].LowWord == 0xFFFF)
}
/* Increment SP by 2 */
- State->GeneralRegs[FAST486_REG_ESP].Long += 2;
+ State->GeneralRegs[FAST486_REG_ESP].LowWord += sizeof(USHORT);
/* Store the value in the result */
*Value = ShortValue;
FORCEINLINE
BOOLEAN
Fast486LoadSegment(PFAST486_STATE State,
- INT Segment,
+ FAST486_SEG_REGS Segment,
USHORT Selector)
{
PFAST486_SEG_REG CachedDescriptor;
/* Check for protected mode */
if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) && !State->Flags.Vm)
{
- /* Make sure the GDT contains the entry */
- if (GET_SEGMENT_INDEX(Selector) >= (State->Gdtr.Size + 1))
+ if (!(Selector & SEGMENT_TABLE_INDICATOR))
{
- Fast486Exception(State, FAST486_EXCEPTION_GP);
- return FALSE;
+ /* Make sure the GDT contains the entry */
+ if (GET_SEGMENT_INDEX(Selector) >= (State->Gdtr.Size + 1))
+ {
+ Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+ return FALSE;
+ }
+
+ /* Read the GDT */
+ if (!Fast486ReadLinearMemory(State,
+ State->Gdtr.Address
+ + GET_SEGMENT_INDEX(Selector),
+ &GdtEntry,
+ sizeof(GdtEntry)))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
}
+ else
+ {
+ /* Make sure the LDT contains the entry */
+ if (GET_SEGMENT_INDEX(Selector) >= (State->Ldtr.Limit + 1))
+ {
+ Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+ return FALSE;
+ }
- /* Read the GDT */
- // FIXME: This code is only correct when paging is disabled!!!
- State->MemReadCallback(State,
- State->Gdtr.Address
- + GET_SEGMENT_INDEX(Selector),
- &GdtEntry,
- sizeof(GdtEntry));
+ /* Read the LDT */
+ if (!Fast486ReadLinearMemory(State,
+ State->Ldtr.Base
+ + GET_SEGMENT_INDEX(Selector),
+ &GdtEntry,
+ sizeof(GdtEntry)))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+ }
if (Segment == FAST486_REG_SS)
{
if (!GdtEntry.SystemType)
{
/* This is a special descriptor */
- Fast486Exception(State, FAST486_EXCEPTION_GP);
+ Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
return FALSE;
}
if (GdtEntry.Executable || !GdtEntry.ReadWrite)
{
- Fast486Exception(State, FAST486_EXCEPTION_GP);
+ Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
return FALSE;
}
if ((GET_SEGMENT_RPL(Selector) != Fast486GetCurrentPrivLevel(State))
|| (GET_SEGMENT_RPL(Selector) != GdtEntry.Dpl))
{
- Fast486Exception(State, FAST486_EXCEPTION_GP);
+ Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
return FALSE;
}
if (!GdtEntry.Present)
{
- Fast486Exception(State, FAST486_EXCEPTION_SS);
+ Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_SS, Selector);
return FALSE;
}
}
else if (Segment == FAST486_REG_CS)
{
/* Loading the code segment */
- // TODO: NOT IMPLEMENTED
- }
- else
- {
- /* Loading a data segment */
- if (!GdtEntry.SystemType)
+ if (GET_SEGMENT_INDEX(Selector) == 0)
{
- /* This is a special descriptor */
Fast486Exception(State, FAST486_EXCEPTION_GP);
return FALSE;
}
- if ((GET_SEGMENT_RPL(Selector) > GdtEntry.Dpl)
- && (Fast486GetCurrentPrivLevel(State) > GdtEntry.Dpl))
+ if (!GdtEntry.SystemType)
{
- Fast486Exception(State, FAST486_EXCEPTION_GP);
- return FALSE;
+ // TODO: Call/interrupt/task gates NOT IMPLEMENTED!
+ UNIMPLEMENTED;
}
+ else
+ {
+ if (!GdtEntry.Present)
+ {
+ Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_NP, Selector);
+ return FALSE;
+ }
- if (!GdtEntry.Present)
+ if (!GdtEntry.Executable)
+ {
+ Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+ return FALSE;
+ }
+
+ if (GdtEntry.DirConf)
+ {
+ /* Conforming Code Segment */
+
+ if (GdtEntry.Dpl > Fast486GetCurrentPrivLevel(State))
+ {
+ /* Must be accessed from lower-privileged code */
+ Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+ return FALSE;
+ }
+ }
+ else
+ {
+ /* Regular code segment */
+
+ if ((GET_SEGMENT_RPL(Selector) > Fast486GetCurrentPrivLevel(State))
+ || (Fast486GetCurrentPrivLevel(State) != GdtEntry.Dpl))
+ {
+ Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+ return FALSE;
+ }
+ }
+
+ /* Update CPL */
+ State->Cpl = GET_SEGMENT_RPL(Selector);
+ }
+ }
+ else
+ {
+ /* Loading a data segment */
+
+ if (GET_SEGMENT_INDEX(Selector) != 0)
{
- Fast486Exception(State, FAST486_EXCEPTION_NP);
- return FALSE;
+ if (!GdtEntry.SystemType)
+ {
+ /* This is a special descriptor */
+ Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+ return FALSE;
+ }
+
+ if ((GET_SEGMENT_RPL(Selector) > GdtEntry.Dpl)
+ || (Fast486GetCurrentPrivLevel(State) > GdtEntry.Dpl))
+ {
+ Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+ return FALSE;
+ }
+
+ if (!GdtEntry.Present)
+ {
+ Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_NP, Selector);
+ return FALSE;
+ }
+ }
+ else
+ {
+ /* This is a NULL selector */
+ RtlZeroMemory(&GdtEntry, sizeof(GdtEntry));
}
}
/* Update the cache entry */
CachedDescriptor->Selector = Selector;
- CachedDescriptor->Base = GdtEntry.Base | (GdtEntry.BaseHigh << 24);
+ CachedDescriptor->Base = GdtEntry.Base | (GdtEntry.BaseMid << 16) | (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->Rpl = GET_SEGMENT_RPL(Selector);
CachedDescriptor->Dpl = GdtEntry.Dpl;
CachedDescriptor->Present = GdtEntry.Present;
CachedDescriptor->Size = GdtEntry.Size;
if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
{
/* Read from the IDT */
- // FIXME: This code is only correct when paging is disabled!!!
- State->MemReadCallback(State,
- State->Idtr.Address
- + Number * sizeof(*IdtEntry),
- IdtEntry,
- sizeof(*IdtEntry));
+ if (!Fast486ReadLinearMemory(State,
+ State->Idtr.Address
+ + Number * sizeof(*IdtEntry),
+ IdtEntry,
+ sizeof(*IdtEntry)))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
}
else
{
/* Read from the real-mode IVT */
-
+
/* Paging is always disabled in real mode */
State->MemReadCallback(State,
State->Idtr.Address
IdtEntry->OffsetHigh = 0;
}
- /*
- * Once paging support is implemented this function
- * will not always return true
- */
return TRUE;
}
Index = (SibByte >> 3) & 0x07;
if (Index != FAST486_REG_ESP) Index = State->GeneralRegs[Index].Long;
else Index = 0;
- Base = State->GeneralRegs[SibByte & 0x07].Long;
+
+ if (((SibByte & 0x07) != FAST486_REG_EBP) || (Mode != 0))
+ {
+ /* Use the register a base */
+ Base = State->GeneralRegs[SibByte & 0x07].Long;
+ }
+ else
+ {
+ /* Fetch the base */
+ if (!Fast486FetchDword(State, &Base))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+ }
+
+ if ((SibByte & 0x07) == FAST486_REG_ESP)
+ {
+ /* Check if there is no segment override */
+ if (!(State->PrefixFlags & FAST486_PREFIX_SEG))
+ {
+ /* Add a SS: prefix */
+ State->PrefixFlags |= FAST486_PREFIX_SEG;
+ State->SegmentOverride = FAST486_REG_SS;
+ }
+ }
/* Calculate the address */
ModRegRm->MemoryAddress = Base + Index * Scale;
if (Mode == 1)
{
CHAR Offset;
-
+
/* Fetch the byte */
if (!Fast486FetchByte(State, (PUCHAR)&Offset))
{
else if ((Mode == 2) || ((Mode == 0) && (RegMem == FAST486_REG_EBP)))
{
LONG Offset;
-
+
/* Fetch the dword */
if (!Fast486FetchDword(State, (PULONG)&Offset))
{
switch (RegMem)
{
case 0:
- case 2:
{
- /* (SS:)[BX + SI] */
+ /* [BX + SI] */
ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EBX].LowWord
+ State->GeneralRegs[FAST486_REG_ESI].LowWord;
}
case 1:
- case 3:
{
- /* (SS:)[BX + DI] */
+ /* [BX + DI] */
ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EBX].LowWord
+ State->GeneralRegs[FAST486_REG_EDI].LowWord;
break;
}
+ case 2:
+ {
+ /* SS:[BP + SI] */
+ ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EBP].LowWord
+ + State->GeneralRegs[FAST486_REG_ESI].LowWord;
+
+ break;
+ }
+
+ case 3:
+ {
+ /* SS:[BP + DI] */
+ ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EBP].LowWord
+ + State->GeneralRegs[FAST486_REG_EDI].LowWord;
+
+ break;
+ }
+
case 4:
{
/* [SI] */
if (Mode == 1)
{
CHAR Offset;
-
+
/* Fetch the byte */
if (!Fast486FetchByte(State, (PUCHAR)&Offset))
{
else if ((Mode == 2) || ((Mode == 0) && (RegMem == 6)))
{
SHORT Offset;
-
+
/* Fetch the word */
if (!Fast486FetchWord(State, (PUSHORT)&Offset))
{
{
FAST486_SEG_REGS Segment = FAST486_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)
+ if (RegValue)
{
- /* Get the second register value */
- if (ModRegRm->SecondRegister & 0x04)
+ /* Get the register value */
+ if (ModRegRm->Register & 0x04)
{
/* AH, CH, DH, BH */
- *RmValue = State->GeneralRegs[ModRegRm->SecondRegister & 0x03].HighByte;
+ *RegValue = State->GeneralRegs[ModRegRm->Register & 0x03].HighByte;
}
else
{
/* AL, CL, DL, BL */
- *RmValue = State->GeneralRegs[ModRegRm->SecondRegister & 0x03].LowByte;
+ *RegValue = State->GeneralRegs[ModRegRm->Register & 0x03].LowByte;
}
}
- else
+
+ if (RmValue)
{
- /* Check for the segment override */
- if (State->PrefixFlags & FAST486_PREFIX_SEG)
+ if (!ModRegRm->Memory)
{
- /* Use the override segment instead */
- Segment = State->SegmentOverride;
+ /* 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;
+ }
}
-
- /* Read memory */
- if (!Fast486ReadMemory(State,
- Segment,
- ModRegRm->MemoryAddress,
- FALSE,
- RmValue,
- sizeof(UCHAR)))
+ else
{
- /* Exception occurred */
- return FALSE;
+ /* Check for the segment override */
+ if (State->PrefixFlags & FAST486_PREFIX_SEG)
+ {
+ /* Use the override segment instead */
+ Segment = State->SegmentOverride;
+ }
+
+ /* Read memory */
+ if (!Fast486ReadMemory(State,
+ Segment,
+ ModRegRm->MemoryAddress,
+ FALSE,
+ RmValue,
+ sizeof(UCHAR)))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
}
}
{
FAST486_SEG_REGS Segment = FAST486_REG_DS;
- /* Get the register value */
- *RegValue = State->GeneralRegs[ModRegRm->Register].LowWord;
-
- if (!ModRegRm->Memory)
+ if (RegValue)
{
- /* Get the second register value */
- *RmValue = State->GeneralRegs[ModRegRm->SecondRegister].LowWord;
+ /* Get the register value */
+ *RegValue = State->GeneralRegs[ModRegRm->Register].LowWord;
}
- else
+
+ if (RmValue)
{
- /* Check for the segment override */
- if (State->PrefixFlags & FAST486_PREFIX_SEG)
+ if (!ModRegRm->Memory)
{
- /* Use the override segment instead */
- Segment = State->SegmentOverride;
+ /* Get the second register value */
+ *RmValue = State->GeneralRegs[ModRegRm->SecondRegister].LowWord;
}
-
- /* Read memory */
- if (!Fast486ReadMemory(State,
- Segment,
- ModRegRm->MemoryAddress,
- FALSE,
- RmValue,
- sizeof(USHORT)))
+ else
{
- /* Exception occurred */
- return FALSE;
+ /* Check for the segment override */
+ if (State->PrefixFlags & FAST486_PREFIX_SEG)
+ {
+ /* Use the override segment instead */
+ Segment = State->SegmentOverride;
+ }
+
+ /* Read memory */
+ if (!Fast486ReadMemory(State,
+ Segment,
+ ModRegRm->MemoryAddress,
+ FALSE,
+ RmValue,
+ sizeof(USHORT)))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
}
}
{
FAST486_SEG_REGS Segment = FAST486_REG_DS;
- /* Get the register value */
- *RegValue = State->GeneralRegs[ModRegRm->Register].Long;
-
- if (!ModRegRm->Memory)
+ if (RegValue)
{
- /* Get the second register value */
- *RmValue = State->GeneralRegs[ModRegRm->SecondRegister].Long;
+ /* Get the register value */
+ *RegValue = State->GeneralRegs[ModRegRm->Register].Long;
}
- else
+
+ if (RmValue)
{
- /* Check for the segment override */
- if (State->PrefixFlags & FAST486_PREFIX_SEG)
+ if (!ModRegRm->Memory)
{
- /* Use the override segment instead */
- Segment = State->SegmentOverride;
+ /* Get the second register value */
+ *RmValue = State->GeneralRegs[ModRegRm->SecondRegister].Long;
}
-
- /* Read memory */
- if (!Fast486ReadMemory(State,
- Segment,
- ModRegRm->MemoryAddress,
- FALSE,
- RmValue,
- sizeof(ULONG)))
+ else
{
- /* Exception occurred */
- return FALSE;
+ /* Check for the segment override */
+ if (State->PrefixFlags & FAST486_PREFIX_SEG)
+ {
+ /* Use the override segment instead */
+ Segment = State->SegmentOverride;
+ }
+
+ /* Read memory */
+ if (!Fast486ReadMemory(State,
+ Segment,
+ ModRegRm->MemoryAddress,
+ FALSE,
+ RmValue,
+ sizeof(ULONG)))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
}
}