[FAST486]
authorAleksandar Andrejevic <aandrejevic@reactos.org>
Sun, 10 May 2015 21:59:07 +0000 (21:59 +0000)
committerAleksandar Andrejevic <aandrejevic@reactos.org>
Sun, 10 May 2015 21:59:07 +0000 (21:59 +0000)
- Fix VM86-related stuff.
- Optimize MOV.

svn path=/trunk/; revision=67645

reactos/lib/fast486/common.c
reactos/lib/fast486/common.inl
reactos/lib/fast486/opcodes.c

index 03ba743..36c69d4 100644 (file)
@@ -67,7 +67,7 @@ Fast486ReadMemory(PFAST486_STATE State,
     }
 
     /* Check for protected mode */
-    if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
+    if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) && !State->Flags.Vm)
     {
         /* Privilege checks */
 
@@ -189,7 +189,7 @@ Fast486WriteMemory(PFAST486_STATE State,
     }
 
     /* Check for protected mode */
-    if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
+    if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) && !State->Flags.Vm)
     {
         /* Privilege checks */
 
@@ -304,6 +304,7 @@ Fast486InterruptInternal(PFAST486_STATE State,
     {
         USHORT OldSs = State->SegmentRegs[FAST486_REG_SS].Selector;
         ULONG OldEsp = State->GeneralRegs[FAST486_REG_ESP].Long;
+        BOOLEAN OldVm = State->Flags.Vm;
 
         if (IdtEntry->Type == FAST486_TASK_GATE_SIGNATURE)
         {
@@ -398,6 +399,12 @@ Fast486InterruptInternal(PFAST486_STATE State,
             }
 
             State->GeneralRegs[FAST486_REG_ESP].Long = NewEsp;
+
+            if (State->Flags.Vm)
+            {
+                /* Clear the VM flag */
+                State->Flags.Vm = FALSE;
+            }
         }
 
         /* Load new CS */
@@ -418,27 +425,44 @@ Fast486InterruptInternal(PFAST486_STATE State,
             State->InstPtr.LowWord = IdtEntry->Offset;
         }
 
-        /* Check if the interrupt handler is more privileged or we're in VM86 mode (again) */
-        if ((OldCpl > GET_SEGMENT_RPL(IdtEntry->Selector)) || State->Flags.Vm)
+        if (OldVm)
         {
-            if (State->Flags.Vm)
+            /* Push GS, FS, DS and ES */
+            if (!Fast486StackPushInternal(State,
+                                          GateSize,
+                                          State->SegmentRegs[FAST486_REG_GS].Selector))
             {
-                /* Clear the VM flag */
-                State->Flags.Vm = FALSE;
-
-                /* Push GS, FS, DS and ES */
-                if (!Fast486StackPush(State, State->SegmentRegs[FAST486_REG_GS].Selector)) return FALSE;
-                if (!Fast486StackPush(State, State->SegmentRegs[FAST486_REG_FS].Selector)) return FALSE;
-                if (!Fast486StackPush(State, State->SegmentRegs[FAST486_REG_DS].Selector)) return FALSE;
-                if (!Fast486StackPush(State, State->SegmentRegs[FAST486_REG_ES].Selector)) return FALSE;
-
-                /* Now load them with NULL selectors, since they are useless in protected mode */
-                if (!Fast486LoadSegment(State, FAST486_REG_GS, 0)) return FALSE;
-                if (!Fast486LoadSegment(State, FAST486_REG_FS, 0)) return FALSE;
-                if (!Fast486LoadSegment(State, FAST486_REG_DS, 0)) return FALSE;
-                if (!Fast486LoadSegment(State, FAST486_REG_ES, 0)) return FALSE;
+                return FALSE;
+            }
+            if (!Fast486StackPushInternal(State,
+                                          GateSize,
+                                          State->SegmentRegs[FAST486_REG_FS].Selector))
+            {
+                return FALSE;
+            }
+            if (!Fast486StackPushInternal(State,
+                                          GateSize,
+                                          State->SegmentRegs[FAST486_REG_DS].Selector))
+            {
+                return FALSE;
+            }
+            if (!Fast486StackPushInternal(State,
+                                          GateSize,
+                                          State->SegmentRegs[FAST486_REG_ES].Selector))
+            {
+                return FALSE;
             }
 
+            /* Now load them with NULL selectors, since they are useless in protected mode */
+            if (!Fast486LoadSegment(State, FAST486_REG_GS, 0)) return FALSE;
+            if (!Fast486LoadSegment(State, FAST486_REG_FS, 0)) return FALSE;
+            if (!Fast486LoadSegment(State, FAST486_REG_DS, 0)) return FALSE;
+            if (!Fast486LoadSegment(State, FAST486_REG_ES, 0)) return FALSE;
+        }
+
+        /* Check if the interrupt handler is more privileged or we're in VM86 mode (again) */
+        if ((OldCpl > GET_SEGMENT_RPL(IdtEntry->Selector)) || OldVm)
+        {
             /* Push SS selector */
             if (!Fast486StackPushInternal(State, GateSize, OldSs)) return FALSE;
 
index e2527c6..fed1386 100644 (file)
@@ -554,8 +554,24 @@ Fast486LoadSegmentInternal(PFAST486_STATE State,
     CachedDescriptor = &State->SegmentRegs[Segment];
 
     /* Check for protected mode */
-    if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) && !State->Flags.Vm)
+    if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
     {
+        /* Check for VM86 mode */
+        if (State->Flags.Vm)
+        {
+            /* Update the cached descriptor with VM86 values */
+            CachedDescriptor->Selector = Selector;
+            CachedDescriptor->Base = Selector << 4;
+            CachedDescriptor->Limit = 0xFFFF;
+            CachedDescriptor->ReadWrite = TRUE;
+            CachedDescriptor->DirConf = FALSE;
+            CachedDescriptor->SystemType = TRUE;
+            CachedDescriptor->Dpl = CachedDescriptor->Rpl = 3;
+            CachedDescriptor->Present = TRUE;
+            CachedDescriptor->Size = FALSE;
+            return TRUE;
+        }
+
         if (!Fast486ReadDescriptorEntry(State, Selector, &Valid, &GdtEntry))
         {
             /* Exception occurred */
index d9ced5e..ed2c886 100644 (file)
@@ -3727,7 +3727,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodePushByteImm)
 
 FAST486_OPCODE_HANDLER(Fast486OpcodeMovByteModrm)
 {
-    UCHAR FirstValue, SecondValue, Result;
+    UCHAR Result;
     FAST486_MOD_REG_RM ModRegRm;
     BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
 
@@ -3743,24 +3743,28 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeMovByteModrm)
         return;
     }
 
-    if (!Fast486ReadModrmByteOperands(State,
-                                      &ModRegRm,
-                                      &FirstValue,
-                                      &SecondValue))
+    if (Opcode & FAST486_OPCODE_WRITE_REG)
     {
-        /* Exception occurred */
-        return;
+        if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Result))
+        {
+            /* Exception occurred */
+            return;
+        }
+    }
+    else
+    {
+        if (!Fast486ReadModrmByteOperands(State, &ModRegRm, &Result, NULL))
+        {
+            /* Exception occurred */
+            return;
+        }
     }
-
-    if (Opcode & FAST486_OPCODE_WRITE_REG) Result = SecondValue;
-    else Result = FirstValue;
 
     /* Write back the result */
     Fast486WriteModrmByteOperands(State,
                                   &ModRegRm,
                                   Opcode & FAST486_OPCODE_WRITE_REG,
                                   Result);
-
 }
 
 FAST486_OPCODE_HANDLER(Fast486OpcodeMovModrm)
