X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Farch%2Fx86%2Fmiscregfile.cc;h=388a83e8df9c89b044c211ade5983435cfce0f04;hb=06cdbe5ea7138d0f340448438d64e98c72936e1b;hp=14ba3c7cce2bf4a73bd8ff5a795f91940113900b;hpb=8edc9d79cee3edd6d16a8254a0180aaa242974c7;p=gem5.git diff --git a/src/arch/x86/miscregfile.cc b/src/arch/x86/miscregfile.cc index 14ba3c7cc..388a83e8d 100644 --- a/src/arch/x86/miscregfile.cc +++ b/src/arch/x86/miscregfile.cc @@ -1,5 +1,5 @@ /* - * 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 @@ -29,7 +29,7 @@ */ /* - * 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, @@ -86,6 +86,10 @@ */ #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; @@ -100,36 +104,181 @@ string X86ISA::getMiscRegName(RegIndex index) void MiscRegFile::clear() { - //When there are actually misc regs implemented, this will clear them + // Blank everything. 0 might not be an appropriate value for some things. + memset(regVal, 0, NumMiscRegs * sizeof(MiscReg)); } -MiscReg MiscRegFile::readRegNoEffect(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::readReg(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::setRegNoEffect(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::setReg(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); }