regop.isa revision 5075:4ae876c5037d
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 230output header {{ 231 void 232 divide(uint64_t dividend, uint64_t divisor, 233 uint64_t "ient, uint64_t &remainder); 234}}; 235 236output decoder {{ 237 void 238 divide(uint64_t dividend, uint64_t divisor, 239 uint64_t "ient, uint64_t &remainder) 240 { 241 //Check for divide by zero. 242 if (divisor == 0) 243 panic("Divide by zero!\\n"); 244 //If the divisor is bigger than the dividend, don't do anything. 245 if (divisor <= dividend) { 246 //Shift the divisor so it's msb lines up with the dividend. 247 int dividendMsb = findMsbSet(dividend); 248 int divisorMsb = findMsbSet(divisor); 249 int shift = dividendMsb - divisorMsb; 250 divisor <<= shift; 251 //Compute what we'll add to the quotient if the divisor isn't 252 //now larger than the dividend. 253 uint64_t quotientBit = 1; 254 quotientBit <<= shift; 255 //If we need to step back a bit (no pun intended) because the 256 //divisor got too to large, do that here. This is the "or two" 257 //part of one or two bit division. 258 if (divisor > dividend) { 259 quotientBit >>= 1; 260 divisor >>= 1; 261 } 262 //Decrement the remainder and increment the quotient. 263 quotient += quotientBit; 264 remainder -= divisor; 265 } 266 } 267}}; 268 269let {{ 270 # Make these empty strings so that concatenating onto 271 # them will always work. 272 header_output = "" 273 decoder_output = "" 274 exec_output = "" 275 276 immTemplates = ( 277 MicroRegOpImmDeclare, 278 MicroRegOpImmConstructor, 279 MicroRegOpImmExecute) 280 281 regTemplates = ( 282 MicroRegOpDeclare, 283 MicroRegOpConstructor, 284 MicroRegOpExecute) 285 286 class RegOpMeta(type): 287 def buildCppClasses(self, name, Name, suffix, \ 288 code, flag_code, cond_check, else_code): 289 290 # Globals to stick the output in 291 global header_output 292 global decoder_output 293 global exec_output 294 295 # Stick all the code together so it can be searched at once 296 allCode = "|".join((code, flag_code, cond_check, else_code)) 297 298 # If op2 is used anywhere, make register and immediate versions 299 # of this code. 300 matcher = re.compile("(?<!\\w)(?P<prefix>s?)op2(?P<typeQual>\\.\\w+)?") 301 match = matcher.search(allCode) 302 if match: 303 typeQual = "" 304 if match.group("typeQual"): 305 typeQual = match.group("typeQual") 306 src2_name = "%spsrc2%s" % (match.group("prefix"), typeQual) 307 self.buildCppClasses(name, Name, suffix, 308 matcher.sub(src2_name, code), 309 matcher.sub(src2_name, flag_code), 310 matcher.sub(src2_name, cond_check), 311 matcher.sub(src2_name, else_code)) 312 self.buildCppClasses(name + "i", Name, suffix + "Imm", 313 matcher.sub("imm8", code), 314 matcher.sub("imm8", flag_code), 315 matcher.sub("imm8", cond_check), 316 matcher.sub("imm8", else_code)) 317 return 318 319 # If there's something optional to do with flags, generate 320 # a version without it and fix up this version to use it. 321 if flag_code is not "" or cond_check is not "true": 322 self.buildCppClasses(name, Name, suffix, 323 code, "", "true", else_code) 324 suffix = "Flags" + suffix 325 326 # If psrc1 or psrc2 is used, we need to actually insert code to 327 # compute it. 328 matcher = re.compile("(?<!\w)psrc1(?!\w)") 329 if matcher.search(allCode): 330 code = "uint64_t psrc1 = pick(SrcReg1, 0, dataSize);" + code 331 matcher = re.compile("(?<!\w)psrc2(?!\w)") 332 if matcher.search(allCode): 333 code = "uint64_t psrc2 = pick(SrcReg2, 1, dataSize);" + code 334 # Also make available versions which do sign extension 335 matcher = re.compile("(?<!\w)spsrc1(?!\w)") 336 if matcher.search(allCode): 337 code = "int64_t spsrc1 = signedPick(SrcReg1, 0, dataSize);" + code 338 matcher = re.compile("(?<!\w)spsrc2(?!\w)") 339 if matcher.search(allCode): 340 code = "int64_t spsrc2 = signedPick(SrcReg2, 1, dataSize);" + code 341 342 base = "X86ISA::RegOp" 343 344 # If imm8 shows up in the code, use the immediate templates, if 345 # not, hopefully the register ones will be correct. 346 templates = regTemplates 347 matcher = re.compile("(?<!\w)imm8(?!\w)") 348 if matcher.search(allCode): 349 base += "Imm" 350 templates = immTemplates 351 352 # Get everything ready for the substitution 353 iop = InstObjParams(name, Name + suffix, base, 354 {"code" : code, 355 "flag_code" : flag_code, 356 "cond_check" : cond_check, 357 "else_code" : else_code}) 358 359 # Generate the actual code (finally!) 360 header_output += templates[0].subst(iop) 361 decoder_output += templates[1].subst(iop) 362 exec_output += templates[2].subst(iop) 363 364 365 def __new__(mcls, Name, bases, dict): 366 abstract = False 367 name = Name.lower() 368 if "abstract" in dict: 369 abstract = dict['abstract'] 370 del dict['abstract'] 371 372 cls = super(RegOpMeta, mcls).__new__(mcls, Name, bases, dict) 373 if not abstract: 374 cls.className = Name 375 cls.base_mnemonic = name 376 code = cls.code 377 flag_code = cls.flag_code 378 cond_check = cls.cond_check 379 else_code = cls.else_code 380 381 # Set up the C++ classes 382 mcls.buildCppClasses(cls, name, Name, "", 383 code, flag_code, cond_check, else_code) 384 385 # Hook into the microassembler dict 386 global microopClasses 387 microopClasses[name] = cls 388 389 allCode = "|".join((code, flag_code, cond_check, else_code)) 390 391 # If op2 is used anywhere, make register and immediate versions 392 # of this code. 393 matcher = re.compile("op2(?P<typeQual>\\.\\w+)?") 394 if matcher.search(allCode): 395 microopClasses[name + 'i'] = cls 396 return cls 397 398 399 class RegOp(X86Microop): 400 __metaclass__ = RegOpMeta 401 # This class itself doesn't act as a microop 402 abstract = True 403 404 # Default template parameter values 405 flag_code = "" 406 cond_check = "true" 407 else_code = ";" 408 409 def __init__(self, dest, src1, op2, flags = None, dataSize = "env.dataSize"): 410 self.dest = dest 411 self.src1 = src1 412 self.op2 = op2 413 self.flags = flags 414 self.dataSize = dataSize 415 if flags is None: 416 self.ext = 0 417 else: 418 if not isinstance(flags, (list, tuple)): 419 raise Exception, "flags must be a list or tuple of flags" 420 self.ext = " | ".join(flags) 421 self.className += "Flags" 422 423 def getAllocator(self, *microFlags): 424 className = self.className 425 if self.mnemonic == self.base_mnemonic + 'i': 426 className += "Imm" 427 allocator = '''new %(class_name)s(machInst, mnemonic 428 %(flags)s, %(src1)s, %(op2)s, %(dest)s, 429 %(dataSize)s, %(ext)s)''' % { 430 "class_name" : className, 431 "flags" : self.microFlagsText(microFlags), 432 "src1" : self.src1, "op2" : self.op2, 433 "dest" : self.dest, 434 "dataSize" : self.dataSize, 435 "ext" : self.ext} 436 return allocator 437 438 class LogicRegOp(RegOp): 439 abstract = True 440 flag_code = ''' 441 //Don't have genFlags handle the OF or CF bits 442 uint64_t mask = CFBit | OFBit; 443 ccFlagBits = genFlags(ccFlagBits, ext & ~mask, DestReg, psrc1, op2); 444 //If a logic microop wants to set these, it wants to set them to 0. 445 ccFlagBits &= ~(CFBit & ext); 446 ccFlagBits &= ~(OFBit & ext); 447 ''' 448 449 class FlagRegOp(RegOp): 450 abstract = True 451 flag_code = \ 452 "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, op2);" 453 454 class SubRegOp(RegOp): 455 abstract = True 456 flag_code = \ 457 "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, ~op2, true);" 458 459 class CondRegOp(RegOp): 460 abstract = True 461 cond_check = "checkCondition(ccFlagBits)" 462 463 class RdRegOp(RegOp): 464 abstract = True 465 def __init__(self, dest, src1=None, dataSize="env.dataSize"): 466 if not src1: 467 src1 = dest 468 super(RdRegOp, self).__init__(dest, src1, "NUM_INTREGS", None, dataSize) 469 470 class WrRegOp(RegOp): 471 abstract = True 472 def __init__(self, src1, src2, flags=None, dataSize="env.dataSize"): 473 super(WrRegOp, self).__init__("NUM_INTREGS", src1, src2, flags, dataSize) 474 475 class Add(FlagRegOp): 476 code = 'DestReg = merge(DestReg, psrc1 + op2, dataSize);' 477 478 class Or(LogicRegOp): 479 code = 'DestReg = merge(DestReg, psrc1 | op2, dataSize);' 480 481 class Adc(FlagRegOp): 482 code = ''' 483 CCFlagBits flags = ccFlagBits; 484 DestReg = merge(DestReg, psrc1 + op2 + flags.CF, dataSize); 485 ''' 486 487 class Sbb(SubRegOp): 488 code = ''' 489 CCFlagBits flags = ccFlagBits; 490 DestReg = merge(DestReg, psrc1 - op2 - flags.CF, dataSize); 491 ''' 492 493 class And(LogicRegOp): 494 code = 'DestReg = merge(DestReg, psrc1 & op2, dataSize)' 495 496 class Sub(SubRegOp): 497 code = 'DestReg = merge(DestReg, psrc1 - op2, dataSize)' 498 499 class Xor(LogicRegOp): 500 code = 'DestReg = merge(DestReg, psrc1 ^ op2, dataSize)' 501 502 # Neither of these is quite correct because it assumes that right shifting 503 # a signed or unsigned value does sign or zero extension respectively. 504 # The C standard says that what happens on a right shift with a 1 in the 505 # MSB position is undefined. On x86 and under likely most compilers the 506 # "right thing" happens, but this isn't a guarantee. 507 class Mul1s(WrRegOp): 508 code = ''' 509 ProdLow = psrc1 * op2; 510 int halfSize = (dataSize * 8) / 2; 511 int64_t spsrc1_h = spsrc1 >> halfSize; 512 int64_t spsrc1_l = spsrc1 & mask(halfSize); 513 int64_t spsrc2_h = sop2 >> halfSize; 514 int64_t spsrc2_l = sop2 & mask(halfSize); 515 ProdHi = ((spsrc1_l * spsrc2_h + spsrc1_h * spsrc2_l + 516 ((spsrc1_l * spsrc2_l) >> halfSize)) >> halfSize) + 517 spsrc1_h * spsrc2_h; 518 ''' 519 520 class Mul1u(WrRegOp): 521 code = ''' 522 ProdLow = psrc1 * op2; 523 int halfSize = (dataSize * 8) / 2; 524 uint64_t psrc1_h = psrc1 >> halfSize; 525 uint64_t psrc1_l = psrc1 & mask(halfSize); 526 uint64_t psrc2_h = op2 >> halfSize; 527 uint64_t psrc2_l = op2 & mask(halfSize); 528 ProdHi = ((psrc1_l * psrc2_h + psrc1_h * psrc2_l + 529 ((psrc1_l * psrc2_l) >> halfSize)) >> halfSize) + 530 psrc1_h * psrc2_h; 531 ''' 532 533 class Mulel(RdRegOp): 534 code = 'DestReg = merge(SrcReg1, ProdLow, dataSize);' 535 536 class Muleh(RdRegOp): 537 def __init__(self, dest, src1=None, flags=None, dataSize="env.dataSize"): 538 if not src1: 539 src1 = dest 540 super(RdRegOp, self).__init__(dest, src1, "NUM_INTREGS", flags, dataSize) 541 code = 'DestReg = merge(SrcReg1, ProdHi, dataSize);' 542 flag_code = ''' 543 if (ProdHi) 544 ccFlagBits = ccFlagBits | (ext & (CFBit | OFBit | ECFBit)); 545 else 546 ccFlagBits = ccFlagBits & ~(ext & (CFBit | OFBit | ECFBit)); 547 ''' 548 549 # One or two bit divide 550 class Div1(WrRegOp): 551 code = ''' 552 //These are temporaries so that modifying them later won't make 553 //the ISA parser think they're also sources. 554 uint64_t quotient = 0; 555 uint64_t remainder = psrc1; 556 //Similarly, this is a temporary so changing it doesn't make it 557 //a source. 558 uint64_t divisor = op2; 559 //This is a temporary just for consistency and clarity. 560 uint64_t dividend = remainder; 561 //Do the division. 562 divide(dividend, divisor, quotient, remainder); 563 //Record the final results. 564 Remainder = remainder; 565 Quotient = quotient; 566 Divisor = divisor; 567 ''' 568 569 # Step divide 570 class Div2(RegOp): 571 code = ''' 572 uint64_t dividend = Remainder; 573 uint64_t divisor = Divisor; 574 uint64_t quotient = Quotient; 575 uint64_t remainder = dividend; 576 int remaining = op2; 577 //If we overshot, do nothing. This lets us unrool division loops a 578 //little. 579 if (remaining) { 580 //Shift in bits from the low order portion of the dividend 581 while(dividend < divisor && remaining) { 582 dividend = (dividend << 1) | bits(SrcReg1, remaining - 1); 583 quotient <<= 1; 584 remaining--; 585 } 586 remainder = dividend; 587 //Do the division. 588 divide(dividend, divisor, quotient, remainder); 589 } 590 //Keep track of how many bits there are still to pull in. 591 DestReg = merge(DestReg, remaining, dataSize); 592 //Record the final results 593 Remainder = remainder; 594 Quotient = quotient; 595 ''' 596 flag_code = ''' 597 if (DestReg == 0) 598 ccFlagBits = ccFlagBits | (ext & EZFBit); 599 else 600 ccFlagBits = ccFlagBits & ~(ext & EZFBit); 601 ''' 602 603 class Divq(RdRegOp): 604 code = 'DestReg = merge(SrcReg1, Quotient, dataSize);' 605 606 class Divr(RdRegOp): 607 code = 'DestReg = merge(SrcReg1, Remainder, dataSize);' 608 609 class Mov(CondRegOp): 610 code = 'DestReg = merge(SrcReg1, op2, dataSize)' 611 else_code = 'DestReg=DestReg;' 612 613 # Shift instructions 614 615 class Sll(FlagRegOp): 616 code = ''' 617 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 618 DestReg = merge(DestReg, psrc1 << shiftAmt, dataSize); 619 ''' 620 621 class Srl(FlagRegOp): 622 code = ''' 623 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 624 // Because what happens to the bits shift -in- on a right shift 625 // is not defined in the C/C++ standard, we have to mask them out 626 // to be sure they're zero. 627 uint64_t logicalMask = mask(dataSize * 8 - shiftAmt); 628 DestReg = merge(DestReg, (psrc1 >> shiftAmt) & logicalMask, dataSize); 629 ''' 630 631 class Sra(FlagRegOp): 632 code = ''' 633 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 634 // Because what happens to the bits shift -in- on a right shift 635 // is not defined in the C/C++ standard, we have to sign extend 636 // them manually to be sure. 637 uint64_t arithMask = 638 -bits(psrc1, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt); 639 DestReg = merge(DestReg, (psrc1 >> shiftAmt) | arithMask, dataSize); 640 ''' 641 642 class Ror(FlagRegOp): 643 code = ''' 644 uint8_t shiftAmt = 645 (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 646 if(shiftAmt) 647 { 648 uint64_t top = psrc1 << (dataSize * 8 - shiftAmt); 649 uint64_t bottom = bits(psrc1, dataSize * 8, shiftAmt); 650 DestReg = merge(DestReg, top | bottom, dataSize); 651 } 652 else 653 DestReg = DestReg; 654 ''' 655 656 class Rcr(FlagRegOp): 657 code = ''' 658 uint8_t shiftAmt = 659 (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 660 if(shiftAmt) 661 { 662 CCFlagBits flags = ccFlagBits; 663 uint64_t top = flags.CF << (dataSize * 8 - shiftAmt); 664 if(shiftAmt > 1) 665 top |= psrc1 << (dataSize * 8 - shiftAmt - 1); 666 uint64_t bottom = bits(psrc1, dataSize * 8, shiftAmt); 667 DestReg = merge(DestReg, top | bottom, dataSize); 668 } 669 else 670 DestReg = DestReg; 671 ''' 672 673 class Rol(FlagRegOp): 674 code = ''' 675 uint8_t shiftAmt = 676 (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 677 if(shiftAmt) 678 { 679 uint64_t top = psrc1 << shiftAmt; 680 uint64_t bottom = 681 bits(psrc1, dataSize * 8 - 1, dataSize * 8 - shiftAmt); 682 DestReg = merge(DestReg, top | bottom, dataSize); 683 } 684 else 685 DestReg = DestReg; 686 ''' 687 688 class Rcl(FlagRegOp): 689 code = ''' 690 uint8_t shiftAmt = 691 (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 692 if(shiftAmt) 693 { 694 CCFlagBits flags = ccFlagBits; 695 uint64_t top = psrc1 << shiftAmt; 696 uint64_t bottom = flags.CF << (shiftAmt - 1); 697 if(shiftAmt > 1) 698 bottom |= 699 bits(psrc1, dataSize * 8 - 1, 700 dataSize * 8 - shiftAmt + 1); 701 DestReg = merge(DestReg, top | bottom, dataSize); 702 } 703 else 704 DestReg = DestReg; 705 ''' 706 707 class Wrip(WrRegOp, CondRegOp): 708 code = 'RIP = psrc1 + op2' 709 else_code="RIP = RIP;" 710 711 class Br(WrRegOp, CondRegOp): 712 code = 'nuIP = psrc1 + op2;' 713 else_code='nuIP = nuIP;' 714 715 class Wruflags(WrRegOp): 716 code = 'ccFlagBits = psrc1 ^ op2' 717 718 class Rdip(RdRegOp): 719 code = 'DestReg = RIP' 720 721 class Ruflags(RdRegOp): 722 code = 'DestReg = ccFlagBits' 723 724 class Ruflag(RegOp): 725 code = ''' 726 int flag = bits(ccFlagBits, imm8 + 0*psrc1); 727 DestReg = merge(DestReg, flag, dataSize); 728 ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) : 729 (ccFlagBits & ~EZFBit); 730 ''' 731 def __init__(self, dest, imm, flags=None, \ 732 dataSize="env.dataSize"): 733 super(Ruflag, self).__init__(dest, \ 734 "NUM_INTREGS", imm, flags, dataSize) 735 736 class Sext(RegOp): 737 code = ''' 738 IntReg val = psrc1; 739 int sign_bit = bits(val, imm8-1, imm8-1); 740 uint64_t maskVal = mask(imm8); 741 val = sign_bit ? (val | ~maskVal) : (val & maskVal); 742 DestReg = merge(DestReg, val, dataSize); 743 ''' 744 745 class Zext(RegOp): 746 code = 'DestReg = bits(psrc1, imm8-1, 0);' 747 748 class Compfp(WrRegOp): 749 # This class sets the condition codes in rflags according to the 750 # rules for comparing floating point. 751 code = ''' 752 // ZF PF CF 753 // Unordered 1 1 1 754 // Greater than 0 0 0 755 // Less than 0 0 1 756 // Equal 1 0 0 757 // OF = SF = AF = 0 758 ccFlagBits = ccFlagBits & ~(OFBit | SFBit | AFBit | 759 ZFBit | PFBit | CFBit); 760 if (isnan(FpSrcReg1) || isnan(FpSrcReg2)) 761 ccFlagBits = ccFlagBits | (ZFBit | PFBit | CFBit); 762 else if(FpSrcReg1 < FpSrcReg2) 763 ccFlagBits = ccFlagBits | CFBit; 764 else if(FpSrcReg1 == FpSrcReg2) 765 ccFlagBits = ccFlagBits | ZFBit; 766 ''' 767 768 class Xorfp(RegOp): 769 code = 'FpDestReg.uqw = FpSrcReg1.uqw ^ FpSrcReg2.uqw;' 770 771 class Sqrtfp(RegOp): 772 code = 'FpDestReg = sqrt(FpSrcReg2);' 773 774 class Movfp(CondRegOp): 775 code = 'FpDestReg.uqw = FpSrcReg2.uqw;' 776 else_code = 'FpDestReg.uqw = FpDestReg.uqw;' 777 778 # Conversion microops 779 class ConvOp(RegOp): 780 abstract = True 781 def __init__(self, dest, src1): 782 super(ConvOp, self).__init__(dest, src1, "NUM_INTREGS") 783 784 #FIXME This needs to always use 32 bits unless REX.W is present 785 class cvtf_i2d(ConvOp): 786 code = 'FpDestReg = spsrc1;' 787 788 class cvtf_i2d_hi(ConvOp): 789 code = 'FpDestReg = bits(SrcReg1, 63, 32);' 790 791 class cvtf_d2i(ConvOp): 792 code = ''' 793 int64_t intSrcReg1 = static_cast<int64_t>(FpSrcReg1); 794 DestReg = merge(DestReg, intSrcReg1, dataSize); 795 ''' 796 797 # These need to consider size at some point. They'll always use doubles 798 # for the moment. 799 class addfp(RegOp): 800 code = 'FpDestReg = FpSrcReg1 + FpSrcReg2;' 801 802 class mulfp(RegOp): 803 code = 'FpDestReg = FpSrcReg1 * FpSrcReg2;' 804 805 class divfp(RegOp): 806 code = 'FpDestReg = FpSrcReg1 / FpSrcReg2;' 807 808 class subfp(RegOp): 809 code = 'FpDestReg = FpSrcReg1 - FpSrcReg2;' 810}}; 811