summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/x86/isa/base.isa27
-rw-r--r--src/arch/x86/isa/bitfields.isa5
-rw-r--r--src/arch/x86/isa/insts/data_transfer/move.py4
-rw-r--r--src/arch/x86/isa/insts/data_transfer/stack_operations.py10
-rw-r--r--src/arch/x86/isa/insts/logical.py16
-rw-r--r--src/arch/x86/isa/macroop.isa23
-rw-r--r--src/arch/x86/isa/microops/ldstop.isa317
-rw-r--r--src/arch/x86/isa/operands.isa8
-rw-r--r--src/arch/x86/isa_traits.hh2
-rw-r--r--src/arch/x86/types.hh12
-rw-r--r--src/arch/x86/utility.hh3
11 files changed, 381 insertions, 46 deletions
diff --git a/src/arch/x86/isa/base.isa b/src/arch/x86/isa/base.isa
index d9bd87f2d..eed969b47 100644
--- a/src/arch/x86/isa/base.isa
+++ b/src/arch/x86/isa/base.isa
@@ -182,6 +182,33 @@ output decoder {{
ccprintf(os, "\t%s : %s ", instMnemonic, mnemonic);
}
+ void printSegment(std::ostream &os, int segment)
+ {
+ switch (segment)
+ {
+ case 0:
+ ccprintf(os, "ES");
+ break;
+ case 1:
+ ccprintf(os, "CS");
+ break;
+ case 2:
+ ccprintf(os, "SS");
+ break;
+ case 3:
+ ccprintf(os, "DS");
+ break;
+ case 4:
+ ccprintf(os, "FS");
+ break;
+ case 5:
+ ccprintf(os, "GS");
+ break;
+ default:
+ panic("Unrecognized segment %d\n", segment);
+ }
+ }
+
void
X86StaticInst::printSrcReg(std::ostream &os, int reg) const
{
diff --git a/src/arch/x86/isa/bitfields.isa b/src/arch/x86/isa/bitfields.isa
index 82fa4f25b..8707bbb4c 100644
--- a/src/arch/x86/isa/bitfields.isa
+++ b/src/arch/x86/isa/bitfields.isa
@@ -100,3 +100,8 @@ def bitfield SIB_BASE sib.base;
def bitfield OPSIZE opSize;
def bitfield ADDRSIZE addrSize;
+def bitfield STACKSIZE stackSize;
+
+def bitfield MODE mode;
+def bitfield MODE_MODE mode.mode;
+def bitfield MODE_SUBMODE mode.submode;
diff --git a/src/arch/x86/isa/insts/data_transfer/move.py b/src/arch/x86/isa/insts/data_transfer/move.py
index 9d23b24e8..ff4af0af4 100644
--- a/src/arch/x86/isa/insts/data_transfer/move.py
+++ b/src/arch/x86/isa/insts/data_transfer/move.py
@@ -67,11 +67,11 @@ def macroop MOV_R_M {
};
def macroop MOV_R_I {
- limm "env.reg", "env.immediate"
+ limm "env.reg", "IMMEDIATE"
};
def macroop MOV_M_I {
- limm "env.reg", "env.immediate"
+ limm "env.reg", "IMMEDIATE"
#Do a store to put the register operand into memory
};
'''
diff --git a/src/arch/x86/isa/insts/data_transfer/stack_operations.py b/src/arch/x86/isa/insts/data_transfer/stack_operations.py
index b7ec0ec66..50b690354 100644
--- a/src/arch/x86/isa/insts/data_transfer/stack_operations.py
+++ b/src/arch/x86/isa/insts/data_transfer/stack_operations.py
@@ -55,15 +55,21 @@
microcode = '''
def macroop POP_R {
+
+ # Make the default data size of pops 64 bits in 64 bit mode
.adjust_env "if(machInst.mode.submode == SixtyFourBitMode && env.dataSize == 4) env.dataSize = 8\;"
- # There needs to be a load here to actually "pop" the data
+
+ ld "env.reg", 2, [0, "NUM_INTREGS", "INTREG_RSP"]
addi "INTREG_RSP", "INTREG_RSP", "env.dataSize"
};
def macroop PUSH_R {
+
+ # Make the default data size of pops 64 bits in 64 bit mode
.adjust_env "if(machInst.mode.submode == SixtyFourBitMode && env.dataSize == 4) env.dataSize = 8\;"
+
subi "INTREG_RSP", "INTREG_RSP", "env.dataSize"
- # There needs to be a store here to actually "push" the data
+ st "env.reg", 2, [0, "NUM_INTREGS", "INTREG_RSP"]
};
'''
#let {{
diff --git a/src/arch/x86/isa/insts/logical.py b/src/arch/x86/isa/insts/logical.py
index ec0ed97b2..824c75053 100644
--- a/src/arch/x86/isa/insts/logical.py
+++ b/src/arch/x86/isa/insts/logical.py
@@ -61,34 +61,34 @@ def macroop XOR_R_R
def macroop XOR_R_I
{
- limm "NUM_INTREGS", "env.immediate"
- xor "env.reg", "env.reg", "NUM_INTREGS"
+ limm "NUM_INTREGS+1", "IMMEDIATE"
+ xor "env.reg", "env.reg", "NUM_INTREGS+1"
};
def macroop XOR_M_R
{
#Do a load to get one of the sources
- xor "NUM_INTREGS", "NUM_INTREGS", "env.reg"
+ xor "NUM_INTREGS+1", "NUM_INTREGS+1", "env.reg"
#Do a store to write the destination
};
def macroop XOR_R_M
{
#Do a load to get one of the sources
- xor "env.reg", "env.reg", "NUM_INTREGS"
+ xor "env.reg", "env.reg", "NUM_INTREGS+1"
};
def macroop AND_R_I
{
- limm "NUM_INTREGS", "env.immediate"
- and "env.reg", "env.reg", "NUM_INTREGS"
+ limm "NUM_INTREGS+1", "IMMEDIATE"
+ and "env.reg", "env.reg", "NUM_INTREGS+1"
};
def macroop AND_M_I
{
#Do a load to get one of the sources
- limm "NUM_INTREGS", "env.immediate"
- and "NUM_INTREGS", "NUM_INTREGS", "NUM_INTREGS+1"
+ limm "NUM_INTREGS+1", "IMMEDIATE"
+ and "NUM_INTREGS+1", "NUM_INTREGS+1", "NUM_INTREGS+2"
#Do a store to write the destination
};
'''
diff --git a/src/arch/x86/isa/macroop.isa b/src/arch/x86/isa/macroop.isa
index 2d928d7c9..0cc818409 100644
--- a/src/arch/x86/isa/macroop.isa
+++ b/src/arch/x86/isa/macroop.isa
@@ -189,17 +189,18 @@ output header {{
{
X86ISA::RegIndex reg;
X86ISA::RegIndex regm;
- uint64_t immediate;
- uint64_t displacement;
- int addressSize;
+ uint8_t scale;
+ X86ISA::RegIndex index;
+ X86ISA::RegIndex base;
int dataSize;
+ int addressSize;
+ int stackSize;
EmulEnv(X86ISA::RegIndex _reg, X86ISA::RegIndex _regm,
- uint64_t _immediate, uint64_t _displacement,
- int _addressSize, int _dataSize) :
+ int _dataSize, int _addressSize, int _stackSize) :
reg(_reg), regm(_regm),
- immediate(_immediate), displacement(_displacement),
- addressSize(_addressSize), dataSize(_dataSize)
+ dataSize(_dataSize), addressSize(_addressSize),
+ stackSize(_stackSize)
{;}
};
}};
@@ -211,17 +212,15 @@ let {{
self.regUsed = False
self.regm = "0"
self.regmUsed = False
- self.immediate = "IMMEDIATE"
- self.displacement = "DISPLACEMENT"
self.addressSize = "ADDRSIZE"
self.dataSize = "OPSIZE"
+ self.stackSize = "STACKSIZE"
def getAllocator(self):
return '''EmulEnv(%(reg)s,
%(regm)s,
- %(immediate)s,
- %(displacement)s,
+ %(dataSize)s,
%(addressSize)s,
- %(dataSize)s)''' % \
+ %(stackSize)s)''' % \
self.__dict__
def addReg(self, reg):
if not self.regUsed:
diff --git a/src/arch/x86/isa/microops/ldstop.isa b/src/arch/x86/isa/microops/ldstop.isa
index 7e164fa82..38b690e6a 100644
--- a/src/arch/x86/isa/microops/ldstop.isa
+++ b/src/arch/x86/isa/microops/ldstop.isa
@@ -59,8 +59,14 @@
//
//////////////////////////////////////////////////////////////////////////
-def template MicroLdStOpDeclare {{
- class %(class_name)s : public X86MicroopBase
+
+// Load templates
+
+output header {{
+ /**
+ * Base class for load and store ops
+ */
+ class LdStOp : public X86MicroopBase
{
protected:
const uint8_t scale;
@@ -71,6 +77,195 @@ def template MicroLdStOpDeclare {{
const RegIndex data;
const uint8_t dataSize;
const uint8_t addressSize;
+
+ //Constructor
+ LdStOp(ExtMachInst _machInst,
+ const char * mnem, 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,
+ OpClass __opClass) :
+ X86MicroopBase(machInst, mnem, _instMnem,
+ isMicro, isDelayed, isFirst, isLast, __opClass),
+ scale(_scale), index(_index), base(_base),
+ disp(_disp), segment(_segment),
+ data(_data),
+ dataSize(_dataSize), addressSize(_addressSize)
+ {}
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string LdStOp::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ std::stringstream response;
+
+ printMnemonic(response, instMnem, mnemonic);
+ printReg(response, data);
+ response << ", ";
+ printSegment(response, segment);
+ ccprintf(response, ":[%d*", scale);
+ printReg(response, index);
+ response << " + ";
+ printReg(response, base);
+ ccprintf(response, " + %#x]", disp);
+ return response.str();
+ }
+}};
+
+def template MicroLoadExecute {{
+ 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);
+
+ fault = xc->read(EA, (%(mem_acc_type)s%(mem_acc_size)s_t&)Mem, 0);
+ if(fault == NoFault)
+ {
+ %(code)s;
+ }
+ if(fault == NoFault)
+ {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+def template MicroLoadInitiateAcc {{
+ Fault %(class_name)s::initiateAcc(%(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);
+
+ fault = xc->read(EA, (%(mem_acc_type)s%(mem_acc_size)s_t&)Mem, 0);
+
+ return fault;
+ }
+}};
+
+def template MicroLoadCompleteAcc {{
+ Fault %(class_name)s::completeAcc(PacketPtr pkt,
+ %(CPU_exec_context)s * xc,
+ Trace::InstRecord * traceData) const
+ {
+ Fault fault = NoFault;
+
+ %(op_decl)s;
+ %(op_rd)s;
+
+ Mem = pkt->get<typeof(Mem)>();
+ %(code)s;
+
+ if(fault == NoFault)
+ {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+// Store templates
+
+def template MicroStoreExecute {{
+ 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)
+ {
+ fault = xc->write((%(mem_acc_type)s%(mem_acc_size)s_t)Mem,
+ EA, 0, 0);
+ }
+ if(fault == NoFault)
+ {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+def template MicroStoreInitiateAcc {{
+ Fault %(class_name)s::initiateAcc(%(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)
+ {
+ fault = xc->write((%(mem_acc_type)s%(mem_acc_size)s_t)Mem,
+ EA, 0, 0);
+ }
+ if(fault == NoFault)
+ {
+ %(op_wb)s;
+ }
+ return fault;
+ }
+}};
+
+def template MicroStoreCompleteAcc {{
+ Fault %(class_name)s::completeAcc(PacketPtr, %(CPU_exec_context)s * xc,
+ Trace::InstRecord * traceData) const
+ {
+ return NoFault;
+ }
+}};
+
+// Common templates
+
+//This delcares the initiateAcc function in memory operations
+def template InitiateAccDeclare {{
+ Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
+}};
+
+//This declares the completeAcc function in memory operations
+def template CompleteAccDeclare {{
+ Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const;
+}};
+
+def template MicroLdStOpDeclare {{
+ class %(class_name)s : public %(base_class)s
+ {
+ protected:
void buildMe();
public:
@@ -90,6 +285,10 @@ def template MicroLdStOpDeclare {{
uint8_t _dataSize, uint8_t _addressSize);
%(BasicExecDeclare)s
+
+ %(InitiateAccDeclare)s
+
+ %(CompleteAccDeclare)s
};
}};
@@ -107,11 +306,10 @@ def template MicroLdStOpConstructor {{
RegIndex _data,
uint8_t _dataSize, uint8_t _addressSize) :
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
- false, false, false, false, %(op_class)s),
- scale(_scale), index(_index), base(_base),
- disp(_disp), segment(_segment),
- data(_data),
- dataSize(_dataSize), addressSize(_addressSize)
+ false, false, false, false,
+ _scale, _index, _base,
+ _disp, _segment, _data,
+ _dataSize, _addressSize, %(op_class)s)
{
buildMe();
}
@@ -120,17 +318,106 @@ def template MicroLdStOpConstructor {{
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) :
+ uint64_t _disp, uint8_t _segment,
+ RegIndex _data,
+ uint8_t _dataSize, uint8_t _addressSize) :
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
- isMicro, isDelayed, isFirst, isLast, %(op_class)s),
- scale(_scale), index(_index), base(_base),
- disp(_disp), segment(_segment),
- data(_data),
- dataSize(_dataSize), addressSize(_addressSize)
+ isMicro, isDelayed, isFirst, isLast,
+ _scale, _index, _base,
+ _disp, _segment, _data,
+ _dataSize, _addressSize, %(op_class)s)
{
buildMe();
}
}};
+let {{
+ class LdStOp(X86Microop):
+ def __init__(self, data, segment, addr, disp):
+ self.data = data
+ [self.scale, self.index, self.base] = addr
+ self.disp = disp
+ self.segment = segment
+ self.dataSize = "env.dataSize"
+ self.addressSize = "env.addressSize"
+
+ def getAllocator(self, *microFlags):
+ allocator = '''new %(class_name)s(machInst, mnemonic
+ %(flags)s, %(scale)s, %(index)s, %(base)s,
+ %(disp)s, %(segment)s, %(data)s,
+ %(dataSize)s, %(addressSize)s)''' % {
+ "class_name" : self.className,
+ "flags" : self.microFlagsText(microFlags),
+ "scale" : self.scale, "index" : self.index,
+ "base" : self.base,
+ "disp" : self.disp,
+ "segment" : self.segment, "data" : self.data,
+ "dataSize" : self.dataSize, "addressSize" : self.addressSize}
+ return allocator
+}};
+
+let {{
+
+ # Make these empty strings so that concatenating onto
+ # them will always work.
+ header_output = ""
+ decoder_output = ""
+ exec_output = ""
+
+ calculateEA = "EA = scale * Index + Base + disp;"
+
+ def defineMicroLoadOp(mnemonic, code):
+ global header_output
+ global decoder_output
+ global exec_output
+ global microopClasses
+ Name = mnemonic
+ name = mnemonic.lower()
+
+ # Build up the all register version of this micro op
+ iop = InstObjParams(name, Name, 'LdStOp',
+ {"code": code, "ea_code": calculateEA})
+ header_output += MicroLdStOpDeclare.subst(iop)
+ decoder_output += MicroLdStOpConstructor.subst(iop)
+ exec_output += MicroLoadExecute.subst(iop)
+ exec_output += MicroLoadInitiateAcc.subst(iop)
+ exec_output += MicroLoadCompleteAcc.subst(iop)
+
+ class LoadOp(LdStOp):
+ def __init__(self, data, segment, addr, disp = 0):
+ super(LoadOp, self).__init__(data, segment, addr, disp)
+ self.className = Name
+ self.mnemonic = name
+
+ microopClasses[name] = LoadOp
+
+ defineMicroLoadOp('Ld', 'Data = merge(Data, Mem, dataSize);')
+
+ def defineMicroStoreOp(mnemonic, code):
+ global header_output
+ global decoder_output
+ global exec_output
+ global microopClasses
+ Name = mnemonic
+ name = mnemonic.lower()
+
+ # Build up the all register version of this micro op
+ iop = InstObjParams(name, Name, 'LdStOp',
+ {"code": code, "ea_code": calculateEA})
+ header_output += MicroLdStOpDeclare.subst(iop)
+ decoder_output += MicroLdStOpConstructor.subst(iop)
+ exec_output += MicroStoreExecute.subst(iop)
+ exec_output += MicroStoreInitiateAcc.subst(iop)
+ exec_output += MicroStoreCompleteAcc.subst(iop)
+
+ class StoreOp(LdStOp):
+ def __init__(self, data, addr, segment):
+ super(LoadOp, self).__init__(data, addr, segment)
+ self.className = Name
+ self.mnemonic = name
+
+ microopClasses[name] = StoreOp
+
+ defineMicroLoadOp('St', 'Mem = Data;')
+}};
+
diff --git a/src/arch/x86/isa/operands.isa b/src/arch/x86/isa/operands.isa
index 1564c23e9..b2ac17d66 100644
--- a/src/arch/x86/isa/operands.isa
+++ b/src/arch/x86/isa/operands.isa
@@ -99,7 +99,9 @@ def operands {{
'DestReg': ('IntReg', 'uqw', 'dest', 'IsInteger', 1),
'SrcReg1': ('IntReg', 'uqw', 'src1', 'IsInteger', 2),
'SrcReg2': ('IntReg', 'uqw', 'src2', 'IsInteger', 3),
- 'IntRegOp0': ('IntReg', 'udw', 'param0', 'IsInteger', 1),
- 'IntRegOp1': ('IntReg', 'udw', 'param1', 'IsInteger', 2),
- 'IntRegOp2': ('IntReg', 'udw', 'param2', 'IsInteger', 2),
+ 'Base': ('IntReg', 'uqw', 'base', 'IsInteger', 4),
+ 'Index': ('IntReg', 'uqw', 'index', 'IsInteger', 5),
+ 'Data': ('IntReg', 'uqw', 'data', 'IsInteger', 6),
+ 'RIP': ('NPC', 'uqw', None, (None, None, 'IsControl'), 10),
+ 'Mem': ('Mem', 'uqw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 100)
}};
diff --git a/src/arch/x86/isa_traits.hh b/src/arch/x86/isa_traits.hh
index 7aba6248a..4c02ee35e 100644
--- a/src/arch/x86/isa_traits.hh
+++ b/src/arch/x86/isa_traits.hh
@@ -93,7 +93,7 @@ namespace X86ISA
// semantically meaningful register indices
//There is no such register in X86
- const int ZeroReg = 0;
+ const int ZeroReg = NUM_INTREGS;
const int StackPointerReg = INTREG_RSP;
//X86 doesn't seem to have a link register
const int ReturnAddressReg = 0;
diff --git a/src/arch/x86/types.hh b/src/arch/x86/types.hh
index fc9f1d82b..298dff80b 100644
--- a/src/arch/x86/types.hh
+++ b/src/arch/x86/types.hh
@@ -169,6 +169,8 @@ namespace X86ISA
uint8_t opSize;
//The effective address size.
uint8_t addrSize;
+ //The effective stack size.
+ uint8_t stackSize;
//Mode information
OperatingMode mode;
@@ -193,8 +195,6 @@ namespace X86ISA
inline static bool
operator == (const ExtMachInst &emi1, const ExtMachInst &emi2)
{
- if(emi1.mode != emi2.mode)
- return false;
if(emi1.legacy != emi2.legacy)
return false;
if(emi1.rex != emi2.rex)
@@ -215,6 +215,14 @@ namespace X86ISA
return false;
if(emi1.displacement != emi2.displacement)
return false;
+ if(emi1.mode != emi2.mode)
+ return false;
+ if(emi1.opSize != emi2.opSize)
+ return false;
+ if(emi1.addrSize != emi2.addrSize)
+ return false;
+ if(emi1.stackSize != emi2.stackSize)
+ return false;
return true;
}
diff --git a/src/arch/x86/utility.hh b/src/arch/x86/utility.hh
index ed401a519..3f3f1cca3 100644
--- a/src/arch/x86/utility.hh
+++ b/src/arch/x86/utility.hh
@@ -79,7 +79,8 @@ namespace __hash_namespace {
((uint64_t)emi.opcode.prefixB << 8) |
((uint64_t)emi.opcode.op)) ^
emi.immediate ^ emi.displacement ^
- emi.mode ^ emi.opSize;
+ emi.mode ^
+ emi.opSize ^ emi.addrSize ^ emi.stackSize;
};
};
}