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

View file

@ -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;
/* Make sure this is the right instruction */
ASSERT((Opcode & 0xFE) == 0xC4);
OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
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;
}
}
SOFT386_OPCODE_HANDLER(Soft386OpcodeLds)
{
// TODO: NOT IMPLEMENTED
UNIMPLEMENTED;
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;

View file

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

View file

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

View file

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

View file

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