X86: Implement the wrcr microop which writes a control register, and some control register work.
--HG-- extra : convert_revision : 3e9daef9cdd0665c033420e5b4f981649e9908ab
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
'''
|
||||
}};
|
||||
|
||||
@@ -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)
|
||||
}};
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user