summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2007-12-01 23:05:01 -0800
committerGabe Black <gblack@eecs.umich.edu>2007-12-01 23:05:01 -0800
commitfe833dd2c33818a1f92f87ea26b17e6b85d3976e (patch)
treed87babd2357acd86c2617460f704b911d8480945 /src
parentdc6f96017135da7f3beae5055195de3cf8e47c6c (diff)
downloadgem5-fe833dd2c33818a1f92f87ea26b17e6b85d3976e.tar.xz
X86: First crack at far returns. This is grossly approximate.
--HG-- extra : convert_revision : 23da0338af1f7663ae5ddf2289fb45dd32f37c42
Diffstat (limited to 'src')
-rw-r--r--src/arch/x86/isa/decoder/one_byte_opcodes.isa5
-rw-r--r--src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py32
-rw-r--r--src/arch/x86/isa/microops/regop.isa34
3 files changed, 55 insertions, 16 deletions
diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa
index 0d1d7aacd..332ae1641 100644
--- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa
+++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa
@@ -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 {
diff --git a/src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py b/src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py
index 8993f5ac4..0b2e81cbd 100644
--- a/src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py
+++ b/src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py
@@ -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"
+};
'''
diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa
index 7f72fcf1d..de9f76e73 100644
--- a/src/arch/x86/isa/microops/regop.isa
+++ b/src/arch/x86/isa/microops/regop.isa
@@ -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;
'''
}};