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
PSOFT386_STATE State
);
+typedef
+VOID
+(NTAPI *SOFT386_BOP_PROC)
+(
+ PSOFT386_STATE State,
+ USHORT BopCode
+);
+
typedef union _SOFT386_REG
{
union
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;
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,
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)
return FALSE;
}
- if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
+ if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
{
/* The OPSIZE prefix toggles the size */
Size = !Size;
return FALSE;
}
- if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
+ if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
{
/* The OPSIZE prefix toggles the size */
Size = !Size;
return FALSE;
}
- if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
+ if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
{
/* The OPSIZE prefix toggles the size */
Size = !Size;
return FALSE;
}
- if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
+ if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
{
/* The OPSIZE prefix toggles the size */
Size = !Size;
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);
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));
State->IoReadCallback = IoReadCallback;
State->IoWriteCallback = IoWriteCallback;
State->IdleCallback = IdleCallback;
+ State->BopCallback = BopCallback;
}
VOID
/* 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);
}
}
-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);
}
}
-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);
}
}
-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;
}
}
-#ifndef NEW_EMULATOR
-
static VOID EmulatorBop(WORD Code)
{
WORD StackSegment, StackPointer, CodeSegment, InstructionPointer;
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 */
}
}
+#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);
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);
};
#ifndef NEW_EMULATOR
+
+#define NTVDMCALL __cdecl
extern softx86_ctx EmulatorContext;
extern softx87_ctx FpuEmulatorContext;
+
#else
+
+#define NTVDMCALL __stdcall
extern SOFT386_STATE EmulatorContext;
+
#endif
/* FUNCTIONS ******************************************************************/