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.isa98
1 files changed, 54 insertions, 44 deletions
diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa
index 35f319528..b751b9b4f 100644
--- a/src/arch/x86/isa/microops/regop.isa
+++ b/src/arch/x86/isa/microops/regop.isa
@@ -1030,7 +1030,9 @@ let {{
src1, src2, flags, dataSize)
code = '''
// The selector is in source 1 and can be at most 16 bits.
- SegSelector selector = psrc1;
+ SegSelector selector = DestReg;
+ SegDescriptor desc = SrcReg1;
+ HandyM5Reg m5reg = M5Reg;
switch (imm8)
{
@@ -1044,15 +1046,31 @@ let {{
"not implemented.\\n");
break;
case SegSSCheck:
- panic("SS selector checks not implemented.\\n");
+ if (selector.si || selector.ti) {
+ if (!desc.p) {
+ //FIXME This needs to also push the selector.
+ return new StackFault;
+ }
+ } else {
+ if ((m5reg.mode != SixtyFourBitMode || m5reg.cpl == 3) ||
+ !(desc.s == 1 &&
+ desc.type.codeOrData == 0 && desc.type.w) ||
+ (desc.dpl != m5reg.cpl) ||
+ (selector.rpl != m5reg.cpl)) {
+ return new GeneralProtection(psrc1 & 0xFFFF);
+ }
+ }
break;
case SegIretCheck:
{
- SegAttr csAttr = CSAttr;
- if (!selector.si && !selector.ti)
- return new GeneralProtection(psrc1 & 0xFFFF);
- if (selector.rpl < csAttr.dpl)
+ 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))
return new GeneralProtection(psrc1 & 0xFFFF);
+ if (!desc.p)
+ return new SegmentNotPresent;
break;
}
case SegIntCSCheck:
@@ -1062,21 +1080,6 @@ let {{
default:
panic("Undefined segment check type.\\n");
}
-
- // Compute the address of the descriptor and set DestReg to it.
- if (selector.ti) {
- // A descriptor in the LDT
- Addr target = (selector.si << 3) + LDTRBase;
- if (!LDTRSel || (selector.si << 3) + dataSize > LDTRLimit)
- fault = new GeneralProtection(selector & mask(16));
- DestReg = target;
- } else {
- // A descriptor in the GDT
- Addr target = (selector.si << 3) + GDTRBase;
- if ((selector.si << 3) + dataSize > GDTRLimit)
- fault = new GeneralProtection(selector & mask(16));
- DestReg = target;
- }
'''
flag_code = '''
// Check for a NULL selector and set ZF,EZF appropriately.
@@ -1108,32 +1111,39 @@ let {{
class Wrdl(RegOp):
code = '''
SegDescriptor desc = SrcReg1;
- SegAttr attr = 0;
- attr.dpl = desc.dpl;
- attr.defaultSize = desc.d;
- if (!desc.s) {
+ SegSelector selector = SrcReg2;
+ if (selector.si || selector.ti) {
+ 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;
+ attr.readable = 1;
+ attr.writable = desc.type.w;
+ }
+ Addr base = desc.baseLow | (desc.baseHigh << 24);
+ Addr limit = desc.limitLow | (desc.limitHigh << 16);
+ if (desc.g)
+ limit = (limit << 12) | mask(12);
+ SegBaseDest = base;
+ SegLimitDest = limit;
+ SegAttrDest = attr;
+ }
+ } else {
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;
- attr.readable = 1;
- attr.writable = desc.type.w;
- }
- Addr base = desc.baseLow | (desc.baseHigh << 24);
- Addr limit = desc.limitLow | (desc.limitHigh << 16);
- if (desc.g)
- limit = (limit << 12) | mask(12);
- SegBaseDest = base;
- SegLimitDest = limit;
- SegAttrDest = attr;
}
'''
}};