regop.isa revision 4612:a29c0616839d
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 %(flag_code)s; 166 167 //Write the resulting state to the execution context 168 if(fault == NoFault) 169 { 170 %(op_wb)s; 171 } 172 return fault; 173 } 174}}; 175 176def template MicroRegOpImmExecute {{ 177 Fault %(class_name)sImm::execute(%(CPU_exec_context)s *xc, 178 Trace::InstRecord *traceData) const 179 { 180 Fault fault = NoFault; 181 182 %(op_decl)s; 183 %(op_rd)s; 184 %(code)s; 185 %(flag_code)s; 186 187 //Write the resulting state to the execution context 188 if(fault == NoFault) 189 { 190 %(op_wb)s; 191 } 192 return fault; 193 } 194}}; 195 196def template MicroRegOpDeclare {{ 197 class %(class_name)s : public %(base_class)s 198 { 199 protected: 200 void buildMe(); 201 202 public: 203 %(class_name)s(ExtMachInst _machInst, 204 const char * instMnem, 205 bool isMicro, bool isDelayed, bool isFirst, bool isLast, 206 RegIndex _src1, RegIndex _src2, RegIndex _dest, 207 bool _setStatus, uint8_t _dataSize, uint8_t _ext); 208 209 %(class_name)s(ExtMachInst _machInst, 210 const char * instMnem, 211 RegIndex _src1, RegIndex _src2, RegIndex _dest, 212 bool _setStatus, uint8_t _dataSize, uint8_t _ext); 213 214 %(BasicExecDeclare)s 215 }; 216}}; 217 218def template MicroRegOpImmDeclare {{ 219 220 class %(class_name)sImm : public %(base_class)s 221 { 222 protected: 223 void buildMe(); 224 225 public: 226 %(class_name)sImm(ExtMachInst _machInst, 227 const char * instMnem, 228 bool isMicro, bool isDelayed, bool isFirst, bool isLast, 229 RegIndex _src1, uint8_t _imm8, RegIndex _dest, 230 bool _setStatus, uint8_t _dataSize, uint8_t _ext); 231 232 %(class_name)sImm(ExtMachInst _machInst, 233 const char * instMnem, 234 RegIndex _src1, uint8_t _imm8, RegIndex _dest, 235 bool _setStatus, uint8_t _dataSize, uint8_t _ext); 236 237 %(BasicExecDeclare)s 238 }; 239}}; 240 241def template MicroRegOpConstructor {{ 242 243 inline void %(class_name)s::buildMe() 244 { 245 %(constructor)s; 246 } 247 248 inline %(class_name)s::%(class_name)s( 249 ExtMachInst machInst, const char * instMnem, 250 RegIndex _src1, RegIndex _src2, RegIndex _dest, 251 bool _setStatus, uint8_t _dataSize, uint8_t _ext) : 252 %(base_class)s(machInst, "%(mnemonic)s", instMnem, 253 false, false, false, false, 254 _src1, _src2, _dest, _setStatus, _dataSize, _ext, 255 %(op_class)s) 256 { 257 buildMe(); 258 } 259 260 inline %(class_name)s::%(class_name)s( 261 ExtMachInst machInst, const char * instMnem, 262 bool isMicro, bool isDelayed, bool isFirst, bool isLast, 263 RegIndex _src1, RegIndex _src2, RegIndex _dest, 264 bool _setStatus, uint8_t _dataSize, uint8_t _ext) : 265 %(base_class)s(machInst, "%(mnemonic)s", instMnem, 266 isMicro, isDelayed, isFirst, isLast, 267 _src1, _src2, _dest, _setStatus, _dataSize, _ext, 268 %(op_class)s) 269 { 270 buildMe(); 271 } 272}}; 273 274def template MicroRegOpImmConstructor {{ 275 276 inline void %(class_name)sImm::buildMe() 277 { 278 %(constructor)s; 279 } 280 281 inline %(class_name)sImm::%(class_name)sImm( 282 ExtMachInst machInst, const char * instMnem, 283 RegIndex _src1, uint8_t _imm8, RegIndex _dest, 284 bool _setStatus, uint8_t _dataSize, uint8_t _ext) : 285 %(base_class)s(machInst, "%(mnemonic)s", instMnem, 286 false, false, false, false, 287 _src1, _imm8, _dest, _setStatus, _dataSize, _ext, 288 %(op_class)s) 289 { 290 buildMe(); 291 } 292 293 inline %(class_name)sImm::%(class_name)sImm( 294 ExtMachInst machInst, const char * instMnem, 295 bool isMicro, bool isDelayed, bool isFirst, bool isLast, 296 RegIndex _src1, uint8_t _imm8, RegIndex _dest, 297 bool _setStatus, uint8_t _dataSize, uint8_t _ext) : 298 %(base_class)s(machInst, "%(mnemonic)s", instMnem, 299 isMicro, isDelayed, isFirst, isLast, 300 _src1, _imm8, _dest, _setStatus, _dataSize, _ext, 301 %(op_class)s) 302 { 303 buildMe(); 304 } 305}}; 306 307let {{ 308 class RegOp(X86Microop): 309 def __init__(self, dest, src1, src2, setStatus): 310 self.dest = dest 311 self.src1 = src1 312 self.src2 = src2 313 self.setStatus = setStatus 314 self.dataSize = "env.dataSize" 315 self.ext = 0 316 317 def getAllocator(self, *microFlags): 318 allocator = '''new %(class_name)s(machInst, mnemonic 319 %(flags)s, %(src1)s, %(src2)s, %(dest)s, 320 %(setStatus)s, %(dataSize)s, %(ext)s)''' % { 321 "class_name" : self.className, 322 "flags" : self.microFlagsText(microFlags), 323 "src1" : self.src1, "src2" : self.src2, 324 "dest" : self.dest, 325 "setStatus" : self.cppBool(self.setStatus), 326 "dataSize" : self.dataSize, 327 "ext" : self.ext} 328 return allocator 329 330 class RegOpImm(X86Microop): 331 def __init__(self, dest, src1, imm8, setStatus): 332 self.dest = dest 333 self.src1 = src1 334 self.imm8 = imm8 335 self.setStatus = setStatus 336 self.dataSize = "env.dataSize" 337 self.ext = 0 338 339 def getAllocator(self, *microFlags): 340 allocator = '''new %(class_name)s(machInst, mnemonic 341 %(flags)s, %(src1)s, %(imm8)s, %(dest)s, 342 %(setStatus)s, %(dataSize)s, %(ext)s)''' % { 343 "class_name" : self.className, 344 "flags" : self.microFlagsText(microFlags), 345 "src1" : self.src1, "imm8" : self.imm8, 346 "dest" : self.dest, 347 "setStatus" : self.cppBool(self.setStatus), 348 "dataSize" : self.dataSize, 349 "ext" : self.ext} 350 return allocator 351}}; 352 353let {{ 354 355 # Make these empty strings so that concatenating onto 356 # them will always work. 357 header_output = "" 358 decoder_output = "" 359 exec_output = "" 360 361 def setUpMicroRegOp(name, Name, base, code, child, flagCode): 362 global header_output 363 global decoder_output 364 global exec_output 365 global microopClasses 366 367 iop = InstObjParams(name, Name, base, 368 {"code" : code, 369 "flag_code" : flagCode}) 370 header_output += MicroRegOpDeclare.subst(iop) 371 decoder_output += MicroRegOpConstructor.subst(iop) 372 exec_output += MicroRegOpExecute.subst(iop) 373 374 microopClasses[name] = child 375 376 def defineMicroRegOp(mnemonic, code, flagCode): 377 Name = mnemonic 378 name = mnemonic.lower() 379 380 # Find op2 in each of the instruction definitions. Create two versions 381 # of the code, one with an integer operand, and one with an immediate 382 # operand. 383 matcher = re.compile("op2(?P<typeQual>\\.\\w+)?") 384 regCode = matcher.sub("SrcReg2", code) 385 immCode = matcher.sub("imm8", code) 386 387 # Build the all register version of this micro op 388 class RegOpChild(RegOp): 389 def __init__(self, dest, src1, src2, setStatus=False): 390 super(RegOpChild, self).__init__(dest, src1, src2, setStatus) 391 self.className = Name 392 self.mnemonic = name 393 394 setUpMicroRegOp(name, Name, "RegOp", regCode, RegOpChild, flagCode); 395 396 # Build the immediate version of this micro op 397 class RegOpChildImm(RegOpImm): 398 def __init__(self, dest, src1, src2, setStatus=False): 399 super(RegOpChildImm, self).__init__(dest, src1, src2, setStatus) 400 self.className = Name + "Imm" 401 self.mnemonic = name + "i" 402 403 setUpMicroRegOp(name + "i", Name + "Imm", "RegOpImm", immCode, RegOpChildImm, flagCode); 404 405 defineMicroRegOp('Add', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)', "") #Needs to set OF,CF,SF 406 defineMicroRegOp('Or', 'DestReg = merge(DestReg, SrcReg1 | op2, dataSize)', "") 407 defineMicroRegOp('Adc', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)', "") #Needs to add in CF, set OF,CF,SF 408 defineMicroRegOp('Sbb', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)', "") #Needs to subtract CF, set OF,CF,SF 409 defineMicroRegOp('And', 'DestReg = merge(DestReg, SrcReg1 & op2, dataSize)', "") 410 defineMicroRegOp('Sub', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)', "") #Needs to set OF,CF,SF 411 defineMicroRegOp('Xor', 'DestReg = merge(DestReg, SrcReg1 ^ op2, dataSize)', "") 412 defineMicroRegOp('Cmp', 'DestReg = merge(DestReg, DestReg - op2, dataSize)', "") #Needs to set OF,CF,SF and not DestReg 413 defineMicroRegOp('Mov', 'DestReg = merge(SrcReg1, op2, dataSize)', "") 414 415 # This has it's own function because Wr ops have implicit destinations 416 def defineMicroRegOpWr(mnemonic, code): 417 Name = mnemonic 418 name = mnemonic.lower() 419 420 # Find op2 in each of the instruction definitions. Create two versions 421 # of the code, one with an integer operand, and one with an immediate 422 # operand. 423 matcher = re.compile("op2(?P<typeQual>\\.\\w+)?") 424 regCode = matcher.sub("SrcReg2", code) 425 immCode = matcher.sub("imm8", code) 426 427 # Build the all register version of this micro op 428 class RegOpChild(RegOp): 429 def __init__(self, src1, src2): 430 super(RegOpChild, self).__init__("NUM_INTREGS", src1, src2, False) 431 self.className = Name 432 self.mnemonic = name 433 434 setUpMicroRegOp(name, Name, "RegOp", regCode, RegOpChild, ""); 435 436 # Build the immediate version of this micro op 437 class RegOpChildImm(RegOpImm): 438 def __init__(self, src1, src2): 439 super(RegOpChildImm, self).__init__("NUM_INTREGS", src1, src2, False) 440 self.className = Name + "Imm" 441 self.mnemonic = name + "i" 442 443 setUpMicroRegOp(name + "i", Name + "Imm", "RegOpImm", immCode, RegOpChildImm, ""); 444 445 defineMicroRegOpWr('Wrip', 'RIP = SrcReg1 + op2') 446 447 # This has it's own function because Rd ops don't always have two parameters 448 def defineMicroRegOpRd(mnemonic, code): 449 Name = mnemonic 450 name = mnemonic.lower() 451 452 class RegOpChild(RegOp): 453 def __init__(self, dest, src1 = "NUM_INTREGS"): 454 super(RegOpChild, self).__init__(dest, src1, "NUM_INTREGS", False) 455 self.className = Name 456 self.mnemonic = name 457 458 setUpMicroRegOp(name, Name, "RegOp", code, RegOpChild, ""); 459 460 defineMicroRegOpRd('Rdip', 'DestReg = RIP') 461 462 def defineMicroRegOpImm(mnemonic, code): 463 Name = mnemonic 464 name = mnemonic.lower() 465 466 class RegOpChild(RegOpImm): 467 def __init__(self, dest, src1, src2): 468 super(RegOpChild, self).__init__(dest, src1, src2, False) 469 self.className = Name 470 self.mnemonic = name 471 472 setUpMicroRegOp(name, Name, "RegOpImm", code, RegOpChild, ""); 473 474 defineMicroRegOpImm('Sext', ''' 475 IntReg val = SrcReg1; 476 int sign_bit = bits(val, imm8-1, imm8-1); 477 val = sign_bit ? (val | ~mask(imm8)) : val; 478 DestReg = merge(DestReg, val, dataSize);''') 479}}; 480