[SOFT386]
authorAleksandar Andrejevic <aandrejevic@reactos.org>
Sat, 28 Sep 2013 00:29:16 +0000 (00:29 +0000)
committerAleksandar Andrejevic <aandrejevic@reactos.org>
Sat, 28 Sep 2013 00:29:16 +0000 (00:29 +0000)
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

include/reactos/libs/soft386/soft386.h
lib/soft386/opcodes.c
lib/soft386/opcodes.h
lib/soft386/soft386.c
subsystems/ntvdm/emulator.c
subsystems/ntvdm/emulator.h

index 2df1947..21b6171 100644 (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;
index d614df4..45dcf46 100644 (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;
 
-    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;
index fb13042..b3c1450 100644 (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);
index 4f449d3..02cd048 100644 (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
index 6fba6da..b1bf563 100644 (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);
index 427c520..3427050 100644 (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 ******************************************************************/