macroop.isa revision 12236:126ac9da6050
15323Sgblack@eecs.umich.edu// -*- mode:c++ -*- 22934Sktlim@umich.edu 32934Sktlim@umich.edu// Copyright (c) 2007 The Hewlett-Packard Development Company 42934Sktlim@umich.edu// All rights reserved. 52934Sktlim@umich.edu// 62934Sktlim@umich.edu// The license below extends only to copyright in the software and shall 72934Sktlim@umich.edu// not be construed as granting a license to any other intellectual 82934Sktlim@umich.edu// property including but not limited to intellectual property relating 92934Sktlim@umich.edu// to a hardware implementation of the functionality of the software 102934Sktlim@umich.edu// licensed hereunder. You may use the software subject to the license 112934Sktlim@umich.edu// terms below provided that you ensure that this notice is replicated 122934Sktlim@umich.edu// unmodified and in its entirety in all distributions of the software, 132934Sktlim@umich.edu// modified or unmodified, in source code or in binary form. 142934Sktlim@umich.edu// 152934Sktlim@umich.edu// Redistribution and use in source and binary forms, with or without 162934Sktlim@umich.edu// modification, are permitted provided that the following conditions are 172934Sktlim@umich.edu// met: redistributions of source code must retain the above copyright 182934Sktlim@umich.edu// notice, this list of conditions and the following disclaimer; 192934Sktlim@umich.edu// redistributions in binary form must reproduce the above copyright 202934Sktlim@umich.edu// notice, this list of conditions and the following disclaimer in the 212934Sktlim@umich.edu// documentation and/or other materials provided with the distribution; 222934Sktlim@umich.edu// neither the name of the copyright holders nor the names of its 232934Sktlim@umich.edu// contributors may be used to endorse or promote products derived from 242934Sktlim@umich.edu// this software without specific prior written permission. 252934Sktlim@umich.edu// 262934Sktlim@umich.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 272934Sktlim@umich.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 282934Sktlim@umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 292934Sktlim@umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 302969Sktlim@umich.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 312934Sktlim@umich.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 322995Ssaidi@eecs.umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 332934Sktlim@umich.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 342934Sktlim@umich.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 352934Sktlim@umich.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 362934Sktlim@umich.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 372934Sktlim@umich.edu// 382934Sktlim@umich.edu// Authors: Gabe Black 392934Sktlim@umich.edu 402934Sktlim@umich.edu////////////////////////////////////////////////////////////////////////////// 414520Ssaidi@eecs.umich.edu// 424520Ssaidi@eecs.umich.edu// Architecture independent 434982Ssaidi@eecs.umich.edu// 444520Ssaidi@eecs.umich.edu 454520Ssaidi@eecs.umich.edu// Execute method for macroops. 462934Sktlim@umich.edudef template MacroExecPanic {{ 472934Sktlim@umich.edu Fault execute(ExecContext *, Trace::InstRecord *) const 483005Sstever@eecs.umich.edu { 493005Sstever@eecs.umich.edu panic("Tried to execute macroop directly!"); 503304Sstever@eecs.umich.edu return NoFault; 512995Ssaidi@eecs.umich.edu } 522934Sktlim@umich.edu}}; 532934Sktlim@umich.edu 544965Ssaidi@eecs.umich.eduoutput header {{ 555266Sksewell@umich.edu 562934Sktlim@umich.edu // Base class for combinationally generated macroops 572934Sktlim@umich.edu class Macroop : public X86ISA::MacroopBase 582934Sktlim@umich.edu { 592934Sktlim@umich.edu public: 602934Sktlim@umich.edu Macroop(const char *mnem, ExtMachInst _machInst, 612995Ssaidi@eecs.umich.edu uint32_t _numMicroops, X86ISA::EmulEnv _env) 622934Sktlim@umich.edu : MacroopBase(mnem, _machInst, _numMicroops, _env) 632934Sktlim@umich.edu {} 642934Sktlim@umich.edu 652934Sktlim@umich.edu Fault 662934Sktlim@umich.edu execute(ExecContext *, Trace::InstRecord *) const 672995Ssaidi@eecs.umich.edu { 682934Sktlim@umich.edu panic("Tried to execute macroop directly!"); 692934Sktlim@umich.edu } 702953Sktlim@umich.edu }; 715478Snate@binkert.org}}; 722934Sktlim@umich.edu 733449Shsul@eecs.umich.edu////////////////////////////////////////////////////////////////////////////// 742934Sktlim@umich.edu// 752934Sktlim@umich.edu// X86 specific 762934Sktlim@umich.edu// 772934Sktlim@umich.edu////////////////////////////////////////////////////////////////////////////// 782934Sktlim@umich.edu 793584Ssaidi@eecs.umich.edu// Basic instruction class declaration template. 804486Sbinkertn@umich.edudef template MacroDeclare {{ 814486Sbinkertn@umich.edu namespace X86Macroop 824486Sbinkertn@umich.edu { 834486Sbinkertn@umich.edu /** 844486Sbinkertn@umich.edu * Static instruction class for "%(mnemonic)s". 854486Sbinkertn@umich.edu */ 864486Sbinkertn@umich.edu class %(class_name)s : public %(base_class)s 873584Ssaidi@eecs.umich.edu { 883584Ssaidi@eecs.umich.edu private: 893584Ssaidi@eecs.umich.edu %(declareLabels)s 903584Ssaidi@eecs.umich.edu public: 913584Ssaidi@eecs.umich.edu // Constructor. 923743Sgblack@eecs.umich.edu %(class_name)s(ExtMachInst machInst, X86ISA::EmulEnv _env); 933584Ssaidi@eecs.umich.edu 944972Ssaidi@eecs.umich.edu std::string 953743Sgblack@eecs.umich.edu generateDisassembly(Addr pc, const SymbolTable *symtab) const; 964104Ssaidi@eecs.umich.edu }; 973743Sgblack@eecs.umich.edu } 983823Ssaidi@eecs.umich.edu}}; 993814Ssaidi@eecs.umich.edu 1003743Sgblack@eecs.umich.edudef template MacroDisassembly {{ 1013743Sgblack@eecs.umich.edu std::string 1023584Ssaidi@eecs.umich.edu X86Macroop::%(class_name)s::generateDisassembly(Addr pc, 1033814Ssaidi@eecs.umich.edu const SymbolTable *symtab) const 1043584Ssaidi@eecs.umich.edu { 1053745Sgblack@eecs.umich.edu std::stringstream out; 1063745Sgblack@eecs.umich.edu out << mnemonic << "\t"; 1073745Sgblack@eecs.umich.edu 1083584Ssaidi@eecs.umich.edu int regSize = %(regSize)s; 1093898Ssaidi@eecs.umich.edu %(disassembly)s 1103898Ssaidi@eecs.umich.edu // Shut up gcc. 1113898Ssaidi@eecs.umich.edu regSize = regSize; 1124103Ssaidi@eecs.umich.edu return out.str(); 1134103Ssaidi@eecs.umich.edu } 1144103Ssaidi@eecs.umich.edu}}; 1153745Sgblack@eecs.umich.edu 1163745Sgblack@eecs.umich.edu// Basic instruction class constructor template. 1173745Sgblack@eecs.umich.edudef template MacroConstructor {{ 1183584Ssaidi@eecs.umich.edu X86Macroop::%(class_name)s::%(class_name)s( 1193584Ssaidi@eecs.umich.edu ExtMachInst machInst, EmulEnv _env) 1203584Ssaidi@eecs.umich.edu : %(base_class)s("%(mnemonic)s", machInst, %(num_microops)s, _env) 1215222Sksewell@umich.edu { 1225222Sksewell@umich.edu %(adjust_env)s; 1235222Sksewell@umich.edu %(adjust_imm)s; 1245222Sksewell@umich.edu %(adjust_disp)s; 1255222Sksewell@umich.edu %(init_env)s; 1265222Sksewell@umich.edu %(constructor)s; 1275222Sksewell@umich.edu const char *macrocodeBlock = "%(class_name)s"; 1285222Sksewell@umich.edu //alloc_microops is the code that sets up the microops 1295222Sksewell@umich.edu //array in the parent class. 1305222Sksewell@umich.edu %(alloc_microops)s; 1315222Sksewell@umich.edu } 1325222Sksewell@umich.edu}}; 1335222Sksewell@umich.edu 1345222Sksewell@umich.edulet {{ 1355222Sksewell@umich.edu from micro_asm import Combinational_Macroop, Rom_Macroop 1365222Sksewell@umich.edu class X86Macroop(Combinational_Macroop): 1375222Sksewell@umich.edu def add_microop(self, mnemonic, microop): 1385222Sksewell@umich.edu microop.mnemonic = mnemonic 1395222Sksewell@umich.edu microop.micropc = len(self.microops) 1405222Sksewell@umich.edu self.microops.append(microop) 1415222Sksewell@umich.edu def setAdjustEnv(self, val): 1425222Sksewell@umich.edu self.adjust_env = val 1435222Sksewell@umich.edu def adjustImm(self, val): 1445222Sksewell@umich.edu self.adjust_imm += val 1455222Sksewell@umich.edu def adjustDisp(self, val): 1465222Sksewell@umich.edu self.adjust_disp += val 1475222Sksewell@umich.edu def serializing(self): 1485222Sksewell@umich.edu self.serializing = True 1495222Sksewell@umich.edu 1505222Sksewell@umich.edu def function_call(self): 1515478Snate@binkert.org self.function_call = True 1525222Sksewell@umich.edu def function_return(self): 1535222Sksewell@umich.edu self.function_return = True 1545222Sksewell@umich.edu 1555222Sksewell@umich.edu def __init__(self, name): 1565222Sksewell@umich.edu super(X86Macroop, self).__init__(name) 1575222Sksewell@umich.edu self.directives = { 1585323Sgblack@eecs.umich.edu "adjust_env" : self.setAdjustEnv, 1595357Sgblack@eecs.umich.edu "adjust_imm" : self.adjustImm, 1605323Sgblack@eecs.umich.edu "adjust_disp" : self.adjustDisp, 1615323Sgblack@eecs.umich.edu "serializing" : self.serializing, 1625613Sgblack@eecs.umich.edu "function_call" : self.function_call, 1635613Sgblack@eecs.umich.edu "function_return" : self.function_return 1645613Sgblack@eecs.umich.edu } 1655613Sgblack@eecs.umich.edu self.declared = False 1665133Sgblack@eecs.umich.edu self.adjust_env = "" 1675133Sgblack@eecs.umich.edu self.init_env = "" 1685133Sgblack@eecs.umich.edu self.adjust_imm = ''' 1695133Sgblack@eecs.umich.edu uint64_t adjustedImm = IMMEDIATE; 1705133Sgblack@eecs.umich.edu //This is to pacify gcc in case the immediate isn't used. 1715133Sgblack@eecs.umich.edu adjustedImm = adjustedImm; 1725323Sgblack@eecs.umich.edu ''' 1735450Sgblack@eecs.umich.edu self.adjust_disp = ''' 1745133Sgblack@eecs.umich.edu uint64_t adjustedDisp = DISPLACEMENT; 1755133Sgblack@eecs.umich.edu //This is to pacify gcc in case the displacement isn't used. 1765613Sgblack@eecs.umich.edu adjustedDisp = adjustedDisp; 1775613Sgblack@eecs.umich.edu ''' 1785613Sgblack@eecs.umich.edu self.serializing = False 1795613Sgblack@eecs.umich.edu self.function_call = False 1805613Sgblack@eecs.umich.edu self.function_return = False 1815613Sgblack@eecs.umich.edu 1825613Sgblack@eecs.umich.edu def getAllocator(self, env): 1835638Sgblack@eecs.umich.edu return "new X86Macroop::%s(machInst, %s)" % \ 1845613Sgblack@eecs.umich.edu (self.name, env.getAllocator()) 1855613Sgblack@eecs.umich.edu def getMnemonic(self): 1865613Sgblack@eecs.umich.edu mnemonic = self.name.lower() 1875613Sgblack@eecs.umich.edu mnemonic = re.match(r'[^_]*', mnemonic).group(0) 1885615Sgblack@eecs.umich.edu return mnemonic 1895615Sgblack@eecs.umich.edu def getDeclaration(self): 1905615Sgblack@eecs.umich.edu #FIXME This first parameter should be the mnemonic. I need to 1915615Sgblack@eecs.umich.edu #write some code which pulls that out 1925641Sgblack@eecs.umich.edu declareLabels = "" 1935641Sgblack@eecs.umich.edu for (label, microop) in self.labels.items(): 1945641Sgblack@eecs.umich.edu declareLabels += "const static uint64_t label_%s = %d;\n" \ 1955641Sgblack@eecs.umich.edu % (label, microop.micropc) 1965641Sgblack@eecs.umich.edu iop = InstObjParams(self.getMnemonic(), self.name, "Macroop", 1975641Sgblack@eecs.umich.edu {"code" : "", 1985641Sgblack@eecs.umich.edu "declareLabels" : declareLabels 1995641Sgblack@eecs.umich.edu }) 2005613Sgblack@eecs.umich.edu return MacroDeclare.subst(iop); 2015613Sgblack@eecs.umich.edu def getDefinition(self, env): 2025613Sgblack@eecs.umich.edu #FIXME This first parameter should be the mnemonic. I need to 2035613Sgblack@eecs.umich.edu #write some code which pulls that out 2045613Sgblack@eecs.umich.edu numMicroops = len(self.microops) 2055613Sgblack@eecs.umich.edu allocMicroops = '' 2065613Sgblack@eecs.umich.edu micropc = 0 2075450Sgblack@eecs.umich.edu for op in self.microops: 2085450Sgblack@eecs.umich.edu flags = ["IsMicroop"] 2095450Sgblack@eecs.umich.edu if micropc == numMicroops - 1: 2105450Sgblack@eecs.umich.edu flags.append("IsLastMicroop") 2115450Sgblack@eecs.umich.edu 2125450Sgblack@eecs.umich.edu if self.serializing: 2135450Sgblack@eecs.umich.edu flags.append("IsSerializing") 2145450Sgblack@eecs.umich.edu flags.append("IsSerializeAfter") 2155450Sgblack@eecs.umich.edu 2165450Sgblack@eecs.umich.edu if self.function_call: 2175450Sgblack@eecs.umich.edu flags.append("IsCall") 2185450Sgblack@eecs.umich.edu if self.function_return: 2195450Sgblack@eecs.umich.edu flags.append("IsReturn") 2205450Sgblack@eecs.umich.edu else: 2215450Sgblack@eecs.umich.edu flags.append("IsDelayedCommit") 2225450Sgblack@eecs.umich.edu if micropc == 0: 2235330Sgblack@eecs.umich.edu flags.append("IsFirstMicroop") 2245416Sgblack@eecs.umich.edu allocMicroops += \ 2255330Sgblack@eecs.umich.edu "microops[%d] = %s;\n" % \ 2265133Sgblack@eecs.umich.edu (micropc, op.getAllocator(flags)) 2275133Sgblack@eecs.umich.edu micropc += 1 2283584Ssaidi@eecs.umich.edu if env.useStackSize: 2293025Ssaidi@eecs.umich.edu useStackSize = "true" 2302934Sktlim@umich.edu else: 2312995Ssaidi@eecs.umich.edu useStackSize = "false" 2322995Ssaidi@eecs.umich.edu if env.memoryInst: 2334981Ssaidi@eecs.umich.edu memoryInst = "true" 2344981Ssaidi@eecs.umich.edu else: 2354981Ssaidi@eecs.umich.edu memoryInst = "false" 2364981Ssaidi@eecs.umich.edu regSize = '''(%s || (env.base == INTREG_RSP && %s) ? 2373025Ssaidi@eecs.umich.edu env.stackSize : 2383025Ssaidi@eecs.umich.edu env.dataSize)''' % (useStackSize, memoryInst) 2393025Ssaidi@eecs.umich.edu iop = InstObjParams(self.getMnemonic(), self.name, "Macroop", 2402934Sktlim@umich.edu {"code" : "", "num_microops" : numMicroops, 2412934Sktlim@umich.edu "alloc_microops" : allocMicroops, 2425253Sksewell@umich.edu "adjust_env" : self.adjust_env, 2435263Sksewell@umich.edu "adjust_imm" : self.adjust_imm, 2445253Sksewell@umich.edu "adjust_disp" : self.adjust_disp, 2455253Sksewell@umich.edu "disassembly" : env.disassembly, 2465253Sksewell@umich.edu "regSize" : regSize, 2475253Sksewell@umich.edu "init_env" : self.initEnv}) 2485253Sksewell@umich.edu return MacroConstructor.subst(iop) + \ 2495253Sksewell@umich.edu MacroDisassembly.subst(iop); 2505253Sksewell@umich.edu}}; 2515253Sksewell@umich.edu 2525253Sksewell@umich.edulet {{ 2535253Sksewell@umich.edu class EmulEnv(object): 2545253Sksewell@umich.edu def __init__(self): 2555253Sksewell@umich.edu self.reg = "0" 2565253Sksewell@umich.edu self.regUsed = False 2575253Sksewell@umich.edu self.regm = "0" 2585253Sksewell@umich.edu self.regmUsed = False 2595253Sksewell@umich.edu self.seg = "SEGMENT_REG_DS" 2605253Sksewell@umich.edu self.size = None 2615253Sksewell@umich.edu self.addressSize = "ADDRSIZE" 2625253Sksewell@umich.edu self.dataSize = "OPSIZE" 2635253Sksewell@umich.edu self.stackSize = "STACKSIZE" 2645253Sksewell@umich.edu self.doModRM = False 2655253Sksewell@umich.edu self.disassembly = "" 2665253Sksewell@umich.edu self.firstArgument = True 2675253Sksewell@umich.edu self.useStackSize = False 2685253Sksewell@umich.edu self.memoryInst = False 2695253Sksewell@umich.edu 2705253Sksewell@umich.edu def addToDisassembly(self, code): 2715253Sksewell@umich.edu if not self.firstArgument: 2725253Sksewell@umich.edu self.disassembly += "out << \", \";\n" 2735253Sksewell@umich.edu self.firstArgument = False 2745253Sksewell@umich.edu self.disassembly += code 2755253Sksewell@umich.edu 2765253Sksewell@umich.edu def getAllocator(self): 2775253Sksewell@umich.edu if self.size == 'b': 2785253Sksewell@umich.edu self.dataSize = 1 2795253Sksewell@umich.edu elif self.size == 'd': 2805253Sksewell@umich.edu self.dataSize = 4 2815253Sksewell@umich.edu #This is for "double plus" which is normally a double word unless 2825253Sksewell@umich.edu #the REX W bit is set, in which case it's a quad word. It's used 2835253Sksewell@umich.edu #for some SSE instructions. 2845253Sksewell@umich.edu elif self.size == 'dp': 2855253Sksewell@umich.edu self.dataSize = "(REX_W ? 8 : 4)" 2865253Sksewell@umich.edu elif self.size == 'q': 2875253Sksewell@umich.edu self.dataSize = 8 2885253Sksewell@umich.edu elif self.size == 'v': 2895253Sksewell@umich.edu self.dataSize = "OPSIZE" 2905253Sksewell@umich.edu elif self.size == 'w': 2915253Sksewell@umich.edu self.dataSize = 2 2925253Sksewell@umich.edu elif self.size == 'z': 2935253Sksewell@umich.edu self.dataSize = "((OPSIZE == 8) ? 4 : OPSIZE)" 2945253Sksewell@umich.edu elif self.size: 2955253Sksewell@umich.edu raise Exception, "Unrecognized size type %s!" % self.size 2965253Sksewell@umich.edu return '''EmulEnv(%(reg)s, 2975253Sksewell@umich.edu %(regm)s, 2985253Sksewell@umich.edu %(dataSize)s, 2995253Sksewell@umich.edu %(addressSize)s, 3005253Sksewell@umich.edu %(stackSize)s)''' % \ 3015253Sksewell@umich.edu self.__dict__ 3025253Sksewell@umich.edu 3035253Sksewell@umich.edu def addReg(self, reg): 3045253Sksewell@umich.edu if not self.regUsed: 3055253Sksewell@umich.edu self.reg = reg 3065253Sksewell@umich.edu self.regUsed = True 3075253Sksewell@umich.edu elif not self.regmUsed: 3085253Sksewell@umich.edu self.regm = reg 3095253Sksewell@umich.edu self.regmUsed = True 3105253Sksewell@umich.edu else: 3115253Sksewell@umich.edu raise Exception, "EmulEnv is out of register specialization spots." 312 def setSize(self, size): 313 if not self.size: 314 self.size = size 315 else: 316 if self.size != size: 317 raise Exception, "Conflicting register sizes %s and %s!" %\ 318 (self.size, size) 319}}; 320 321let {{ 322 doModRMString = "env.doModRM(machInst);\n" 323 noModRMString = "env.setSeg(machInst);\n" 324 def genMacroop(Name, env): 325 blocks = OutputBlocks() 326 if not macroopDict.has_key(Name): 327 raise Exception, "Unrecognized instruction: %s" % Name 328 macroop = macroopDict[Name] 329 if not macroop.declared: 330 if env.doModRM: 331 macroop.initEnv = doModRMString 332 else: 333 macroop.initEnv = noModRMString 334 blocks.header_output = macroop.getDeclaration() 335 blocks.decoder_output = macroop.getDefinition(env) 336 macroop.declared = True 337 blocks.decode_block = "return %s;\n" % macroop.getAllocator(env) 338 return blocks 339}}; 340