+ 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);