[FAST486]
authorAleksandar Andrejevic <aandrejevic@reactos.org>
Sat, 26 Oct 2013 00:56:11 +0000 (00:56 +0000)
committerAleksandar Andrejevic <aandrejevic@reactos.org>
Sat, 26 Oct 2013 00:56:11 +0000 (00:56 +0000)
Implement the MOV instruction for control and debug registers.
Remove definitions for non-existant registers CR1, CR4, CR5, CR6 and CR7.
The standard 80486 doesn't have a CR4 register (although some implementations
of the 80486 had large page support and CR4, it was not reliable).
As for the debug registers, DR4 is the same as DR6, and DR5 is the same as DR7.

svn path=/branches/ntvdm/; revision=60747

include/reactos/libs/fast486/fast486.h
lib/fast486/extraops.c
lib/fast486/extraops.h
lib/fast486/fast486.c

index 07b3589..c2501f7 100644 (file)
@@ -26,8 +26,8 @@
 
 #define FAST486_NUM_GEN_REGS    8
 #define FAST486_NUM_SEG_REGS    6
-#define FAST486_NUM_CTRL_REGS   8
-#define FAST486_NUM_DBG_REGS    8
+#define FAST486_NUM_CTRL_REGS   3
+#define FAST486_NUM_DBG_REGS    6
 
 #define FAST486_CR0_PE  (1 << 0)
 #define FAST486_CR0_MP  (1 << 1)
 #define FAST486_CR0_CD  (1 << 30)
 #define FAST486_CR0_PG  (1 << 31)
 
+#define FAST486_DR4_B0 (1 << 0)
+#define FAST486_DR4_B1 (1 << 1)
+#define FAST486_DR4_B2 (1 << 2)
+#define FAST486_DR4_B3 (1 << 3)
+#define FAST486_DR4_BD (1 << 13)
+#define FAST486_DR4_BS (1 << 14)
+#define FAST486_DR4_BT (1 << 15)
+
+#define FAST486_DR5_L0 (1 << 0)
+#define FAST486_DR5_G0 (1 << 1)
+#define FAST486_DR5_L1 (1 << 2)
+#define FAST486_DR5_G1 (1 << 3)
+#define FAST486_DR5_L2 (1 << 4)
+#define FAST486_DR5_G2 (1 << 5)
+#define FAST486_DR5_L3 (1 << 6)
+#define FAST486_DR5_G3 (1 << 7)
+#define FAST486_DR5_LE (1 << 8)
+#define FAST486_DR5_GE (1 << 9)
+#define FAST486_DR5_GD (1 << 13)
+
+#define FAST486_DBG_BREAK_EXEC 0
+#define FAST486_DBG_BREAK_WRITE 1
+#define FAST486_DBG_BREAK_READWRITE 3
+
+#define FAST486_DR4_RESERVED 0xFFFF1FF0
+#define FAST486_DR5_RESERVED 0x0000DC00
+
 #define FAST486_IDT_TASK_GATE       0x5
 #define FAST486_IDT_INT_GATE        0x6
 #define FAST486_IDT_TRAP_GATE       0x7
@@ -81,26 +108,21 @@ typedef enum _FAST486_SEG_REGS
 
 typedef enum _FAST486_CTRL_REGS
 {
-    FAST486_REG_CR0,
-    FAST486_REG_CR1,
-    FAST486_REG_CR2,
-    FAST486_REG_CR3,
-    FAST486_REG_CR4,
-    FAST486_REG_CR5,
-    FAST486_REG_CR6,
-    FAST486_REG_CR7
+    FAST486_REG_CR0 = 0,
+    FAST486_REG_CR2 = 1,
+    FAST486_REG_CR3 = 2,
 } FAST486_CTRL_REGS, *PFAST486_CTRL_REGS;
 
 typedef enum _FAST486_DBG_REGS
 {
-    FAST486_REG_DR0,
-    FAST486_REG_DR1,
-    FAST486_REG_DR2,
-    FAST486_REG_DR3,
-    FAST486_REG_DR4,
-    FAST486_REG_DR5,
-    FAST486_REG_DR6,
-    FAST486_REG_DR7
+    FAST486_REG_DR0 = 0,
+    FAST486_REG_DR1 = 1,
+    FAST486_REG_DR2 = 2,
+    FAST486_REG_DR3 = 3,
+    FAST486_REG_DR4 = 4,
+    FAST486_REG_DR5 = 5,
+    FAST486_REG_DR6 = 4, // alias to DR4
+    FAST486_REG_DR7 = 5  // alias to DR5
 } FAST486_DBG_REGS, *PFAST486_DBG_REGS;
 
 typedef enum _FAST486_EXCEPTIONS
