regop.isa revision 5433
1// Copyright (c) 2007-2008 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 enum SegmentSelectorCheck { 236 SegNoCheck, SegCSCheck, SegCallGateCheck, 237 SegSSCheck, SegIretCheck, SegIntCSCheck 238 }; 239}}; 240 241output decoder {{ 242 void 243 divide(uint64_t dividend, uint64_t divisor, 244 uint64_t "ient, uint64_t &remainder) 245 { 246 //Check for divide by zero. 247 if (divisor == 0) 248 panic("Divide by zero!\\n"); 249 //If the divisor is bigger than the dividend, don't do anything. 250 if (divisor <= dividend) { 251 //Shift the divisor so it's msb lines up with the dividend. 252 int dividendMsb = findMsbSet(dividend); 253 int divisorMsb = findMsbSet(divisor); 254 int shift = dividendMsb - divisorMsb; 255 divisor <<= shift; 256 //Compute what we'll add to the quotient if the divisor isn't 257 //now larger than the dividend. 258 uint64_t quotientBit = 1; 259 quotientBit <<= shift; 260 //If we need to step back a bit (no pun intended) because the 261 //divisor got too to large, do that here. This is the "or two" 262 //part of one or two bit division. 263 if (divisor > dividend) { 264 quotientBit >>= 1; 265 divisor >>= 1; 266 } 267 //Decrement the remainder and increment the quotient. 268 quotient += quotientBit; 269 remainder -= divisor; 270 } 271 } 272}}; 273 274let {{ 275 # Make these empty strings so that concatenating onto 276 # them will always work. 277 header_output = "" 278 decoder_output = "" 279 exec_output = "" 280 281 immTemplates = ( 282 MicroRegOpImmDeclare, 283 MicroRegOpImmConstructor, 284 MicroRegOpImmExecute) 285 286 regTemplates = ( 287 MicroRegOpDeclare, 288 MicroRegOpConstructor, 289 MicroRegOpExecute) 290 291 class RegOpMeta(type): 292 def buildCppClasses(self, name, Name, suffix, \ 293 code, flag_code, cond_check, else_code): 294 295 # Globals to stick the output in 296 global header_output 297 global decoder_output 298 global exec_output 299 300 # Stick all the code together so it can be searched at once 301 allCode = "|".join((code, flag_code, cond_check, else_code)) 302 303 # If op2 is used anywhere, make register and immediate versions 304 # of this code. 305 matcher = re.compile("(?<!\\w)(?P<prefix>s?)op2(?P<typeQual>\\.\\w+)?") 306 match = matcher.search(allCode) 307 if match: 308 typeQual = "" 309 if match.group("typeQual"): 310 typeQual = match.group("typeQual") 311 src2_name = "%spsrc2%s" % (match.group("prefix"), typeQual) 312 self.buildCppClasses(name, Name, suffix, 313 matcher.sub(src2_name, code), 314 matcher.sub(src2_name, flag_code), 315 matcher.sub(src2_name, cond_check), 316 matcher.sub(src2_name, else_code)) 317 self.buildCppClasses(name + "i", Name, suffix + "Imm", 318 matcher.sub("imm8", code), 319 matcher.sub("imm8", flag_code), 320 matcher.sub("imm8", cond_check), 321 matcher.sub("imm8", else_code)) 322 return 323 324 # If there's something optional to do with flags, generate 325 # a version without it and fix up this version to use it. 326 if flag_code != "" or cond_check != "true": 327 self.buildCppClasses(name, Name, suffix, 328 code, "", "true", else_code) 329 suffix = "Flags" + suffix 330 331 # If psrc1 or psrc2 is used, we need to actually insert code to 332 # compute it. 333 matcher = re.compile("(?<!\w)psrc1(?!\w)") 334 if matcher.search(allCode): 335 code = "uint64_t psrc1 = pick(SrcReg1, 0, dataSize);" + code 336 matcher = re.compile("(?<!\w)psrc2(?!\w)") 337 if matcher.search(allCode): 338 code = "uint64_t psrc2 = pick(SrcReg2, 1, dataSize);" + code 339 # Also make available versions which do sign extension 340 matcher = re.compile("(?<!\w)spsrc1(?!\w)") 341 if matcher.search(allCode): 342 code = "int64_t spsrc1 = signedPick(SrcReg1, 0, dataSize);" + code 343 matcher = re.compile("(?<!\w)spsrc2(?!\w)") 344 if matcher.search(allCode): 345 code = "int64_t spsrc2 = signedPick(SrcReg2, 1, dataSize);" + code 346 347 base = "X86ISA::RegOp" 348 349 # If imm8 shows up in the code, use the immediate templates, if 350 # not, hopefully the register ones will be correct. 351 templates = regTemplates 352 matcher = re.compile("(?<!\w)imm8(?!\w)") 353 if matcher.search(allCode): 354 base += "Imm" 355 templates = immTemplates 356 357 # Get everything ready for the substitution 358 iop = InstObjParams(name, Name + suffix, base, 359 {"code" : code, 360 "flag_code" : flag_code, 361 "cond_check" : cond_check, 362 "else_code" : else_code}) 363 364 # Generate the actual code (finally!) 365 header_output += templates[0].subst(iop) 366 decoder_output += templates[1].subst(iop) 367 exec_output += templates[2].subst(iop) 368 369 370 def __new__(mcls, Name, bases, dict): 371 abstract = False 372 name = Name.lower() 373 if "abstract" in dict: 374 abstract = dict['abstract'] 375 del dict['abstract'] 376 377 cls = super(RegOpMeta, mcls).__new__(mcls, Name, bases, dict) 378 if not abstract: 379 cls.className = Name 380 cls.base_mnemonic = name 381 code = cls.code 382 flag_code = cls.flag_code 383 cond_check = cls.cond_check 384 else_code = cls.else_code 385 386 # Set up the C++ classes 387 mcls.buildCppClasses(cls, name, Name, "", 388 code, flag_code, cond_check, else_code) 389 390 # Hook into the microassembler dict 391 global microopClasses 392 microopClasses[name] = cls 393 394 allCode = "|".join((code, flag_code, cond_check, else_code)) 395 396 # If op2 is used anywhere, make register and immediate versions 397 # of this code. 398 matcher = re.compile("op2(?P<typeQual>\\.\\w+)?") 399 if matcher.search(allCode): 400 microopClasses[name + 'i'] = cls 401 return cls 402 403 404 class RegOp(X86Microop): 405 __metaclass__ = RegOpMeta 406 # This class itself doesn't act as a microop 407 abstract = True 408 409 # Default template parameter values 410 flag_code = "" 411 cond_check = "true" 412 else_code = ";" 413 414 def __init__(self, dest, src1, op2, flags = None, dataSize = "env.dataSize"): 415 self.dest = dest 416 self.src1 = src1 417 self.op2 = op2 418 self.flags = flags 419 self.dataSize = dataSize 420 if flags is None: 421 self.ext = 0 422 else: 423 if not isinstance(flags, (list, tuple)): 424 raise Exception, "flags must be a list or tuple of flags" 425 self.ext = " | ".join(flags) 426 self.className += "Flags" 427 428 def getAllocator(self, *microFlags): 429 className = self.className 430 if self.mnemonic == self.base_mnemonic + 'i': 431 className += "Imm" 432 allocator = '''new %(class_name)s(machInst, mnemonic 433 %(flags)s, %(src1)s, %(op2)s, %(dest)s, 434 %(dataSize)s, %(ext)s)''' % { 435 "class_name" : className, 436 "flags" : self.microFlagsText(microFlags), 437 "src1" : self.src1, "op2" : self.op2, 438 "dest" : self.dest, 439 "dataSize" : self.dataSize, 440 "ext" : self.ext} 441 return allocator 442 443 class LogicRegOp(RegOp): 444 abstract = True 445 flag_code = ''' 446 //Don't have genFlags handle the OF or CF bits 447 uint64_t mask = CFBit | ECFBit | OFBit; 448 ccFlagBits = genFlags(ccFlagBits, ext & ~mask, DestReg, psrc1, op2); 449 //If a logic microop wants to set these, it wants to set them to 0. 450 ccFlagBits &= ~(CFBit & ext); 451 ccFlagBits &= ~(ECFBit & ext); 452 ccFlagBits &= ~(OFBit & ext); 453 ''' 454 455 class FlagRegOp(RegOp): 456 abstract = True 457 flag_code = \ 458 "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, op2);" 459 460 class SubRegOp(RegOp): 461 abstract = True 462 flag_code = \ 463 "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, ~op2, true);" 464 465 class CondRegOp(RegOp): 466 abstract = True 467 cond_check = "checkCondition(ccFlagBits, ext)" 468 469 class RdRegOp(RegOp): 470 abstract = True 471 def __init__(self, dest, src1=None, dataSize="env.dataSize"): 472 if not src1: 473 src1 = dest 474 super(RdRegOp, self).__init__(dest, src1, "NUM_INTREGS", None, dataSize) 475 476 class WrRegOp(RegOp): 477 abstract = True 478 def __init__(self, src1, src2, flags=None, dataSize="env.dataSize"): 479 super(WrRegOp, self).__init__("NUM_INTREGS", src1, src2, flags, dataSize) 480 481 class Add(FlagRegOp): 482 code = 'DestReg = merge(DestReg, psrc1 + op2, dataSize);' 483 484 class Or(LogicRegOp): 485 code = 'DestReg = merge(DestReg, psrc1 | op2, dataSize);' 486 487 class Adc(FlagRegOp): 488 code = ''' 489 CCFlagBits flags = ccFlagBits; 490 DestReg = merge(DestReg, psrc1 + op2 + flags.cf, dataSize); 491 ''' 492 493 class Sbb(SubRegOp): 494 code = ''' 495 CCFlagBits flags = ccFlagBits; 496 DestReg = merge(DestReg, psrc1 - op2 - flags.cf, dataSize); 497 ''' 498 499 class And(LogicRegOp): 500 code = 'DestReg = merge(DestReg, psrc1 & op2, dataSize)' 501 502 class Sub(SubRegOp): 503 code = 'DestReg = merge(DestReg, psrc1 - op2, dataSize)' 504 505 class Xor(LogicRegOp): 506 code = 'DestReg = merge(DestReg, psrc1 ^ op2, dataSize)' 507 508 # Neither of these is quite correct because it assumes that right shifting 509 # a signed or unsigned value does sign or zero extension respectively. 510 # The C standard says that what happens on a right shift with a 1 in the 511 # MSB position is undefined. On x86 and under likely most compilers the 512 # "right thing" happens, but this isn't a guarantee. 513 class Mul1s(WrRegOp): 514 code = ''' 515 ProdLow = psrc1 * op2; 516 int halfSize = (dataSize * 8) / 2; 517 int64_t spsrc1_h = spsrc1 >> halfSize; 518 int64_t spsrc1_l = spsrc1 & mask(halfSize); 519 int64_t spsrc2_h = sop2 >> halfSize; 520 int64_t spsrc2_l = sop2 & mask(halfSize); 521 ProdHi = ((spsrc1_l * spsrc2_h + spsrc1_h * spsrc2_l + 522 ((spsrc1_l * spsrc2_l) >> halfSize)) >> halfSize) + 523 spsrc1_h * spsrc2_h; 524 ''' 525 526 class Mul1u(WrRegOp): 527 code = ''' 528 ProdLow = psrc1 * op2; 529 int halfSize = (dataSize * 8) / 2; 530 uint64_t psrc1_h = psrc1 >> halfSize; 531 uint64_t psrc1_l = psrc1 & mask(halfSize); 532 uint64_t psrc2_h = op2 >> halfSize; 533 uint64_t psrc2_l = op2 & mask(halfSize); 534 ProdHi = ((psrc1_l * psrc2_h + psrc1_h * psrc2_l + 535 ((psrc1_l * psrc2_l) >> halfSize)) >> halfSize) + 536 psrc1_h * psrc2_h; 537 ''' 538 539 class Mulel(RdRegOp): 540 code = 'DestReg = merge(SrcReg1, ProdLow, dataSize);' 541 542 class Muleh(RdRegOp): 543 def __init__(self, dest, src1=None, flags=None, dataSize="env.dataSize"): 544 if not src1: 545 src1 = dest 546 super(RdRegOp, self).__init__(dest, src1, "NUM_INTREGS", flags, dataSize) 547 code = 'DestReg = merge(SrcReg1, ProdHi, dataSize);' 548 flag_code = ''' 549 if (ProdHi) 550 ccFlagBits = ccFlagBits | (ext & (CFBit | OFBit | ECFBit)); 551 else 552 ccFlagBits = ccFlagBits & ~(ext & (CFBit | OFBit | ECFBit)); 553 ''' 554 555 # One or two bit divide 556 class Div1(WrRegOp): 557 code = ''' 558 //These are temporaries so that modifying them later won't make 559 //the ISA parser think they're also sources. 560 uint64_t quotient = 0; 561 uint64_t remainder = psrc1; 562 //Similarly, this is a temporary so changing it doesn't make it 563 //a source. 564 uint64_t divisor = op2; 565 //This is a temporary just for consistency and clarity. 566 uint64_t dividend = remainder; 567 //Do the division. 568 divide(dividend, divisor, quotient, remainder); 569 //Record the final results. 570 Remainder = remainder; 571 Quotient = quotient; 572 Divisor = divisor; 573 ''' 574 575 # Step divide 576 class Div2(RegOp): 577 code = ''' 578 uint64_t dividend = Remainder; 579 uint64_t divisor = Divisor; 580 uint64_t quotient = Quotient; 581 uint64_t remainder = dividend; 582 int remaining = op2; 583 //If we overshot, do nothing. This lets us unrool division loops a 584 //little. 585 if (remaining) { 586 //Shift in bits from the low order portion of the dividend 587 while(dividend < divisor && remaining) { 588 dividend = (dividend << 1) | bits(SrcReg1, remaining - 1); 589 quotient <<= 1; 590 remaining--; 591 } 592 remainder = dividend; 593 //Do the division. 594 divide(dividend, divisor, quotient, remainder); 595 } 596 //Keep track of how many bits there are still to pull in. 597 DestReg = merge(DestReg, remaining, dataSize); 598 //Record the final results 599 Remainder = remainder; 600 Quotient = quotient; 601 ''' 602 flag_code = ''' 603 if (DestReg == 0) 604 ccFlagBits = ccFlagBits | (ext & EZFBit); 605 else 606 ccFlagBits = ccFlagBits & ~(ext & EZFBit); 607 ''' 608 609 class Divq(RdRegOp): 610 code = 'DestReg = merge(SrcReg1, Quotient, dataSize);' 611 612 class Divr(RdRegOp): 613 code = 'DestReg = merge(SrcReg1, Remainder, dataSize);' 614 615 class Mov(CondRegOp): 616 code = 'DestReg = merge(SrcReg1, op2, dataSize)' 617 else_code = 'DestReg=DestReg;' 618 619 # Shift instructions 620 621 class Sll(RegOp): 622 code = ''' 623 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 624 DestReg = merge(DestReg, psrc1 << shiftAmt, dataSize); 625 ''' 626 flag_code = ''' 627 // If the shift amount is zero, no flags should be modified. 628 if (shiftAmt) { 629 //Zero out any flags we might modify. This way we only have to 630 //worry about setting them. 631 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit)); 632 int CFBits = 0; 633 //Figure out if we -would- set the CF bits if requested. 634 if (bits(SrcReg1, dataSize * 8 - shiftAmt)) 635 CFBits = 1; 636 //If some combination of the CF bits need to be set, set them. 637 if ((ext & (CFBit | ECFBit)) && CFBits) 638 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit)); 639 //Figure out what the OF bit should be. 640 if ((ext & OFBit) && (CFBits ^ bits(DestReg, dataSize * 8 - 1))) 641 ccFlagBits = ccFlagBits | OFBit; 642 //Use the regular mechanisms to calculate the other flags. 643 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), 644 DestReg, psrc1, op2); 645 } 646 ''' 647 648 class Srl(RegOp): 649 code = ''' 650 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 651 // Because what happens to the bits shift -in- on a right shift 652 // is not defined in the C/C++ standard, we have to mask them out 653 // to be sure they're zero. 654 uint64_t logicalMask = mask(dataSize * 8 - shiftAmt); 655 DestReg = merge(DestReg, (psrc1 >> shiftAmt) & logicalMask, dataSize); 656 ''' 657 flag_code = ''' 658 // If the shift amount is zero, no flags should be modified. 659 if (shiftAmt) { 660 //Zero out any flags we might modify. This way we only have to 661 //worry about setting them. 662 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit)); 663 //If some combination of the CF bits need to be set, set them. 664 if ((ext & (CFBit | ECFBit)) && bits(SrcReg1, shiftAmt - 1)) 665 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit)); 666 //Figure out what the OF bit should be. 667 if ((ext & OFBit) && bits(SrcReg1, dataSize * 8 - 1)) 668 ccFlagBits = ccFlagBits | OFBit; 669 //Use the regular mechanisms to calculate the other flags. 670 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), 671 DestReg, psrc1, op2); 672 } 673 ''' 674 675 class Sra(RegOp): 676 code = ''' 677 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 678 // Because what happens to the bits shift -in- on a right shift 679 // is not defined in the C/C++ standard, we have to sign extend 680 // them manually to be sure. 681 uint64_t arithMask = 682 -bits(psrc1, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt); 683 DestReg = merge(DestReg, (psrc1 >> shiftAmt) | arithMask, dataSize); 684 ''' 685 flag_code = ''' 686 // If the shift amount is zero, no flags should be modified. 687 if (shiftAmt) { 688 //Zero out any flags we might modify. This way we only have to 689 //worry about setting them. 690 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit)); 691 //If some combination of the CF bits need to be set, set them. 692 if ((ext & (CFBit | ECFBit)) && bits(SrcReg1, shiftAmt - 1)) 693 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit)); 694 //Use the regular mechanisms to calculate the other flags. 695 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), 696 DestReg, psrc1, op2); 697 } 698 ''' 699 700 class Ror(RegOp): 701 code = ''' 702 uint8_t shiftAmt = 703 (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 704 if(shiftAmt) 705 { 706 uint64_t top = psrc1 << (dataSize * 8 - shiftAmt); 707 uint64_t bottom = bits(psrc1, dataSize * 8, shiftAmt); 708 DestReg = merge(DestReg, top | bottom, dataSize); 709 } 710 else 711 DestReg = DestReg; 712 ''' 713 flag_code = ''' 714 // If the shift amount is zero, no flags should be modified. 715 if (shiftAmt) { 716 //Zero out any flags we might modify. This way we only have to 717 //worry about setting them. 718 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit)); 719 //Find the most and second most significant bits of the result. 720 int msb = bits(DestReg, dataSize * 8 - 1); 721 int smsb = bits(DestReg, dataSize * 8 - 2); 722 //If some combination of the CF bits need to be set, set them. 723 if ((ext & (CFBit | ECFBit)) && msb) 724 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit)); 725 //Figure out what the OF bit should be. 726 if ((ext & OFBit) && (msb ^ smsb)) 727 ccFlagBits = ccFlagBits | OFBit; 728 //Use the regular mechanisms to calculate the other flags. 729 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), 730 DestReg, psrc1, op2); 731 } 732 ''' 733 734 class Rcr(RegOp): 735 code = ''' 736 uint8_t shiftAmt = 737 (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 738 if(shiftAmt) 739 { 740 CCFlagBits flags = ccFlagBits; 741 uint64_t top = flags.cf << (dataSize * 8 - shiftAmt); 742 if(shiftAmt > 1) 743 top |= psrc1 << (dataSize * 8 - shiftAmt - 1); 744 uint64_t bottom = bits(psrc1, dataSize * 8, shiftAmt); 745 DestReg = merge(DestReg, top | bottom, dataSize); 746 } 747 else 748 DestReg = DestReg; 749 ''' 750 flag_code = ''' 751 // If the shift amount is zero, no flags should be modified. 752 if (shiftAmt) { 753 //Zero out any flags we might modify. This way we only have to 754 //worry about setting them. 755 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit)); 756 //Figure out what the OF bit should be. 757 if ((ext & OFBit) && ((ccFlagBits & CFBit) ^ 758 bits(SrcReg1, dataSize * 8 - 1))) 759 ccFlagBits = ccFlagBits | OFBit; 760 //If some combination of the CF bits need to be set, set them. 761 if ((ext & (CFBit | ECFBit)) && bits(SrcReg1, shiftAmt - 1)) 762 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit)); 763 //Use the regular mechanisms to calculate the other flags. 764 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), 765 DestReg, psrc1, op2); 766 } 767 ''' 768 769 class Rol(RegOp): 770 code = ''' 771 uint8_t shiftAmt = 772 (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 773 if(shiftAmt) 774 { 775 uint64_t top = psrc1 << shiftAmt; 776 uint64_t bottom = 777 bits(psrc1, dataSize * 8 - 1, dataSize * 8 - shiftAmt); 778 DestReg = merge(DestReg, top | bottom, dataSize); 779 } 780 else 781 DestReg = DestReg; 782 ''' 783 flag_code = ''' 784 // If the shift amount is zero, no flags should be modified. 785 if (shiftAmt) { 786 //Zero out any flags we might modify. This way we only have to 787 //worry about setting them. 788 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit)); 789 //The CF bits, if set, would be set to the lsb of the result. 790 int lsb = DestReg & 0x1; 791 int msb = bits(DestReg, dataSize * 8 - 1); 792 //If some combination of the CF bits need to be set, set them. 793 if ((ext & (CFBit | ECFBit)) && lsb) 794 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit)); 795 //Figure out what the OF bit should be. 796 if ((ext & OFBit) && (msb ^ lsb)) 797 ccFlagBits = ccFlagBits | OFBit; 798 //Use the regular mechanisms to calculate the other flags. 799 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), 800 DestReg, psrc1, op2); 801 } 802 ''' 803 804 class Rcl(RegOp): 805 code = ''' 806 uint8_t shiftAmt = 807 (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 808 if(shiftAmt) 809 { 810 CCFlagBits flags = ccFlagBits; 811 uint64_t top = psrc1 << shiftAmt; 812 uint64_t bottom = flags.cf << (shiftAmt - 1); 813 if(shiftAmt > 1) 814 bottom |= 815 bits(psrc1, dataSize * 8 - 1, 816 dataSize * 8 - shiftAmt + 1); 817 DestReg = merge(DestReg, top | bottom, dataSize); 818 } 819 else 820 DestReg = DestReg; 821 ''' 822 flag_code = ''' 823 // If the shift amount is zero, no flags should be modified. 824 if (shiftAmt) { 825 //Zero out any flags we might modify. This way we only have to 826 //worry about setting them. 827 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit)); 828 int msb = bits(DestReg, dataSize * 8 - 1); 829 int CFBits = bits(SrcReg1, dataSize * 8 - shiftAmt); 830 //If some combination of the CF bits need to be set, set them. 831 if ((ext & (CFBit | ECFBit)) && CFBits) 832 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit)); 833 //Figure out what the OF bit should be. 834 if ((ext & OFBit) && (msb ^ CFBits)) 835 ccFlagBits = ccFlagBits | OFBit; 836 //Use the regular mechanisms to calculate the other flags. 837 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), 838 DestReg, psrc1, op2); 839 } 840 ''' 841 842 class Wrip(WrRegOp, CondRegOp): 843 code = 'RIP = psrc1 + sop2 + CSBase' 844 else_code="RIP = RIP;" 845 846 class Br(WrRegOp, CondRegOp): 847 code = 'nuIP = psrc1 + op2;' 848 else_code='nuIP = nuIP;' 849 850 class Wruflags(WrRegOp): 851 code = 'ccFlagBits = psrc1 ^ op2' 852 853 class Wrflags(WrRegOp): 854 code = ''' 855 MiscReg newFlags = psrc1 ^ op2; 856 MiscReg userFlagMask = 0xDD5; 857 // Get only the user flags 858 ccFlagBits = newFlags & userFlagMask; 859 // Get everything else 860 nccFlagBits = newFlags & ~userFlagMask; 861 ''' 862 863 class Rdip(RdRegOp): 864 code = 'DestReg = RIP - CSBase' 865 866 class Ruflags(RdRegOp): 867 code = 'DestReg = ccFlagBits' 868 869 class Rflags(RdRegOp): 870 code = 'DestReg = ccFlagBits | nccFlagBits' 871 872 class Ruflag(RegOp): 873 code = ''' 874 int flag = bits(ccFlagBits, imm8); 875 DestReg = merge(DestReg, flag, dataSize); 876 ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) : 877 (ccFlagBits & ~EZFBit); 878 ''' 879 def __init__(self, dest, imm, flags=None, \ 880 dataSize="env.dataSize"): 881 super(Ruflag, self).__init__(dest, \ 882 "NUM_INTREGS", imm, flags, dataSize) 883 884 class Rflag(RegOp): 885 code = ''' 886 MiscReg flagMask = 0x3F7FDD5; 887 MiscReg flags = (nccFlagBits | ccFlagBits) & flagMask; 888 int flag = bits(flags, imm8); 889 DestReg = merge(DestReg, flag, dataSize); 890 ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) : 891 (ccFlagBits & ~EZFBit); 892 ''' 893 def __init__(self, dest, imm, flags=None, \ 894 dataSize="env.dataSize"): 895 super(Rflag, self).__init__(dest, \ 896 "NUM_INTREGS", imm, flags, dataSize) 897 898 class Sext(RegOp): 899 code = ''' 900 IntReg val = psrc1; 901 // Mask the bit position so that it wraps. 902 int bitPos = op2 & (dataSize * 8 - 1); 903 int sign_bit = bits(val, bitPos, bitPos); 904 uint64_t maskVal = mask(bitPos+1); 905 val = sign_bit ? (val | ~maskVal) : (val & maskVal); 906 DestReg = merge(DestReg, val, dataSize); 907 ''' 908 flag_code = ''' 909 if (!sign_bit) 910 ccFlagBits = ccFlagBits & 911 ~(ext & (CFBit | ECFBit | ZFBit | EZFBit)); 912 else 913 ccFlagBits = ccFlagBits | 914 (ext & (CFBit | ECFBit | ZFBit | EZFBit)); 915 ''' 916 917 class Zext(RegOp): 918 code = 'DestReg = bits(psrc1, op2, 0);' 919 920 class Rdcr(RegOp): 921 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 922 super(Rdcr, self).__init__(dest, \ 923 src1, "NUM_INTREGS", flags, dataSize) 924 code = ''' 925 if (dest == 1 || (dest > 4 && dest < 8) || (dest > 8)) { 926 fault = new InvalidOpcode(); 927 } else { 928 DestReg = ControlSrc1; 929 } 930 ''' 931 932 class Wrcr(RegOp): 933 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 934 super(Wrcr, self).__init__(dest, \ 935 src1, "NUM_INTREGS", flags, dataSize) 936 code = ''' 937 if (dest == 1 || (dest > 4 && dest < 8) || (dest > 8)) { 938 fault = new InvalidOpcode(); 939 } else { 940 // There are *s in the line below so it doesn't confuse the 941 // parser. They may be unnecessary. 942 //Mis*cReg old*Val = pick(Cont*rolDest, 0, dat*aSize); 943 MiscReg newVal = psrc1; 944 945 // Check for any modifications that would cause a fault. 946 switch(dest) { 947 case 0: 948 { 949 Efer efer = EferOp; 950 CR0 cr0 = newVal; 951 CR4 oldCr4 = CR4Op; 952 if (bits(newVal, 63, 32) || 953 (!cr0.pe && cr0.pg) || 954 (!cr0.cd && cr0.nw) || 955 (cr0.pg && efer.lme && !oldCr4.pae)) 956 fault = new GeneralProtection(0); 957 } 958 break; 959 case 2: 960 break; 961 case 3: 962 break; 963 case 4: 964 { 965 CR4 cr4 = newVal; 966 // PAE can't be disabled in long mode. 967 if (bits(newVal, 63, 11) || 968 (machInst.mode.mode == LongMode && !cr4.pae)) 969 fault = new GeneralProtection(0); 970 } 971 break; 972 case 8: 973 { 974 if (bits(newVal, 63, 4)) 975 fault = new GeneralProtection(0); 976 } 977 default: 978 panic("Unrecognized control register %d.\\n", dest); 979 } 980 ControlDest = newVal; 981 } 982 ''' 983 984 # Microops for manipulating segmentation registers 985 class SegOp(RegOp): 986 abstract = True 987 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 988 super(SegOp, self).__init__(dest, \ 989 src1, "NUM_INTREGS", flags, dataSize) 990 991 class Wrbase(SegOp): 992 code = ''' 993 SegBaseDest = psrc1; 994 ''' 995 996 class Wrlimit(SegOp): 997 code = ''' 998 SegLimitDest = psrc1; 999 ''' 1000 1001 class Wrsel(SegOp): 1002 code = ''' 1003 SegSelDest = psrc1; 1004 ''' 1005 1006 class Rdbase(SegOp): 1007 code = ''' 1008 DestReg = SegBaseDest; 1009 ''' 1010 1011 class Rdlimit(SegOp): 1012 code = ''' 1013 DestReg = SegLimitSrc1; 1014 ''' 1015 1016 class RdAttr(SegOp): 1017 code = ''' 1018 DestReg = SegAttrSrc1; 1019 ''' 1020 1021 class Rdsel(SegOp): 1022 code = ''' 1023 DestReg = SegSelSrc1; 1024 ''' 1025 1026 class Chks(RegOp): 1027 def __init__(self, dest, src1, src2=0, 1028 flags=None, dataSize="env.dataSize"): 1029 super(Chks, self).__init__(dest, 1030 src1, src2, flags, dataSize) 1031 code = ''' 1032 // The selector is in source 1 and can be at most 16 bits. 1033 SegSelector selector = DestReg; 1034 SegDescriptor desc = SrcReg1; 1035 HandyM5Reg m5reg = M5Reg; 1036 1037 switch (imm8) 1038 { 1039 case SegNoCheck: 1040 break; 1041 case SegCSCheck: 1042 panic("CS checks for far calls/jumps not implemented.\\n"); 1043 break; 1044 case SegCallGateCheck: 1045 panic("CS checks for far calls/jumps through call gates" 1046 "not implemented.\\n"); 1047 break; 1048 case SegSSCheck: 1049 if (selector.si || selector.ti) { 1050 if (!desc.p) { 1051 //FIXME This needs to also push the selector. 1052 return new StackFault; 1053 } 1054 } else { 1055 if ((m5reg.mode != SixtyFourBitMode || m5reg.cpl == 3) || 1056 !(desc.s == 1 && 1057 desc.type.codeOrData == 0 && desc.type.w) || 1058 (desc.dpl != m5reg.cpl) || 1059 (selector.rpl != m5reg.cpl)) { 1060 return new GeneralProtection(psrc1 & 0xFFFF); 1061 } 1062 } 1063 break; 1064 case SegIretCheck: 1065 { 1066 if ((!selector.si && !selector.ti) || 1067 (selector.rpl < m5reg.cpl) || 1068 !(desc.s == 1 && desc.type.codeOrData == 1) || 1069 (!desc.type.c && desc.dpl != selector.rpl) || 1070 (desc.type.c && desc.dpl > selector.rpl)) 1071 return new GeneralProtection(psrc1 & 0xFFFF); 1072 if (!desc.p) 1073 return new SegmentNotPresent; 1074 break; 1075 } 1076 case SegIntCSCheck: 1077 panic("CS selector checks for interrupts and exceptions" 1078 "not implemented.\\n"); 1079 break; 1080 default: 1081 panic("Undefined segment check type.\\n"); 1082 } 1083 ''' 1084 flag_code = ''' 1085 // Check for a NULL selector and set ZF,EZF appropriately. 1086 ccFlagBits = ccFlagBits & ~(ext & (ZFBit | EZFBit)); 1087 if (!selector.si && !selector.ti) 1088 ccFlagBits = ccFlagBits | (ext & (ZFBit | EZFBit)); 1089 ''' 1090 1091 class Wrdh(RegOp): 1092 code = ''' 1093 1094 ''' 1095 1096 class Wrtsc(WrRegOp): 1097 code = ''' 1098 TscOp = psrc1; 1099 ''' 1100 1101 class Rdtsc(RdRegOp): 1102 code = ''' 1103 DestReg = TscOp; 1104 ''' 1105 1106 class Rdm5reg(RdRegOp): 1107 code = ''' 1108 DestReg = M5Reg; 1109 ''' 1110 1111 class Wrdl(RegOp): 1112 code = ''' 1113 SegDescriptor desc = SrcReg1; 1114 SegSelector selector = SrcReg2; 1115 if (selector.si || selector.ti) { 1116 SegAttr attr = 0; 1117 attr.dpl = desc.dpl; 1118 attr.defaultSize = desc.d; 1119 if (!desc.s) { 1120 SegBaseDest = SegBaseDest; 1121 SegLimitDest = SegLimitDest; 1122 SegAttrDest = SegAttrDest; 1123 panic("System segment encountered.\\n"); 1124 } else { 1125 if (!desc.p) 1126 panic("Segment not present.\\n"); 1127 if (desc.type.codeOrData) { 1128 attr.readable = desc.type.r; 1129 attr.longMode = desc.l; 1130 } else { 1131 attr.expandDown = desc.type.e; 1132 attr.readable = 1; 1133 attr.writable = desc.type.w; 1134 } 1135 Addr base = desc.baseLow | (desc.baseHigh << 24); 1136 Addr limit = desc.limitLow | (desc.limitHigh << 16); 1137 if (desc.g) 1138 limit = (limit << 12) | mask(12); 1139 SegBaseDest = base; 1140 SegLimitDest = limit; 1141 SegAttrDest = attr; 1142 } 1143 } else { 1144 SegBaseDest = SegBaseDest; 1145 SegLimitDest = SegLimitDest; 1146 SegAttrDest = SegAttrDest; 1147 } 1148 ''' 1149}}; 1150