mirror of
https://github.com/reactos/reactos.git
synced 2025-07-29 03:12:00 +00:00
[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
This commit is contained in:
parent
c27ff5b52f
commit
85f05060e4
6 changed files with 993 additions and 1118 deletions
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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_
|
||||
|
||||
|
|
955
lib/soft386/common.inl
Normal file
955
lib/soft386/common.inl
Normal file
|
@ -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 */
|
|
@ -12,13 +12,13 @@
|
|||
// #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
|
||||
|
|
|
@ -12,13 +12,13 @@
|
|||
// #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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue