summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/arch/x86/isa/microops/regop.isa5
-rw-r--r--src/arch/x86/isa/operands.isa1
-rw-r--r--src/arch/x86/miscregfile.cc30
-rw-r--r--src/arch/x86/miscregs.hh9
4 files changed, 44 insertions, 1 deletions
diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa
index 6bd26608e..35f319528 100644
--- a/src/arch/x86/isa/microops/regop.isa
+++ b/src/arch/x86/isa/microops/regop.isa
@@ -1100,6 +1100,11 @@ let {{
DestReg = TscOp;
'''
+ class Rdm5reg(RdRegOp):
+ code = '''
+ DestReg = M5Reg;
+ '''
+
class Wrdl(RegOp):
code = '''
SegDescriptor desc = SrcReg1;
diff --git a/src/arch/x86/isa/operands.isa b/src/arch/x86/isa/operands.isa
index f002b2cea..446580c1b 100644
--- a/src/arch/x86/isa/operands.isa
+++ b/src/arch/x86/isa/operands.isa
@@ -151,5 +151,6 @@ def operands {{
'CSBase': ('ControlReg', 'udw', 'MISCREG_CS_EFF_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 207),
'CSAttr': ('ControlReg', 'udw', 'MISCREG_CS_ATTR', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 208),
'TscOp': ('ControlReg', 'udw', 'MISCREG_TSC', (None, None, ['IsSerializeAfter', 'IsSerializing', 'IsNonSpeculative']), 209),
+ 'M5Reg': ('ControlReg', 'udw', 'MISCREG_M5_REG', (None, None, None), 210),
'Mem': ('Mem', 'uqw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 300)
}};
diff --git a/src/arch/x86/miscregfile.cc b/src/arch/x86/miscregfile.cc
index 930bf53c7..6abeb7d34 100644
--- a/src/arch/x86/miscregfile.cc
+++ b/src/arch/x86/miscregfile.cc
@@ -300,17 +300,39 @@ void MiscRegFile::setReg(int miscReg,
CR0 toggled = regVal[miscReg] ^ val;
CR0 newCR0 = val;
Efer efer = regVal[MISCREG_EFER];
+ HandyM5Reg m5reg = regVal[MISCREG_M5_REG];
if (toggled.pg && efer.lme) {
if (newCR0.pg) {
//Turning on long mode
efer.lma = 1;
+ m5reg.mode = LongMode;
regVal[MISCREG_EFER] = efer;
} else {
//Turning off long mode
efer.lma = 0;
+ m5reg.mode = LegacyMode;
regVal[MISCREG_EFER] = efer;
}
}
+ // Figure out what submode we're in.
+ if (m5reg.mode == LongMode) {
+ SegAttr csAttr = regVal[MISCREG_CS_ATTR];
+ if (csAttr.longMode)
+ m5reg.submode = SixtyFourBitMode;
+ else
+ m5reg.submode = CompatabilityMode;
+ } else {
+ if (newCR0.pe) {
+ RFLAGS rflags = regVal[MISCREG_RFLAGS];
+ if (rflags.vm)
+ m5reg.submode = Virtual8086Mode;
+ else
+ m5reg.submode = ProtectedMode;
+ } else {
+ m5reg.submode = RealMode;
+ }
+ }
+ regVal[MISCREG_M5_REG] = m5reg;
if (toggled.pg) {
tc->getITBPtr()->invalidateAll();
tc->getDTBPtr()->invalidateAll();
@@ -341,20 +363,26 @@ void MiscRegFile::setReg(int miscReg,
{
SegAttr toggled = regVal[miscReg] ^ val;
SegAttr newCSAttr = val;
+ HandyM5Reg m5reg = regVal[MISCREG_M5_REG];
if (toggled.longMode) {
- SegAttr newCSAttr = val;
if (newCSAttr.longMode) {
+ if (m5reg.mode == LongMode)
+ m5reg.submode = SixtyFourBitMode;
regVal[MISCREG_ES_EFF_BASE] = 0;
regVal[MISCREG_CS_EFF_BASE] = 0;
regVal[MISCREG_SS_EFF_BASE] = 0;
regVal[MISCREG_DS_EFF_BASE] = 0;
} else {
+ if (m5reg.mode == LongMode)
+ m5reg.submode = CompatabilityMode;
regVal[MISCREG_ES_EFF_BASE] = regVal[MISCREG_ES_BASE];
regVal[MISCREG_CS_EFF_BASE] = regVal[MISCREG_CS_BASE];
regVal[MISCREG_SS_EFF_BASE] = regVal[MISCREG_SS_BASE];
regVal[MISCREG_DS_EFF_BASE] = regVal[MISCREG_DS_BASE];
}
}
+ m5reg.cpl = newCSAttr.dpl;
+ regVal[MISCREG_M5_REG] = m5reg;
}
break;
// These segments always actually use their bases, or in other words
diff --git a/src/arch/x86/miscregs.hh b/src/arch/x86/miscregs.hh
index 90f1d9fda..caa1e817b 100644
--- a/src/arch/x86/miscregs.hh
+++ b/src/arch/x86/miscregs.hh
@@ -130,6 +130,9 @@ namespace X86ISA
// Flags register
MISCREG_RFLAGS = MISCREG_DR_BASE + NumDRegs,
+ //Register to keep handy values like the CPU mode in.
+ MISCREG_M5_REG,
+
/*
* Model Specific Registers
*/
@@ -563,6 +566,12 @@ namespace X86ISA
Bitfield<0> cf; // Carry Flag
EndBitUnion(RFLAGS)
+ BitUnion64(HandyM5Reg)
+ Bitfield<0> mode;
+ Bitfield<3, 1> submode;
+ Bitfield<5, 4> cpl;
+ EndBitUnion(HandyM5Reg)
+
/**
* Control registers
*/