diff options
Diffstat (limited to 'src/arch/x86/miscregfile.cc')
-rw-r--r-- | src/arch/x86/miscregfile.cc | 71 |
1 files changed, 42 insertions, 29 deletions
diff --git a/src/arch/x86/miscregfile.cc b/src/arch/x86/miscregfile.cc index 0316603e5..b3ce7076e 100644 --- a/src/arch/x86/miscregfile.cc +++ b/src/arch/x86/miscregfile.cc @@ -96,6 +96,31 @@ using namespace std; class Checkpoint; +void MiscRegFile::updateHandyM5Reg(Efer efer, CR0 cr0, + SegAttr csAttr, RFLAGS rflags) +{ + HandyM5Reg m5reg; + if (efer.lma) { + m5reg.mode = LongMode; + if (csAttr.longMode) + m5reg.submode = SixtyFourBitMode; + else + m5reg.submode = CompatabilityMode; + } else { + m5reg.mode = LegacyMode; + if (cr0.pe) { + if (rflags.vm) + m5reg.submode = Virtual8086Mode; + else + m5reg.submode = ProtectedMode; + } else { + m5reg.submode = RealMode; + } + } + m5reg.cpl = csAttr.dpl; + regVal[MISCREG_M5_REG] = m5reg; +} + void MiscRegFile::clear() { // Blank everything. 0 might not be an appropriate value for some things, @@ -151,39 +176,17 @@ void MiscRegFile::setReg(MiscRegIndex 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(); @@ -191,6 +194,10 @@ void MiscRegFile::setReg(MiscRegIndex miscReg, //This must always be 1. newCR0.et = 1; newVal = newCR0; + updateHandyM5Reg(regVal[MISCREG_EFER], + newCR0, + regVal[MISCREG_CS_ATTR], + regVal[MISCREG_RFLAGS]); } break; case MISCREG_CR2: @@ -214,26 +221,23 @@ void MiscRegFile::setReg(MiscRegIndex miscReg, { SegAttr toggled = regVal[miscReg] ^ val; SegAttr newCSAttr = val; - HandyM5Reg m5reg = regVal[MISCREG_M5_REG]; if (toggled.longMode) { 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; + updateHandyM5Reg(regVal[MISCREG_EFER], + regVal[MISCREG_CR0], + newCSAttr, + regVal[MISCREG_RFLAGS]); } break; // These segments always actually use their bases, or in other words @@ -333,6 +337,15 @@ void MiscRegFile::setReg(MiscRegIndex miscReg, dr7.len3 = newDR7.len3; } break; + case MISCREG_M5_REG: + // Writing anything to the m5reg with side effects makes it update + // based on the current values of the relevant registers. The actual + // value written is discarded. + updateHandyM5Reg(regVal[MISCREG_EFER], + regVal[MISCREG_CR0], + regVal[MISCREG_CS_ATTR], + regVal[MISCREG_RFLAGS]); + return; default: break; } |