regop.isa revision 5246
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 != "" or cond_check != "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 | ECFBit | 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 &= ~(ECFBit & ext); 447 ccFlagBits &= ~(OFBit & ext); 448 ''' 449 450 class FlagRegOp(RegOp): 451 abstract = True 452 flag_code = \ 453 "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, op2);" 454 455 class SubRegOp(RegOp): 456 abstract = True 457 flag_code = \ 458 "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, ~op2, true);" 459 460 class CondRegOp(RegOp): 461 abstract = True 462 cond_check = "checkCondition(ccFlagBits, ext)" 463 464 class RdRegOp(RegOp): 465 abstract = True 466 def __init__(self, dest, src1=None, dataSize="env.dataSize"): 467 if not src1: 468 src1 = dest 469 super(RdRegOp, self).__init__(dest, src1, "NUM_INTREGS", None, dataSize) 470 471 class WrRegOp(RegOp): 472 abstract = True 473 def __init__(self, src1, src2, flags=None, dataSize="env.dataSize"): 474 super(WrRegOp, self).__init__("NUM_INTREGS", src1, src2, flags, dataSize) 475 476 class Add(FlagRegOp): 477 code = 'DestReg = merge(DestReg, psrc1 + op2, dataSize);' 478 479 class Or(LogicRegOp): 480 code = 'DestReg = merge(DestReg, psrc1 | op2, dataSize);' 481 482 class Adc(FlagRegOp): 483 code = ''' 484 CCFlagBits flags = ccFlagBits; 485 DestReg = merge(DestReg, psrc1 + op2 + flags.cf, dataSize); 486 ''' 487 488 class Sbb(SubRegOp): 489 code = ''' 490 CCFlagBits flags = ccFlagBits; 491 DestReg = merge(DestReg, psrc1 - op2 - flags.cf, dataSize); 492 ''' 493 494 class And(LogicRegOp): 495 code = 'DestReg = merge(DestReg, psrc1 & op2, dataSize)' 496 497 class Sub(SubRegOp): 498 code = 'DestReg = merge(DestReg, psrc1 - op2, dataSize)' 499 500 class Xor(LogicRegOp): 501 code = 'DestReg = merge(DestReg, psrc1 ^ op2, dataSize)' 502 503 # Neither of these is quite correct because it assumes that right shifting 504 # a signed or unsigned value does sign or zero extension respectively. 505 # The C standard says that what happens on a right shift with a 1 in the 506 # MSB position is undefined. On x86 and under likely most compilers the 507 # "right thing" happens, but this isn't a guarantee. 508 class Mul1s(WrRegOp): 509 code = ''' 510 ProdLow = psrc1 * op2; 511 int halfSize = (dataSize * 8) / 2; 512 int64_t spsrc1_h = spsrc1 >> halfSize; 513 int64_t spsrc1_l = spsrc1 & mask(halfSize); 514 int64_t spsrc2_h = sop2 >> halfSize; 515 int64_t spsrc2_l = sop2 & mask(halfSize); 516 ProdHi = ((spsrc1_l * spsrc2_h + spsrc1_h * spsrc2_l + 517 ((spsrc1_l * spsrc2_l) >> halfSize)) >> halfSize) + 518 spsrc1_h * spsrc2_h; 519 ''' 520 521 class Mul1u(WrRegOp): 522 code = ''' 523 ProdLow = psrc1 * op2; 524 int halfSize = (dataSize * 8) / 2; 525 uint64_t psrc1_h = psrc1 >> halfSize; 526 uint64_t psrc1_l = psrc1 & mask(halfSize); 527 uint64_t psrc2_h = op2 >> halfSize; 528 uint64_t psrc2_l = op2 & mask(halfSize); 529 ProdHi = ((psrc1_l * psrc2_h + psrc1_h * psrc2_l + 530 ((psrc1_l * psrc2_l) >> halfSize)) >> halfSize) + 531 psrc1_h * psrc2_h; 532 ''' 533 534 class Mulel(RdRegOp): 535 code = 'DestReg = merge(SrcReg1, ProdLow, dataSize);' 536 537 class Muleh(RdRegOp): 538 def __init__(self, dest, src1=None, flags=None, dataSize="env.dataSize"): 539 if not src1: 540 src1 = dest 541 super(RdRegOp, self).__init__(dest, src1, "NUM_INTREGS", flags, dataSize) 542 code = 'DestReg = merge(SrcReg1, ProdHi, dataSize);' 543 flag_code = ''' 544 if (ProdHi) 545 ccFlagBits = ccFlagBits | (ext & (CFBit | OFBit | ECFBit)); 546 else 547 ccFlagBits = ccFlagBits & ~(ext & (CFBit | OFBit | ECFBit)); 548 ''' 549 550 # One or two bit divide 551 class Div1(WrRegOp): 552 code = ''' 553 //These are temporaries so that modifying them later won't make 554 //the ISA parser think they're also sources. 555 uint64_t quotient = 0; 556 uint64_t remainder = psrc1; 557 //Similarly, this is a temporary so changing it doesn't make it 558 //a source. 559 uint64_t divisor = op2; 560 //This is a temporary just for consistency and clarity. 561 uint64_t dividend = remainder; 562 //Do the division. 563 divide(dividend, divisor, quotient, remainder); 564 //Record the final results. 565 Remainder = remainder; 566 Quotient = quotient; 567 Divisor = divisor; 568 ''' 569 570 # Step divide 571 class Div2(RegOp): 572 code = ''' 573 uint64_t dividend = Remainder; 574 uint64_t divisor = Divisor; 575 uint64_t quotient = Quotient; 576 uint64_t remainder = dividend; 577 int remaining = op2; 578 //If we overshot, do nothing. This lets us unrool division loops a 579 //little. 580 if (remaining) { 581 //Shift in bits from the low order portion of the dividend 582 while(dividend < divisor && remaining) { 583 dividend = (dividend << 1) | bits(SrcReg1, remaining - 1); 584 quotient <<= 1; 585 remaining--; 586 } 587 remainder = dividend; 588 //Do the division. 589 divide(dividend, divisor, quotient, remainder); 590 } 591 //Keep track of how many bits there are still to pull in. 592 DestReg = merge(DestReg, remaining, dataSize); 593 //Record the final results 594 Remainder = remainder; 595 Quotient = quotient; 596 ''' 597 flag_code = ''' 598 if (DestReg == 0) 599 ccFlagBits = ccFlagBits | (ext & EZFBit); 600 else 601 ccFlagBits = ccFlagBits & ~(ext & EZFBit); 602 ''' 603 604 class Divq(RdRegOp): 605 code = 'DestReg = merge(SrcReg1, Quotient, dataSize);' 606 607 class Divr(RdRegOp): 608 code = 'DestReg = merge(SrcReg1, Remainder, dataSize);' 609 610 class Mov(CondRegOp): 611 code = 'DestReg = merge(SrcReg1, op2, dataSize)' 612 else_code = 'DestReg=DestReg;' 613 614 # Shift instructions 615 616 class Sll(RegOp): 617 code = ''' 618 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 619 DestReg = merge(DestReg, psrc1 << shiftAmt, dataSize); 620 ''' 621 flag_code = ''' 622 // If the shift amount is zero, no flags should be modified. 623 if (shiftAmt) { 624 //Zero out any flags we might modify. This way we only have to 625 //worry about setting them. 626 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit)); 627 int CFBits = 0; 628 //Figure out if we -would- set the CF bits if requested. 629 if (bits(SrcReg1, dataSize * 8 - shiftAmt)) 630 CFBits = 1; 631 //If some combination of the CF bits need to be set, set them. 632 if ((ext & (CFBit | ECFBit)) && CFBits) 633 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit)); 634 //Figure out what the OF bit should be. 635 if ((ext & OFBit) && (CFBits ^ bits(DestReg, dataSize * 8 - 1))) 636 ccFlagBits = ccFlagBits | OFBit; 637 //Use the regular mechanisms to calculate the other flags. 638 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), 639 DestReg, psrc1, op2); 640 } 641 ''' 642 643 class Srl(RegOp): 644 code = ''' 645 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 646 // Because what happens to the bits shift -in- on a right shift 647 // is not defined in the C/C++ standard, we have to mask them out 648 // to be sure they're zero. 649 uint64_t logicalMask = mask(dataSize * 8 - shiftAmt); 650 DestReg = merge(DestReg, (psrc1 >> shiftAmt) & logicalMask, dataSize); 651 ''' 652 flag_code = ''' 653 // If the shift amount is zero, no flags should be modified. 654 if (shiftAmt) { 655 //Zero out any flags we might modify. This way we only have to 656 //worry about setting them. 657 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit)); 658 //If some combination of the CF bits need to be set, set them. 659 if ((ext & (CFBit | ECFBit)) && bits(SrcReg1, shiftAmt - 1)) 660 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit)); 661 //Figure out what the OF bit should be. 662 if ((ext & OFBit) && bits(SrcReg1, dataSize * 8 - 1)) 663 ccFlagBits = ccFlagBits | OFBit; 664 //Use the regular mechanisms to calculate the other flags. 665 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), 666 DestReg, psrc1, op2); 667 } 668 ''' 669 670 class Sra(RegOp): 671 code = ''' 672 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 673 // Because what happens to the bits shift -in- on a right shift 674 // is not defined in the C/C++ standard, we have to sign extend 675 // them manually to be sure. 676 uint64_t arithMask = 677 -bits(psrc1, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt); 678 DestReg = merge(DestReg, (psrc1 >> shiftAmt) | arithMask, dataSize); 679 ''' 680 flag_code = ''' 681 // If the shift amount is zero, no flags should be modified. 682 if (shiftAmt) { 683 //Zero out any flags we might modify. This way we only have to 684 //worry about setting them. 685 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit)); 686 //If some combination of the CF bits need to be set, set them. 687 if ((ext & (CFBit | ECFBit)) && bits(SrcReg1, shiftAmt - 1)) 688 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit)); 689 //Use the regular mechanisms to calculate the other flags. 690 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), 691 DestReg, psrc1, op2); 692 } 693 ''' 694 695 class Ror(RegOp): 696 code = ''' 697 uint8_t shiftAmt = 698 (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 699 if(shiftAmt) 700 { 701 uint64_t top = psrc1 << (dataSize * 8 - shiftAmt); 702 uint64_t bottom = bits(psrc1, dataSize * 8, shiftAmt); 703 DestReg = merge(DestReg, top | bottom, dataSize); 704 } 705 else 706 DestReg = DestReg; 707 ''' 708 flag_code = ''' 709 // If the shift amount is zero, no flags should be modified. 710 if (shiftAmt) { 711 //Zero out any flags we might modify. This way we only have to 712 //worry about setting them. 713 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit)); 714 //Find the most and second most significant bits of the result. 715 int msb = bits(DestReg, dataSize * 8 - 1); 716 int smsb = bits(DestReg, dataSize * 8 - 2); 717 //If some combination of the CF bits need to be set, set them. 718 if ((ext & (CFBit | ECFBit)) && msb) 719 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit)); 720 //Figure out what the OF bit should be. 721 if ((ext & OFBit) && (msb ^ smsb)) 722 ccFlagBits = ccFlagBits | OFBit; 723 //Use the regular mechanisms to calculate the other flags. 724 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), 725 DestReg, psrc1, op2); 726 } 727 ''' 728 729 class Rcr(RegOp): 730 code = ''' 731 uint8_t shiftAmt = 732 (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 733 if(shiftAmt) 734 { 735 CCFlagBits flags = ccFlagBits; 736 uint64_t top = flags.cf << (dataSize * 8 - shiftAmt); 737 if(shiftAmt > 1) 738 top |= psrc1 << (dataSize * 8 - shiftAmt - 1); 739 uint64_t bottom = bits(psrc1, dataSize * 8, shiftAmt); 740 DestReg = merge(DestReg, top | bottom, dataSize); 741 } 742 else 743 DestReg = DestReg; 744 ''' 745 flag_code = ''' 746 // If the shift amount is zero, no flags should be modified. 747 if (shiftAmt) { 748 //Zero out any flags we might modify. This way we only have to 749 //worry about setting them. 750 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit)); 751 //Figure out what the OF bit should be. 752 if ((ext & OFBit) && ((ccFlagBits & CFBit) ^ 753 bits(SrcReg1, dataSize * 8 - 1))) 754 ccFlagBits = ccFlagBits | OFBit; 755 //If some combination of the CF bits need to be set, set them. 756 if ((ext & (CFBit | ECFBit)) && bits(SrcReg1, shiftAmt - 1)) 757 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit)); 758 //Use the regular mechanisms to calculate the other flags. 759 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), 760 DestReg, psrc1, op2); 761 } 762 ''' 763 764 class Rol(RegOp): 765 code = ''' 766 uint8_t shiftAmt = 767 (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 768 if(shiftAmt) 769 { 770 uint64_t top = psrc1 << shiftAmt; 771 uint64_t bottom = 772 bits(psrc1, dataSize * 8 - 1, dataSize * 8 - shiftAmt); 773 DestReg = merge(DestReg, top | bottom, dataSize); 774 } 775 else 776 DestReg = DestReg; 777 ''' 778 flag_code = ''' 779 // If the shift amount is zero, no flags should be modified. 780 if (shiftAmt) { 781 //Zero out any flags we might modify. This way we only have to 782 //worry about setting them. 783 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit)); 784 //The CF bits, if set, would be set to the lsb of the result. 785 int lsb = DestReg & 0x1; 786 int msb = bits(DestReg, dataSize * 8 - 1); 787 //If some combination of the CF bits need to be set, set them. 788 if ((ext & (CFBit | ECFBit)) && lsb) 789 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit)); 790 //Figure out what the OF bit should be. 791 if ((ext & OFBit) && (msb ^ lsb)) 792 ccFlagBits = ccFlagBits | OFBit; 793 //Use the regular mechanisms to calculate the other flags. 794 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), 795 DestReg, psrc1, op2); 796 } 797 ''' 798 799 class Rcl(RegOp): 800 code = ''' 801 uint8_t shiftAmt = 802 (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 803 if(shiftAmt) 804 { 805 CCFlagBits flags = ccFlagBits; 806 uint64_t top = psrc1 << shiftAmt; 807 uint64_t bottom = flags.cf << (shiftAmt - 1); 808 if(shiftAmt > 1) 809 bottom |= 810 bits(psrc1, dataSize * 8 - 1, 811 dataSize * 8 - shiftAmt + 1); 812 DestReg = merge(DestReg, top | bottom, dataSize); 813 } 814 else 815 DestReg = DestReg; 816 ''' 817 flag_code = ''' 818 // If the shift amount is zero, no flags should be modified. 819 if (shiftAmt) { 820 //Zero out any flags we might modify. This way we only have to 821 //worry about setting them. 822 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit)); 823 int msb = bits(DestReg, dataSize * 8 - 1); 824 int CFBits = bits(SrcReg1, dataSize * 8 - shiftAmt); 825 //If some combination of the CF bits need to be set, set them. 826 if ((ext & (CFBit | ECFBit)) && CFBits) 827 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit)); 828 //Figure out what the OF bit should be. 829 if ((ext & OFBit) && (msb ^ CFBits)) 830 ccFlagBits = ccFlagBits | OFBit; 831 //Use the regular mechanisms to calculate the other flags. 832 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), 833 DestReg, psrc1, op2); 834 } 835 ''' 836 837 class Wrip(WrRegOp, CondRegOp): 838 code = 'RIP = psrc1 + sop2 + CSBase' 839 else_code="RIP = RIP;" 840 841 class Br(WrRegOp, CondRegOp): 842 code = 'nuIP = psrc1 + op2;' 843 else_code='nuIP = nuIP;' 844 845 class Wruflags(WrRegOp): 846 code = 'ccFlagBits = psrc1 ^ op2' 847 848 class Rdip(RdRegOp): 849 code = 'DestReg = RIP - CSBase' 850 851 class Ruflags(RdRegOp): 852 code = 'DestReg = ccFlagBits' 853 854 class Ruflag(RegOp): 855 code = ''' 856 int flag = bits(ccFlagBits, imm8); 857 DestReg = merge(DestReg, flag, dataSize); 858 ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) : 859 (ccFlagBits & ~EZFBit); 860 ''' 861 def __init__(self, dest, imm, flags=None, \ 862 dataSize="env.dataSize"): 863 super(Ruflag, self).__init__(dest, \ 864 "NUM_INTREGS", imm, flags, dataSize) 865 866 class Sext(RegOp): 867 code = ''' 868 IntReg val = psrc1; 869 // Mask the bit position so that it wraps. 870 int bitPos = op2 & (dataSize * 8 - 1); 871 int sign_bit = bits(val, bitPos, bitPos); 872 uint64_t maskVal = mask(bitPos+1); 873 val = sign_bit ? (val | ~maskVal) : (val & maskVal); 874 DestReg = merge(DestReg, val, dataSize); 875 ''' 876 flag_code = ''' 877 if (!sign_bit) 878 ccFlagBits = ccFlagBits & 879 ~(ext & (CFBit | ECFBit | ZFBit | EZFBit)); 880 else 881 ccFlagBits = ccFlagBits | 882 (ext & (CFBit | ECFBit | ZFBit | EZFBit)); 883 ''' 884 885 class Zext(RegOp): 886 code = 'DestReg = bits(psrc1, op2, 0);' 887 888 class Wrcr(RegOp): 889 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 890 super(Wrcr, self).__init__(dest, \ 891 src1, "NUM_INTREGS", flags, dataSize) 892 code = ''' 893 if (dest == 1 || (dest > 4 && dest < 8) || (dest > 8)) { 894 fault = new InvalidOpcode(); 895 } else { 896 // There are *s in the line below so it doesn't confuse the 897 // parser. They may be unnecessary. 898 //Mis*cReg old*Val = pick(Cont*rolDest, 0, dat*aSize); 899 MiscReg newVal = psrc1; 900 901 // Check for any modifications that would cause a fault. 902 switch(dest) { 903 case 0: 904 { 905 Efer efer = EferOp; 906 CR0 cr0 = newVal; 907 CR4 oldCr4 = CR4Op; 908 if (bits(newVal, 63, 32) || 909 (!cr0.pe && cr0.pg) || 910 (!cr0.cd && cr0.nw) || 911 (cr0.pg && efer.lme && !oldCr4.pae)) 912 fault = new GeneralProtection(0); 913 } 914 break; 915 case 2: 916 break; 917 case 3: 918 break; 919 case 4: 920 { 921 CR4 cr4 = newVal; 922 // PAE can't be disabled in long mode. 923 if (bits(newVal, 63, 11) || 924 (machInst.mode.mode == LongMode && !cr4.pae)) 925 fault = new GeneralProtection(0); 926 } 927 break; 928 case 8: 929 { 930 if (bits(newVal, 63, 4)) 931 fault = new GeneralProtection(0); 932 } 933 default: 934 panic("Unrecognized control register %d.\\n", dest); 935 } 936 ControlDest = newVal; 937 } 938 ''' 939}}; 940