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
|
||||
);
|
||||
|
||||
typedef
|
||||
VOID
|
||||
(NTAPI *SOFT386_BOP_PROC)
|
||||
(
|
||||
PSOFT386_STATE State,
|
||||
USHORT BopCode
|
||||
);
|
||||
|
||||
typedef union _SOFT386_REG
|
||||
{
|
||||
union
|
||||
|
@ -295,6 +303,7 @@ struct _SOFT386_STATE
|
|||
SOFT386_IO_READ_PROC IoReadCallback;
|
||||
SOFT386_IO_WRITE_PROC IoWriteCallback;
|
||||
SOFT386_IDLE_PROC IdleCallback;
|
||||
SOFT386_BOP_PROC BopCallback;
|
||||
SOFT386_REG GeneralRegs[SOFT386_NUM_GEN_REGS];
|
||||
SOFT386_SEG_REG SegmentRegs[SOFT386_NUM_SEG_REGS];
|
||||
SOFT386_REG InstPtr;
|
||||
|
|
|
@ -221,8 +221,8 @@ Soft386OpcodeHandlers[SOFT386_NUM_OPCODE_HANDLERS] =
|
|||
NULL, // TODO: OPCODE 0xC1 NOT SUPPORTED
|
||||
Soft386OpcodeRet,
|
||||
Soft386OpcodeRet,
|
||||
Soft386OpcodeLes,
|
||||
Soft386OpcodeLds,
|
||||
Soft386OpcodeLdsLes,
|
||||
Soft386OpcodeLdsLes,
|
||||
NULL, // TODO: OPCODE 0xC6 NOT SUPPORTED
|
||||
NULL, // TODO: OPCODE 0xC7 NOT SUPPORTED
|
||||
Soft386OpcodeEnter,
|
||||
|
@ -4474,20 +4474,99 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeRet)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
SOFT386_OPCODE_HANDLER(Soft386OpcodeLes)
|
||||
SOFT386_OPCODE_HANDLER(Soft386OpcodeLdsLes)
|
||||
{
|
||||
// TODO: NOT IMPLEMENTED
|
||||
UNIMPLEMENTED;
|
||||
UCHAR FarPointer[6];
|
||||
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)
|
||||
{
|
||||
// TODO: NOT IMPLEMENTED
|
||||
UNIMPLEMENTED;
|
||||
OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
|
||||
|
||||
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)
|
||||
|
@ -4508,7 +4587,7 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeEnter)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
|
||||
if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
|
||||
{
|
||||
/* The OPSIZE prefix toggles the size */
|
||||
Size = !Size;
|
||||
|
@ -4577,7 +4656,7 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeLeave)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
|
||||
if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
|
||||
{
|
||||
/* The OPSIZE prefix toggles the size */
|
||||
Size = !Size;
|
||||
|
@ -4705,7 +4784,7 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeIret)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
|
||||
if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
|
||||
{
|
||||
/* The OPSIZE prefix toggles the size */
|
||||
Size = !Size;
|
||||
|
@ -5001,7 +5080,7 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeLoop)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
|
||||
if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
|
||||
{
|
||||
/* The OPSIZE prefix toggles the size */
|
||||
Size = !Size;
|
||||
|
|
|
@ -115,8 +115,7 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodePopFlags);
|
|||
SOFT386_OPCODE_HANDLER(Soft386OpcodeSahf);
|
||||
SOFT386_OPCODE_HANDLER(Soft386OpcodeLahf);
|
||||
SOFT386_OPCODE_HANDLER(Soft386OpcodeRet);
|
||||
SOFT386_OPCODE_HANDLER(Soft386OpcodeLes);
|
||||
SOFT386_OPCODE_HANDLER(Soft386OpcodeLds);
|
||||
SOFT386_OPCODE_HANDLER(Soft386OpcodeLdsLes);
|
||||
SOFT386_OPCODE_HANDLER(Soft386OpcodeEnter);
|
||||
SOFT386_OPCODE_HANDLER(Soft386OpcodeLeave);
|
||||
SOFT386_OPCODE_HANDLER(Soft386OpcodeRetFarImm);
|
||||
|
|
|
@ -211,6 +211,7 @@ Soft386Reset(PSOFT386_STATE State)
|
|||
SOFT386_IO_READ_PROC IoReadCallback = State->IoReadCallback;
|
||||
SOFT386_IO_WRITE_PROC IoWriteCallback = State->IoWriteCallback;
|
||||
SOFT386_IDLE_PROC IdleCallback = State->IdleCallback;
|
||||
SOFT386_BOP_PROC BopCallback = State->BopCallback;
|
||||
|
||||
/* Clear the entire structure */
|
||||
RtlZeroMemory(State, sizeof(*State));
|
||||
|
@ -245,6 +246,7 @@ Soft386Reset(PSOFT386_STATE State)
|
|||
State->IoReadCallback = IoReadCallback;
|
||||
State->IoWriteCallback = IoWriteCallback;
|
||||
State->IdleCallback = IdleCallback;
|
||||
State->BopCallback = BopCallback;
|
||||
}
|
||||
|
||||
VOID
|
||||
|
|
|
@ -31,7 +31,7 @@ static BOOLEAN A20Line = FALSE;
|
|||
|
||||
/* 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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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(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;
|
||||
|
||||
|
@ -228,8 +228,6 @@ static VOID EmulatorWriteIo(PVOID Context, UINT Address, LPBYTE Buffer, INT Size
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef NEW_EMULATOR
|
||||
|
||||
static VOID EmulatorBop(WORD Code)
|
||||
{
|
||||
WORD StackSegment, StackPointer, CodeSegment, InstructionPointer;
|
||||
|
@ -241,8 +239,8 @@ static VOID EmulatorBop(WORD Code)
|
|||
StackSegment = EmulatorContext.state->segment_reg[SX86_SREG_SS].val;
|
||||
StackPointer = EmulatorContext.state->general_reg[SX86_REG_SP].val;
|
||||
#else
|
||||
StackSegment = EmulatorContext.SegmentRegs[SOFT386_REG_SS].LowWord;
|
||||
StackPointer = EmulatorContext.SegmentRegs[SOFT386_REG_SP].LowWord;
|
||||
StackSegment = EmulatorContext.SegmentRegs[SOFT386_REG_SS].Selector;
|
||||
StackPointer = EmulatorContext.GeneralRegs[SOFT386_REG_ESP].LowWord;
|
||||
#endif
|
||||
|
||||
/* 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)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(Context);
|
||||
|
@ -412,6 +425,7 @@ BOOLEAN EmulatorInitialize()
|
|||
EmulatorContext.MemWriteCallback = (SOFT386_MEM_WRITE_PROC)EmulatorWriteMemory;
|
||||
EmulatorContext.IoReadCallback = (SOFT386_IO_READ_PROC)EmulatorReadIo;
|
||||
EmulatorContext.IoWriteCallback = (SOFT386_IO_WRITE_PROC)EmulatorWriteIo;
|
||||
EmulatorContext.BopCallback = (SOFT386_BOP_PROC)EmulatorBiosOperation;
|
||||
|
||||
/* Reset the CPU */
|
||||
Soft386Reset(&EmulatorContext);
|
||||
|
|
|
@ -86,10 +86,16 @@ enum
|
|||
};
|
||||
|
||||
#ifndef NEW_EMULATOR
|
||||
|
||||
#define NTVDMCALL __cdecl
|
||||
extern softx86_ctx EmulatorContext;
|
||||
extern softx87_ctx FpuEmulatorContext;
|
||||
|
||||
#else
|
||||
|
||||
#define NTVDMCALL __stdcall
|
||||
extern SOFT386_STATE EmulatorContext;
|
||||
|
||||
#endif
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
|
Loading…
Reference in a new issue