index e83312e..8ac7fc2 100644 (file)
@@ -71,10 +71,10 @@ Fast486ExtendedHandlers[FAST486_NUM_OPCODE_HANDLERS] =
     NULL, // Invalid
     NULL, // Invalid
     NULL, // Invalid
-    NULL, // TODO: OPCODE 0x20 NOT IMPLEMENTED
-    NULL, // TODO: OPCODE 0x21 NOT IMPLEMENTED
-    NULL, // TODO: OPCODE 0x22 NOT IMPLEMENTED
-    NULL, // TODO: OPCODE 0x23 NOT IMPLEMENTED
+    Fast486ExtOpcodeStoreControlReg,
+    Fast486ExtOpcodeStoreDebugReg,
+    Fast486ExtOpcodeLoadControlReg,
+    Fast486ExtOpcodeLoadDebugReg,
     NULL, // TODO: OPCODE 0x24 NOT IMPLEMENTED
     NULL, // Invalid
     NULL, // TODO: OPCODE 0x26 NOT IMPLEMENTED
@@ -209,7 +209,7 @@ Fast486ExtendedHandlers[FAST486_NUM_OPCODE_HANDLERS] =
     NULL, // Invalid
     Fast486ExtOpcodePushGs,
     Fast486ExtOpcodePopGs,
-    NULL, // TODO: OPCODE 0xAA NOT IMPLEMENTED
+    NULL, // Invalid
     Fast486ExtOpcodeBts,
     NULL, // TODO: OPCODE 0xAC NOT IMPLEMENTED
     NULL, // TODO: OPCODE 0xAD NOT IMPLEMENTED
@@ -299,6 +299,202 @@ Fast486ExtendedHandlers[FAST486_NUM_OPCODE_HANDLERS] =
 
 /* PUBLIC FUNCTIONS ***********************************************************/
 
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeStoreControlReg)
+{
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+    FAST486_MOD_REG_RM ModRegRm;
+
+    NO_LOCK_PREFIX();
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* The current privilege level must be zero */
+    if (Fast486GetCurrentPrivLevel(State) != 0)
+    {
+        Fast486Exception(State, FAST486_EXCEPTION_GP);
+        return FALSE;
+    }
+
+    if ((ModRegRm.Register == 1) || (ModRegRm.Register > 3))
+    {
+        /* CR1, CR4, CR5, CR6 and CR7 don't exist */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    if (ModRegRm.Register != 0)
+    {
+        /* CR2 and CR3 and are stored in array indexes 1 and 2 */
+        ModRegRm.Register--;
+    }
+
+    /* Store the value of the control register */
+    State->GeneralRegs[ModRegRm.SecondRegister].Long = State->ControlRegisters[ModRegRm.Register];
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeStoreDebugReg)
+{
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+    FAST486_MOD_REG_RM ModRegRm;
+
+    NO_LOCK_PREFIX();
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* The current privilege level must be zero */
+    if (Fast486GetCurrentPrivLevel(State) != 0)
+    {
+        Fast486Exception(State, FAST486_EXCEPTION_GP);
+        return FALSE;
+    }
+
+    if ((ModRegRm.Register == 6) || (ModRegRm.Register == 7))
+    {
+        /* DR6 and DR7 are aliases to DR4 and DR5 */
+        ModRegRm.Register -= 2;
+    }
+
+    if (State->DebugRegisters[FAST486_REG_DR5] & FAST486_DR5_GD)
+    {
+        /* Disallow access to debug registers */
+        Fast486Exception(State, FAST486_EXCEPTION_GP);
+        return FALSE;
+    }
+
+    /* Store the value of the debug register */
+    State->GeneralRegs[ModRegRm.SecondRegister].Long = State->DebugRegisters[ModRegRm.Register];
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLoadControlReg)
+{
+    ULONG Value;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+    FAST486_MOD_REG_RM ModRegRm;
+
+    NO_LOCK_PREFIX();
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* The current privilege level must be zero */
+    if (Fast486GetCurrentPrivLevel(State) != 0)
+    {
+        Fast486Exception(State, FAST486_EXCEPTION_GP);
+        return FALSE;
+    }
+
+    if ((ModRegRm.Register == 1) || (ModRegRm.Register > 3))
+    {
+        /* CR1, CR4, CR5, CR6 and CR7 don't exist */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+    
+    if (ModRegRm.Register != 0)
+    {
+        /* CR2 and CR3 and are stored in array indexes 1 and 2 */
+        ModRegRm.Register--;
+    }
+
+    /* Get the value */
+    Value = State->GeneralRegs[ModRegRm.SecondRegister].Long;
+
+    if (ModRegRm.Register == (INT)FAST486_REG_CR0)
+    {
+        /* CR0 checks */
+
+        if (((Value & (FAST486_CR0_PG | FAST486_CR0_PE)) == FAST486_CR0_PG)
+            || ((Value & (FAST486_CR0_CD | FAST486_CR0_NW)) == FAST486_CR0_NW))
+        {
+            /* Invalid value */
+            Fast486Exception(State, FAST486_EXCEPTION_GP);
+            return FALSE;
+        }
+    }
+
+    /* Load a value to the control register */
+    State->ControlRegisters[ModRegRm.Register] = Value;
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLoadDebugReg)
+{
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+    FAST486_MOD_REG_RM ModRegRm;
+
+    NO_LOCK_PREFIX();
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* The current privilege level must be zero */
+    if (Fast486GetCurrentPrivLevel(State) != 0)
+    {
+        Fast486Exception(State, FAST486_EXCEPTION_GP);
+        return FALSE;
+    }
+
+    if ((ModRegRm.Register == 6) || (ModRegRm.Register == 7))
+    {
+        /* DR6 and DR7 are aliases to DR4 and DR5 */
+        ModRegRm.Register -= 2;
+    }
+
+    if (State->DebugRegisters[FAST486_REG_DR5] & FAST486_DR5_GD)
+    {
+        /* Disallow access to debug registers */
+        Fast486Exception(State, FAST486_EXCEPTION_GP);
+        return FALSE;
+    }
+
+    /* Load a value to the debug register */
+    State->DebugRegisters[ModRegRm.Register] = State->GeneralRegs[ModRegRm.SecondRegister].Long;
+
+    if (ModRegRm.Register == (INT)FAST486_REG_DR4)
+    {
+        /* The reserved bits are 1 */
+        State->DebugRegisters[ModRegRm.Register] |= FAST486_DR4_RESERVED;
+    }
+    else if (ModRegRm.Register == (INT)FAST486_REG_DR5)
+    {
+        /* The reserved bits are 0 */
+        State->DebugRegisters[ModRegRm.Register] &= ~FAST486_DR5_RESERVED;
+    }
+
+    /* Return success */
+    return TRUE;
+}
+
 FAST486_OPCODE_HANDLER(Fast486ExtOpcodePushFs)
 {
     /* Call the internal API */
@@ -1062,3 +1258,4 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeExtended)
         return FALSE;
     }
 }
