diff options
-rw-r--r-- | src/arch/x86/isa/base.isa | 27 | ||||
-rw-r--r-- | src/arch/x86/isa/bitfields.isa | 5 | ||||
-rw-r--r-- | src/arch/x86/isa/insts/data_transfer/move.py | 4 | ||||
-rw-r--r-- | src/arch/x86/isa/insts/data_transfer/stack_operations.py | 10 | ||||
-rw-r--r-- | src/arch/x86/isa/insts/logical.py | 16 | ||||
-rw-r--r-- | src/arch/x86/isa/macroop.isa | 23 | ||||
-rw-r--r-- | src/arch/x86/isa/microops/ldstop.isa | 317 | ||||
-rw-r--r-- | src/arch/x86/isa/operands.isa | 8 | ||||
-rw-r--r-- | src/arch/x86/isa_traits.hh | 2 | ||||
-rw-r--r-- | src/arch/x86/types.hh | 12 | ||||
-rw-r--r-- | src/arch/x86/utility.hh | 3 |
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; }; }; } |