summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2007-06-20 15:02:50 +0000
committerGabe Black <gblack@eecs.umich.edu>2007-06-20 15:02:50 +0000
commita68ddf685c739220d09fdc44000dd217d0707f8e (patch)
tree5026458b55d8032a56b52bba3dc35a4281e540c7
parentd2ccf5e50917701a4eab9f1848c8d524ccf0c7cc (diff)
downloadgem5-a68ddf685c739220d09fdc44000dd217d0707f8e.tar.xz
Make memory instructions work better, add more macroop implementations, add an lea microop, move EmulEnv into it's own .cc and .hh.
--HG-- extra : convert_revision : 1212b8463eab1c1dcba7182c487d1e9184cf9bea
-rw-r--r--src/arch/x86/SConscript1
-rw-r--r--src/arch/x86/isa/decoder/one_byte_opcodes.isa42
-rw-r--r--src/arch/x86/isa/includes.isa1
-rw-r--r--src/arch/x86/isa/insts/arithmetic/add_and_subtract.py14
-rw-r--r--src/arch/x86/isa/insts/compare_and_test/test.py32
-rw-r--r--src/arch/x86/isa/insts/data_transfer/move.py4
-rw-r--r--src/arch/x86/isa/insts/load_effective_address.py10
-rw-r--r--src/arch/x86/isa/macroop.isa47
-rw-r--r--src/arch/x86/isa/microops/ldstop.isa73
-rw-r--r--src/arch/x86/isa/specialize.isa39
-rw-r--r--src/arch/x86/predecoder.cc17
-rw-r--r--src/arch/x86/types.hh2
12 files changed, 186 insertions, 96 deletions
diff --git a/src/arch/x86/SConscript b/src/arch/x86/SConscript
index 2e2c5b006..6de243c9c 100644
--- a/src/arch/x86/SConscript
+++ b/src/arch/x86/SConscript
@@ -85,6 +85,7 @@
Import('*')
if env['TARGET_ISA'] == 'x86':
+ Source('emulenv.cc')
Source('floatregfile.cc')
Source('intregfile.cc')
Source('miscregfile.cc')
diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa
index c3f95137a..3b4e72347 100644
--- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa
+++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa
@@ -280,7 +280,17 @@
}
0x10: decode OPCODE_OP_BOTTOM3 {
0x0: group1_Eb_Ib();
- 0x1: group1_Ev_Iz();
+ //0x1: group1_Ev_Iz();
+ 0x1: decode MODRM_REG {
+ 0x0: add_Ev_Iz();
+ 0x1: or_Ev_Ibz();
+ 0x2: adc_Ev_Iz();
+ 0x3: sbb_Ev_Iz();
+ 0x4: Inst::AND(Ev,Iz);
+ 0x5: Inst::SUB(Ev,Iz);
+ 0x6: xor_Ev_Iz();
+ 0x7: cmp_Ev_Iz();
+ }
0x2: decode MODE_SUBMODE {
0x0: This_should_be_an_illegal_instruction();
default: group1_Eb_Ib();
@@ -296,8 +306,8 @@
0x6: xor_Eb_Ib();
0x7: cmp_Eb_Ib();
}
- 0x4: test_Eb_Gb();
- 0x5: test_Ev_Gv();
+ 0x4: Inst::TEST(Eb,Gb);
+ 0x5: Inst::TEST(Ev,Gv);
0x6: xchg_Eb_Gb();
0x7: xchg_Ev_Gv();
}
@@ -307,7 +317,7 @@
0x2: Inst::MOV(Gb,Eb);
0x3: Inst::MOV(Gv,Eb);
0x4: mov_MwRv_Sw(); //What to do with this one?
- 0x5: lea_Gv_M();
+ 0x5: Inst::LEA(Gv,M);
0x6: mov_Sw_MwRv();
0x7: group10_Ev(); //Make sure this is Ev
}
@@ -353,8 +363,8 @@
0x7: cmps_Yv_Xv();
}
0x15: decode OPCODE_OP_BOTTOM3 {
- 0x0: test_Al_Ib();
- 0x1: test_rAX_Iz();
+ 0x0: Inst::TEST(rAl,Ib);
+ 0x1: Inst::TEST(rAX,Iz);
0x2: stos_Yb_Al();
0x3: stos_Yv_rAX();
0x4: lods_Al_Xb();
@@ -372,15 +382,17 @@
0x6: mov_Dh_Ib();
0x7: mov_Bh_Ib();
}
- 0x17: decode OPCODE_OP_BOTTOM3 {
- 0x0: mov_rAX_Iv();
- 0x1: mov_rCX_Iv();
- 0x2: mov_rDX_Iv();
- 0x3: mov_rBX_Iv();
- 0x4: mov_rSP_Iv();
- 0x5: mov_rBP_Iv();
- 0x6: mov_rSI_Iv();
- 0x7: mov_rDI_Iv();
+ format Inst {
+ 0x17: decode OPCODE_OP_BOTTOM3 {
+ 0x0: MOV(rAX,Iv);
+ 0x1: MOV(rCX,Iv);
+ 0x2: MOV(rDX,Iv);
+ 0x3: MOV(rBX,Iv);
+ 0x4: MOV(rSP,Iv);
+ 0x5: MOV(rBP,Iv);
+ 0x6: MOV(rSI,Iv);
+ 0x7: MOV(rDI,Iv);
+ }
}
0x18: decode OPCODE_OP_BOTTOM3 {
0x0: group2_Eb_Ib();
diff --git a/src/arch/x86/isa/includes.isa b/src/arch/x86/isa/includes.isa
index 8bb282150..14406931b 100644
--- a/src/arch/x86/isa/includes.isa
+++ b/src/arch/x86/isa/includes.isa
@@ -96,6 +96,7 @@ output header {{
#include <sstream>
#include <iostream>
+#include "arch/x86/emulenv.hh"
#include "arch/x86/faults.hh"
#include "arch/x86/isa_traits.hh"
#include "arch/x86/regfile.hh"
diff --git a/src/arch/x86/isa/insts/arithmetic/add_and_subtract.py b/src/arch/x86/isa/insts/arithmetic/add_and_subtract.py
index 283152f30..349c2bb46 100644
--- a/src/arch/x86/isa/insts/arithmetic/add_and_subtract.py
+++ b/src/arch/x86/isa/insts/arithmetic/add_and_subtract.py
@@ -53,7 +53,19 @@
#
# Authors: Gabe Black
-microcode = ""
+microcode = '''
+def macroop SUB_R_I
+{
+ subi "env.reg", "env.reg", "IMMEDIATE"
+};
+
+def macroop SUB_M_I
+{
+ #Load into t1
+ subi "NUM_INTREGS+1", "NUM_INTREGS+1", "IMMEDIATE"
+ #save from t1
+};
+'''
#let {{
# class ADC(Inst):
# "Adc ^0 ^0 ^1"
diff --git a/src/arch/x86/isa/insts/compare_and_test/test.py b/src/arch/x86/isa/insts/compare_and_test/test.py
index b4d1cf9b8..36abab5d1 100644
--- a/src/arch/x86/isa/insts/compare_and_test/test.py
+++ b/src/arch/x86/isa/insts/compare_and_test/test.py
@@ -53,8 +53,30 @@
#
# Authors: Gabe Black
-microcode = ""
-#let {{
-# class TEST(Inst):
-# "GenFault ${new UnimpInstFault}"
-#}};
+microcode = '''
+def macroop TEST_M_R
+{
+ ld "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \
+ "DISPLACEMENT"
+ and "NUM_INTREGS", "NUM_INTREGS+1", "env.reg"
+};
+
+def macroop TEST_R_R
+{
+ and "NUM_INTREGS", "env.reg", "env.regm"
+};
+
+def macroop TEST_M_I
+{
+ ld "NUM_INTREGS+1", 3, ["env.scale", "env.index", "env.base"], \
+ "DISPLACEMENT"
+ limm "NUM_INTREGS+2", "IMMEDIATE"
+ and "NUM_INTREGS", "NUM_INTREGS+1", "NUM_INTREGS+2"
+};
+
+def macroop TEST_R_I
+{
+ limm "NUM_INTREGS+1", "IMMEDIATE"
+ and "NUM_INTREGS", "env.reg", "NUM_INTREGS+1"
+};
+'''
diff --git a/src/arch/x86/isa/insts/data_transfer/move.py b/src/arch/x86/isa/insts/data_transfer/move.py
index 1464e6379..c674329ea 100644
--- a/src/arch/x86/isa/insts/data_transfer/move.py
+++ b/src/arch/x86/isa/insts/data_transfer/move.py
@@ -59,11 +59,11 @@ def macroop MOV_R_R {
};
def macroop MOV_M_R {
- #Do a store to put the register operand into memory
+ st "env.reg", 3, ["env.scale", "env.index", "env.base"], "DISPLACEMENT"
};
def macroop MOV_R_M {
- #Do a load to fill the register operand from memory
+ ld "env.reg", 3, ["env.scale", "env.index", "env.base"], "DISPLACEMENT"
};
def macroop MOV_R_I {
diff --git a/src/arch/x86/isa/insts/load_effective_address.py b/src/arch/x86/isa/insts/load_effective_address.py
index dab6960b1..ac32638a0 100644
--- a/src/arch/x86/isa/insts/load_effective_address.py
+++ b/src/arch/x86/isa/insts/load_effective_address.py
@@ -53,8 +53,8 @@
#
# Authors: Gabe Black
-microcode = ""
-#let {{
-# class LEA(Inst):
-# "GenFault ${new UnimpInstFault}"
-#}};
+microcode = '''
+def macroop LEA_R_M {
+ lea "env.reg", 3, ["env.scale", "env.index", "env.base"], "DISPLACEMENT"
+};
+'''
diff --git a/src/arch/x86/isa/macroop.isa b/src/arch/x86/isa/macroop.isa
index 0cc818409..8453a4fe9 100644
--- a/src/arch/x86/isa/macroop.isa
+++ b/src/arch/x86/isa/macroop.isa
@@ -111,6 +111,12 @@ output header {{
};
}};
+//////////////////////////////////////////////////////////////////////////////
+//
+// X86 specific
+//
+//////////////////////////////////////////////////////////////////////////////
+
// Basic instruction class declaration template.
def template MacroDeclare {{
namespace X86Macroop
@@ -122,17 +128,19 @@ def template MacroDeclare {{
{
public:
// Constructor.
- %(class_name)s(ExtMachInst machInst, EmulEnv env);
+ %(class_name)s(ExtMachInst machInst, X86ISA::EmulEnv env);
};
};
}};
// Basic instruction class constructor template.
def template MacroConstructor {{
- inline X86Macroop::%(class_name)s::%(class_name)s(ExtMachInst machInst, EmulEnv env)
+ inline X86Macroop::%(class_name)s::%(class_name)s(
+ ExtMachInst machInst, EmulEnv env)
: %(base_class)s("%(mnemonic)s", machInst, %(num_microops)s)
{
%(adjust_env)s;
+ %(do_modrm)s;
%(constructor)s;
//alloc_microops is the code that sets up the microops
//array in the parent class.
@@ -140,11 +148,6 @@ def template MacroConstructor {{
}
}};
-//////////////////////////////////////////////////////////////////////////////
-//
-// X86 specific
-//
-
let {{
from micro_asm import Combinational_Macroop, Rom_Macroop
class X86Macroop(Combinational_Macroop):
@@ -157,6 +160,7 @@ let {{
}
self.declared = False
self.adjust_env = ""
+ self.doModRM = ""
def getAllocator(self, env):
return "new X86Macroop::%s(machInst, %s)" % (self.name, env.getAllocator())
def getDeclaration(self):
@@ -180,31 +184,11 @@ let {{
iop = InstObjParams(self.name, self.name, "Macroop",
{"code" : "", "num_microops" : numMicroops,
"alloc_microops" : allocMicroops,
- "adjust_env" : self.adjust_env})
+ "adjust_env" : self.adjust_env,
+ "do_modrm" : self.doModRM})
return MacroConstructor.subst(iop);
}};
-output header {{
- struct EmulEnv
- {
- X86ISA::RegIndex reg;
- X86ISA::RegIndex regm;
- uint8_t scale;
- X86ISA::RegIndex index;
- X86ISA::RegIndex base;
- int dataSize;
- int addressSize;
- int stackSize;
-
- EmulEnv(X86ISA::RegIndex _reg, X86ISA::RegIndex _regm,
- int _dataSize, int _addressSize, int _stackSize) :
- reg(_reg), regm(_regm),
- dataSize(_dataSize), addressSize(_addressSize),
- stackSize(_stackSize)
- {;}
- };
-}};
-
let {{
class EmulEnv(object):
def __init__(self):
@@ -215,6 +199,8 @@ let {{
self.addressSize = "ADDRSIZE"
self.dataSize = "OPSIZE"
self.stackSize = "STACKSIZE"
+ self.doModRM = False
+
def getAllocator(self):
return '''EmulEnv(%(reg)s,
%(regm)s,
@@ -234,12 +220,15 @@ let {{
}};
let {{
+ doModRMString = "env.doModRM(machInst);\n"
def genMacroop(Name, env):
blocks = OutputBlocks()
if not macroopDict.has_key(Name):
raise Exception, "Unrecognized instruction: %s" % Name
macroop = macroopDict[Name]
if not macroop.declared:
+ if env.doModRM:
+ macroop.doModRM = doModRMString
blocks.header_output = macroop.getDeclaration()
blocks.decoder_output = macroop.getDefinition()
macroop.declared = True
diff --git a/src/arch/x86/isa/microops/ldstop.isa b/src/arch/x86/isa/microops/ldstop.isa
index 38b690e6a..fbff899a0 100644
--- a/src/arch/x86/isa/microops/ldstop.isa
+++ b/src/arch/x86/isa/microops/ldstop.isa
@@ -59,9 +59,6 @@
//
//////////////////////////////////////////////////////////////////////////
-
-// Load templates
-
output header {{
/**
* Base class for load and store ops
@@ -119,6 +116,58 @@ output decoder {{
}
}};
+// LEA template
+
+def template MicroLeaExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+ Addr EA;
+
+ %(op_decl)s;
+ %(op_rd)s;
+ %(ea_code)s;
+ DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
+
+ %(code)s;
+ if(fault == NoFault)
+ {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+def template MicroLeaDeclare {{
+ class %(class_name)s : public %(base_class)s
+ {
+ protected:
+ void buildMe();
+
+ public:
+ %(class_name)s(ExtMachInst _machInst,
+ const char * instMnem,
+ bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+ uint8_t _scale, RegIndex _index, RegIndex _base,
+ uint64_t _disp, uint8_t _segment,
+ RegIndex _data,
+ uint8_t _dataSize, uint8_t _addressSize);
+
+ %(class_name)s(ExtMachInst _machInst,
+ const char * instMnem,
+ uint8_t _scale, RegIndex _index, RegIndex _base,
+ uint64_t _disp, uint8_t _segment,
+ RegIndex _data,
+ uint8_t _dataSize, uint8_t _addressSize);
+
+ %(BasicExecDeclare)s
+ };
+}};
+
+// Load templates
+
def template MicroLoadExecute {{
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
Trace::InstRecord *traceData) const
@@ -411,13 +460,27 @@ let {{
exec_output += MicroStoreCompleteAcc.subst(iop)
class StoreOp(LdStOp):
- def __init__(self, data, addr, segment):
- super(LoadOp, self).__init__(data, addr, segment)
+ def __init__(self, data, segment, addr, disp = 0):
+ super(LoadOp, self).__init__(data, segment, addr, disp)
self.className = Name
self.mnemonic = name
microopClasses[name] = StoreOp
defineMicroLoadOp('St', 'Mem = Data;')
+
+ iop = InstObjParams("lea", "Lea", 'LdStOp',
+ {"code": "Data = merge(Data, EA, dataSize);", "ea_code": calculateEA})
+ header_output += MicroLeaDeclare.subst(iop)
+ decoder_output += MicroLdStOpConstructor.subst(iop)
+ exec_output += MicroLeaExecute.subst(iop)
+
+ class LeaOp(LdStOp):
+ def __init__(self, data, segment, addr, disp = 0):
+ super(LeaOp, self).__init__(data, segment, addr, disp)
+ self.className = "Lea"
+ self.mnemonic = "lea"
+
+ microopClasses["lea"] = LeaOp
}};
diff --git a/src/arch/x86/isa/specialize.isa b/src/arch/x86/isa/specialize.isa
index bb2be47d9..10e57ba18 100644
--- a/src/arch/x86/isa/specialize.isa
+++ b/src/arch/x86/isa/specialize.isa
@@ -85,7 +85,7 @@ let {{
let {{
class OpType(object):
- parser = re.compile(r"(?P<tag>[A-Z][A-Z]*)(?P<size>[a-z][a-z]*)|(r(?P<reg>[A-Z0-9]*)(?P<rsize>[a-z]*))")
+ parser = re.compile(r"(?P<tag>[A-Z]+)(?P<size>[a-z]*)|(r(?P<reg>[A-Z0-9]+)(?P<rsize>[a-z]*))")
def __init__(self, opTypeString):
match = OpType.parser.search(opTypeString)
if match == None:
@@ -105,14 +105,15 @@ let {{
while len(opTypes):
# Parse the operand type string we're working with
opType = OpType(opTypes[0])
+ opTypes.pop(0)
if opType.reg:
#Figure out what to do with fixed register operands
#This is the index to use, so we should stick it some place.
if opType.reg in ("A", "B", "C", "D"):
- env.addReg("INTREG_R%sX" % opType.reg)
+ env.addReg("INTREG_R%sX | (REX_B << 3)" % opType.reg)
else:
- env.addReg("INTREG_R%s" % opType.reg)
+ env.addReg("INTREG_R%s | (REX_B << 3)" % opType.reg)
if opType.size:
if opType.rsize in ("l", "h", "b"):
print "byte"
@@ -121,6 +122,11 @@ let {{
else:
print "Didn't recognize fixed register size %s!" % opType.rsize
Name += "_R"
+ elif opType.tag == "M":
+ # This refers to memory. The macroop constructor sets up modrm
+ # addressing. Non memory modrm settings should cause an error.
+ Name += "_M"
+ env.doModRM = True
elif opType.tag == None or opType.size == None:
raise Exception, "Problem parsing operand tag: %s" % opType.tag
elif opType.tag in ("C", "D", "G", "P", "S", "T", "V"):
@@ -130,39 +136,24 @@ let {{
elif opType.tag in ("E", "Q", "W"):
# This might refer to memory or to a register. We need to
# divide it up farther.
- regTypes = copy.copy(opTypes)
- regTypes.pop(0)
regEnv = copy.copy(env)
regEnv.addReg(ModRMRMIndex)
- regName = Name + "_R"
- # This needs to refer to memory, but we'll fill in the details
- # later. It needs to take into account unaligned memory
- # addresses.
- memTypes = copy.copy(opTypes)
- memTypes.pop(0)
+ # This refers to memory. The macroop constructor should set up
+ # modrm addressing.
memEnv = copy.copy(env)
- memName = Name + "_M"
- print "%0"
+ memEnv.doModRM = True
return doSplitDecode(specializeInst, "MODRM_MOD",
- {"3" : (regName, regTypes, regEnv)},
- (memName, memTypes, memEnv))
+ {"3" : (Name + "_R", copy.copy(opTypes), regEnv)},
+ (Name + "_M", copy.copy(opTypes), memEnv))
elif opType.tag in ("I", "J"):
# Immediates
Name += "_I"
- elif opType.tag == "M":
- # This needs to refer to memory, but we'll fill in the details
- # later. It needs to take into account unaligned memory
- # addresses.
- print "%0"
- Name += "_M"
elif opType.tag in ("PR", "R", "VR"):
- # There should probably be a check here to verify that mod
- # is equal to 11b
+ # Non register modrm settings should cause an error
env.addReg(ModRMRMIndex)
Name += "_R"
else:
raise Exception, "Unrecognized tag %s." % opType.tag
- opTypes.pop(0)
# Generate code to return a macroop of the given name which will
# operate in the "emulation environment" env
diff --git a/src/arch/x86/predecoder.cc b/src/arch/x86/predecoder.cc
index 3ed18aeb2..bbbad7dd0 100644
--- a/src/arch/x86/predecoder.cc
+++ b/src/arch/x86/predecoder.cc
@@ -264,31 +264,29 @@ namespace X86ISA
Predecoder::State Predecoder::doModRMState(uint8_t nextByte)
{
State nextState = ErrorState;
- emi.modRM = nextByte;
+ ModRM modRM;
+ modRM = nextByte;
DPRINTF(Predecoder, "Found modrm byte %#x.\n", nextByte);
if (0) {//FIXME in 16 bit mode
//figure out 16 bit displacement size
- if(nextByte & 0xC7 == 0x06 ||
- nextByte & 0xC0 == 0x80)
+ if(modRM.mod == 0 && modRM.rm == 6 || modRM.mod == 2)
displacementSize = 2;
- else if(nextByte & 0xC0 == 0x40)
+ else if(modRM.mod == 1)
displacementSize = 1;
else
displacementSize = 0;
} else {
//figure out 32/64 bit displacement size
- if(nextByte & 0xC6 == 0x04 ||
- nextByte & 0xC0 == 0x80)
+ if(modRM.mod == 0 && modRM.rm == 4 || modRM.mod == 2)
displacementSize = 4;
- else if(nextByte & 0xC0 == 0x40)
+ else if(modRM.mod == 1)
displacementSize = 1;
else
displacementSize = 0;
}
//If there's an SIB, get that next.
//There is no SIB in 16 bit mode.
- if(nextByte & 0x7 == 4 &&
- nextByte & 0xC0 != 0xC0) {
+ if(modRM.rm == 4 && modRM.mod != 3) {
// && in 32/64 bit mode)
nextState = SIBState;
} else if(displacementSize) {
@@ -301,6 +299,7 @@ namespace X86ISA
}
//The ModRM byte is consumed no matter what
consumeByte();
+ emi.modRM = modRM;
return nextState;
}
diff --git a/src/arch/x86/types.hh b/src/arch/x86/types.hh
index 298dff80b..61ab2bac9 100644
--- a/src/arch/x86/types.hh
+++ b/src/arch/x86/types.hh
@@ -160,7 +160,7 @@ namespace X86ISA
} opcode;
//Modifier bytes
ModRM modRM;
- uint8_t sib;
+ Sib sib;
//Immediate fields
uint64_t immediate;
uint64_t displacement;