diff options
author | Gabe Black <gblack@eecs.umich.edu> | 2007-06-19 14:18:25 +0000 |
---|---|---|
committer | Gabe Black <gblack@eecs.umich.edu> | 2007-06-19 14:18:25 +0000 |
commit | 6e286cddfaf6286f96e06c26266070f6fbbd7749 (patch) | |
tree | f318b62e376304d0b7f353a68794e4da160f5c8e | |
parent | 8caef7d25a6a150fa6369234bbdc8c14ef637df8 (diff) | |
download | gem5-6e286cddfaf6286f96e06c26266070f6fbbd7749.tar.xz |
Get rid of the immediate and displacement components of the EmulEnv struct and use them directly out of the instruction. The extra copies are conceptually realistic but are just innefficient as implemented. Also don't use the zeroeth microcode register for general storage since it's now the zero register, and implement a load and a store microops.
--HG--
extra : convert_revision : 0686296ca8b72940d961ecc6051063bfda1e932d
-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 |
9 files changed, 349 insertions, 46 deletions
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; }; }; } |