macroop.isa revision 12584:2af98e1fb894
15633Sgblack@eecs.umich.edu// -*- mode:c++ -*- 25633Sgblack@eecs.umich.edu 35633Sgblack@eecs.umich.edu// Copyright (c) 2007 The Hewlett-Packard Development Company 45633Sgblack@eecs.umich.edu// All rights reserved. 55633Sgblack@eecs.umich.edu// 65633Sgblack@eecs.umich.edu// The license below extends only to copyright in the software and shall 75633Sgblack@eecs.umich.edu// not be construed as granting a license to any other intellectual 85633Sgblack@eecs.umich.edu// property including but not limited to intellectual property relating 95633Sgblack@eecs.umich.edu// to a hardware implementation of the functionality of the software 105633Sgblack@eecs.umich.edu// licensed hereunder. You may use the software subject to the license 115633Sgblack@eecs.umich.edu// terms below provided that you ensure that this notice is replicated 125633Sgblack@eecs.umich.edu// unmodified and in its entirety in all distributions of the software, 135633Sgblack@eecs.umich.edu// modified or unmodified, in source code or in binary form. 145633Sgblack@eecs.umich.edu// 155633Sgblack@eecs.umich.edu// Redistribution and use in source and binary forms, with or without 165633Sgblack@eecs.umich.edu// modification, are permitted provided that the following conditions are 175633Sgblack@eecs.umich.edu// met: redistributions of source code must retain the above copyright 185633Sgblack@eecs.umich.edu// notice, this list of conditions and the following disclaimer; 195633Sgblack@eecs.umich.edu// redistributions in binary form must reproduce the above copyright 205633Sgblack@eecs.umich.edu// notice, this list of conditions and the following disclaimer in the 215633Sgblack@eecs.umich.edu// documentation and/or other materials provided with the distribution; 225633Sgblack@eecs.umich.edu// neither the name of the copyright holders nor the names of its 235633Sgblack@eecs.umich.edu// contributors may be used to endorse or promote products derived from 245633Sgblack@eecs.umich.edu// this software without specific prior written permission. 255633Sgblack@eecs.umich.edu// 265633Sgblack@eecs.umich.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 275633Sgblack@eecs.umich.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 285633Sgblack@eecs.umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 295633Sgblack@eecs.umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 305633Sgblack@eecs.umich.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 315633Sgblack@eecs.umich.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 325633Sgblack@eecs.umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 335633Sgblack@eecs.umich.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 346216Snate@binkert.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 355651Sgblack@eecs.umich.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 365633Sgblack@eecs.umich.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 375651Sgblack@eecs.umich.edu// 386045Sgblack@eecs.umich.edu// Authors: Gabe Black 395651Sgblack@eecs.umich.edu 405651Sgblack@eecs.umich.edu////////////////////////////////////////////////////////////////////////////// 415633Sgblack@eecs.umich.edu// 425827Sgblack@eecs.umich.edu// Architecture independent 435827Sgblack@eecs.umich.edu// 445827Sgblack@eecs.umich.edu 455633Sgblack@eecs.umich.edu// Execute method for macroops. 466138Sgblack@eecs.umich.edudef template MacroExecPanic {{ 476138Sgblack@eecs.umich.edu Fault execute(ExecContext *, Trace::InstRecord *) const 485633Sgblack@eecs.umich.edu { 495633Sgblack@eecs.umich.edu panic("Tried to execute macroop directly!"); 506138Sgblack@eecs.umich.edu return NoFault; 516138Sgblack@eecs.umich.edu } 525633Sgblack@eecs.umich.edu}}; 535633Sgblack@eecs.umich.edu 545651Sgblack@eecs.umich.eduoutput header {{ 555651Sgblack@eecs.umich.edu 565651Sgblack@eecs.umich.edu // Base class for combinationally generated macroops 575651Sgblack@eecs.umich.edu class Macroop : public X86ISA::MacroopBase 585651Sgblack@eecs.umich.edu { 595651Sgblack@eecs.umich.edu public: 605651Sgblack@eecs.umich.edu Macroop(const char *mnem, ExtMachInst _machInst, 615651Sgblack@eecs.umich.edu uint32_t _numMicroops, X86ISA::EmulEnv _env) 625651Sgblack@eecs.umich.edu : MacroopBase(mnem, _machInst, _numMicroops, _env) 635651Sgblack@eecs.umich.edu {} 645651Sgblack@eecs.umich.edu 655651Sgblack@eecs.umich.edu Fault 665651Sgblack@eecs.umich.edu execute(ExecContext *, Trace::InstRecord *) const 675651Sgblack@eecs.umich.edu { 685651Sgblack@eecs.umich.edu panic("Tried to execute macroop directly!"); 695651Sgblack@eecs.umich.edu } 705651Sgblack@eecs.umich.edu }; 715651Sgblack@eecs.umich.edu}}; 725651Sgblack@eecs.umich.edu 735651Sgblack@eecs.umich.edu////////////////////////////////////////////////////////////////////////////// 745651Sgblack@eecs.umich.edu// 755651Sgblack@eecs.umich.edu// X86 specific 765651Sgblack@eecs.umich.edu// 775651Sgblack@eecs.umich.edu////////////////////////////////////////////////////////////////////////////// 786064Sgblack@eecs.umich.edu 796064Sgblack@eecs.umich.edu// Basic instruction class declaration template. 806064Sgblack@eecs.umich.edudef template MacroDeclare {{ 816064Sgblack@eecs.umich.edu namespace X86Macroop 826064Sgblack@eecs.umich.edu { 836045Sgblack@eecs.umich.edu /** 846045Sgblack@eecs.umich.edu * Static instruction class for "%(mnemonic)s". 856138Sgblack@eecs.umich.edu */ 866138Sgblack@eecs.umich.edu class %(class_name)s : public %(base_class)s 876045Sgblack@eecs.umich.edu { 885651Sgblack@eecs.umich.edu private: 895651Sgblack@eecs.umich.edu %(declareLabels)s 905651Sgblack@eecs.umich.edu public: 915651Sgblack@eecs.umich.edu // Constructor. 925651Sgblack@eecs.umich.edu %(class_name)s(ExtMachInst machInst, X86ISA::EmulEnv _env); 935651Sgblack@eecs.umich.edu 945651Sgblack@eecs.umich.edu std::string 955651Sgblack@eecs.umich.edu generateDisassembly(Addr pc, const SymbolTable *symtab) const; 965651Sgblack@eecs.umich.edu }; 975651Sgblack@eecs.umich.edu } 985651Sgblack@eecs.umich.edu}}; 995633Sgblack@eecs.umich.edu 1005651Sgblack@eecs.umich.edudef template MacroDisassembly {{ 1015651Sgblack@eecs.umich.edu std::string 1025651Sgblack@eecs.umich.edu X86Macroop::%(class_name)s::generateDisassembly(Addr pc, 1035651Sgblack@eecs.umich.edu const SymbolTable *symtab) const 1045651Sgblack@eecs.umich.edu { 1055651Sgblack@eecs.umich.edu std::stringstream out; 1065651Sgblack@eecs.umich.edu out << mnemonic << "\t"; 1075651Sgblack@eecs.umich.edu 1085651Sgblack@eecs.umich.edu int regSize = %(regSize)s; 1095651Sgblack@eecs.umich.edu %(disassembly)s 1105633Sgblack@eecs.umich.edu // Shut up gcc. 1115633Sgblack@eecs.umich.edu regSize = regSize; 1125651Sgblack@eecs.umich.edu return out.str(); 1135633Sgblack@eecs.umich.edu } 1145651Sgblack@eecs.umich.edu}}; 1155651Sgblack@eecs.umich.edu 1165651Sgblack@eecs.umich.edu// Basic instruction class constructor template. 1175651Sgblack@eecs.umich.edudef template MacroConstructor {{ 1185651Sgblack@eecs.umich.edu X86Macroop::%(class_name)s::%(class_name)s( 1195827Sgblack@eecs.umich.edu ExtMachInst machInst, EmulEnv _env) 1205827Sgblack@eecs.umich.edu : %(base_class)s("%(mnemonic)s", machInst, %(num_microops)s, _env) 1215827Sgblack@eecs.umich.edu { 1225827Sgblack@eecs.umich.edu %(adjust_env)s; 1235827Sgblack@eecs.umich.edu %(adjust_imm)s; 1245827Sgblack@eecs.umich.edu %(adjust_disp)s; 1255827Sgblack@eecs.umich.edu %(init_env)s; 1265827Sgblack@eecs.umich.edu %(constructor)s; 1275827Sgblack@eecs.umich.edu const char *macrocodeBlock = "%(class_name)s"; 1285827Sgblack@eecs.umich.edu //alloc_microops is the code that sets up the microops 1295827Sgblack@eecs.umich.edu //array in the parent class. 1305827Sgblack@eecs.umich.edu %(alloc_microops)s; 1315651Sgblack@eecs.umich.edu } 1325651Sgblack@eecs.umich.edu}}; 1335651Sgblack@eecs.umich.edu 1345651Sgblack@eecs.umich.edulet {{ 1355651Sgblack@eecs.umich.edu from micro_asm import Combinational_Macroop, Rom_Macroop 1365651Sgblack@eecs.umich.edu class X86Macroop(Combinational_Macroop): 1375651Sgblack@eecs.umich.edu def add_microop(self, mnemonic, microop): 1386064Sgblack@eecs.umich.edu microop.mnemonic = mnemonic 1396064Sgblack@eecs.umich.edu microop.micropc = len(self.microops) 1406064Sgblack@eecs.umich.edu self.microops.append(microop) 1416064Sgblack@eecs.umich.edu def setAdjustEnv(self, val): 1426064Sgblack@eecs.umich.edu self.adjust_env = val 1436064Sgblack@eecs.umich.edu def adjustImm(self, val): 1446064Sgblack@eecs.umich.edu self.adjust_imm += val 1456064Sgblack@eecs.umich.edu def adjustDisp(self, val): 1465651Sgblack@eecs.umich.edu self.adjust_disp += val 1475651Sgblack@eecs.umich.edu def serializeBefore(self): 1485651Sgblack@eecs.umich.edu self.serialize_before = True 1495651Sgblack@eecs.umich.edu def serializeAfter(self): 1505651Sgblack@eecs.umich.edu self.serialize_after = True 1515633Sgblack@eecs.umich.edu 1525633Sgblack@eecs.umich.edu def function_call(self): 1535827Sgblack@eecs.umich.edu self.function_call = True 1545633Sgblack@eecs.umich.edu def function_return(self): 1555827Sgblack@eecs.umich.edu self.function_return = True 1565633Sgblack@eecs.umich.edu 1575827Sgblack@eecs.umich.edu def __init__(self, name): 1585633Sgblack@eecs.umich.edu super(X86Macroop, self).__init__(name) 1595827Sgblack@eecs.umich.edu self.directives = { 1605657Sgblack@eecs.umich.edu "adjust_env" : self.setAdjustEnv, 1615633Sgblack@eecs.umich.edu "adjust_imm" : self.adjustImm, 1625633Sgblack@eecs.umich.edu "adjust_disp" : self.adjustDisp, 1635633Sgblack@eecs.umich.edu "serialize_before" : self.serializeBefore, 1645633Sgblack@eecs.umich.edu "serialize_after" : self.serializeAfter, 1655633Sgblack@eecs.umich.edu "function_call" : self.function_call, 1665633Sgblack@eecs.umich.edu "function_return" : self.function_return 1675827Sgblack@eecs.umich.edu } 1685827Sgblack@eecs.umich.edu self.declared = False 1695633Sgblack@eecs.umich.edu self.adjust_env = "" 1705633Sgblack@eecs.umich.edu self.init_env = "" 1715633Sgblack@eecs.umich.edu self.adjust_imm = ''' 1725827Sgblack@eecs.umich.edu uint64_t adjustedImm = IMMEDIATE; 1735827Sgblack@eecs.umich.edu //This is to pacify gcc in case the immediate isn't used. 1745827Sgblack@eecs.umich.edu adjustedImm = adjustedImm; 1755827Sgblack@eecs.umich.edu ''' 1765827Sgblack@eecs.umich.edu self.adjust_disp = ''' 1775827Sgblack@eecs.umich.edu uint64_t adjustedDisp = DISPLACEMENT; 1785827Sgblack@eecs.umich.edu //This is to pacify gcc in case the displacement isn't used. 1795827Sgblack@eecs.umich.edu adjustedDisp = adjustedDisp; 1805827Sgblack@eecs.umich.edu ''' 1815827Sgblack@eecs.umich.edu self.serialize_before = False 1825827Sgblack@eecs.umich.edu self.serialize_after = False 1835827Sgblack@eecs.umich.edu self.function_call = False 1845827Sgblack@eecs.umich.edu self.function_return = False 1855827Sgblack@eecs.umich.edu 1865827Sgblack@eecs.umich.edu def getAllocator(self, env): 1875633Sgblack@eecs.umich.edu return "new X86Macroop::%s(machInst, %s)" % \ 1885633Sgblack@eecs.umich.edu (self.name, env.getAllocator()) 1895827Sgblack@eecs.umich.edu def getMnemonic(self): 1905633Sgblack@eecs.umich.edu mnemonic = self.name.lower() 1915827Sgblack@eecs.umich.edu mnemonic = re.match(r'[^_]*', mnemonic).group(0) 1925827Sgblack@eecs.umich.edu return mnemonic 1935827Sgblack@eecs.umich.edu def getDeclaration(self): 1945827Sgblack@eecs.umich.edu #FIXME This first parameter should be the mnemonic. I need to 1955827Sgblack@eecs.umich.edu #write some code which pulls that out 1965827Sgblack@eecs.umich.edu declareLabels = "" 1975827Sgblack@eecs.umich.edu for (label, microop) in self.labels.items(): 1985827Sgblack@eecs.umich.edu declareLabels += "const static uint64_t label_%s = %d;\n" \ 1995827Sgblack@eecs.umich.edu % (label, microop.micropc) 2005827Sgblack@eecs.umich.edu iop = InstObjParams(self.getMnemonic(), self.name, "Macroop", 2015827Sgblack@eecs.umich.edu {"code" : "", 2025827Sgblack@eecs.umich.edu "declareLabels" : declareLabels 2035827Sgblack@eecs.umich.edu }) 2045827Sgblack@eecs.umich.edu return MacroDeclare.subst(iop); 2055827Sgblack@eecs.umich.edu def getDefinition(self, env): 2065827Sgblack@eecs.umich.edu #FIXME This first parameter should be the mnemonic. I need to 2075827Sgblack@eecs.umich.edu #write some code which pulls that out 2085827Sgblack@eecs.umich.edu numMicroops = len(self.microops) 2095827Sgblack@eecs.umich.edu allocMicroops = '' 2105827Sgblack@eecs.umich.edu micropc = 0 2115827Sgblack@eecs.umich.edu for op in self.microops: 2125827Sgblack@eecs.umich.edu flags = ["IsMicroop"] 2135827Sgblack@eecs.umich.edu if micropc == 0: 2145827Sgblack@eecs.umich.edu flags.append("IsFirstMicroop") 2155827Sgblack@eecs.umich.edu 2165827Sgblack@eecs.umich.edu if self.serialize_before: 2175827Sgblack@eecs.umich.edu flags.append("IsSerializing") 2185827Sgblack@eecs.umich.edu flags.append("IsSerializeBefore") 2195827Sgblack@eecs.umich.edu 2205827Sgblack@eecs.umich.edu if micropc == numMicroops - 1: 2215827Sgblack@eecs.umich.edu flags.append("IsLastMicroop") 2225827Sgblack@eecs.umich.edu 2235827Sgblack@eecs.umich.edu if self.serialize_after: 2245827Sgblack@eecs.umich.edu flags.append("IsSerializing") 2255827Sgblack@eecs.umich.edu flags.append("IsSerializeAfter") 2265827Sgblack@eecs.umich.edu 2275827Sgblack@eecs.umich.edu if self.function_call: 2285827Sgblack@eecs.umich.edu flags.append("IsCall") 2295827Sgblack@eecs.umich.edu if self.function_return: 2305827Sgblack@eecs.umich.edu flags.append("IsReturn") 2315827Sgblack@eecs.umich.edu else: 2325827Sgblack@eecs.umich.edu flags.append("IsDelayedCommit") 2335827Sgblack@eecs.umich.edu 2345633Sgblack@eecs.umich.edu allocMicroops += \ 2355633Sgblack@eecs.umich.edu "microops[%d] = %s;\n" % \ 2365633Sgblack@eecs.umich.edu (micropc, op.getAllocator(flags)) 2377811Ssteve.reinhardt@amd.com micropc += 1 2385633Sgblack@eecs.umich.edu if env.useStackSize: 2395633Sgblack@eecs.umich.edu useStackSize = "true" 240 else: 241 useStackSize = "false" 242 if env.memoryInst: 243 memoryInst = "true" 244 else: 245 memoryInst = "false" 246 regSize = '''(%s || (env.base == INTREG_RSP && %s) ? 247 env.stackSize : 248 env.dataSize)''' % (useStackSize, memoryInst) 249 iop = InstObjParams(self.getMnemonic(), self.name, "Macroop", 250 {"code" : "", "num_microops" : numMicroops, 251 "alloc_microops" : allocMicroops, 252 "adjust_env" : self.adjust_env, 253 "adjust_imm" : self.adjust_imm, 254 "adjust_disp" : self.adjust_disp, 255 "disassembly" : env.disassembly, 256 "regSize" : regSize, 257 "init_env" : self.initEnv}) 258 return MacroConstructor.subst(iop) + \ 259 MacroDisassembly.subst(iop); 260}}; 261 262let {{ 263 class EmulEnv(object): 264 def __init__(self): 265 self.reg = "0" 266 self.regUsed = False 267 self.regm = "0" 268 self.regmUsed = False 269 self.seg = "SEGMENT_REG_DS" 270 self.size = None 271 self.addressSize = "ADDRSIZE" 272 self.dataSize = "OPSIZE" 273 self.stackSize = "STACKSIZE" 274 self.doModRM = False 275 self.disassembly = "" 276 self.firstArgument = True 277 self.useStackSize = False 278 self.memoryInst = False 279 280 def addToDisassembly(self, code): 281 if not self.firstArgument: 282 self.disassembly += "out << \", \";\n" 283 self.firstArgument = False 284 self.disassembly += code 285 286 def getAllocator(self): 287 if self.size == 'b': 288 self.dataSize = 1 289 elif self.size == 'd': 290 self.dataSize = 4 291 #This is for "double plus" which is normally a double word unless 292 #the REX W bit is set, in which case it's a quad word. It's used 293 #for some SSE instructions. 294 elif self.size == 'dp': 295 self.dataSize = "(REX_W ? 8 : 4)" 296 elif self.size == 'q': 297 self.dataSize = 8 298 elif self.size == 'v': 299 self.dataSize = "OPSIZE" 300 elif self.size == 'w': 301 self.dataSize = 2 302 elif self.size == 'z': 303 self.dataSize = "((OPSIZE == 8) ? 4 : OPSIZE)" 304 elif self.size: 305 raise Exception, "Unrecognized size type %s!" % self.size 306 return '''EmulEnv(%(reg)s, 307 %(regm)s, 308 %(dataSize)s, 309 %(addressSize)s, 310 %(stackSize)s)''' % \ 311 self.__dict__ 312 313 def addReg(self, reg): 314 if not self.regUsed: 315 self.reg = reg 316 self.regUsed = True 317 elif not self.regmUsed: 318 self.regm = reg 319 self.regmUsed = True 320 else: 321 raise Exception, "EmulEnv is out of register specialization spots." 322 def setSize(self, size): 323 if not self.size: 324 self.size = size 325 else: 326 if self.size != size: 327 raise Exception, "Conflicting register sizes %s and %s!" %\ 328 (self.size, size) 329}}; 330 331let {{ 332 doModRMString = "env.doModRM(machInst);\n" 333 noModRMString = "env.setSeg(machInst);\n" 334 def genMacroop(Name, env): 335 blocks = OutputBlocks() 336 if not macroopDict.has_key(Name): 337 raise Exception, "Unrecognized instruction: %s" % Name 338 macroop = macroopDict[Name] 339 if not macroop.declared: 340 if env.doModRM: 341 macroop.initEnv = doModRMString 342 else: 343 macroop.initEnv = noModRMString 344 blocks.header_output = macroop.getDeclaration() 345 blocks.decoder_output = macroop.getDefinition(env) 346 macroop.declared = True 347 blocks.decode_block = "return %s;\n" % macroop.getAllocator(env) 348 return blocks 349}}; 350