mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
[SOFT386]
Implement the LES and LDS instructions. Add optional support for BOPs (NTVDM-specific). Fix prefix handling in some functions. [NTVDM] Enable BOPs for Soft386 (when NEW_EMULATOR is defined). Fix the calling convention issue (softx86 uses cdecl, soft386 uses stdcall). svn path=/branches/ntvdm/; revision=60395
This commit is contained in:
parent
dc29fa9ab1
commit
7e119cf40b
6 changed files with 135 additions and 26 deletions
|
@ -157,6 +157,14 @@ VOID
|
||||||
PSOFT386_STATE State
|
PSOFT386_STATE State
|
||||||
);
|
);
|
||||||
|
|
||||||
|
typedef
|
||||||
|
VOID
|
||||||
|
(NTAPI *SOFT386_BOP_PROC)
|
||||||
|
(
|
||||||
|
PSOFT386_STATE State,
|
||||||
|
USHORT BopCode
|
||||||
|
);
|
||||||
|
|
||||||
typedef union _SOFT386_REG
|
typedef union _SOFT386_REG
|
||||||
{
|
{
|
||||||
union
|
union
|
||||||
|
@ -295,6 +303,7 @@ struct _SOFT386_STATE
|
||||||
SOFT386_IO_READ_PROC IoReadCallback;
|
SOFT386_IO_READ_PROC IoReadCallback;
|
||||||
SOFT386_IO_WRITE_PROC IoWriteCallback;
|
SOFT386_IO_WRITE_PROC IoWriteCallback;
|
||||||
SOFT386_IDLE_PROC IdleCallback;
|
SOFT386_IDLE_PROC IdleCallback;
|
||||||
|
SOFT386_BOP_PROC BopCallback;
|
||||||
SOFT386_REG GeneralRegs[SOFT386_NUM_GEN_REGS];
|
SOFT386_REG GeneralRegs[SOFT386_NUM_GEN_REGS];
|
||||||
SOFT386_SEG_REG SegmentRegs[SOFT386_NUM_SEG_REGS];
|
SOFT386_SEG_REG SegmentRegs[SOFT386_NUM_SEG_REGS];
|
||||||
SOFT386_REG InstPtr;
|
SOFT386_REG InstPtr;
|
||||||
|
|
|
@ -221,8 +221,8 @@ Soft386OpcodeHandlers[SOFT386_NUM_OPCODE_HANDLERS] =
|
||||||
NULL, // TODO: OPCODE 0xC1 NOT SUPPORTED
|
NULL, // TODO: OPCODE 0xC1 NOT SUPPORTED
|
||||||
Soft386OpcodeRet,
|
Soft386OpcodeRet,
|
||||||
Soft386OpcodeRet,
|
Soft386OpcodeRet,
|
||||||
Soft386OpcodeLes,
|
Soft386OpcodeLdsLes,
|
||||||
Soft386OpcodeLds,
|
Soft386OpcodeLdsLes,
|
||||||
NULL, // TODO: OPCODE 0xC6 NOT SUPPORTED
|
NULL, // TODO: OPCODE 0xC6 NOT SUPPORTED
|
||||||
NULL, // TODO: OPCODE 0xC7 NOT SUPPORTED
|
NULL, // TODO: OPCODE 0xC7 NOT SUPPORTED
|
||||||
Soft386OpcodeEnter,
|
Soft386OpcodeEnter,
|
||||||
|
@ -4474,20 +4474,99 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeRet)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SOFT386_OPCODE_HANDLER(Soft386OpcodeLes)
|
SOFT386_OPCODE_HANDLER(Soft386OpcodeLdsLes)
|
||||||
{
|
{
|
||||||
// TODO: NOT IMPLEMENTED
|
UCHAR FarPointer[6];
|
||||||
UNIMPLEMENTED;
|
BOOLEAN OperandSize, AddressSize;
|
||||||
|
SOFT386_MOD_REG_RM ModRegRm;
|
||||||
|
|
||||||
return FALSE;
|
/* Make sure this is the right instruction */
|
||||||
}
|
ASSERT((Opcode & 0xFE) == 0xC4);
|
||||||
|
|
||||||
SOFT386_OPCODE_HANDLER(Soft386OpcodeLds)
|
OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
|
||||||
{
|
|
||||||
// TODO: NOT IMPLEMENTED
|
|
||||||
UNIMPLEMENTED;
|
|
||||||
|
|
||||||
return FALSE;
|
if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
|
||||||
|
{
|
||||||
|
/* The ADSIZE prefix toggles the size */
|
||||||
|
AddressSize = !AddressSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the operands */
|
||||||
|
if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
|
||||||
|
{
|
||||||
|
/* Exception occurred */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ModRegRm.Memory)
|
||||||
|
{
|
||||||
|
/* Check if this is a BOP and the host supports BOPs */
|
||||||
|
if ((Opcode == 0xC4)
|
||||||
|
&& (ModRegRm.Register == SOFT386_REG_EAX)
|
||||||
|
&& (ModRegRm.SecondRegister == SOFT386_REG_EBP)
|
||||||
|
&& (State->BopCallback != NULL))
|
||||||
|
{
|
||||||
|
USHORT BopCode;
|
||||||
|
|
||||||
|
/* Fetch the BOP code */
|
||||||
|
if (!Soft386FetchWord(State, &BopCode))
|
||||||
|
{
|
||||||
|
/* Exception occurred */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call the BOP handler */
|
||||||
|
State->BopCallback(State, BopCode);
|
||||||
|
|
||||||
|
/* Return success */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Invalid */
|
||||||
|
Soft386Exception(State, SOFT386_EXCEPTION_UD);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Soft386ReadMemory(State,
|
||||||
|
(State->PrefixFlags & SOFT386_PREFIX_SEG)
|
||||||
|
? State->SegmentOverride : SOFT386_REG_DS,
|
||||||
|
ModRegRm.MemoryAddress,
|
||||||
|
FALSE,
|
||||||
|
FarPointer,
|
||||||
|
OperandSize ? 6 : 4))
|
||||||
|
{
|
||||||
|
/* Exception occurred */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OperandSize)
|
||||||
|
{
|
||||||
|
ULONG Offset = *((PULONG)FarPointer);
|
||||||
|
USHORT Segment = *((PUSHORT)&FarPointer[sizeof(ULONG)]);
|
||||||
|
|
||||||
|
/* Set the register to the offset */
|
||||||
|
State->GeneralRegs[ModRegRm.Register].Long = Offset;
|
||||||
|
|
||||||
|
/* Load the segment */
|
||||||
|
return Soft386LoadSegment(State,
|
||||||
|
(Opcode == 0xC4)
|
||||||
|
? SOFT386_REG_ES : SOFT386_REG_DS,
|
||||||
|
Segment);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
USHORT Offset = *((PUSHORT)FarPointer);
|
||||||
|
USHORT Segment = *((PUSHORT)&FarPointer[sizeof(USHORT)]);
|
||||||
|
|
||||||
|
/* Set the register to the offset */
|
||||||
|
State->GeneralRegs[ModRegRm.Register].LowWord = Offset;
|
||||||
|
|
||||||
|
/* Load the segment */
|
||||||
|
return Soft386LoadSegment(State,
|
||||||
|
(Opcode == 0xC4)
|
||||||
|
? SOFT386_REG_ES : SOFT386_REG_DS,
|
||||||
|
Segment);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SOFT386_OPCODE_HANDLER(Soft386OpcodeEnter)
|
SOFT386_OPCODE_HANDLER(Soft386OpcodeEnter)
|
||||||
|
@ -4508,7 +4587,7 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeEnter)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
|
if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
|
||||||
{
|
{
|
||||||
/* The OPSIZE prefix toggles the size */
|
/* The OPSIZE prefix toggles the size */
|
||||||
Size = !Size;
|
Size = !Size;
|
||||||
|
@ -4577,7 +4656,7 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeLeave)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
|
if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
|
||||||
{
|
{
|
||||||
/* The OPSIZE prefix toggles the size */
|
/* The OPSIZE prefix toggles the size */
|
||||||
Size = !Size;
|
Size = !Size;
|
||||||
|
@ -4705,7 +4784,7 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeIret)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
|
if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
|
||||||
{
|
{
|
||||||
/* The OPSIZE prefix toggles the size */
|
/* The OPSIZE prefix toggles the size */
|
||||||
Size = !Size;
|
Size = !Size;
|
||||||
|
@ -5001,7 +5080,7 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeLoop)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
|
if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
|
||||||
{
|
{
|
||||||
/* The OPSIZE prefix toggles the size */
|
/* The OPSIZE prefix toggles the size */
|
||||||
Size = !Size;
|
Size = !Size;
|
||||||
|
|
|
@ -115,8 +115,7 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodePopFlags);
|
||||||
SOFT386_OPCODE_HANDLER(Soft386OpcodeSahf);
|
SOFT386_OPCODE_HANDLER(Soft386OpcodeSahf);
|
||||||
SOFT386_OPCODE_HANDLER(Soft386OpcodeLahf);
|
SOFT386_OPCODE_HANDLER(Soft386OpcodeLahf);
|
||||||
SOFT386_OPCODE_HANDLER(Soft386OpcodeRet);
|
SOFT386_OPCODE_HANDLER(Soft386OpcodeRet);
|
||||||
SOFT386_OPCODE_HANDLER(Soft386OpcodeLes);
|
SOFT386_OPCODE_HANDLER(Soft386OpcodeLdsLes);
|
||||||
SOFT386_OPCODE_HANDLER(Soft386OpcodeLds);
|
|
||||||
SOFT386_OPCODE_HANDLER(Soft386OpcodeEnter);
|
SOFT386_OPCODE_HANDLER(Soft386OpcodeEnter);
|
||||||
SOFT386_OPCODE_HANDLER(Soft386OpcodeLeave);
|
SOFT386_OPCODE_HANDLER(Soft386OpcodeLeave);
|
||||||
SOFT386_OPCODE_HANDLER(Soft386OpcodeRetFarImm);
|
SOFT386_OPCODE_HANDLER(Soft386OpcodeRetFarImm);
|
||||||
|
|
|
@ -211,6 +211,7 @@ Soft386Reset(PSOFT386_STATE State)
|
||||||
SOFT386_IO_READ_PROC IoReadCallback = State->IoReadCallback;
|
SOFT386_IO_READ_PROC IoReadCallback = State->IoReadCallback;
|
||||||
SOFT386_IO_WRITE_PROC IoWriteCallback = State->IoWriteCallback;
|
SOFT386_IO_WRITE_PROC IoWriteCallback = State->IoWriteCallback;
|
||||||
SOFT386_IDLE_PROC IdleCallback = State->IdleCallback;
|
SOFT386_IDLE_PROC IdleCallback = State->IdleCallback;
|
||||||
|
SOFT386_BOP_PROC BopCallback = State->BopCallback;
|
||||||
|
|
||||||
/* Clear the entire structure */
|
/* Clear the entire structure */
|
||||||
RtlZeroMemory(State, sizeof(*State));
|
RtlZeroMemory(State, sizeof(*State));
|
||||||
|
@ -245,6 +246,7 @@ Soft386Reset(PSOFT386_STATE State)
|
||||||
State->IoReadCallback = IoReadCallback;
|
State->IoReadCallback = IoReadCallback;
|
||||||
State->IoWriteCallback = IoWriteCallback;
|
State->IoWriteCallback = IoWriteCallback;
|
||||||
State->IdleCallback = IdleCallback;
|
State->IdleCallback = IdleCallback;
|
||||||
|
State->BopCallback = BopCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
|
|
@ -31,7 +31,7 @@ static BOOLEAN A20Line = FALSE;
|
||||||
|
|
||||||
/* PRIVATE FUNCTIONS **********************************************************/
|
/* PRIVATE FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
static VOID EmulatorReadMemory(PVOID Context, UINT Address, LPBYTE Buffer, INT Size)
|
static VOID NTVDMCALL EmulatorReadMemory(PVOID Context, UINT Address, LPBYTE Buffer, INT Size)
|
||||||
{
|
{
|
||||||
UNREFERENCED_PARAMETER(Context);
|
UNREFERENCED_PARAMETER(Context);
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ static VOID EmulatorReadMemory(PVOID Context, UINT Address, LPBYTE Buffer, INT S
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID EmulatorWriteMemory(PVOID Context, UINT Address, LPBYTE Buffer, INT Size)
|
static VOID NTVDMCALL EmulatorWriteMemory(PVOID Context, UINT Address, LPBYTE Buffer, INT Size)
|
||||||
{
|
{
|
||||||
UNREFERENCED_PARAMETER(Context);
|
UNREFERENCED_PARAMETER(Context);
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ static VOID EmulatorWriteMemory(PVOID Context, UINT Address, LPBYTE Buffer, INT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID EmulatorReadIo(PVOID Context, UINT Address, LPBYTE Buffer, INT Size)
|
static VOID NTVDMCALL EmulatorReadIo(PVOID Context, UINT Address, LPBYTE Buffer, INT Size)
|
||||||
{
|
{
|
||||||
UNREFERENCED_PARAMETER(Context);
|
UNREFERENCED_PARAMETER(Context);
|
||||||
UNREFERENCED_PARAMETER(Size);
|
UNREFERENCED_PARAMETER(Size);
|
||||||
|
@ -152,7 +152,7 @@ static VOID EmulatorReadIo(PVOID Context, UINT Address, LPBYTE Buffer, INT Size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID EmulatorWriteIo(PVOID Context, UINT Address, LPBYTE Buffer, INT Size)
|
static VOID NTVDMCALL EmulatorWriteIo(PVOID Context, UINT Address, LPBYTE Buffer, INT Size)
|
||||||
{
|
{
|
||||||
BYTE Byte = *Buffer;
|
BYTE Byte = *Buffer;
|
||||||
|
|
||||||
|
@ -228,8 +228,6 @@ static VOID EmulatorWriteIo(PVOID Context, UINT Address, LPBYTE Buffer, INT Size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NEW_EMULATOR
|
|
||||||
|
|
||||||
static VOID EmulatorBop(WORD Code)
|
static VOID EmulatorBop(WORD Code)
|
||||||
{
|
{
|
||||||
WORD StackSegment, StackPointer, CodeSegment, InstructionPointer;
|
WORD StackSegment, StackPointer, CodeSegment, InstructionPointer;
|
||||||
|
@ -241,8 +239,8 @@ static VOID EmulatorBop(WORD Code)
|
||||||
StackSegment = EmulatorContext.state->segment_reg[SX86_SREG_SS].val;
|
StackSegment = EmulatorContext.state->segment_reg[SX86_SREG_SS].val;
|
||||||
StackPointer = EmulatorContext.state->general_reg[SX86_REG_SP].val;
|
StackPointer = EmulatorContext.state->general_reg[SX86_REG_SP].val;
|
||||||
#else
|
#else
|
||||||
StackSegment = EmulatorContext.SegmentRegs[SOFT386_REG_SS].LowWord;
|
StackSegment = EmulatorContext.SegmentRegs[SOFT386_REG_SS].Selector;
|
||||||
StackPointer = EmulatorContext.SegmentRegs[SOFT386_REG_SP].LowWord;
|
StackPointer = EmulatorContext.GeneralRegs[SOFT386_REG_ESP].LowWord;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Get the stack */
|
/* Get the stack */
|
||||||
|
@ -341,6 +339,21 @@ static VOID EmulatorBop(WORD Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef NEW_EMULATOR
|
||||||
|
static VOID WINAPI EmulatorBiosOperation(PSOFT386_STATE State, WORD Code)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* HACK: To maintain softx86 compatbility, just call the old EmulatorBop here.
|
||||||
|
* Later on, when softx86 is no longer needed, the code from EmulatorBop should
|
||||||
|
* be moved here and should use the "State" variable.
|
||||||
|
*/
|
||||||
|
EmulatorBop(Code);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NEW_EMULATOR
|
||||||
|
|
||||||
static VOID EmulatorSoftwareInt(PVOID Context, BYTE Number)
|
static VOID EmulatorSoftwareInt(PVOID Context, BYTE Number)
|
||||||
{
|
{
|
||||||
UNREFERENCED_PARAMETER(Context);
|
UNREFERENCED_PARAMETER(Context);
|
||||||
|
@ -412,6 +425,7 @@ BOOLEAN EmulatorInitialize()
|
||||||
EmulatorContext.MemWriteCallback = (SOFT386_MEM_WRITE_PROC)EmulatorWriteMemory;
|
EmulatorContext.MemWriteCallback = (SOFT386_MEM_WRITE_PROC)EmulatorWriteMemory;
|
||||||
EmulatorContext.IoReadCallback = (SOFT386_IO_READ_PROC)EmulatorReadIo;
|
EmulatorContext.IoReadCallback = (SOFT386_IO_READ_PROC)EmulatorReadIo;
|
||||||
EmulatorContext.IoWriteCallback = (SOFT386_IO_WRITE_PROC)EmulatorWriteIo;
|
EmulatorContext.IoWriteCallback = (SOFT386_IO_WRITE_PROC)EmulatorWriteIo;
|
||||||
|
EmulatorContext.BopCallback = (SOFT386_BOP_PROC)EmulatorBiosOperation;
|
||||||
|
|
||||||
/* Reset the CPU */
|
/* Reset the CPU */
|
||||||
Soft386Reset(&EmulatorContext);
|
Soft386Reset(&EmulatorContext);
|
||||||
|
|
|
@ -86,10 +86,16 @@ enum
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef NEW_EMULATOR
|
#ifndef NEW_EMULATOR
|
||||||
|
|
||||||
|
#define NTVDMCALL __cdecl
|
||||||
extern softx86_ctx EmulatorContext;
|
extern softx86_ctx EmulatorContext;
|
||||||
extern softx87_ctx FpuEmulatorContext;
|
extern softx87_ctx FpuEmulatorContext;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
#define NTVDMCALL __stdcall
|
||||||
extern SOFT386_STATE EmulatorContext;
|
extern SOFT386_STATE EmulatorContext;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* FUNCTIONS ******************************************************************/
|
/* FUNCTIONS ******************************************************************/
|
||||||
|
|
Loading…
Reference in a new issue