macroop.isa revision 7621:3a6468fa514f
1// -*- mode:c++ -*- 2 3// Copyright (c) 2007 The Hewlett-Packard Development Company 4// All rights reserved. 5// 6// The license below extends only to copyright in the software and shall 7// not be construed as granting a license to any other intellectual 8// property including but not limited to intellectual property relating 9// to a hardware implementation of the functionality of the software 10// licensed hereunder. You may use the software subject to the license 11// terms below provided that you ensure that this notice is replicated 12// unmodified and in its entirety in all distributions of the software, 13// modified or unmodified, in source code or in binary form. 14// 15// Redistribution and use in source and binary forms, with or without 16// modification, are permitted provided that the following conditions are 17// met: redistributions of source code must retain the above copyright 18// notice, this list of conditions and the following disclaimer; 19// redistributions in binary form must reproduce the above copyright 20// notice, this list of conditions and the following disclaimer in the 21// documentation and/or other materials provided with the distribution; 22// neither the name of the copyright holders nor the names of its 23// contributors may be used to endorse or promote products derived from 24// this software without specific prior written permission. 25// 26// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37// 38// Authors: Gabe Black 39 40////////////////////////////////////////////////////////////////////////////// 41// 42// Architecture independent 43// 44 45// Execute method for macroops. 46def template MacroExecPanic {{ 47 Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const 48 { 49 panic("Tried to execute macroop directly!"); 50 return NoFault; 51 } 52}}; 53 54output header {{ 55 56 // Base class for combinationally generated macroops 57 class Macroop : public X86ISA::MacroopBase 58 { 59 public: 60 Macroop(const char *mnem, ExtMachInst _machInst, 61 uint32_t _numMicroops, X86ISA::EmulEnv _env) 62 : MacroopBase(mnem, _machInst, _numMicroops, _env) 63 {} 64 %(MacroExecPanic)s 65 }; 66}}; 67 68////////////////////////////////////////////////////////////////////////////// 69// 70// X86 specific 71// 72////////////////////////////////////////////////////////////////////////////// 73 74// Basic instruction class declaration template. 75def template MacroDeclare {{ 76 namespace X86Macroop 77 { 78 /** 79 * Static instruction class for "%(mnemonic)s". 80 */ 81 class %(class_name)s : public %(base_class)s 82 { 83 private: 84 %(declareLabels)s 85 public: 86 // Constructor. 87 %(class_name)s(ExtMachInst machInst, X86ISA::EmulEnv _env); 88 89 std::string 90 generateDisassembly(Addr pc, const SymbolTable *symtab) const; 91 }; 92 }; 93}}; 94 95def template MacroDisassembly {{ 96 std::string 97 X86Macroop::%(class_name)s::generateDisassembly(Addr pc, 98 const SymbolTable *symtab) const 99 { 100 std::stringstream out; 101 out << mnemonic << "\t"; 102 103 int regSize = %(regSize)s; 104 %(disassembly)s 105 // Shut up gcc. 106 regSize = regSize; 107 return out.str(); 108 } 109}}; 110 111// Basic instruction class constructor template. 112def template MacroConstructor {{ 113 inline X86Macroop::%(class_name)s::%(class_name)s( 114 ExtMachInst machInst, EmulEnv _env) 115 : %(base_class)s("%(mnemonic)s", machInst, %(num_microops)s, _env) 116 { 117 %(adjust_env)s; 118 %(adjust_imm)s; 119 %(adjust_disp)s; 120 %(init_env)s; 121 %(constructor)s; 122 const char *macrocodeBlock = "%(class_name)s"; 123 //alloc_microops is the code that sets up the microops 124 //array in the parent class. 125 %(alloc_microops)s; 126 } 127}}; 128 129let {{ 130 from micro_asm import Combinational_Macroop, Rom_Macroop 131 class X86Macroop(Combinational_Macroop): 132 def add_microop(self, mnemonic, microop): 133 microop.mnemonic = mnemonic 134 microop.micropc = len(self.microops) 135 self.microops.append(microop) 136 def setAdjustEnv(self, val): 137 self.adjust_env = val 138 def adjustImm(self, val): 139 self.adjust_imm += val 140 def adjustDisp(self, val): 141 self.adjust_disp += val 142 def serializing(self): 143 self.serializing = True 144 def __init__(self, name): 145 super(X86Macroop, self).__init__(name) 146 self.directives = { 147 "adjust_env" : self.setAdjustEnv, 148 "adjust_imm" : self.adjustImm, 149 "adjust_disp" : self.adjustDisp, 150 "serializing" : self.serializing 151 } 152 self.declared = False 153 self.adjust_env = "" 154 self.init_env = "" 155 self.adjust_imm = ''' 156 uint64_t adjustedImm = IMMEDIATE; 157 //This is to pacify gcc in case the immediate isn't used. 158 adjustedImm = adjustedImm; 159 ''' 160 self.adjust_disp = ''' 161 uint64_t adjustedDisp = DISPLACEMENT; 162 //This is to pacify gcc in case the displacement isn't used. 163 adjustedDisp = adjustedDisp; 164 ''' 165 self.serializing = False 166 def getAllocator(self, env): 167 return "new X86Macroop::%s(machInst, %s)" % \ 168 (self.name, env.getAllocator()) 169 def getMnemonic(self): 170 mnemonic = self.name.lower() 171 mnemonic = re.match(r'[^_]*', mnemonic).group(0) 172 return mnemonic 173 def getDeclaration(self): 174 #FIXME This first parameter should be the mnemonic. I need to 175 #write some code which pulls that out 176 declareLabels = "" 177 for (label, microop) in self.labels.items(): 178 declareLabels += "const static uint64_t label_%s = %d;\n" \ 179 % (label, microop.micropc) 180 iop = InstObjParams(self.getMnemonic(), self.name, "Macroop", 181 {"code" : "", 182 "declareLabels" : declareLabels 183 }) 184 return MacroDeclare.subst(iop); 185 def getDefinition(self, env): 186 #FIXME This first parameter should be the mnemonic. I need to 187 #write some code which pulls that out 188 numMicroops = len(self.microops) 189 allocMicroops = '' 190 micropc = 0 191 for op in self.microops: 192 flags = ["IsMicroop"] 193 if micropc == numMicroops - 1: 194 flags.append("IsLastMicroop") 195 if self.serializing: 196 flags.append("IsSerializing") 197 flags.append("IsSerializeAfter") 198 else: 199 flags.append("IsDelayedCommit") 200 if micropc == 0: 201 flags.append("IsFirstMicroop") 202 allocMicroops += \ 203 "microops[%d] = %s;\n" % \ 204 (micropc, op.getAllocator(flags)) 205 micropc += 1 206 if env.useStackSize: 207 useStackSize = "true" 208 else: 209 useStackSize = "false" 210 if env.memoryInst: 211 memoryInst = "true" 212 else: 213 memoryInst = "false" 214 regSize = '''(%s || (env.base == INTREG_RSP && %s) ? 215 env.stackSize : 216 env.dataSize)''' % (useStackSize, memoryInst) 217 iop = InstObjParams(self.getMnemonic(), self.name, "Macroop", 218 {"code" : "", "num_microops" : numMicroops, 219 "alloc_microops" : allocMicroops, 220 "adjust_env" : self.adjust_env, 221 "adjust_imm" : self.adjust_imm, 222 "adjust_disp" : self.adjust_disp, 223 "disassembly" : env.disassembly, 224 "regSize" : regSize, 225 "init_env" : self.initEnv}) 226 return MacroConstructor.subst(iop) + \ 227 MacroDisassembly.subst(iop); 228}}; 229 230let {{ 231 class EmulEnv(object): 232 def __init__(self): 233 self.reg = "0" 234 self.regUsed = False 235 self.regm = "0" 236 self.regmUsed = False 237 self.seg = "SEGMENT_REG_DS" 238 self.size = None 239 self.addressSize = "ADDRSIZE" 240 self.dataSize = "OPSIZE" 241 self.stackSize = "STACKSIZE" 242 self.doModRM = False 243 self.disassembly = "" 244 self.firstArgument = True 245 self.useStackSize = False 246 self.memoryInst = False 247 248 def addToDisassembly(self, code): 249 if not self.firstArgument: 250 self.disassembly += "out << \", \";\n" 251 self.firstArgument = False 252 self.disassembly += code 253 254 def getAllocator(self): 255 if self.size == 'b': 256 self.dataSize = 1 257 elif self.size == 'd': 258 self.dataSize = 4 259 #This is for "double plus" which is normally a double word unless 260 #the REX W bit is set, in which case it's a quad word. It's used 261 #for some SSE instructions. 262 elif self.size == 'dp': 263 self.dataSize = "(REX_W ? 8 : 4)" 264 elif self.size == 'q': 265 self.dataSize = 8 266 elif self.size == 'v': 267 self.dataSize = "OPSIZE" 268 elif self.size == 'w': 269 self.dataSize = 2 270 elif self.size == 'z': 271 self.dataSize = "((OPSIZE == 8) ? 4 : OPSIZE)" 272 elif self.size: 273 raise Exception, "Unrecognized size type %s!" % self.size 274 return '''EmulEnv(%(reg)s, 275 %(regm)s, 276 %(dataSize)s, 277 %(addressSize)s, 278 %(stackSize)s)''' % \ 279 self.__dict__ 280 281 def addReg(self, reg): 282 if not self.regUsed: 283 self.reg = reg 284 self.regUsed = True 285 elif not self.regmUsed: 286 self.regm = reg 287 self.regmUsed = True 288 else: 289 raise Exception, "EmulEnv is out of register specialization spots." 290 def setSize(self, size): 291 if not self.size: 292 self.size = size 293 else: 294 if self.size != size: 295 raise Exception, "Conflicting register sizes %s and %s!" %\ 296 (self.size, size) 297}}; 298 299let {{ 300 doModRMString = "env.doModRM(machInst);\n" 301 noModRMString = "env.setSeg(machInst);\n" 302 def genMacroop(Name, env): 303 blocks = OutputBlocks() 304 if not macroopDict.has_key(Name): 305 raise Exception, "Unrecognized instruction: %s" % Name 306 macroop = macroopDict[Name] 307 if not macroop.declared: 308 if env.doModRM: 309 macroop.initEnv = doModRMString 310 else: 311 macroop.initEnv = noModRMString 312 blocks.header_output = macroop.getDeclaration() 313 blocks.decoder_output = macroop.getDefinition(env) 314 macroop.declared = True 315 blocks.decode_block = "return %s;\n" % macroop.getAllocator(env) 316 return blocks 317}}; 318