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