[FAST486]

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
This commit is contained in:
Aleksandar Andrejevic 2013-10-26 00:56:11 +00:00
parent 87f5903d48
commit 1525a235a2
4 changed files with 251 additions and 36 deletions

View 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)
@ -41,6 +41,33 @@
#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

View 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;
}
}

View file

@ -23,6 +23,10 @@
#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);

View 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