macroop.isa revision 10184:bbfa3152bdea
12SN/A// -*- mode:c++ -*- 21762SN/A 32SN/A// Copyright (c) 2007 The Hewlett-Packard Development Company 42SN/A// All rights reserved. 52SN/A// 62SN/A// The license below extends only to copyright in the software and shall 72SN/A// not be construed as granting a license to any other intellectual 82SN/A// property including but not limited to intellectual property relating 92SN/A// to a hardware implementation of the functionality of the software 102SN/A// licensed hereunder. You may use the software subject to the license 112SN/A// terms below provided that you ensure that this notice is replicated 122SN/A// unmodified and in its entirety in all distributions of the software, 132SN/A// modified or unmodified, in source code or in binary form. 142SN/A// 152SN/A// Redistribution and use in source and binary forms, with or without 162SN/A// modification, are permitted provided that the following conditions are 172SN/A// met: redistributions of source code must retain the above copyright 182SN/A// notice, this list of conditions and the following disclaimer; 192SN/A// redistributions in binary form must reproduce the above copyright 202SN/A// notice, this list of conditions and the following disclaimer in the 212SN/A// documentation and/or other materials provided with the distribution; 222SN/A// neither the name of the copyright holders nor the names of its 232SN/A// contributors may be used to endorse or promote products derived from 242SN/A// this software without specific prior written permission. 252SN/A// 262SN/A// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 272665Ssaidi@eecs.umich.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 282665Ssaidi@eecs.umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 292665Ssaidi@eecs.umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 302SN/A// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 312SN/A// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 324997Sgblack@eecs.umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 331110SN/A// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 344997Sgblack@eecs.umich.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 358229Snate@binkert.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 368229Snate@binkert.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 372680Sktlim@umich.edu// 388229Snate@binkert.org// Authors: Gabe Black 392800Ssaidi@eecs.umich.edu 408780Sgblack@eecs.umich.edu////////////////////////////////////////////////////////////////////////////// 412SN/A// 425569Snate@binkert.org// Architecture independent 432167SN/A// 442203SN/A 452203SN/A// Execute method for macroops. 462222SN/Adef template MacroExecPanic {{ 472166SN/A Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const 482203SN/A { 492203SN/A panic("Tried to execute macroop directly!"); 502222SN/A return NoFault; 512166SN/A } 522147SN/A}}; 532147SN/A 542222SN/Aoutput header {{ 552147SN/A 562147SN/A // Base class for combinationally generated macroops 572147SN/A class Macroop : public X86ISA::MacroopBase 582222SN/A { 592147SN/A public: 602147SN/A Macroop(const char *mnem, ExtMachInst _machInst, 612147SN/A uint32_t _numMicroops, X86ISA::EmulEnv _env) 622222SN/A : MacroopBase(mnem, _machInst, _numMicroops, _env) 632147SN/A {} 642147SN/A %(MacroExecPanic)s 652147SN/A }; 662222SN/A}}; 672147SN/A 682147SN/A////////////////////////////////////////////////////////////////////////////// 692147SN/A// 702222SN/A// X86 specific 712147SN/A// 728405Sksewell@umich.edu////////////////////////////////////////////////////////////////////////////// 732147SN/A 742222SN/A// Basic instruction class declaration template. 752147SN/Adef template MacroDeclare {{ 768405Sksewell@umich.edu namespace X86Macroop 772147SN/A { 782222SN/A /** 792147SN/A * Static instruction class for "%(mnemonic)s". 802289SN/A */ 812289SN/A class %(class_name)s : public %(base_class)s 822289SN/A { 832289SN/A private: 842147SN/A %(declareLabels)s 852147SN/A public: 862222SN/A // Constructor. 872147SN/A %(class_name)s(ExtMachInst machInst, X86ISA::EmulEnv _env); 882147SN/A 892147SN/A std::string 902222SN/A generateDisassembly(Addr pc, const SymbolTable *symtab) const; 912147SN/A }; 922147SN/A } 932147SN/A}}; 942222SN/A 952147SN/Adef template MacroDisassembly {{ 962147SN/A std::string 972147SN/A X86Macroop::%(class_name)s::generateDisassembly(Addr pc, 982222SN/A const SymbolTable *symtab) const 992147SN/A { 1002147SN/A std::stringstream out; 1012147SN/A out << mnemonic << "\t"; 1022222SN/A 1032147SN/A int regSize = %(regSize)s; 1042147SN/A %(disassembly)s 1052147SN/A // Shut up gcc. 1062222SN/A regSize = regSize; 1072147SN/A return out.str(); 1085569Snate@binkert.org } 1097678Sgblack@eecs.umich.edu}}; 1102174SN/A 1112680Sktlim@umich.edu// Basic instruction class constructor template. 1128780Sgblack@eecs.umich.edudef template MacroConstructor {{ 1138780Sgblack@eecs.umich.edu X86Macroop::%(class_name)s::%(class_name)s( 1142222SN/A ExtMachInst machInst, EmulEnv _env) 1152174SN/A : %(base_class)s("%(mnemonic)s", machInst, %(num_microops)s, _env) 1167720Sgblack@eecs.umich.edu { 1177720Sgblack@eecs.umich.edu %(adjust_env)s; 1182196SN/A %(adjust_imm)s; 1197720Sgblack@eecs.umich.edu %(adjust_disp)s; 1207720Sgblack@eecs.umich.edu %(init_env)s; 1212196SN/A %(constructor)s; 1222201SN/A const char *macrocodeBlock = "%(class_name)s"; 1232196SN/A //alloc_microops is the code that sets up the microops 1245568Snate@binkert.org //array in the parent class. 1255568Snate@binkert.org %(alloc_microops)s; 1262196SN/A } 1272196SN/A}}; 1287720Sgblack@eecs.umich.edu 1297720Sgblack@eecs.umich.edulet {{ 1302174SN/A from micro_asm import Combinational_Macroop, Rom_Macroop 1312174SN/A class X86Macroop(Combinational_Macroop): 1325569Snate@binkert.org def add_microop(self, mnemonic, microop): 1337678Sgblack@eecs.umich.edu microop.mnemonic = mnemonic 1342201SN/A microop.micropc = len(self.microops) 1352680Sktlim@umich.edu self.microops.append(microop) 1368780Sgblack@eecs.umich.edu def setAdjustEnv(self, val): 1378780Sgblack@eecs.umich.edu self.adjust_env = val 1382201SN/A def adjustImm(self, val): 1392201SN/A self.adjust_imm += val 1402201SN/A def adjustDisp(self, val): 1415569Snate@binkert.org self.adjust_disp += val 1427678Sgblack@eecs.umich.edu def serializing(self): 1432289SN/A self.serializing = True 1448780Sgblack@eecs.umich.edu 1458780Sgblack@eecs.umich.edu def function_call(self): 1468780Sgblack@eecs.umich.edu self.function_call = True 1478780Sgblack@eecs.umich.edu def function_return(self): 1488780Sgblack@eecs.umich.edu self.function_return = True 1498780Sgblack@eecs.umich.edu 1508780Sgblack@eecs.umich.edu def __init__(self, name): 1518780Sgblack@eecs.umich.edu super(X86Macroop, self).__init__(name) 1528780Sgblack@eecs.umich.edu self.directives = { 1538780Sgblack@eecs.umich.edu "adjust_env" : self.setAdjustEnv, 1542289SN/A "adjust_imm" : self.adjustImm, 1558780Sgblack@eecs.umich.edu "adjust_disp" : self.adjustDisp, 1568780Sgblack@eecs.umich.edu "serializing" : self.serializing, 1578780Sgblack@eecs.umich.edu "function_call" : self.function_call, 1588780Sgblack@eecs.umich.edu "function_return" : self.function_return 1598780Sgblack@eecs.umich.edu } 1608780Sgblack@eecs.umich.edu self.declared = False 1612289SN/A self.adjust_env = "" 1628780Sgblack@eecs.umich.edu self.init_env = "" 1638780Sgblack@eecs.umich.edu self.adjust_imm = ''' 1648780Sgblack@eecs.umich.edu uint64_t adjustedImm = IMMEDIATE; 1658780Sgblack@eecs.umich.edu //This is to pacify gcc in case the immediate isn't used. 1662289SN/A adjustedImm = adjustedImm; 1672289SN/A ''' 1682680Sktlim@umich.edu self.adjust_disp = ''' 1692289SN/A uint64_t adjustedDisp = DISPLACEMENT; 1702289SN/A //This is to pacify gcc in case the displacement isn't used. 1715569Snate@binkert.org adjustedDisp = adjustedDisp; 1727678Sgblack@eecs.umich.edu ''' 1732289SN/A self.serializing = False 1748780Sgblack@eecs.umich.edu self.function_call = False 1758780Sgblack@eecs.umich.edu self.function_return = False 1768780Sgblack@eecs.umich.edu 1778780Sgblack@eecs.umich.edu def getAllocator(self, env): 1788780Sgblack@eecs.umich.edu return "new X86Macroop::%s(machInst, %s)" % \ 1798780Sgblack@eecs.umich.edu (self.name, env.getAllocator()) 1802289SN/A def getMnemonic(self): 1812289SN/A mnemonic = self.name.lower() 1822680Sktlim@umich.edu mnemonic = re.match(r'[^_]*', mnemonic).group(0) 1832289SN/A return mnemonic 1842289SN/A def getDeclaration(self): 1855569Snate@binkert.org #FIXME This first parameter should be the mnemonic. I need to 1867678Sgblack@eecs.umich.edu #write some code which pulls that out 1874997Sgblack@eecs.umich.edu declareLabels = "" 1888780Sgblack@eecs.umich.edu for (label, microop) in self.labels.items(): 1898780Sgblack@eecs.umich.edu declareLabels += "const static uint64_t label_%s = %d;\n" \ 1904997Sgblack@eecs.umich.edu % (label, microop.micropc) 1918780Sgblack@eecs.umich.edu iop = InstObjParams(self.getMnemonic(), self.name, "Macroop", 1928780Sgblack@eecs.umich.edu {"code" : "", 1938780Sgblack@eecs.umich.edu "declareLabels" : declareLabels 1948780Sgblack@eecs.umich.edu }) 1958780Sgblack@eecs.umich.edu return MacroDeclare.subst(iop); 1968780Sgblack@eecs.umich.edu def getDefinition(self, env): 1978780Sgblack@eecs.umich.edu #FIXME This first parameter should be the mnemonic. I need to 1988780Sgblack@eecs.umich.edu #write some code which pulls that out 1998780Sgblack@eecs.umich.edu numMicroops = len(self.microops) 2004997Sgblack@eecs.umich.edu allocMicroops = '' 2014997Sgblack@eecs.umich.edu micropc = 0 2024997Sgblack@eecs.umich.edu for op in self.microops: 2035569Snate@binkert.org flags = ["IsMicroop"] 2047678Sgblack@eecs.umich.edu if micropc == numMicroops - 1: 2054997Sgblack@eecs.umich.edu flags.append("IsLastMicroop") 2068780Sgblack@eecs.umich.edu 2078780Sgblack@eecs.umich.edu if self.serializing: 2084997Sgblack@eecs.umich.edu flags.append("IsSerializing") 2098780Sgblack@eecs.umich.edu flags.append("IsSerializeAfter") 2108780Sgblack@eecs.umich.edu 2118780Sgblack@eecs.umich.edu if self.function_call: 2128780Sgblack@eecs.umich.edu flags.append("IsCall") 2138780Sgblack@eecs.umich.edu if self.function_return: 2148780Sgblack@eecs.umich.edu flags.append("IsReturn") 2158780Sgblack@eecs.umich.edu else: 2168780Sgblack@eecs.umich.edu flags.append("IsDelayedCommit") 2178780Sgblack@eecs.umich.edu if micropc == 0: 2188780Sgblack@eecs.umich.edu flags.append("IsFirstMicroop") 2198780Sgblack@eecs.umich.edu allocMicroops += \ 2208780Sgblack@eecs.umich.edu "microops[%d] = %s;\n" % \ 2214997Sgblack@eecs.umich.edu (micropc, op.getAllocator(flags)) 2224997Sgblack@eecs.umich.edu micropc += 1 2234997Sgblack@eecs.umich.edu if env.useStackSize: 2242167SN/A useStackSize = "true" 2252167SN/A else: 226 useStackSize = "false" 227 if env.memoryInst: 228 memoryInst = "true" 229 else: 230 memoryInst = "false" 231 regSize = '''(%s || (env.base == INTREG_RSP && %s) ? 232 env.stackSize : 233 env.dataSize)''' % (useStackSize, memoryInst) 234 iop = InstObjParams(self.getMnemonic(), self.name, "Macroop", 235 {"code" : "", "num_microops" : numMicroops, 236 "alloc_microops" : allocMicroops, 237 "adjust_env" : self.adjust_env, 238 "adjust_imm" : self.adjust_imm, 239 "adjust_disp" : self.adjust_disp, 240 "disassembly" : env.disassembly, 241 "regSize" : regSize, 242 "init_env" : self.initEnv}) 243 return MacroConstructor.subst(iop) + \ 244 MacroDisassembly.subst(iop); 245}}; 246 247let {{ 248 class EmulEnv(object): 249 def __init__(self): 250 self.reg = "0" 251 self.regUsed = False 252 self.regm = "0" 253 self.regmUsed = False 254 self.seg = "SEGMENT_REG_DS" 255 self.size = None 256 self.addressSize = "ADDRSIZE" 257 self.dataSize = "OPSIZE" 258 self.stackSize = "STACKSIZE" 259 self.doModRM = False 260 self.disassembly = "" 261 self.firstArgument = True 262 self.useStackSize = False 263 self.memoryInst = False 264 265 def addToDisassembly(self, code): 266 if not self.firstArgument: 267 self.disassembly += "out << \", \";\n" 268 self.firstArgument = False 269 self.disassembly += code 270 271 def getAllocator(self): 272 if self.size == 'b': 273 self.dataSize = 1 274 elif self.size == 'd': 275 self.dataSize = 4 276 #This is for "double plus" which is normally a double word unless 277 #the REX W bit is set, in which case it's a quad word. It's used 278 #for some SSE instructions. 279 elif self.size == 'dp': 280 self.dataSize = "(REX_W ? 8 : 4)" 281 elif self.size == 'q': 282 self.dataSize = 8 283 elif self.size == 'v': 284 self.dataSize = "OPSIZE" 285 elif self.size == 'w': 286 self.dataSize = 2 287 elif self.size == 'z': 288 self.dataSize = "((OPSIZE == 8) ? 4 : OPSIZE)" 289 elif self.size: 290 raise Exception, "Unrecognized size type %s!" % self.size 291 return '''EmulEnv(%(reg)s, 292 %(regm)s, 293 %(dataSize)s, 294 %(addressSize)s, 295 %(stackSize)s)''' % \ 296 self.__dict__ 297 298 def addReg(self, reg): 299 if not self.regUsed: 300 self.reg = reg 301 self.regUsed = True 302 elif not self.regmUsed: 303 self.regm = reg 304 self.regmUsed = True 305 else: 306 raise Exception, "EmulEnv is out of register specialization spots." 307 def setSize(self, size): 308 if not self.size: 309 self.size = size 310 else: 311 if self.size != size: 312 raise Exception, "Conflicting register sizes %s and %s!" %\ 313 (self.size, size) 314}}; 315 316let {{ 317 doModRMString = "env.doModRM(machInst);\n" 318 noModRMString = "env.setSeg(machInst);\n" 319 def genMacroop(Name, env): 320 blocks = OutputBlocks() 321 if not macroopDict.has_key(Name): 322 raise Exception, "Unrecognized instruction: %s" % Name 323 macroop = macroopDict[Name] 324 if not macroop.declared: 325 if env.doModRM: 326 macroop.initEnv = doModRMString 327 else: 328 macroop.initEnv = noModRMString 329 blocks.header_output = macroop.getDeclaration() 330 blocks.decoder_output = macroop.getDefinition(env) 331 macroop.declared = True 332 blocks.decode_block = "return %s;\n" % macroop.getAllocator(env) 333 return blocks 334}}; 335