X86: First crack at far returns. This is grossly approximate.

--HG--
extra : convert_revision : 23da0338af1f7663ae5ddf2289fb45dd32f37c42
This commit is contained in:
Gabe Black
2007-12-01 23:05:01 -08:00
parent dc6f960171
commit fe833dd2c3
3 changed files with 55 additions and 16 deletions

View File

@@ -413,7 +413,10 @@
0x0: Inst::ENTER(Iw,Iw);
0x1: Inst::LEAVE();
0x2: ret_far_Iw();
0x3: ret_far();
0x3: decode MODE_SUBMODE {
0x3, 0x4: ret_far_real();
default: Inst::RET_FAR();
}
0x4: int3();
0x5: int_Ib();
0x6: decode MODE_SUBMODE {

View File

@@ -77,4 +77,36 @@ def macroop RET_NEAR_I
add rsp, rsp, t2
wripi t1, 0
};
def macroop RET_FAR {
.adjust_env oszIn64Override
# Get the return RIP
ld t1, ss, [1, t0, rsp]
# Get the return CS
ld t2, ss, [1, t0, rsp], dsz
# Get the rpl
andi t3, t2, 0x3
# Get the cpl
# Here we'd check if we're changing priviledge levels. We'll just hope
# that doesn't happen yet.
# Do stuff if they're equal
chks t4, t2, flags=(EZF,)
fault "new GeneralProtection(0)", flags=(CEZF,)
ld t3, flatseg, [1, t0, t4], addressSize=8, dataSize=8
wrdl cs, t3, t2
# There should be validity checks on the RIP checks here, but I'll do
# that later.
wrip t0, t1
bri t0, label("end")
# Do other stuff if they're not.
end:
fault "NoFault"
};
'''

View File

@@ -1010,27 +1010,31 @@ let {{
code = '''
SegDescriptor desc = SrcReg1;
SegAttr attr = 0;
Addr base = 0, limit = 0;
attr.dpl = desc.dpl;
attr.defaultSize = desc.d;
if (!desc.p)
panic("Segment not present.\\n");
if (!desc.s)
if (!desc.s) {
SegBaseDest = SegBaseDest;
SegLimitDest = SegLimitDest;
SegAttrDest = SegAttrDest;
panic("System segment encountered.\\n");
if (desc.type.codeOrData) {
panic("Code segment encountered with c = %d, r = %d, a = %d.\\n",
desc.type.c, desc.type.r, desc.type.a);
} else {
attr.expandDown = desc.type.e;
attr.readable = 1;
attr.writable = desc.type.w;
base = desc.baseLow | (desc.baseHigh << 24);
limit = desc.limitLow | (desc.limitHigh << 16);
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;
}
SegBaseDest = base;
SegLimitDest = limit;
SegAttrDest = attr;
'''
}};