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