regop.isa revision 4592
1// Copyright (c) 2007 The Hewlett-Packard Development Company 2// All rights reserved. 3// 4// Redistribution and use of this software in source and binary forms, 5// with or without modification, are permitted provided that the 6// following conditions are met: 7// 8// The software must be used only for Non-Commercial Use which means any 9// use which is NOT directed to receiving any direct monetary 10// compensation for, or commercial advantage from such use. Illustrative 11// examples of non-commercial use are academic research, personal study, 12// teaching, education and corporate research & development. 13// Illustrative examples of commercial use are distributing products for 14// commercial advantage and providing services using the software for 15// commercial advantage. 16// 17// If you wish to use this software or functionality therein that may be 18// covered by patents for commercial use, please contact: 19// Director of Intellectual Property Licensing 20// Office of Strategy and Technology 21// Hewlett-Packard Company 22// 1501 Page Mill Road 23// Palo Alto, California 94304 24// 25// Redistributions of source code must retain the above copyright notice, 26// this list of conditions and the following disclaimer. Redistributions 27// in binary form must reproduce the above copyright notice, this list of 28// conditions and the following disclaimer in the documentation and/or 29// other materials provided with the distribution. Neither the name of 30// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its 31// contributors may be used to endorse or promote products derived from 32// this software without specific prior written permission. No right of 33// sublicense is granted herewith. Derivatives of the software and 34// output created using the software may be prepared, but only for 35// Non-Commercial Uses. Derivatives of the software may be shared with 36// others provided: (i) the others agree to abide by the list of 37// conditions herein which includes the Non-Commercial Use restrictions; 38// and (ii) such Derivatives of the software include the above copyright 39// notice to acknowledge the contribution from this software where 40// applicable, this list of conditions and the disclaimer below. 41// 42// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 43// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 44// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 45// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 46// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 47// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 48// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 49// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 50// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 51// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 52// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 53// 54// Authors: Gabe Black 55 56////////////////////////////////////////////////////////////////////////// 57// 58// RegOp Microop templates 59// 60////////////////////////////////////////////////////////////////////////// 61 62output header {{ 63 /** 64 * Base classes for RegOps which provides a generateDisassembly method. 65 */ 66 class RegOp : public X86MicroopBase 67 { 68 protected: 69 const RegIndex src1; 70 const RegIndex src2; 71 const RegIndex dest; 72 const bool setStatus; 73 const uint8_t dataSize; 74 const uint8_t ext; 75 76 // Constructor 77 RegOp(ExtMachInst _machInst, 78 const char *mnem, const char *_instMnem, 79 bool isMicro, bool isDelayed, 80 bool isFirst, bool isLast, 81 RegIndex _src1, RegIndex _src2, RegIndex _dest, 82 bool _setStatus, uint8_t _dataSize, uint8_t _ext, 83 OpClass __opClass) : 84 X86MicroopBase(_machInst, mnem, _instMnem, 85 isMicro, isDelayed, isFirst, isLast, 86 __opClass), 87 src1(_src1), src2(_src2), dest(_dest), 88 setStatus(_setStatus), dataSize(_dataSize), ext(_ext) 89 { 90 } 91 92 std::string generateDisassembly(Addr pc, 93 const SymbolTable *symtab) const; 94 }; 95 96 class RegOpImm : public X86MicroopBase 97 { 98 protected: 99 const RegIndex src1; 100 const uint8_t imm8; 101 const RegIndex dest; 102 const bool setStatus; 103 const uint8_t dataSize; 104 const uint8_t ext; 105 106 // Constructor 107 RegOpImm(ExtMachInst _machInst, 108 const char * mnem, const char *_instMnem, 109 bool isMicro, bool isDelayed, 110 bool isFirst, bool isLast, 111 RegIndex _src1, uint8_t _imm8, RegIndex _dest, 112 bool _setStatus, uint8_t _dataSize, uint8_t _ext, 113 OpClass __opClass) : 114 X86MicroopBase(_machInst, mnem, _instMnem, 115 isMicro, isDelayed, isFirst, isLast, 116 __opClass), 117 src1(_src1), imm8(_imm8), dest(_dest), 118 setStatus(_setStatus), dataSize(_dataSize), ext(_ext) 119 { 120 } 121 122 std::string generateDisassembly(Addr pc, 123 const SymbolTable *symtab) const; 124 }; 125}}; 126 127output decoder {{ 128 std::string RegOp::generateDisassembly(Addr pc, 129 const SymbolTable *symtab) const 130 { 131 std::stringstream response; 132 133 printMnemonic(response, instMnem, mnemonic); 134 printReg(response, dest); 135 response << ", "; 136 printReg(response, src1); 137 response << ", "; 138 printReg(response, src2); 139 return response.str(); 140 } 141 142 std::string RegOpImm::generateDisassembly(Addr pc, 143 const SymbolTable *symtab) const 144 { 145 std::stringstream response; 146 147 printMnemonic(response, instMnem, mnemonic); 148 printReg(response, dest); 149 response << ", "; 150 printReg(response, src1); 151 ccprintf(response, ", %#x", imm8); 152 return response.str(); 153 } 154}}; 155 156def template MicroRegOpExecute {{ 157 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 158 Trace::InstRecord *traceData) const 159 { 160 Fault fault = NoFault; 161 162 %(op_decl)s; 163 %(op_rd)s; 164 %(code)s; 165 166 //Write the resulting state to the execution context 167 if(fault == NoFault) 168 { 169 %(op_wb)s; 170 } 171 return fault; 172 } 173}}; 174 175def template MicroRegOpImmExecute {{ 176 Fault %(class_name)sImm::execute(%(CPU_exec_context)s *xc, 177 Trace::InstRecord *traceData) const 178 { 179 Fault fault = NoFault; 180 181 %(op_decl)s; 182 %(op_rd)s; 183 %(code)s; 184 185 //Write the resulting state to the execution context 186 if(fault == NoFault) 187 { 188 %(op_wb)s; 189 } 190 return fault; 191 } 192}}; 193 194def template MicroRegOpDeclare {{ 195 class %(class_name)s : public %(base_class)s 196 { 197 protected: 198 void buildMe(); 199 200 public: 201 %(class_name)s(ExtMachInst _machInst, 202 const char * instMnem, 203 bool isMicro, bool isDelayed, bool isFirst, bool isLast, 204 RegIndex _src1, RegIndex _src2, RegIndex _dest, 205 bool _setStatus, uint8_t _dataSize, uint8_t _ext); 206 207 %(class_name)s(ExtMachInst _machInst, 208 const char * instMnem, 209 RegIndex _src1, RegIndex _src2, RegIndex _dest, 210 bool _setStatus, uint8_t _dataSize, uint8_t _ext); 211 212 %(BasicExecDeclare)s 213 }; 214}}; 215 216def template MicroRegOpImmDeclare {{ 217 218 class %(class_name)sImm : public %(base_class)s 219 { 220 protected: 221 void buildMe(); 222 223 public: 224 %(class_name)sImm(ExtMachInst _machInst, 225 const char * instMnem, 226 bool isMicro, bool isDelayed, bool isFirst, bool isLast, 227 RegIndex _src1, uint8_t _imm8, RegIndex _dest, 228 bool _setStatus, uint8_t _dataSize, uint8_t _ext); 229 230 %(class_name)sImm(ExtMachInst _machInst, 231 const char * instMnem, 232 RegIndex _src1, uint8_t _imm8, RegIndex _dest, 233 bool _setStatus, uint8_t _dataSize, uint8_t _ext); 234 235 %(BasicExecDeclare)s 236 }; 237}}; 238 239def template MicroRegOpConstructor {{ 240 241 inline void %(class_name)s::buildMe() 242 { 243 %(constructor)s; 244 } 245 246 inline %(class_name)s::%(class_name)s( 247 ExtMachInst machInst, const char * instMnem, 248 RegIndex _src1, RegIndex _src2, RegIndex _dest, 249 bool _setStatus, uint8_t _dataSize, uint8_t _ext) : 250 %(base_class)s(machInst, "%(mnemonic)s", instMnem, 251 false, false, false, false, 252 _src1, _src2, _dest, _setStatus, _dataSize, _ext, 253 %(op_class)s) 254 { 255 buildMe(); 256 } 257 258 inline %(class_name)s::%(class_name)s( 259 ExtMachInst machInst, const char * instMnem, 260 bool isMicro, bool isDelayed, bool isFirst, bool isLast, 261 RegIndex _src1, RegIndex _src2, RegIndex _dest, 262 bool _setStatus, uint8_t _dataSize, uint8_t _ext) : 263 %(base_class)s(machInst, "%(mnemonic)s", instMnem, 264 isMicro, isDelayed, isFirst, isLast, 265 _src1, _src2, _dest, _setStatus, _dataSize, _ext, 266 %(op_class)s) 267 { 268 buildMe(); 269 } 270}}; 271 272def template MicroRegOpImmConstructor {{ 273 274 inline void %(class_name)sImm::buildMe() 275 { 276 %(constructor)s; 277 } 278 279 inline %(class_name)sImm::%(class_name)sImm( 280 ExtMachInst machInst, const char * instMnem, 281 RegIndex _src1, uint8_t _imm8, RegIndex _dest, 282 bool _setStatus, uint8_t _dataSize, uint8_t _ext) : 283 %(base_class)s(machInst, "%(mnemonic)s", instMnem, 284 false, false, false, false, 285 _src1, _imm8, _dest, _setStatus, _dataSize, _ext, 286 %(op_class)s) 287 { 288 buildMe(); 289 } 290 291 inline %(class_name)sImm::%(class_name)sImm( 292 ExtMachInst machInst, const char * instMnem, 293 bool isMicro, bool isDelayed, bool isFirst, bool isLast, 294 RegIndex _src1, uint8_t _imm8, RegIndex _dest, 295 bool _setStatus, uint8_t _dataSize, uint8_t _ext) : 296 %(base_class)s(machInst, "%(mnemonic)s", instMnem, 297 isMicro, isDelayed, isFirst, isLast, 298 _src1, _imm8, _dest, _setStatus, _dataSize, _ext, 299 %(op_class)s) 300 { 301 buildMe(); 302 } 303}}; 304 305let {{ 306 class RegOp(X86Microop): 307 def __init__(self, dest, src1, src2): 308 self.dest = dest 309 self.src1 = src1 310 self.src2 = src2 311 self.setStatus = False 312 self.dataSize = "env.dataSize" 313 self.ext = 0 314 315 def getAllocator(self, *microFlags): 316 allocator = '''new %(class_name)s(machInst, mnemonic 317 %(flags)s, %(src1)s, %(src2)s, %(dest)s, 318 %(setStatus)s, %(dataSize)s, %(ext)s)''' % { 319 "class_name" : self.className, 320 "flags" : self.microFlagsText(microFlags), 321 "src1" : self.src1, "src2" : self.src2, 322 "dest" : self.dest, 323 "setStatus" : self.cppBool(self.setStatus), 324 "dataSize" : self.dataSize, 325 "ext" : self.ext} 326 return allocator 327 328 class RegOpImm(X86Microop): 329 def __init__(self, dest, src1, imm8): 330 self.dest = dest 331 self.src1 = src1 332 self.imm8 = imm8 333 self.setStatus = False 334 self.dataSize = "env.dataSize" 335 self.ext = 0 336 337 def getAllocator(self, *microFlags): 338 allocator = '''new %(class_name)s(machInst, mnemonic 339 %(flags)s, %(src1)s, %(imm8)s, %(dest)s, 340 %(setStatus)s, %(dataSize)s, %(ext)s)''' % { 341 "class_name" : self.className, 342 "flags" : self.microFlagsText(microFlags), 343 "src1" : self.src1, "imm8" : self.imm8, 344 "dest" : self.dest, 345 "setStatus" : self.cppBool(self.setStatus), 346 "dataSize" : self.dataSize, 347 "ext" : self.ext} 348 return allocator 349}}; 350 351let {{ 352 353 # Make these empty strings so that concatenating onto 354 # them will always work. 355 header_output = "" 356 decoder_output = "" 357 exec_output = "" 358 359 def defineMicroRegOp(mnemonic, code): 360 global header_output 361 global decoder_output 362 global exec_output 363 global microopClasses 364 Name = mnemonic 365 name = mnemonic.lower() 366 367 # Find op2 in each of the instruction definitions. Create two versions 368 # of the code, one with an integer operand, and one with an immediate 369 # operand. 370 matcher = re.compile("op2(?P<typeQual>\\.\\w+)?") 371 regCode = matcher.sub("SrcReg2", code) 372 immCode = matcher.sub("imm8", code) 373 374 # Build up the all register version of this micro op 375 iop = InstObjParams(name, Name, 'RegOp', {"code" : regCode}) 376 header_output += MicroRegOpDeclare.subst(iop) 377 decoder_output += MicroRegOpConstructor.subst(iop) 378 exec_output += MicroRegOpExecute.subst(iop) 379 380 class RegOpChild(RegOp): 381 def __init__(self, dest, src1, src2): 382 super(RegOpChild, self).__init__(dest, src1, src2) 383 self.className = Name 384 self.mnemonic = name 385 386 microopClasses[name] = RegOpChild 387 388 # Build up the immediate version of this micro op 389 iop = InstObjParams(name + "i", Name, 390 'RegOpImm', {"code" : immCode}) 391 header_output += MicroRegOpImmDeclare.subst(iop) 392 decoder_output += MicroRegOpImmConstructor.subst(iop) 393 exec_output += MicroRegOpImmExecute.subst(iop) 394 395 class RegOpImmChild(RegOpImm): 396 def __init__(self, dest, src1, imm): 397 super(RegOpImmChild, self).__init__(dest, src1, imm) 398 self.className = Name + "Imm" 399 self.mnemonic = name + "i" 400 401 microopClasses[name + "i"] = RegOpImmChild 402 403 defineMicroRegOp('Add', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)') #Needs to set OF,CF,SF 404 defineMicroRegOp('Or', 'DestReg = merge(DestReg, SrcReg1 | op2, dataSize)') 405 defineMicroRegOp('Adc', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)') #Needs to add in CF, set OF,CF,SF 406 defineMicroRegOp('Sbb', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)') #Needs to subtract CF, set OF,CF,SF 407 defineMicroRegOp('And', 'DestReg = merge(DestReg, SrcReg1 & op2, dataSize)') 408 defineMicroRegOp('Sub', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)') #Needs to set OF,CF,SF 409 defineMicroRegOp('Xor', 'DestReg = merge(DestReg, SrcReg1 ^ op2, dataSize)') 410 defineMicroRegOp('Cmp', 'DestReg = merge(DestReg, DestReg - op2, dataSize)') #Needs to set OF,CF,SF and not DestReg 411 defineMicroRegOp('Mov', 'DestReg = merge(SrcReg1, op2, dataSize)') 412 413 # This has it's own function because Wr ops have implicit destinations 414 def defineMicroRegOpWr(mnemonic, code): 415 global header_output 416 global decoder_output 417 global exec_output 418 global microopClasses 419 Name = mnemonic 420 name = mnemonic.lower() 421 422 # Find op2 in each of the instruction definitions. Create two versions 423 # of the code, one with an integer operand, and one with an immediate 424 # operand. 425 matcher = re.compile("op2(?P<typeQual>\\.\\w+)?") 426 regCode = matcher.sub("SrcReg2", code) 427 immCode = matcher.sub("imm8", code) 428 429 # Build up the all register version of this micro op 430 iop = InstObjParams(name, Name, 'RegOp', {"code" : regCode}) 431 header_output += MicroRegOpDeclare.subst(iop) 432 decoder_output += MicroRegOpConstructor.subst(iop) 433 exec_output += MicroRegOpExecute.subst(iop) 434 435 class RegOpChild(RegOp): 436 def __init__(self, src1, src2): 437 super(RegOpChild, self).__init__("NUM_INTREGS", src1, src2) 438 self.className = Name 439 self.mnemonic = name 440 441 microopClasses[name] = RegOpChild 442 443 # Build up the immediate version of this micro op 444 iop = InstObjParams(name + "i", Name, 445 'RegOpImm', {"code" : immCode}) 446 header_output += MicroRegOpImmDeclare.subst(iop) 447 decoder_output += MicroRegOpImmConstructor.subst(iop) 448 exec_output += MicroRegOpImmExecute.subst(iop) 449 450 class RegOpImmChild(RegOpImm): 451 def __init__(self, src1, imm): 452 super(RegOpImmChild, self).__init__("NUM_INTREGS", src1, imm) 453 self.className = Name + "Imm" 454 self.mnemonic = name + "i" 455 456 microopClasses[name + "i"] = RegOpImmChild 457 458 defineMicroRegOpWr('Wrip', 'RIP = SrcReg1 + op2') 459 460 # This has it's own function because Rd ops don't always have two parameters 461 def defineMicroRegOpRd(mnemonic, code): 462 global header_output 463 global decoder_output 464 global exec_output 465 global microopClasses 466 Name = mnemonic 467 name = mnemonic.lower() 468 469 iop = InstObjParams(name, Name, 'RegOp', {"code" : code}) 470 header_output += MicroRegOpDeclare.subst(iop) 471 decoder_output += MicroRegOpConstructor.subst(iop) 472 exec_output += MicroRegOpExecute.subst(iop) 473 474 class RegOpChild(RegOp): 475 def __init__(self, dest, src1 = "NUM_INTREGS"): 476 super(RegOpChild, self).__init__(dest, src1, "NUM_INTREGS") 477 self.className = Name 478 self.mnemonic = name 479 480 microopClasses[name] = RegOpChild 481 482 defineMicroRegOpRd('Rdip', 'DestReg = RIP') 483}}; 484