/*
- * Copyright (c) 2003-2006 The Regents of The University of Michigan
+ * Copyright (c) 2003-2006, 2008 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
*/
/*
- * Copyright (c) 2007 The Hewlett-Packard Development Company
+ * Copyright (c) 2007-2008 The Hewlett-Packard Development Company
* All rights reserved.
*
* Redistribution and use of this software in source and binary forms,
*/
#include "arch/x86/miscregfile.hh"
+#include "arch/x86/tlb.hh"
+#include "cpu/base.hh"
+#include "cpu/thread_context.hh"
+#include "sim/serialize.hh"
using namespace X86ISA;
using namespace std;
void MiscRegFile::clear()
{
- panic("No misc registers in x86 yet!\n");
+ // Blank everything. 0 might not be an appropriate value for some things.
+ memset(regVal, 0, NumMiscRegs * sizeof(MiscReg));
}
-MiscReg MiscRegFile::readReg(int miscReg)
+MiscReg MiscRegFile::readRegNoEffect(MiscRegIndex miscReg)
{
- panic("No misc registers in x86 yet!\n");
+ // Make sure we're not dealing with an illegal control register.
+ // Instructions should filter out these indexes, and nothing else should
+ // attempt to read them directly.
+ assert( miscReg != MISCREG_CR1 &&
+ !(miscReg > MISCREG_CR4 &&
+ miscReg < MISCREG_CR8) &&
+ !(miscReg > MISCREG_CR8 &&
+ miscReg <= MISCREG_CR15));
+
+ return regVal[miscReg];
}
-MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc)
+MiscReg MiscRegFile::readReg(MiscRegIndex miscReg, ThreadContext * tc)
{
- panic("No misc registers in x86 yet!\n");
+ if (miscReg == MISCREG_TSC) {
+ return regVal[MISCREG_TSC] + tc->getCpuPtr()->curCycle();
+ }
+ return readRegNoEffect(miscReg);
}
-void MiscRegFile::setReg(int miscReg, const MiscReg &val)
+void MiscRegFile::setRegNoEffect(MiscRegIndex miscReg, const MiscReg &val)
{
- panic("No misc registers in x86 yet!\n");
+ // Make sure we're not dealing with an illegal control register.
+ // Instructions should filter out these indexes, and nothing else should
+ // attempt to write to them directly.
+ assert( miscReg != MISCREG_CR1 &&
+ !(miscReg > MISCREG_CR4 &&
+ miscReg < MISCREG_CR8) &&
+ !(miscReg > MISCREG_CR8 &&
+ miscReg <= MISCREG_CR15));
+ regVal[miscReg] = val;
}
-void MiscRegFile::setRegWithEffect(int miscReg,
+void MiscRegFile::setReg(MiscRegIndex miscReg,
const MiscReg &val, ThreadContext * tc)
{
- panic("No misc registers in x86 yet!\n");
+ MiscReg newVal = val;
+ switch(miscReg)
+ {
+ case MISCREG_CR0:
+ {
+ 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();
+ }
+ //This must always be 1.
+ newCR0.et = 1;
+ newVal = newCR0;
+ }
+ break;
+ case MISCREG_CR2:
+ break;
+ case MISCREG_CR3:
+ tc->getITBPtr()->invalidateNonGlobal();
+ tc->getDTBPtr()->invalidateNonGlobal();
+ break;
+ case MISCREG_CR4:
+ {
+ CR4 toggled = regVal[miscReg] ^ val;
+ if (toggled.pae || toggled.pse || toggled.pge) {
+ tc->getITBPtr()->invalidateAll();
+ tc->getDTBPtr()->invalidateAll();
+ }
+ }
+ break;
+ case MISCREG_CR8:
+ break;
+ case MISCREG_CS_ATTR:
+ {
+ 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;
+ }
+ break;
+ // These segments always actually use their bases, or in other words
+ // their effective bases must stay equal to their actual bases.
+ case MISCREG_FS_BASE:
+ case MISCREG_GS_BASE:
+ case MISCREG_HS_BASE:
+ case MISCREG_TSL_BASE:
+ case MISCREG_TSG_BASE:
+ case MISCREG_TR_BASE:
+ case MISCREG_IDTR_BASE:
+ regVal[MISCREG_SEG_EFF_BASE(miscReg - MISCREG_SEG_BASE_BASE)] = val;
+ break;
+ // These segments ignore their bases in 64 bit mode.
+ // their effective bases must stay equal to their actual bases.
+ case MISCREG_ES_BASE:
+ case MISCREG_CS_BASE:
+ case MISCREG_SS_BASE:
+ case MISCREG_DS_BASE:
+ {
+ Efer efer = regVal[MISCREG_EFER];
+ SegAttr csAttr = regVal[MISCREG_CS_ATTR];
+ if (!efer.lma || !csAttr.longMode) // Check for non 64 bit mode.
+ regVal[MISCREG_SEG_EFF_BASE(miscReg -
+ MISCREG_SEG_BASE_BASE)] = val;
+ }
+ break;
+ case MISCREG_TSC:
+ regVal[MISCREG_TSC] = val - tc->getCpuPtr()->curCycle();
+ return;
+ default:
+ break;
+ }
+ setRegNoEffect(miscReg, newVal);
}
void MiscRegFile::serialize(std::ostream & os)
{
- panic("No misc registers in x86 yet!\n");
+ SERIALIZE_ARRAY(regVal, NumMiscRegs);
}
void MiscRegFile::unserialize(Checkpoint * cp, const std::string & section)
{
- panic("No misc registers in x86 yet!\n");
+ UNSERIALIZE_ARRAY(regVal, NumMiscRegs);
}