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 X86ISA::MacroopBase 76 { 77 public: 78 Macroop(const char *mnem, ExtMachInst _machInst,
| 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 X86ISA::MacroopBase 76 { 77 public: 78 Macroop(const char *mnem, ExtMachInst _machInst,
|
79 uint32_t _numMicroops, X86ISA::EmulEnv _emulEnv) 80 : MacroopBase(mnem, _machInst, _numMicroops, _emulEnv)
| 79 uint32_t _numMicroops, X86ISA::EmulEnv _env) 80 : MacroopBase(mnem, _machInst, _numMicroops, _env)
|
81 {} 82 %(MacroExecPanic)s 83 }; 84}}; 85 86////////////////////////////////////////////////////////////////////////////// 87// 88// X86 specific 89// 90////////////////////////////////////////////////////////////////////////////// 91 92// Basic instruction class declaration template. 93def template MacroDeclare {{ 94 namespace X86Macroop 95 { 96 /** 97 * Static instruction class for "%(mnemonic)s". 98 */ 99 class %(class_name)s : public %(base_class)s 100 { 101 private: 102 %(declareLabels)s 103 public: 104 // Constructor.
| 81 {} 82 %(MacroExecPanic)s 83 }; 84}}; 85 86////////////////////////////////////////////////////////////////////////////// 87// 88// X86 specific 89// 90////////////////////////////////////////////////////////////////////////////// 91 92// Basic instruction class declaration template. 93def template MacroDeclare {{ 94 namespace X86Macroop 95 { 96 /** 97 * Static instruction class for "%(mnemonic)s". 98 */ 99 class %(class_name)s : public %(base_class)s 100 { 101 private: 102 %(declareLabels)s 103 public: 104 // Constructor.
|
105 %(class_name)s(ExtMachInst machInst, X86ISA::EmulEnv env);
| 105 %(class_name)s(ExtMachInst machInst, X86ISA::EmulEnv _env); 106 107 std::string 108 generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
106 }; 107 }; 108}}; 109
| 109 }; 110 }; 111}}; 112
|
| 113def template MacroDisassembly {{ 114 std::string 115 X86Macroop::%(class_name)s::generateDisassembly(Addr pc, 116 const SymbolTable *symtab) const 117 { 118 std::stringstream out; 119 out << mnemonic << "\t"; 120 121 int regSize = %(regSize)s; 122 %(disassembly)s 123 // Shut up gcc. 124 regSize = regSize; 125 return out.str(); 126 } 127}}; 128
|
110// Basic instruction class constructor template. 111def template MacroConstructor {{ 112 inline X86Macroop::%(class_name)s::%(class_name)s(
| 129// Basic instruction class constructor template. 130def template MacroConstructor {{ 131 inline X86Macroop::%(class_name)s::%(class_name)s(
|
113 ExtMachInst machInst, EmulEnv env) 114 : %(base_class)s("%(mnemonic)s", machInst, %(num_microops)s, env)
| 132 ExtMachInst machInst, EmulEnv _env) 133 : %(base_class)s("%(mnemonic)s", machInst, %(num_microops)s, _env)
|
115 { 116 %(adjust_env)s; 117 %(adjust_imm)s; 118 %(adjust_disp)s; 119 %(do_modrm)s; 120 %(constructor)s;
| 134 { 135 %(adjust_env)s; 136 %(adjust_imm)s; 137 %(adjust_disp)s; 138 %(do_modrm)s; 139 %(constructor)s;
|
| 140 const char *macrocodeBlock = "%(class_name)s";
|
121 //alloc_microops is the code that sets up the microops 122 //array in the parent class. 123 %(alloc_microops)s; 124 } 125}}; 126 127let {{ 128 from micro_asm import Combinational_Macroop, Rom_Macroop 129 class X86Macroop(Combinational_Macroop): 130 def add_microop(self, mnemonic, microop): 131 microop.mnemonic = mnemonic 132 microop.micropc = len(self.microops) 133 self.microops.append(microop) 134 def setAdjustEnv(self, val): 135 self.adjust_env = val 136 def adjustImm(self, val): 137 self.adjust_imm += val 138 def adjustDisp(self, val): 139 self.adjust_disp += val 140 def __init__(self, name): 141 super(X86Macroop, self).__init__(name) 142 self.directives = { 143 "adjust_env" : self.setAdjustEnv, 144 "adjust_imm" : self.adjustImm, 145 "adjust_disp" : self.adjustDisp 146 } 147 self.declared = False 148 self.adjust_env = "" 149 self.doModRM = "" 150 self.adjust_imm = ''' 151 uint64_t adjustedImm = IMMEDIATE; 152 //This is to pacify gcc in case the immediate isn't used. 153 adjustedImm = adjustedImm; 154 ''' 155 self.adjust_disp = ''' 156 uint64_t adjustedDisp = DISPLACEMENT; 157 //This is to pacify gcc in case the displacement isn't used. 158 adjustedDisp = adjustedDisp; 159 ''' 160 def getAllocator(self, env):
| 141 //alloc_microops is the code that sets up the microops 142 //array in the parent class. 143 %(alloc_microops)s; 144 } 145}}; 146 147let {{ 148 from micro_asm import Combinational_Macroop, Rom_Macroop 149 class X86Macroop(Combinational_Macroop): 150 def add_microop(self, mnemonic, microop): 151 microop.mnemonic = mnemonic 152 microop.micropc = len(self.microops) 153 self.microops.append(microop) 154 def setAdjustEnv(self, val): 155 self.adjust_env = val 156 def adjustImm(self, val): 157 self.adjust_imm += val 158 def adjustDisp(self, val): 159 self.adjust_disp += val 160 def __init__(self, name): 161 super(X86Macroop, self).__init__(name) 162 self.directives = { 163 "adjust_env" : self.setAdjustEnv, 164 "adjust_imm" : self.adjustImm, 165 "adjust_disp" : self.adjustDisp 166 } 167 self.declared = False 168 self.adjust_env = "" 169 self.doModRM = "" 170 self.adjust_imm = ''' 171 uint64_t adjustedImm = IMMEDIATE; 172 //This is to pacify gcc in case the immediate isn't used. 173 adjustedImm = adjustedImm; 174 ''' 175 self.adjust_disp = ''' 176 uint64_t adjustedDisp = DISPLACEMENT; 177 //This is to pacify gcc in case the displacement isn't used. 178 adjustedDisp = adjustedDisp; 179 ''' 180 def getAllocator(self, env):
|
161 return "new X86Macroop::%s(machInst, %s)" % (self.name, env.getAllocator())
| 181 return "new X86Macroop::%s(machInst, %s)" % \ 182 (self.name, env.getAllocator()) 183 def getMnemonic(self): 184 mnemonic = self.name.lower() 185 mnemonic = re.match(r'[^_]*', mnemonic).group(0) 186 return mnemonic
|
162 def getDeclaration(self): 163 #FIXME This first parameter should be the mnemonic. I need to 164 #write some code which pulls that out 165 declareLabels = "" 166 for (label, microop) in self.labels.items(): 167 declareLabels += "const static uint64_t label_%s = %d;\n" \ 168 % (label, microop.micropc)
| 187 def getDeclaration(self): 188 #FIXME This first parameter should be the mnemonic. I need to 189 #write some code which pulls that out 190 declareLabels = "" 191 for (label, microop) in self.labels.items(): 192 declareLabels += "const static uint64_t label_%s = %d;\n" \ 193 % (label, microop.micropc)
|
169 iop = InstObjParams(self.name, self.name, "Macroop",
| 194 iop = InstObjParams(self.getMnemonic(), self.name, "Macroop",
|
170 {"code" : "", 171 "declareLabels" : declareLabels 172 }) 173 return MacroDeclare.subst(iop);
| 195 {"code" : "", 196 "declareLabels" : declareLabels 197 }) 198 return MacroDeclare.subst(iop);
|
174 def getDefinition(self):
| 199 def getDefinition(self, env):
|
175 #FIXME This first parameter should be the mnemonic. I need to 176 #write some code which pulls that out 177 numMicroops = len(self.microops) 178 allocMicroops = '' 179 micropc = 0 180 for op in self.microops: 181 isLast = (micropc == numMicroops - 1) 182 allocMicroops += \ 183 "microops[%d] = %s;\n" % \ 184 (micropc, op.getAllocator(True, not isLast, 185 micropc == 0, isLast)) 186 micropc += 1
| 200 #FIXME This first parameter should be the mnemonic. I need to 201 #write some code which pulls that out 202 numMicroops = len(self.microops) 203 allocMicroops = '' 204 micropc = 0 205 for op in self.microops: 206 isLast = (micropc == numMicroops - 1) 207 allocMicroops += \ 208 "microops[%d] = %s;\n" % \ 209 (micropc, op.getAllocator(True, not isLast, 210 micropc == 0, isLast)) 211 micropc += 1
|
187 iop = InstObjParams(self.name, self.name, "Macroop",
| 212 if env.useStackSize: 213 useStackSize = "true" 214 else: 215 useStackSize = "false" 216 if env.memoryInst: 217 memoryInst = "true" 218 else: 219 memoryInst = "false" 220 regSize = '''(%s || (env.base == INTREG_RSP && %s) ? 221 env.stackSize : 222 env.dataSize)''' % (useStackSize, memoryInst) 223 iop = InstObjParams(self.getMnemonic(), self.name, "Macroop",
|
188 {"code" : "", "num_microops" : numMicroops, 189 "alloc_microops" : allocMicroops, 190 "adjust_env" : self.adjust_env, 191 "adjust_imm" : self.adjust_imm, 192 "adjust_disp" : self.adjust_disp,
| 224 {"code" : "", "num_microops" : numMicroops, 225 "alloc_microops" : allocMicroops, 226 "adjust_env" : self.adjust_env, 227 "adjust_imm" : self.adjust_imm, 228 "adjust_disp" : self.adjust_disp,
|
| 229 "disassembly" : env.disassembly, 230 "regSize" : regSize,
|
193 "do_modrm" : self.doModRM})
| 231 "do_modrm" : self.doModRM})
|
194 return MacroConstructor.subst(iop);
| 232 return MacroConstructor.subst(iop) + \ 233 MacroDisassembly.subst(iop);
|
195}}; 196 197let {{ 198 class EmulEnv(object): 199 def __init__(self): 200 self.reg = "0" 201 self.regUsed = False 202 self.regm = "0" 203 self.regmUsed = False 204 self.seg = "SEGMENT_REG_DS" 205 self.size = None 206 self.addressSize = "ADDRSIZE" 207 self.dataSize = "OPSIZE" 208 self.stackSize = "STACKSIZE" 209 self.doModRM = False
| 234}}; 235 236let {{ 237 class EmulEnv(object): 238 def __init__(self): 239 self.reg = "0" 240 self.regUsed = False 241 self.regm = "0" 242 self.regmUsed = False 243 self.seg = "SEGMENT_REG_DS" 244 self.size = None 245 self.addressSize = "ADDRSIZE" 246 self.dataSize = "OPSIZE" 247 self.stackSize = "STACKSIZE" 248 self.doModRM = False
|
| 249 self.disassembly = "" 250 self.firstArgument = True 251 self.useStackSize = False 252 self.memoryInst = False
|
210
| 253
|
| 254 def addToDisassembly(self, code): 255 if not self.firstArgument: 256 self.disassembly += "out << \", \";\n" 257 self.firstArgument = False 258 self.disassembly += code 259
|
211 def getAllocator(self): 212 if self.size == 'b': 213 self.dataSize = 1 214 elif self.size == 'd': 215 self.dataSize = 4 216 #This is for "double plus" which is normally a double word unless 217 #the REX W bit is set, in which case it's a quad word. It's used 218 #for some SSE instructions. 219 elif self.size == 'dp': 220 self.dataSize = "(REX_W ? 8 : 4)" 221 elif self.size == 'q': 222 self.dataSize = 8 223 elif self.size == 'v': 224 self.dataSize = "OPSIZE" 225 elif self.size == 'w': 226 self.dataSize = 2 227 elif self.size == 'z': 228 self.dataSize = "((OPSIZE == 8) ? 4 : OPSIZE)" 229 elif self.size: 230 raise Exception, "Unrecognized size type %s!" % self.size 231 return '''EmulEnv(%(reg)s, 232 %(regm)s, 233 %(dataSize)s, 234 %(addressSize)s, 235 %(stackSize)s)''' % \ 236 self.__dict__ 237 238 def addReg(self, reg): 239 if not self.regUsed: 240 self.reg = reg 241 self.regUsed = True 242 elif not self.regmUsed: 243 self.regm = reg 244 self.regmUsed = True 245 else: 246 raise Exception, "EmulEnv is out of register specialization spots." 247 def setSize(self, size): 248 if not self.size: 249 self.size = size 250 else: 251 if self.size != size: 252 raise Exception, "Conflicting register sizes %s and %s!" %\ 253 (self.size, size) 254}}; 255 256let {{ 257 doModRMString = "env.doModRM(machInst);\n" 258 def genMacroop(Name, env): 259 blocks = OutputBlocks() 260 if not macroopDict.has_key(Name): 261 raise Exception, "Unrecognized instruction: %s" % Name 262 macroop = macroopDict[Name] 263 if not macroop.declared: 264 if env.doModRM: 265 macroop.doModRM = doModRMString 266 blocks.header_output = macroop.getDeclaration()
| 260 def getAllocator(self): 261 if self.size == 'b': 262 self.dataSize = 1 263 elif self.size == 'd': 264 self.dataSize = 4 265 #This is for "double plus" which is normally a double word unless 266 #the REX W bit is set, in which case it's a quad word. It's used 267 #for some SSE instructions. 268 elif self.size == 'dp': 269 self.dataSize = "(REX_W ? 8 : 4)" 270 elif self.size == 'q': 271 self.dataSize = 8 272 elif self.size == 'v': 273 self.dataSize = "OPSIZE" 274 elif self.size == 'w': 275 self.dataSize = 2 276 elif self.size == 'z': 277 self.dataSize = "((OPSIZE == 8) ? 4 : OPSIZE)" 278 elif self.size: 279 raise Exception, "Unrecognized size type %s!" % self.size 280 return '''EmulEnv(%(reg)s, 281 %(regm)s, 282 %(dataSize)s, 283 %(addressSize)s, 284 %(stackSize)s)''' % \ 285 self.__dict__ 286 287 def addReg(self, reg): 288 if not self.regUsed: 289 self.reg = reg 290 self.regUsed = True 291 elif not self.regmUsed: 292 self.regm = reg 293 self.regmUsed = True 294 else: 295 raise Exception, "EmulEnv is out of register specialization spots." 296 def setSize(self, size): 297 if not self.size: 298 self.size = size 299 else: 300 if self.size != size: 301 raise Exception, "Conflicting register sizes %s and %s!" %\ 302 (self.size, size) 303}}; 304 305let {{ 306 doModRMString = "env.doModRM(machInst);\n" 307 def genMacroop(Name, env): 308 blocks = OutputBlocks() 309 if not macroopDict.has_key(Name): 310 raise Exception, "Unrecognized instruction: %s" % Name 311 macroop = macroopDict[Name] 312 if not macroop.declared: 313 if env.doModRM: 314 macroop.doModRM = doModRMString 315 blocks.header_output = macroop.getDeclaration()
|
267 blocks.decoder_output = macroop.getDefinition()
| 316 blocks.decoder_output = macroop.getDefinition(env)
|
268 macroop.declared = True 269 blocks.decode_block = "return %s;\n" % macroop.getAllocator(env) 270 return blocks 271}};
| 317 macroop.declared = True 318 blocks.decode_block = "return %s;\n" % macroop.getAllocator(env) 319 return blocks 320}};
|