summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/x86/isa/decoder/two_byte_opcodes.isa2
-rw-r--r--src/arch/x86/isa/insts/general_purpose/data_transfer/move.py4
-rw-r--r--src/arch/x86/isa/microasm.isa3
-rw-r--r--src/arch/x86/isa/microops/regop.isa52
-rw-r--r--src/arch/x86/isa/operands.isa4
-rw-r--r--src/arch/x86/isa/specialize.isa8
-rw-r--r--src/arch/x86/miscregfile.cc89
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);