summaryrefslogtreecommitdiff
path: root/src/arch/x86/isa
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2007-12-01 23:03:39 -0800
committerGabe Black <gblack@eecs.umich.edu>2007-12-01 23:03:39 -0800
commitdc6f96017135da7f3beae5055195de3cf8e47c6c (patch)
treeb8fad747c652fe34db462bf585be4d184da02d6b /src/arch/x86/isa
parenta548067b01ed99d4abc9483ca11466d3d9d4ceca (diff)
downloadgem5-dc6f96017135da7f3beae5055195de3cf8e47c6c.tar.xz
X86: Reorganize segmentation and implement segment selector movs.
--HG-- extra : convert_revision : 553c3ffeda1f5312cf02493f602e7d4ba2fe66e8
Diffstat (limited to 'src/arch/x86/isa')
-rw-r--r--src/arch/x86/isa/decoder/one_byte_opcodes.isa16
-rw-r--r--src/arch/x86/isa/insts/general_purpose/data_transfer/move.py102
-rw-r--r--src/arch/x86/isa/insts/system/segmentation.py16
-rw-r--r--src/arch/x86/isa/microasm.isa10
-rw-r--r--src/arch/x86/isa/microops/regop.isa97
-rw-r--r--src/arch/x86/isa/operands.isa32
-rw-r--r--src/arch/x86/isa/specialize.isa8
7 files changed, 252 insertions, 29 deletions
diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa
index 62b8c8d59..0d1d7aacd 100644
--- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa
+++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa
@@ -292,9 +292,21 @@
0x1: MOV(Ev,Gv);
0x2: MOV(Gb,Eb);
0x3: MOV(Gv,Ev);
- 0x4: WarnUnimpl::mov_MwRv_Sw(); //What to do with this one?
+ 0x4: decode MODRM_REG {
+ 0x0, 0x1, 0x2,
+ 0x3, 0x4, 0x5: MOV(Ev,Sv);
+ }
0x5: LEA(Gv,M);
- 0x6: WarnUnimpl::mov_Sw_MwRv();
+ 0x6: decode MODE_SUBMODE {
+ 0x3, 0x4: MOV_REAL(Sv,Ev);
+ default: decode MODRM_REG {
+ 0x1: UD2(); // Moving to the CS selector is illegal.
+ 0x2: MOVSS(Sv,Ev);
+ 0x0, 0x3,
+ 0x4, 0x5: MOV(Sv,Ev);
+ default: UD2();
+ }
+ }
//0x7: group10_Ev();
0x7: decode MODRM_REG {
0x0: POP(Ev);
diff --git a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py
index a15fc21ef..aaddcf962 100644
--- a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py
+++ b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py
@@ -192,6 +192,108 @@ def macroop MOVZX_W_R_P {
def macroop MOV_C_R {
wrcr reg, regm
};
+
+def macroop MOV_R_S {
+ rdsel reg, regm
+};
+
+def macroop MOV_M_S {
+ rdsel t1, reg
+ st t1, seg, sib, disp, dataSize=2
+};
+
+def macroop MOV_P_S {
+ rdip t7
+ rdsel t1, reg
+ st t1, seg, riprel, disp, dataSize=2
+};
+
+def macroop MOV_REAL_S_R {
+ zext t2, regm, 15
+ slli t3, t2, 2, dataSize=8
+ wrsel reg, regm
+ wrbase reg, t3
+};
+
+def macroop MOV_REAL_S_M {
+ ld t1, seg, sib, disp, dataSize=2
+ zext t2, t1, 15
+ slli t3, t2, 2, dataSize=8
+ wrsel reg, t1
+ wrbase reg, t3
+};
+
+def macroop MOV_REAL_S_P {
+ rdip t7
+ ld t1, seg, riprel, disp, dataSize=2
+ zext t2, t1, 15
+ slli t3, t2, 2, dataSize=8
+ wrsel reg, t1
+ wrbase reg, t3
+};
+
+def macroop MOV_S_R {
+ chks t1, regm, flags=(EZF,), dataSize=8
+ bri t0, label("end"), flags=(CEZF,)
+ ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8
+ wrdl reg, t2, regm
+end:
+ wrsel reg, regm
+};
+
+def macroop MOV_S_M {
+ ld t1, seg, sib, disp, dataSize=2
+ chks t2, t1, flags=(EZF,), dataSize=8
+ bri t0, label("end"), flags=(CEZF,)
+ ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8
+ wrdl reg, t2, t1
+end:
+ wrsel reg, t1
+};
+
+def macroop MOV_S_P {
+ rdip t7
+ ld t1, seg, riprel, disp, dataSize=2
+ chks t2, t1, flags=(EZF,), dataSize=8
+ bri t0, label("end"), flags=(CEZF,)
+ ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8
+ wrdl reg, t2, t1
+end:
+ wrsel reg, t1
+};
+
+def macroop MOVSS_S_R {
+ chks t1, regm, flags=(EZF,), dataSize=8
+ # This actually needs to use the selector as the error code, but it would
+ # be hard to get that information into the instruction at the moment.
+ fault "new GeneralProtection(0)", flags=(CEZF,)
+ ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8
+ wrdl reg, t2, regm
+ wrsel reg, regm
+};
+
+def macroop MOVSS_S_M {
+ ld t1, seg, sib, disp, dataSize=2
+ chks t2, t1, flags=(EZF,), dataSize=8
+ # This actually needs to use the selector as the error code, but it would
+ # be hard to get that information into the instruction at the moment.
+ fault "new GeneralProtection(0)", flags=(CEZF,)
+ ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8
+ wrdl reg, t2, t1
+ wrsel reg, t1
+};
+
+def macroop MOVSS_S_P {
+ rdip t7
+ ld t1, seg, riprel, disp, dataSize=2
+ chks t2, t1, flags=(EZF,), dataSize=8
+ # This actually needs to use the selector as the error code, but it would
+ # be hard to get that information into the instruction at the moment.
+ fault "new GeneralProtection(0)", flags=(CEZF,)
+ ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8
+ wrdl reg, t2, t1
+ wrsel reg, t1
+};
'''
#let {{
# class MOVD(Inst):
diff --git a/src/arch/x86/isa/insts/system/segmentation.py b/src/arch/x86/isa/insts/system/segmentation.py
index e46941e53..97846f79c 100644
--- a/src/arch/x86/isa/insts/system/segmentation.py
+++ b/src/arch/x86/isa/insts/system/segmentation.py
@@ -62,8 +62,8 @@ def macroop LGDT_M
ld t1, seg, sib, disp, dataSize=2
# Get the base
ld t2, seg, sib, 'adjustedDisp + 2'
- wrbase gdtr, t2
- wrlimit gdtr, t1
+ wrbase tsg, t2
+ wrlimit tsg, t1
};
def macroop LGDT_P
@@ -75,8 +75,8 @@ def macroop LGDT_P
ld t1, seg, riprel, disp, dataSize=2
# Get the base
ld t2, seg, riprel, 'adjustedDisp + 2'
- wrbase gdtr, t2
- wrlimit gdtr, t1
+ wrbase tsg, t2
+ wrlimit tsg, t1
};
#
@@ -93,8 +93,8 @@ def macroop LGDT_16_M
# Get the base
ld t2, seg, sib, 'adjustedDisp + 2', dataSize=4
zexti t2, t2, 23
- wrbase gdtr, t2
- wrlimit gdtr, t1
+ wrbase tsg, t2
+ wrlimit tsg, t1
};
def macroop LGDT_16_P
@@ -107,8 +107,8 @@ def macroop LGDT_16_P
# Get the base
ld t2, seg, riprel, 'adjustedDisp + 2', dataSize=4
zexti t2, t2, 23
- wrbase gdtr, t2
- wrlimit gdtr, t1
+ wrbase tsg, t2
+ wrlimit tsg, t1
};
def macroop LIDT_M
diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa
index 8c499eeed..9e8b65c4e 100644
--- a/src/arch/x86/isa/microasm.isa
+++ b/src/arch/x86/isa/microasm.isa
@@ -81,9 +81,12 @@ let {{
for letter in ("C", "D", "E", "F", "G", "S"):
assembler.symbols["%ss" % letter.lower()] = "SEGMENT_REG_%sS" % letter
- for reg in ("LDTR", "TR", "GDTR", "IDTR"):
+ for reg in ("TR", "IDTR"):
assembler.symbols[reg.lower()] = "SYS_SEGMENT_REG_%s" % reg
+ for reg in ("TSL", "TSG"):
+ assembler.symbols[reg.lower()] = "SEGMENT_REG_%s" % reg
+
# Miscellaneous symbols
symbols = {
"reg" : "env.reg",
@@ -112,7 +115,10 @@ let {{
# This segment selects an internal address space mapped to MSRs,
# CPUID info, etc.
- assembler.symbols["intseg"] = "SEGMENT_REG_INT"
+ assembler.symbols["intseg"] = "SEGMENT_REG_MS"
+ # This segment always has base 0, and doesn't imply any special handling
+ # like the internal segment above
+ assembler.symbols["flatseg"] = "SEGMENT_REG_LS"
for reg in ('ax', 'bx', 'cx', 'dx', 'sp', 'bp', 'si', 'di'):
assembler.symbols["r%s" % reg] = "INTREG_R%s" % reg.upper()
diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa
index f37b4327b..7f72fcf1d 100644
--- a/src/arch/x86/isa/microops/regop.isa
+++ b/src/arch/x86/isa/microops/regop.isa
@@ -937,19 +937,100 @@ let {{
}
'''
- class Wrbase(RegOp):
+ # Microops for manipulating segmentation registers
+ class SegOp(RegOp):
+ abstract = True
def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
- super(Wrbase, self).__init__(dest, \
+ super(SegOp, self).__init__(dest, \
src1, "NUM_INTREGS", flags, dataSize)
+
+ class Wrbase(SegOp):
code = '''
- SysSegBaseDest = psrc1;
+ SegBaseDest = psrc1;
'''
- class Wrlimit(RegOp):
- def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
- super(Wrlimit, self).__init__(dest, \
- src1, "NUM_INTREGS", flags, dataSize)
+ class Wrlimit(SegOp):
+ code = '''
+ SegLimitDest = psrc1;
+ '''
+
+ class Wrsel(SegOp):
+ code = '''
+ SegSelDest = psrc1;
+ '''
+
+ class Rdbase(SegOp):
+ code = '''
+ DestReg = SegBaseDest;
+ '''
+
+ class Rdlimit(SegOp):
+ code = '''
+ DestReg = SegLimitSrc1;
+ '''
+
+ class Rdsel(SegOp):
code = '''
- SysSegLimitDest = psrc1;
+ DestReg = SegSelSrc1;
+ '''
+
+ class Chks(SegOp):
+ 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;
+ }
+ '''
+ flag_code = '''
+ // Check for a NULL selector and set ZF,EZF appropriately.
+ ccFlagBits = ccFlagBits & ~(ext & (ZFBit | EZFBit));
+ if (!selector.esi && !selector.ti)
+ ccFlagBits = ccFlagBits | (ext & (ZFBit | EZFBit));
+ '''
+
+ class Wrdh(RegOp):
+ code = '''
+
+ '''
+
+ class Wrdl(RegOp):
+ 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)
+ 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.g)
+ limit = (limit << 12) | mask(12);
+ }
+ SegBaseDest = base;
+ SegLimitDest = limit;
+ SegAttrDest = attr;
'''
}};
diff --git a/src/arch/x86/isa/operands.isa b/src/arch/x86/isa/operands.isa
index 40c8ee9c2..9345158e9 100644
--- a/src/arch/x86/isa/operands.isa
+++ b/src/arch/x86/isa/operands.isa
@@ -121,14 +121,30 @@ def operands {{
# The TOP register should needs to be more protected so that later
# instructions don't map their indexes with an old value.
'TOP': ('ControlReg', 'ub', 'MISCREG_X87_TOP', None, 61),
+ # The segment base as used by memory instructions.
'SegBase': ('ControlReg', 'uqw', 'MISCREG_SEG_EFF_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),
- 'CSBase': ('ControlReg', 'udw', 'MISCREG_CS_EFF_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 80),
- 'SysSegBaseDest': ('ControlReg', 'uqw', 'MISCREG_SYSSEG_BASE(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 75),
- 'SysSegLimitDest': ('ControlReg', 'uqw', 'MISCREG_SYSSEG_LIMIT(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 76),
- 'Mem': ('Mem', 'uqw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 100)
+ # Operands to get and set registers indexed by the operands of the
+ # original instruction.
+ 'ControlDest': ('ControlReg', 'uqw', 'MISCREG_CR(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 100),
+ 'ControlSrc1': ('ControlReg', 'uqw', 'MISCREG_CR(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 101),
+ 'SegBaseDest': ('ControlReg', 'uqw', 'MISCREG_SEG_BASE(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 102),
+ 'SegBaseSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_BASE(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 103),
+ 'SegLimitDest': ('ControlReg', 'uqw', 'MISCREG_SEG_LIMIT(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 104),
+ 'SegLimitSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_LIMIT(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 105),
+ 'SegSelDest': ('ControlReg', 'uqw', 'MISCREG_SEG_SEL(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 106),
+ 'SegSelSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_SEL(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 107),
+ 'SegAttrDest': ('ControlReg', 'uqw', 'MISCREG_SEG_ATTR(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 108),
+ 'SegAttrSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_ATTR(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 109),
+
+ # Operands to access specific control registers directly.
+ 'EferOp': ('ControlReg', 'uqw', 'MISCREG_EFER', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 200),
+ 'CR4Op': ('ControlReg', 'uqw', 'MISCREG_CR4', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 201),
+ 'LDTRBase': ('ControlReg', 'uqw', 'MISCREG_TSL_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 202),
+ 'LDTRLimit': ('ControlReg', 'uqw', 'MISCREG_TSL_LIMIT', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 203),
+ 'LDTRSel': ('ControlReg', 'uqw', 'MISCREG_TSL', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 204),
+ 'GDTRBase': ('ControlReg', 'uqw', 'MISCREG_TSG_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 205),
+ 'GDTRLimit': ('ControlReg', 'uqw', 'MISCREG_TSG_LIMIT', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 206),
+ 'CSBase': ('ControlReg', 'udw', 'MISCREG_CS_EFF_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 207),
+ 'Mem': ('Mem', 'uqw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 300)
}};
diff --git a/src/arch/x86/isa/specialize.isa b/src/arch/x86/isa/specialize.isa
index 3802d8949..abf734307 100644
--- a/src/arch/x86/isa/specialize.isa
+++ b/src/arch/x86/isa/specialize.isa
@@ -154,12 +154,18 @@ let {{
elif opType.tag == None or opType.size == None:
raise Exception, "Problem parsing operand tag: %s" % opType.tag
elif opType.tag == "C":
+ # A control register indexed by the "reg" field
env.addReg(ModRMRegIndex)
Name += "_C"
elif opType.tag == "D":
+ # A debug register indexed by the "reg" field
env.addReg(ModRMRegIndex)
Name += "_D"
- elif opType.tag in ("G", "P", "S", "T", "V"):
+ elif opType.tag == "S":
+ # A segment selector register indexed by the "reg" field
+ env.addReg(ModRMRegIndex)
+ Name += "_S"
+ elif opType.tag in ("G", "P", "T", "V"):
# Use the "reg" field of the ModRM byte to select the register
env.addReg(ModRMRegIndex)
Name += "_R"