[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:
Aleksandar Andrejevic 2013-09-28 00:29:16 +00:00
parent dc29fa9ab1
commit 7e119cf40b
6 changed files with 135 additions and 26 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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 ******************************************************************/