@@ -3786,19 +3790,26 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeMovModrm)
     /* Check the operand size */
     if (OperandSize)
     {
-        ULONG FirstValue, SecondValue, Result;
+        ULONG Result;
 
-        if (!Fast486ReadModrmDwordOperands(State,
-                                          &ModRegRm,
-                                          &FirstValue,
-                                          &SecondValue))
+
+
+        if (Opcode & FAST486_OPCODE_WRITE_REG)
         {
-            /* Exception occurred */
-            return;
+            if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Result))
+            {
+                /* Exception occurred */
+                return;
+            }
+        }
+        else
+        {
+            if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Result, NULL))
+            {
+                /* Exception occurred */
+                return;
+            }
         }
-
-        if (Opcode & FAST486_OPCODE_WRITE_REG) Result = SecondValue;
-        else Result = FirstValue;
 
         /* Write back the result */
         Fast486WriteModrmDwordOperands(State,
@@ -3808,19 +3819,24 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeMovModrm)
     }
     else
     {
-        USHORT FirstValue, SecondValue, Result;
+        USHORT Result;
 
-        if (!Fast486ReadModrmWordOperands(State,
-                                          &ModRegRm,
-                                          &FirstValue,
-                                          &SecondValue))
+        if (Opcode & FAST486_OPCODE_WRITE_REG)
         {
-            /* Exception occurred */
-            return;
+            if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Result))
+            {
+                /* Exception occurred */
+                return;
+            }
+        }
+        else
+        {
+            if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Result, NULL))
+            {
+                /* Exception occurred */
+                return;
+            }
         }
-
-        if (Opcode & FAST486_OPCODE_WRITE_REG) Result = SecondValue;
-        else Result = FirstValue;
 
         /* Write back the result */
         Fast486WriteModrmWordOperands(State,
@@ -4696,11 +4712,17 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeIret)
             /* Set the new IP */
             State->InstPtr.Long = LOWORD(InstPtr);
 
+            /* Set the new SP */
+            State->GeneralRegs[FAST486_REG_ESP].Long = StackPtr;
+
             /* Set the new flags */
             if (Size) State->Flags.Long = NewFlags.Long & REAL_MODE_FLAGS_MASK;
             else State->Flags.LowWord = NewFlags.LowWord & REAL_MODE_FLAGS_MASK;
             State->Flags.AlwaysSet = State->Flags.Vm = TRUE;
 
+            /* Switch to CPL 3 */
+            State->Cpl = 3;
+
             /* Load the new segments */
             if (!Fast486LoadSegment(State, FAST486_REG_CS, CodeSel)) return;
             if (!Fast486LoadSegment(State, FAST486_REG_SS, StackSel)) return;