From f1f5dd79bf8c2cf2ef64cc1432a4a0601d475e72 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Mon, 12 Nov 2007 14:38:59 -0800 Subject: [PATCH] X86: Implement the wrcr microop which writes a control register, and some control register work. --HG-- extra : convert_revision : 3e9daef9cdd0665c033420e5b4f981649e9908ab --- src/arch/x86/isa/decoder/two_byte_opcodes.isa | 2 +- .../general_purpose/data_transfer/move.py | 4 + src/arch/x86/isa/microasm.isa | 3 + src/arch/x86/isa/microops/regop.isa | 52 +++++++++++ src/arch/x86/isa/operands.isa | 4 + src/arch/x86/isa/specialize.isa | 8 +- src/arch/x86/miscregfile.cc | 89 +++++++++---------- 7 files changed, 113 insertions(+), 49 deletions(-) diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index 233a5602d..f3485bc4e 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -202,7 +202,7 @@ 0x0: decode OPCODE_OP_BOTTOM3 { 0x0: mov_Rd_Cd(); 0x1: mov_Rd_Dd(); - 0x2: mov_Cd_Rd(); + 0x2: Inst::MOV(Cd,Rd); 0x3: mov_Dd_Rd(); 0x4: mov_Rd_Td(); 0x6: mov_Td_Rd(); diff --git a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py index ada7f28a3..a15fc21ef 100644 --- a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py +++ b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py @@ -188,6 +188,10 @@ def macroop MOVZX_W_R_P { ld t1, seg, riprel, disp, dataSize=2 zexti reg, t1, 15 }; + +def macroop MOV_C_R { + wrcr reg, regm +}; ''' #let {{ # class MOVD(Inst): diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa index e05582e37..040bb2036 100644 --- a/src/arch/x86/isa/microasm.isa +++ b/src/arch/x86/isa/microasm.isa @@ -113,6 +113,9 @@ let {{ for reg in ('ax', 'bx', 'cx', 'dx', 'sp', 'bp', 'si', 'di'): assembler.symbols["r%s" % reg] = "INTREG_R%s" % reg.upper() + for reg in range(15): + assembler.symbols["cr%d" % reg] = "MISCREG_CR%d" % reg + for flag in ('CF', 'PF', 'ECF', 'AF', 'EZF', 'ZF', 'SF', 'OF'): assembler.symbols[flag] = flag + "Bit" diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index b5e17d36d..58b267e0d 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -884,4 +884,56 @@ let {{ class Zext(RegOp): code = 'DestReg = bits(psrc1, op2, 0);' + + class Wrcr(RegOp): + def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): + super(Wrcr, self).__init__(dest, \ + src1, "NUM_INTREGS", flags, dataSize) + code = ''' + if (dest == 1 || (dest > 4 && dest < 8) || (dest > 8)) { + fault = new InvalidOpcode(); + } else { + // There are *s in the line below so it doesn't confuse the + // parser. They may be unnecessary. + //Mis*cReg old*Val = pick(Cont*rolDest, 0, dat*aSize); + MiscReg newVal = psrc1; + + // Check for any modifications that would cause a fault. + switch(dest) { + case 0: + { + Efer efer = EferOp; + CR0 cr0 = newVal; + CR4 oldCr4 = CR4Op; + if (bits(newVal, 63, 32) || + (!cr0.pe && cr0.pg) || + (!cr0.cd && cr0.nw) || + (cr0.pg && efer.lme && !oldCr4.pae)) + fault = new GeneralProtection(0); + } + break; + case 2: + break; + case 3: + break; + case 4: + { + CR4 cr4 = newVal; + // PAE can't be disabled in long mode. + if (bits(newVal, 63, 11) || + (machInst.mode.mode == LongMode && !cr4.pae)) + fault = new GeneralProtection(0); + } + break; + case 8: + { + if (bits(newVal, 63, 4)) + fault = new GeneralProtection(0); + } + default: + panic("Unrecognized control register %d.\\n", dest); + } + ControlDest = newVal; + } + ''' }}; diff --git a/src/arch/x86/isa/operands.isa b/src/arch/x86/isa/operands.isa index 8c0eacca2..542638edd 100644 --- a/src/arch/x86/isa/operands.isa +++ b/src/arch/x86/isa/operands.isa @@ -122,5 +122,9 @@ def operands {{ # instructions don't map their indexes with an old value. 'TOP': ('ControlReg', 'ub', 'MISCREG_X87_TOP', None, 61), 'SegBase': ('ControlReg', 'uqw', 'MISCREG_SEG_BASE(segment)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 70), + 'ControlDest': ('ControlReg', 'uqw', 'MISCREG_CR(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 71), + 'ControlSrc1': ('ControlReg', 'uqw', 'MISCREG_CR(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 72), + 'EferOp': ('ControlReg', 'uqw', 'MISCREG_EFER', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 73), + 'CR4Op': ('ControlReg', 'uqw', 'MISCREG_CR4', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 74), 'Mem': ('Mem', 'uqw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 100) }}; diff --git a/src/arch/x86/isa/specialize.isa b/src/arch/x86/isa/specialize.isa index cf6b6ff86..3802d8949 100644 --- a/src/arch/x86/isa/specialize.isa +++ b/src/arch/x86/isa/specialize.isa @@ -153,7 +153,13 @@ let {{ return doRipRelativeDecode(Name, opTypes, env) elif opType.tag == None or opType.size == None: raise Exception, "Problem parsing operand tag: %s" % opType.tag - elif opType.tag in ("C", "D", "G", "P", "S", "T", "V"): + elif opType.tag == "C": + env.addReg(ModRMRegIndex) + Name += "_C" + elif opType.tag == "D": + env.addReg(ModRMRegIndex) + Name += "_D" + elif opType.tag in ("G", "P", "S", "T", "V"): # Use the "reg" field of the ModRM byte to select the register env.addReg(ModRMRegIndex) Name += "_R" diff --git a/src/arch/x86/miscregfile.cc b/src/arch/x86/miscregfile.cc index cd76e96aa..a6aed336f 100644 --- a/src/arch/x86/miscregfile.cc +++ b/src/arch/x86/miscregfile.cc @@ -106,22 +106,15 @@ void MiscRegFile::clear() MiscReg MiscRegFile::readRegNoEffect(int miscReg) { - switch(miscReg) - { - case MISCREG_CR1: - case MISCREG_CR5: - case MISCREG_CR6: - case MISCREG_CR7: - case MISCREG_CR9: - case MISCREG_CR10: - case MISCREG_CR11: - case MISCREG_CR12: - case MISCREG_CR13: - case MISCREG_CR14: - case MISCREG_CR15: - panic("Tried to read invalid control register %d\n", miscReg); - break; - } + // 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]; } @@ -132,22 +125,14 @@ MiscReg MiscRegFile::readReg(int miscReg, ThreadContext * tc) void MiscRegFile::setRegNoEffect(int miscReg, const MiscReg &val) { - switch(miscReg) - { - case MISCREG_CR1: - case MISCREG_CR5: - case MISCREG_CR6: - case MISCREG_CR7: - case MISCREG_CR9: - case MISCREG_CR10: - case MISCREG_CR11: - case MISCREG_CR12: - case MISCREG_CR13: - case MISCREG_CR14: - case MISCREG_CR15: - panic("Tried to write invalid control register %d\n", miscReg); - break; - } + // 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; } @@ -158,23 +143,33 @@ void MiscRegFile::setReg(int miscReg, switch(miscReg) { case MISCREG_CR0: - CR0 toggled = regVal[miscReg] ^ val; - CR0 newCR0 = val; - Efer efer = regVal[MISCREG_EFER]; - if (toggled.pg && efer.lme) { - if (newCR0.pg) { - //Turning on long mode - efer.lma = 1; - regVal[MISCREG_EFER] = efer; - } else { - //Turning off long mode - efer.lma = 0; - regVal[MISCREG_EFER] = efer; + { + CR0 toggled = regVal[miscReg] ^ val; + CR0 newCR0 = val; + Efer efer = regVal[MISCREG_EFER]; + if (toggled.pg && efer.lme) { + if (newCR0.pg) { + //Turning on long mode + efer.lma = 1; + regVal[MISCREG_EFER] = efer; + } else { + //Turning off long mode + efer.lma = 0; + regVal[MISCREG_EFER] = efer; + } } + //This must always be 1. + newCR0.et = 1; + newVal = newCR0; } - //This must always be 1. - newCR0.et = 1; - newVal = newCR0; + break; + case MISCREG_CR2: + break; + case MISCREG_CR3: + break; + case MISCREG_CR4: + break; + case MISCREG_CR8: break; } setRegNoEffect(miscReg, newVal); -- 2.30.2