summaryrefslogtreecommitdiff
path: root/src/arch/x86/isa/microops/regop.isa
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/x86/isa/microops/regop.isa')
-rw-r--r--src/arch/x86/isa/microops/regop.isa323
1 files changed, 275 insertions, 48 deletions
diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa
index e761f0034..f9bc82119 100644
--- a/src/arch/x86/isa/microops/regop.isa
+++ b/src/arch/x86/isa/microops/regop.isa
@@ -1,4 +1,4 @@
-// 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,
@@ -231,6 +231,21 @@ output header {{
void
divide(uint64_t dividend, uint64_t divisor,
uint64_t &quotient, uint64_t &remainder);
+
+ enum SegmentSelectorCheck {
+ SegNoCheck, SegCSCheck, SegCallGateCheck, SegIntGateCheck,
+ SegSoftIntGateCheck, SegSSCheck, SegIretCheck, SegIntCSCheck,
+ SegTRCheck, SegTSSCheck, SegInGDTCheck, SegLDTCheck
+ };
+
+ enum LongModeDescriptorType {
+ LDT64 = 2,
+ AvailableTSS64 = 9,
+ BusyTSS64 = 0xb,
+ CallGate64 = 0xc,
+ IntGate64 = 0xe,
+ TrapGate64 = 0xf
+ };
}};
output decoder {{
@@ -424,7 +439,7 @@ let {{
className = self.className
if self.mnemonic == self.base_mnemonic + 'i':
className += "Imm"
- allocator = '''new %(class_name)s(machInst, mnemonic
+ allocator = '''new %(class_name)s(machInst, macrocodeBlock
%(flags)s, %(src1)s, %(op2)s, %(dest)s,
%(dataSize)s, %(ext)s)''' % {
"class_name" : className,
@@ -838,19 +853,28 @@ let {{
code = 'RIP = psrc1 + sop2 + CSBase'
else_code="RIP = RIP;"
- class Br(WrRegOp, CondRegOp):
- code = 'nuIP = psrc1 + op2;'
- else_code='nuIP = nuIP;'
-
class Wruflags(WrRegOp):
code = 'ccFlagBits = psrc1 ^ op2'
+ class Wrflags(WrRegOp):
+ code = '''
+ MiscReg newFlags = psrc1 ^ op2;
+ MiscReg userFlagMask = 0xDD5;
+ // Get only the user flags
+ ccFlagBits = newFlags & userFlagMask;
+ // Get everything else
+ nccFlagBits = newFlags & ~userFlagMask;
+ '''
+
class Rdip(RdRegOp):
code = 'DestReg = RIP - CSBase'
class Ruflags(RdRegOp):
code = 'DestReg = ccFlagBits'
+ class Rflags(RdRegOp):
+ code = 'DestReg = ccFlagBits | nccFlagBits'
+
class Ruflag(RegOp):
code = '''
int flag = bits(ccFlagBits, imm8);
@@ -863,6 +887,20 @@ let {{
super(Ruflag, self).__init__(dest, \
"NUM_INTREGS", imm, flags, dataSize)
+ class Rflag(RegOp):
+ code = '''
+ MiscReg flagMask = 0x3F7FDD5;
+ MiscReg flags = (nccFlagBits | ccFlagBits) & flagMask;
+ int flag = bits(flags, imm8);
+ DestReg = merge(DestReg, flag, dataSize);
+ ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) :
+ (ccFlagBits & ~EZFBit);
+ '''
+ def __init__(self, dest, imm, flags=None, \
+ dataSize="env.dataSize"):
+ super(Rflag, self).__init__(dest, \
+ "NUM_INTREGS", imm, flags, dataSize)
+
class Sext(RegOp):
code = '''
IntReg val = psrc1;
@@ -883,17 +921,53 @@ let {{
'''
class Zext(RegOp):
- code = 'DestReg = bits(psrc1, op2, 0);'
+ code = 'DestReg = merge(DestReg, bits(psrc1, op2, 0), dataSize);'
+
+ class Rddr(RegOp):
+ def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
+ super(Rddr, self).__init__(dest, \
+ src1, "NUM_INTREGS", flags, dataSize)
+ code = '''
+ CR4 cr4 = CR4Op;
+ DR7 dr7 = DR7Op;
+ if ((cr4.de == 1 && (src1 == 4 || src1 == 5)) || src1 >= 8) {
+ fault = new InvalidOpcode();
+ } else if (dr7.gd) {
+ fault = new DebugException();
+ } else {
+ DestReg = merge(DestReg, DebugSrc1, dataSize);
+ }
+ '''
+
+ class Wrdr(RegOp):
+ def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
+ super(Wrdr, self).__init__(dest, \
+ src1, "NUM_INTREGS", flags, dataSize)
+ code = '''
+ CR4 cr4 = CR4Op;
+ DR7 dr7 = DR7Op;
+ if ((cr4.de == 1 && (dest == 4 || dest == 5)) || dest >= 8) {
+ fault = new InvalidOpcode();
+ } else if ((dest == 6 || dest == 7) &&
+ bits(psrc1, 63, 32) &&
+ machInst.mode.mode == LongMode) {
+ fault = new GeneralProtection(0);
+ } else if (dr7.gd) {
+ fault = new DebugException();
+ } else {
+ DebugDest = psrc1;
+ }
+ '''
class Rdcr(RegOp):
def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
super(Rdcr, self).__init__(dest, \
src1, "NUM_INTREGS", flags, dataSize)
code = '''
- if (dest == 1 || (dest > 4 && dest < 8) || (dest > 8)) {
+ if (src1 == 1 || (src1 > 4 && src1 < 8) || (src1 > 8)) {
fault = new InvalidOpcode();
} else {
- DestReg = ControlSrc1;
+ DestReg = merge(DestReg, ControlSrc1, dataSize);
}
'''
@@ -950,7 +1024,7 @@ let {{
'''
# Microops for manipulating segmentation registers
- class SegOp(RegOp):
+ class SegOp(CondRegOp):
abstract = True
def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
super(SegOp, self).__init__(dest, \
@@ -971,74 +1045,223 @@ let {{
SegSelDest = psrc1;
'''
+ class WrAttr(SegOp):
+ code = '''
+ SegAttrDest = psrc1;
+ '''
+
class Rdbase(SegOp):
code = '''
- DestReg = SegBaseDest;
+ DestReg = merge(DestReg, SegBaseSrc1, dataSize);
'''
class Rdlimit(SegOp):
code = '''
- DestReg = SegLimitSrc1;
+ DestReg = merge(DestReg, SegLimitSrc1, dataSize);
+ '''
+
+ class RdAttr(SegOp):
+ code = '''
+ DestReg = merge(DestReg, SegAttrSrc1, dataSize);
'''
class Rdsel(SegOp):
code = '''
- DestReg = SegSelSrc1;
+ DestReg = merge(DestReg, SegSelSrc1, dataSize);
'''
- class Chks(SegOp):
+ class Rdval(RegOp):
+ def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
+ super(Rdval, self).__init__(dest, \
+ src1, "NUM_INTREGS", flags, dataSize)
code = '''
- // The selector is in source 1.
- SegSelector selector = psrc1;
-
- // Compute the address of the descriptor and set DestReg to it.
- if (selector.ti) {
- // A descriptor in the LDT
- Addr target = (selector.esi << 3) + LDTRBase;
- if (!LDTRSel || (selector.esi << 3) + dataSize > LDTRLimit)
- fault = new GeneralProtection(selector & mask(16));
- DestReg = target;
- } else {
- // A descriptor in the GDT
- Addr target = (selector.esi << 3) + GDTRBase;
- if ((selector.esi << 3) + dataSize > GDTRLimit)
- fault = new GeneralProtection(selector & mask(16));
- DestReg = target;
+ DestReg = MiscRegSrc1;
+ '''
+
+ class Wrval(RegOp):
+ def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
+ super(Wrval, self).__init__(dest, \
+ src1, "NUM_INTREGS", flags, dataSize)
+ code = '''
+ MiscRegDest = SrcReg1;
+ '''
+
+ class Chks(RegOp):
+ def __init__(self, dest, src1, src2=0,
+ flags=None, dataSize="env.dataSize"):
+ super(Chks, self).__init__(dest,
+ src1, src2, flags, dataSize)
+ code = '''
+ // The selector is in source 1 and can be at most 16 bits.
+ SegSelector selector = DestReg;
+ SegDescriptor desc = SrcReg1;
+ HandyM5Reg m5reg = M5Reg;
+
+ switch (imm8)
+ {
+ case SegNoCheck:
+ break;
+ case SegCSCheck:
+ panic("CS checks for far calls/jumps not implemented.\\n");
+ break;
+ case SegCallGateCheck:
+ panic("CS checks for far calls/jumps through call gates"
+ "not implemented.\\n");
+ break;
+ case SegSoftIntGateCheck:
+ // Check permissions.
+ if (desc.dpl < m5reg.cpl) {
+ fault = new GeneralProtection(selector);
+ }
+ // Fall through on purpose
+ case SegIntGateCheck:
+ // Make sure the gate's the right type.
+ if ((m5reg.mode == LongMode && (desc.type & 0xe) != 0xe) ||
+ ((desc.type & 0x6) != 0x6)) {
+ fault = new GeneralProtection(0);
+ }
+ break;
+ case SegSSCheck:
+ if (selector.si || selector.ti) {
+ if (!desc.p) {
+ fault = new StackFault(selector);
+ }
+ } else {
+ if ((m5reg.submode != SixtyFourBitMode ||
+ m5reg.cpl == 3) ||
+ !(desc.s == 1 &&
+ desc.type.codeOrData == 0 && desc.type.w) ||
+ (desc.dpl != m5reg.cpl) ||
+ (selector.rpl != m5reg.cpl)) {
+ fault = new GeneralProtection(selector);
+ }
+ }
+ break;
+ case SegIretCheck:
+ {
+ if ((!selector.si && !selector.ti) ||
+ (selector.rpl < m5reg.cpl) ||
+ !(desc.s == 1 && desc.type.codeOrData == 1) ||
+ (!desc.type.c && desc.dpl != selector.rpl) ||
+ (desc.type.c && desc.dpl > selector.rpl)) {
+ fault = new GeneralProtection(selector);
+ } else if (!desc.p) {
+ fault = new SegmentNotPresent(selector);
+ }
+ break;
+ }
+ case SegIntCSCheck:
+ if (m5reg.mode == LongMode) {
+ if (desc.l != 1 || desc.d != 0) {
+ fault = new GeneralProtection(selector);
+ }
+ } else {
+ panic("Interrupt CS checks not implemented "
+ "in legacy mode.\\n");
+ }
+ break;
+ case SegTRCheck:
+ if (!selector.si || selector.ti) {
+ fault = new GeneralProtection(selector);
+ }
+ break;
+ case SegTSSCheck:
+ if (!desc.p) {
+ fault = new SegmentNotPresent(selector);
+ } else if (!(desc.type == 0x9 ||
+ (desc.type == 1 &&
+ m5reg.mode != LongMode))) {
+ fault = new GeneralProtection(selector);
+ }
+ break;
+ case SegInGDTCheck:
+ if (selector.ti) {
+ fault = new GeneralProtection(selector);
+ }
+ break;
+ case SegLDTCheck:
+ if (!desc.p) {
+ fault = new SegmentNotPresent(selector);
+ } else if (desc.type != 0x2) {
+ fault = new GeneralProtection(selector);
+ }
+ break;
+ default:
+ panic("Undefined segment check type.\\n");
}
'''
flag_code = '''
// Check for a NULL selector and set ZF,EZF appropriately.
ccFlagBits = ccFlagBits & ~(ext & (ZFBit | EZFBit));
- if (!selector.esi && !selector.ti)
+ if (!selector.si && !selector.ti)
ccFlagBits = ccFlagBits | (ext & (ZFBit | EZFBit));
'''
class Wrdh(RegOp):
code = '''
+ SegDescriptor desc = SrcReg1;
+
+ uint64_t target = bits(SrcReg2, 31, 0) << 32;
+ switch(desc.type) {
+ case LDT64:
+ case AvailableTSS64:
+ case BusyTSS64:
+ replaceBits(target, 23, 0, desc.baseLow);
+ replaceBits(target, 31, 24, desc.baseHigh);
+ break;
+ case CallGate64:
+ case IntGate64:
+ case TrapGate64:
+ replaceBits(target, 15, 0, bits(desc, 15, 0));
+ replaceBits(target, 31, 16, bits(desc, 63, 48));
+ break;
+ default:
+ panic("Wrdh used with wrong descriptor type!\\n");
+ }
+ DestReg = target;
+ '''
+
+ class Wrtsc(WrRegOp):
+ code = '''
+ TscOp = psrc1;
+ '''
+
+ class Rdtsc(RdRegOp):
+ code = '''
+ DestReg = TscOp;
+ '''
+ class Rdm5reg(RdRegOp):
+ code = '''
+ DestReg = M5Reg;
'''
class Wrdl(RegOp):
code = '''
SegDescriptor desc = SrcReg1;
- SegAttr attr = 0;
- attr.dpl = desc.dpl;
- attr.defaultSize = desc.d;
- if (!desc.s) {
- SegBaseDest = SegBaseDest;
- SegLimitDest = SegLimitDest;
- SegAttrDest = SegAttrDest;
- panic("System segment encountered.\\n");
- } else {
- if (!desc.p)
- panic("Segment not present.\\n");
- if (desc.type.codeOrData) {
- attr.readable = desc.type.r;
- attr.longMode = desc.l;
- } else {
- attr.expandDown = desc.type.e;
+ SegSelector selector = SrcReg2;
+ if (selector.si || selector.ti) {
+ SegAttr attr = 0;
+ attr.dpl = desc.dpl;
+ attr.defaultSize = desc.d;
+ if (!desc.s) {
+ // The expand down bit happens to be set for gates.
+ if (desc.type.e) {
+ panic("Gate descriptor encountered.\\n");
+ }
attr.readable = 1;
- attr.writable = desc.type.w;
+ attr.writable = 1;
+ } else {
+ if (!desc.p)
+ panic("Segment not present.\\n");
+ if (desc.type.codeOrData) {
+ attr.readable = desc.type.r;
+ attr.longMode = desc.l;
+ } else {
+ attr.expandDown = desc.type.e;
+ attr.readable = 1;
+ attr.writable = desc.type.w;
+ }
}
Addr base = desc.baseLow | (desc.baseHigh << 24);
Addr limit = desc.limitLow | (desc.limitHigh << 16);
@@ -1047,6 +1270,10 @@ let {{
SegBaseDest = base;
SegLimitDest = limit;
SegAttrDest = attr;
+ } else {
+ SegBaseDest = SegBaseDest;
+ SegLimitDest = SegLimitDest;
+ SegAttrDest = SegAttrDest;
}
'''
}};