regop.isa revision 5011:6333ea094184
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 62def template MicroRegOpExecute {{ 63 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 64 Trace::InstRecord *traceData) const 65 { 66 Fault fault = NoFault; 67 68 DPRINTF(X86, "The data size is %d\n", dataSize); 69 %(op_decl)s; 70 %(op_rd)s; 71 72 if(%(cond_check)s) 73 { 74 %(code)s; 75 %(flag_code)s; 76 } 77 else 78 { 79 %(else_code)s; 80 } 81 82 //Write the resulting state to the execution context 83 if(fault == NoFault) 84 { 85 %(op_wb)s; 86 } 87 return fault; 88 } 89}}; 90 91def template MicroRegOpImmExecute {{ 92 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 93 Trace::InstRecord *traceData) const 94 { 95 Fault fault = NoFault; 96 97 %(op_decl)s; 98 %(op_rd)s; 99 100 if(%(cond_check)s) 101 { 102 %(code)s; 103 %(flag_code)s; 104 } 105 else 106 { 107 %(else_code)s; 108 } 109 110 //Write the resulting state to the execution context 111 if(fault == NoFault) 112 { 113 %(op_wb)s; 114 } 115 return fault; 116 } 117}}; 118 119def template MicroRegOpDeclare {{ 120 class %(class_name)s : public %(base_class)s 121 { 122 protected: 123 void buildMe(); 124 125 public: 126 %(class_name)s(ExtMachInst _machInst, 127 const char * instMnem, 128 bool isMicro, bool isDelayed, bool isFirst, bool isLast, 129 RegIndex _src1, RegIndex _src2, RegIndex _dest, 130 uint8_t _dataSize, uint16_t _ext); 131 132 %(class_name)s(ExtMachInst _machInst, 133 const char * instMnem, 134 RegIndex _src1, RegIndex _src2, RegIndex _dest, 135 uint8_t _dataSize, uint16_t _ext); 136 137 %(BasicExecDeclare)s 138 }; 139}}; 140 141def template MicroRegOpImmDeclare {{ 142 143 class %(class_name)s : public %(base_class)s 144 { 145 protected: 146 void buildMe(); 147 148 public: 149 %(class_name)s(ExtMachInst _machInst, 150 const char * instMnem, 151 bool isMicro, bool isDelayed, bool isFirst, bool isLast, 152 RegIndex _src1, uint16_t _imm8, RegIndex _dest, 153 uint8_t _dataSize, uint16_t _ext); 154 155 %(class_name)s(ExtMachInst _machInst, 156 const char * instMnem, 157 RegIndex _src1, uint16_t _imm8, RegIndex _dest, 158 uint8_t _dataSize, uint16_t _ext); 159 160 %(BasicExecDeclare)s 161 }; 162}}; 163 164def template MicroRegOpConstructor {{ 165 166 inline void %(class_name)s::buildMe() 167 { 168 %(constructor)s; 169 } 170 171 inline %(class_name)s::%(class_name)s( 172 ExtMachInst machInst, const char * instMnem, 173 RegIndex _src1, RegIndex _src2, RegIndex _dest, 174 uint8_t _dataSize, uint16_t _ext) : 175 %(base_class)s(machInst, "%(mnemonic)s", instMnem, 176 false, false, false, false, 177 _src1, _src2, _dest, _dataSize, _ext, 178 %(op_class)s) 179 { 180 buildMe(); 181 } 182 183 inline %(class_name)s::%(class_name)s( 184 ExtMachInst machInst, const char * instMnem, 185 bool isMicro, bool isDelayed, bool isFirst, bool isLast, 186 RegIndex _src1, RegIndex _src2, RegIndex _dest, 187 uint8_t _dataSize, uint16_t _ext) : 188 %(base_class)s(machInst, "%(mnemonic)s", instMnem, 189 isMicro, isDelayed, isFirst, isLast, 190 _src1, _src2, _dest, _dataSize, _ext, 191 %(op_class)s) 192 { 193 buildMe(); 194 } 195}}; 196 197def template MicroRegOpImmConstructor {{ 198 199 inline void %(class_name)s::buildMe() 200 { 201 %(constructor)s; 202 } 203 204 inline %(class_name)s::%(class_name)s( 205 ExtMachInst machInst, const char * instMnem, 206 RegIndex _src1, uint16_t _imm8, RegIndex _dest, 207 uint8_t _dataSize, uint16_t _ext) : 208 %(base_class)s(machInst, "%(mnemonic)s", instMnem, 209 false, false, false, false, 210 _src1, _imm8, _dest, _dataSize, _ext, 211 %(op_class)s) 212 { 213 buildMe(); 214 } 215 216 inline %(class_name)s::%(class_name)s( 217 ExtMachInst machInst, const char * instMnem, 218 bool isMicro, bool isDelayed, bool isFirst, bool isLast, 219 RegIndex _src1, uint16_t _imm8, RegIndex _dest, 220 uint8_t _dataSize, uint16_t _ext) : 221 %(base_class)s(machInst, "%(mnemonic)s", instMnem, 222 isMicro, isDelayed, isFirst, isLast, 223 _src1, _imm8, _dest, _dataSize, _ext, 224 %(op_class)s) 225 { 226 buildMe(); 227 } 228}}; 229 230let {{ 231 class X86MicroMeta(type): 232 def __new__(mcls, name, bases, dict): 233 abstract = False 234 if "abstract" in dict: 235 abstract = dict['abstract'] 236 del dict['abstract'] 237 238 cls = type.__new__(mcls, name, bases, dict) 239 if not abstract: 240 allClasses[name] = cls 241 return cls 242 243 class XXX86Microop(object): 244 __metaclass__ = X86MicroMeta 245 abstract = True 246 247 class RegOp(X86Microop): 248 abstract = True 249 def __init__(self, dest, src1, src2, flags, dataSize): 250 self.dest = dest 251 self.src1 = src1 252 self.src2 = src2 253 self.flags = flags 254 self.dataSize = dataSize 255 if flags is None: 256 self.ext = 0 257 else: 258 if not isinstance(flags, (list, tuple)): 259 raise Exception, "flags must be a list or tuple of flags" 260 self.ext = " | ".join(flags) 261 self.className += "Flags" 262 263 def getAllocator(self, *microFlags): 264 allocator = '''new %(class_name)s(machInst, mnemonic 265 %(flags)s, %(src1)s, %(src2)s, %(dest)s, 266 %(dataSize)s, %(ext)s)''' % { 267 "class_name" : self.className, 268 "flags" : self.microFlagsText(microFlags), 269 "src1" : self.src1, "src2" : self.src2, 270 "dest" : self.dest, 271 "dataSize" : self.dataSize, 272 "ext" : self.ext} 273 return allocator 274 275 class RegOpImm(X86Microop): 276 abstract = True 277 def __init__(self, dest, src1, imm8, flags, dataSize): 278 self.dest = dest 279 self.src1 = src1 280 self.imm8 = imm8 281 self.flags = flags 282 self.dataSize = dataSize 283 if flags is None: 284 self.ext = 0 285 else: 286 if not isinstance(flags, (list, tuple)): 287 raise Exception, "flags must be a list or tuple of flags" 288 self.ext = " | ".join(flags) 289 self.className += "Flags" 290 291 def getAllocator(self, *microFlags): 292 allocator = '''new %(class_name)s(machInst, mnemonic 293 %(flags)s, %(src1)s, %(imm8)s, %(dest)s, 294 %(dataSize)s, %(ext)s)''' % { 295 "class_name" : self.className, 296 "flags" : self.microFlagsText(microFlags), 297 "src1" : self.src1, "imm8" : self.imm8, 298 "dest" : self.dest, 299 "dataSize" : self.dataSize, 300 "ext" : self.ext} 301 return allocator 302}}; 303 304let {{ 305 306 # Make these empty strings so that concatenating onto 307 # them will always work. 308 header_output = "" 309 decoder_output = "" 310 exec_output = "" 311 312 # A function which builds the C++ classes that implement the microops 313 def setUpMicroRegOp(name, Name, base, code, flagCode = "", condCheck = "true", elseCode = ";", imm=False): 314 global header_output 315 global decoder_output 316 global exec_output 317 global microopClasses 318 319 iop = InstObjParams(name, Name, base, 320 {"code" : code, 321 "flag_code" : flagCode, 322 "cond_check" : condCheck, 323 "else_code" : elseCode}) 324 if imm: 325 header_output += MicroRegOpImmDeclare.subst(iop) 326 decoder_output += MicroRegOpImmConstructor.subst(iop) 327 exec_output += MicroRegOpImmExecute.subst(iop) 328 else: 329 header_output += MicroRegOpDeclare.subst(iop) 330 decoder_output += MicroRegOpConstructor.subst(iop) 331 exec_output += MicroRegOpExecute.subst(iop) 332 333 334 checkCCFlagBits = "checkCondition(ccFlagBits)" 335 genCCFlagBits = \ 336 "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, op2);" 337 genCCFlagBitsSub = \ 338 "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, ~op2, true);" 339 genCCFlagBitsLogic = ''' 340 //Don't have genFlags handle the OF or CF bits 341 uint64_t mask = CFBit | OFBit; 342 ccFlagBits = genFlags(ccFlagBits, ext & ~mask, DestReg, psrc1, op2); 343 //If a logic microop wants to set these, it wants to set them to 0. 344 ccFlagBits &= ~(CFBit & ext); 345 ccFlagBits &= ~(OFBit & ext); 346 ''' 347 348 regPick = ''' 349 IntReg psrc1 = pick(SrcReg1, 0, dataSize); 350 IntReg psrc2 = pick(SrcReg2, 1, dataSize); 351 ''' 352 immPick = ''' 353 IntReg psrc1 = pick(SrcReg1, 0, dataSize); 354 ''' 355 356 357 # This creates a python representations of a microop which are a cross 358 # product of reg/immediate and flag/no flag versions. 359 def defineMicroRegOp(mnemonic, code, flagCode=genCCFlagBits, \ 360 cc=False, elseCode=";"): 361 Name = mnemonic 362 name = mnemonic.lower() 363 364 # Find op2 in each of the instruction definitions. Create two versions 365 # of the code, one with an integer operand, and one with an immediate 366 # operand. 367 matcher = re.compile("op2(?P<typeQual>\\.\\w+)?") 368 regCode = regPick + matcher.sub("psrc2", code) 369 immCode = immPick + matcher.sub("imm8", code) 370 371 if not cc: 372 condCode = "true" 373 else: 374 flagCode = "" 375 condCode = checkCCFlagBits 376 377 regFlagCode = matcher.sub("psrc2", flagCode) 378 immFlagCode = matcher.sub("imm8", flagCode) 379 380 class RegOpChild(RegOp): 381 mnemonic = name 382 className = Name 383 def __init__(self, dest, src1, src2, \ 384 flags=None, dataSize="env.dataSize"): 385 super(RegOpChild, self).__init__(dest, src1, src2, \ 386 flags, dataSize) 387 388 microopClasses[name] = RegOpChild 389 390 setUpMicroRegOp(name, Name, "X86ISA::RegOp", regCode); 391 setUpMicroRegOp(name, Name + "Flags", "X86ISA::RegOp", 392 regCode, flagCode=regFlagCode, 393 condCheck=condCode, elseCode=elseCode); 394 395 class RegOpChildImm(RegOpImm): 396 mnemonic = name + 'i' 397 className = Name + 'Imm' 398 def __init__(self, dest, src1, src2, \ 399 flags=None, dataSize="env.dataSize"): 400 super(RegOpChildImm, self).__init__(dest, src1, src2, \ 401 flags, dataSize) 402 403 microopClasses[name + 'i'] = RegOpChildImm 404 405 setUpMicroRegOp(name + "i", Name + "Imm", "X86ISA::RegOpImm", \ 406 immCode, imm=True); 407 setUpMicroRegOp(name + "i", Name + "ImmFlags", "X86ISA::RegOpImm", 408 immCode, flagCode=immFlagCode, 409 condCheck=condCode, elseCode=elseCode, imm=True); 410 411 # This has it's own function because Wr ops have implicit destinations 412 def defineMicroRegOpWr(mnemonic, code, elseCode=";"): 413 Name = mnemonic 414 name = mnemonic.lower() 415 416 # Find op2 in each of the instruction definitions. Create two versions 417 # of the code, one with an integer operand, and one with an immediate 418 # operand. 419 matcher = re.compile("op2(?P<typeQual>\\.\\w+)?") 420 regCode = regPick + matcher.sub("psrc2", code) 421 immCode = immPick + matcher.sub("imm8", code) 422 423 class RegOpChild(RegOp): 424 mnemonic = name 425 className = Name 426 def __init__(self, src1, src2, flags=None, dataSize="env.dataSize"): 427 super(RegOpChild, self).__init__("NUM_INTREGS", src1, src2, flags, dataSize) 428 429 microopClasses[name] = RegOpChild 430 431 setUpMicroRegOp(name, Name, "X86ISA::RegOp", regCode); 432 setUpMicroRegOp(name, Name + "Flags", "X86ISA::RegOp", regCode, 433 condCheck = checkCCFlagBits, elseCode = elseCode); 434 435 class RegOpChildImm(RegOpImm): 436 mnemonic = name + 'i' 437 className = Name + 'Imm' 438 def __init__(self, src1, src2, flags=None, dataSize="env.dataSize"): 439 super(RegOpChildImm, self).__init__("NUM_INTREGS", src1, src2, flags, dataSize) 440 441 microopClasses[name + 'i'] = RegOpChildImm 442 443 setUpMicroRegOp(name + 'i', Name + "Imm", "X86ISA::RegOpImm", \ 444 immCode, imm=True); 445 setUpMicroRegOp(name + 'i', Name + "ImmFlags", "X86ISA::RegOpImm", \ 446 immCode, condCheck = checkCCFlagBits, elseCode = elseCode, \ 447 imm=True); 448 449 # This has it's own function because Rd ops don't always have two parameters 450 def defineMicroRegOpRd(mnemonic, code): 451 Name = mnemonic 452 name = mnemonic.lower() 453 454 class RegOpChild(RegOp): 455 className = Name 456 mnemonic = name 457 def __init__(self, dest, src1 = "NUM_INTREGS", dataSize="env.dataSize"): 458 super(RegOpChild, self).__init__(dest, src1, "NUM_INTREGS", None, dataSize) 459 460 microopClasses[name] = RegOpChild 461 462 setUpMicroRegOp(name, Name, "X86ISA::RegOp", code); 463 464 def defineMicroRegOpImm(mnemonic, code, flagCode=""): 465 Name = mnemonic 466 name = mnemonic.lower() 467 code = immPick + code 468 469 class RegOpChild(RegOpImm): 470 className = Name 471 mnemonic = name 472 def __init__(self, dest, src1, src2, \ 473 flags=None, dataSize="env.dataSize"): 474 super(RegOpChild, self).__init__(dest, \ 475 src1, src2, flags, dataSize) 476 477 microopClasses[name] = RegOpChild 478 479 setUpMicroRegOp(name, Name, "X86ISA::RegOpImm", code, imm=True); 480 setUpMicroRegOp(name, Name + "Flags", "X86ISA::RegOpImm", \ 481 code, flagCode=flagCode, imm=True); 482 483 def defineMicroRegOpRdImm(mnemonic, code, flagCode=""): 484 Name = mnemonic 485 name = mnemonic.lower() 486 code = immPick + code 487 488 class RegOpChildRdImm(RegOpImm): 489 className = Name 490 mnemonic = name 491 def __init__(self, dest, imm, flags=None, \ 492 dataSize="env.dataSize"): 493 super(RegOpChildRdImm, self).__init__(dest, \ 494 "NUM_INTREGS", imm, flags, dataSize) 495 496 microopClasses[name] = RegOpChildRdImm 497 498 setUpMicroRegOp(name, Name, "X86ISA::RegOpImm", code, imm=True); 499 setUpMicroRegOp(name, Name + "Flags", "X86ISA::RegOpImm", \ 500 code, flagCode=flagCode, imm=True); 501 502 defineMicroRegOp('Add', 'DestReg = merge(DestReg, psrc1 + op2, dataSize)') 503 defineMicroRegOp('Or', 'DestReg = merge(DestReg, psrc1 | op2, dataSize);', 504 flagCode = genCCFlagBitsLogic) 505 defineMicroRegOp('Adc', ''' 506 CCFlagBits flags = ccFlagBits; 507 DestReg = merge(DestReg, psrc1 + op2 + flags.CF, dataSize); 508 ''') 509 defineMicroRegOp('Sbb', ''' 510 CCFlagBits flags = ccFlagBits; 511 DestReg = merge(DestReg, psrc1 - op2 - flags.CF, dataSize); 512 ''', flagCode = genCCFlagBitsSub) 513 defineMicroRegOp('And', \ 514 'DestReg = merge(DestReg, psrc1 & op2, dataSize)', \ 515 flagCode = genCCFlagBitsLogic) 516 defineMicroRegOp('Sub', \ 517 'DestReg = merge(DestReg, psrc1 - op2, dataSize)', \ 518 flagCode = genCCFlagBitsSub) 519 defineMicroRegOp('Xor', \ 520 'DestReg = merge(DestReg, psrc1 ^ op2, dataSize)', \ 521 flagCode = genCCFlagBitsLogic) 522 defineMicroRegOp('Mul1s', ''' 523 int signPos = (dataSize * 8) / 2 - 1; 524 IntReg srcVal1 = psrc1 | (-bits(psrc1, signPos) << signPos); 525 IntReg srcVal2 = op2 | (-bits(psrc1, signPos) << signPos); 526 DestReg = merge(DestReg, srcVal1 * srcVal2, dataSize) 527 ''') 528 defineMicroRegOp('Mul1u', ''' 529 int halfSize = (dataSize * 8) / 2; 530 IntReg srcVal1 = psrc1 & mask(halfSize); 531 IntReg srcVal2 = op2 & mask(halfSize); 532 DestReg = merge(DestReg, srcVal1 * srcVal2, dataSize) 533 ''') 534 defineMicroRegOp('Mulel', \ 535 'DestReg = merge(DestReg, psrc1 * op2, dataSize)') 536 defineMicroRegOp('Muleh', ''' 537 int halfSize = (dataSize * 8) / 2; 538 uint64_t psrc1_h = psrc1 >> halfSize; 539 uint64_t psrc1_l = psrc1 & mask(halfSize); 540 uint64_t psrc2_h = op2 >> halfSize; 541 uint64_t psrc2_l = op2 & mask(halfSize); 542 uint64_t result = 543 ((psrc1_l * psrc2_h) >> halfSize) + 544 ((psrc1_h * psrc2_l) >> halfSize) + 545 psrc1_h * psrc2_h; 546 DestReg = merge(DestReg, result, dataSize); 547 ''') 548 defineMicroRegOp('Div1', ''' 549 int halfSize = (dataSize * 8) / 2; 550 IntReg quotient = (psrc1 / op2) & mask(halfSize); 551 IntReg remainder = (psrc1 % op2) & mask(halfSize); 552 IntReg result = quotient | (remainder << halfSize); 553 DestReg = merge(DestReg, result, dataSize); 554 ''') 555 defineMicroRegOp('Divq', ''' 556 DestReg = merge(DestReg, psrc1 / op2, dataSize); 557 ''') 558 defineMicroRegOp('Divr', ''' 559 DestReg = merge(DestReg, psrc1 % op2, dataSize); 560 ''') 561 562 # 563 # HACK HACK HACK HACK - Put psrc1 in here but make it inert to shut up gcc. 564 # 565 defineMicroRegOp('Mov', 'DestReg = merge(SrcReg1, psrc1 * 0 + op2, dataSize)', 566 elseCode='DestReg=DestReg;', cc=True) 567 568 # Shift instructions 569 defineMicroRegOp('Sll', ''' 570 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 571 DestReg = merge(DestReg, psrc1 << shiftAmt, dataSize); 572 ''') 573 defineMicroRegOp('Srl', ''' 574 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 575 // Because what happens to the bits shift -in- on a right shift 576 // is not defined in the C/C++ standard, we have to mask them out 577 // to be sure they're zero. 578 uint64_t logicalMask = mask(dataSize * 8 - shiftAmt); 579 DestReg = merge(DestReg, (psrc1 >> shiftAmt) & logicalMask, dataSize); 580 ''') 581 defineMicroRegOp('Sra', ''' 582 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 583 // Because what happens to the bits shift -in- on a right shift 584 // is not defined in the C/C++ standard, we have to sign extend 585 // them manually to be sure. 586 uint64_t arithMask = 587 -bits(op2, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt); 588 DestReg = merge(DestReg, (psrc1 >> shiftAmt) | arithMask, dataSize); 589 ''') 590 defineMicroRegOp('Ror', ''' 591 uint8_t shiftAmt = 592 (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 593 if(shiftAmt) 594 { 595 uint64_t top = psrc1 << (dataSize * 8 - shiftAmt); 596 uint64_t bottom = bits(psrc1, dataSize * 8, shiftAmt); 597 DestReg = merge(DestReg, top | bottom, dataSize); 598 } 599 else 600 DestReg = DestReg; 601 ''') 602 defineMicroRegOp('Rcr', ''' 603 uint8_t shiftAmt = 604 (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 605 if(shiftAmt) 606 { 607 CCFlagBits flags = ccFlagBits; 608 uint64_t top = flags.CF << (dataSize * 8 - shiftAmt); 609 if(shiftAmt > 1) 610 top |= psrc1 << (dataSize * 8 - shiftAmt - 1); 611 uint64_t bottom = bits(psrc1, dataSize * 8, shiftAmt); 612 DestReg = merge(DestReg, top | bottom, dataSize); 613 } 614 else 615 DestReg = DestReg; 616 ''') 617 defineMicroRegOp('Rol', ''' 618 uint8_t shiftAmt = 619 (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 620 if(shiftAmt) 621 { 622 uint64_t top = psrc1 << shiftAmt; 623 uint64_t bottom = 624 bits(psrc1, dataSize * 8 - 1, dataSize * 8 - shiftAmt); 625 DestReg = merge(DestReg, top | bottom, dataSize); 626 } 627 else 628 DestReg = DestReg; 629 ''') 630 defineMicroRegOp('Rcl', ''' 631 uint8_t shiftAmt = 632 (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 633 if(shiftAmt) 634 { 635 CCFlagBits flags = ccFlagBits; 636 uint64_t top = psrc1 << shiftAmt; 637 uint64_t bottom = flags.CF << (shiftAmt - 1); 638 if(shiftAmt > 1) 639 bottom |= 640 bits(psrc1, dataSize * 8 - 1, 641 dataSize * 8 - shiftAmt + 1); 642 DestReg = merge(DestReg, top | bottom, dataSize); 643 } 644 else 645 DestReg = DestReg; 646 ''') 647 648 defineMicroRegOpWr('Wrip', 'RIP = psrc1 + op2', elseCode="RIP = RIP;") 649 defineMicroRegOpWr('Br', 'nuIP = psrc1 + op2;', elseCode='nuIP = nuIP;') 650 defineMicroRegOpWr('Wruflags', 'ccFlagBits = psrc1 ^ op2') 651 652 defineMicroRegOpRd('Rdip', 'DestReg = RIP') 653 defineMicroRegOpRd('Ruflags', 'DestReg = ccFlagBits') 654 defineMicroRegOpRdImm('Ruflag', ''' 655 int flag = bits(ccFlagBits, imm8 + 0*psrc1); 656 DestReg = merge(DestReg, flag, dataSize); 657 ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) : 658 (ccFlagBits & ~EZFBit); 659 ''') 660 661 defineMicroRegOpImm('Sext', ''' 662 IntReg val = psrc1; 663 int sign_bit = bits(val, imm8-1, imm8-1); 664 uint64_t maskVal = mask(imm8); 665 val = sign_bit ? (val | ~maskVal) : (val & maskVal); 666 DestReg = merge(DestReg, val, dataSize); 667 ''') 668 669 defineMicroRegOpImm('Zext', 'DestReg = bits(psrc1, imm8-1, 0);') 670}}; 671