+
index 1f2cf2b..d650c74 100644 (file)
 #define _EXTRAOPS_H_
 
 /* DEFINES ********************************************************************/
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeStoreControlReg);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeStoreDebugReg);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLoadControlReg);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLoadDebugReg);
 FAST486_OPCODE_HANDLER(Fast486ExtOpcodePushFs);
 FAST486_OPCODE_HANDLER(Fast486ExtOpcodePopFs);
 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBitTest);
index 7ec2534..d271a86 100644 (file)
@@ -217,27 +217,19 @@ Fast486DumpState(PFAST486_STATE State)
             State->Flags.Vip ? "VIP" : "vip",
             State->Flags.Iopl);
     DPRINT1("\nControl Registers:\n"
-            "CR0 = %08X\tCR1 = %08X\tCR2 = %08X\tCR3 = %08X\n"
-            "CR4 = %08X\tCR5 = %08X\tCR6 = %08X\tCR7 = %08X\n",
+            "CR0 = %08X\tCR2 = %08X\tCR3 = %08X\n",
             State->ControlRegisters[FAST486_REG_CR0],
-            State->ControlRegisters[FAST486_REG_CR1],
             State->ControlRegisters[FAST486_REG_CR2],
-            State->ControlRegisters[FAST486_REG_CR3],
-            State->ControlRegisters[FAST486_REG_CR4],
-            State->ControlRegisters[FAST486_REG_CR5],
-            State->ControlRegisters[FAST486_REG_CR6],
-            State->ControlRegisters[FAST486_REG_CR7]);
+            State->ControlRegisters[FAST486_REG_CR3]);
     DPRINT1("\nDebug Registers:\n"
-            "DR0 = %08X\tDR1 = %08X\tDR2 = %08X\tDR3 = %08X\n"
-            "DR4 = %08X\tDR5 = %08X\tDR6 = %08X\tDR7 = %08X\n",
+            "DR0 = %08X\tDR1 = %08X\tDR2 = %08X\n"
+            "DR3 = %08X\tDR4 = %08X\tDR5 = %08X\n",
             State->DebugRegisters[FAST486_REG_DR0],
             State->DebugRegisters[FAST486_REG_DR1],
             State->DebugRegisters[FAST486_REG_DR2],
             State->DebugRegisters[FAST486_REG_DR3],
             State->DebugRegisters[FAST486_REG_DR4],
-            State->DebugRegisters[FAST486_REG_DR5],
-            State->DebugRegisters[FAST486_REG_DR6],
-            State->DebugRegisters[FAST486_REG_DR7]);
+            State->DebugRegisters[FAST486_REG_DR5]);
 }
 
 VOID