regop.isa revision 9896
1// Copyright (c) 2007-2008 The Hewlett-Packard Development Company 2// All rights reserved. 3// 4// The license below extends only to copyright in the software and shall 5// not be construed as granting a license to any other intellectual 6// property including but not limited to intellectual property relating 7// to a hardware implementation of the functionality of the software 8// licensed hereunder. You may use the software subject to the license 9// terms below provided that you ensure that this notice is replicated 10// unmodified and in its entirety in all distributions of the software, 11// modified or unmodified, in source code or in binary form. 12// 13// Redistribution and use in source and binary forms, with or without 14// modification, are permitted provided that the following conditions are 15// met: redistributions of source code must retain the above copyright 16// notice, this list of conditions and the following disclaimer; 17// redistributions in binary form must reproduce the above copyright 18// notice, this list of conditions and the following disclaimer in the 19// documentation and/or other materials provided with the distribution; 20// neither the name of the copyright holders nor the names of its 21// contributors may be used to endorse or promote products derived from 22// this software without specific prior written permission. 23// 24// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 30// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35// 36// Authors: Gabe Black 37 38////////////////////////////////////////////////////////////////////////// 39// 40// RegOp Microop templates 41// 42////////////////////////////////////////////////////////////////////////// 43 44def template MicroRegOpExecute {{ 45 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 46 Trace::InstRecord *traceData) const 47 { 48 Fault fault = NoFault; 49 50 DPRINTF(X86, "The data size is %d\n", dataSize); 51 %(op_decl)s; 52 %(op_rd)s; 53 54 IntReg result M5_VAR_USED; 55 56 if(%(cond_check)s) 57 { 58 %(code)s; 59 %(flag_code)s; 60 } 61 else 62 { 63 %(else_code)s; 64 } 65 66 //Write the resulting state to the execution context 67 if(fault == NoFault) 68 { 69 %(op_wb)s; 70 } 71 return fault; 72 } 73}}; 74 75def template MicroRegOpImmExecute {{ 76 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 77 Trace::InstRecord *traceData) const 78 { 79 Fault fault = NoFault; 80 81 %(op_decl)s; 82 %(op_rd)s; 83 84 IntReg result M5_VAR_USED; 85 86 if(%(cond_check)s) 87 { 88 %(code)s; 89 %(flag_code)s; 90 } 91 else 92 { 93 %(else_code)s; 94 } 95 96 //Write the resulting state to the execution context 97 if(fault == NoFault) 98 { 99 %(op_wb)s; 100 } 101 return fault; 102 } 103}}; 104 105def template MicroRegOpDeclare {{ 106 class %(class_name)s : public %(base_class)s 107 { 108 public: 109 %(class_name)s(ExtMachInst _machInst, 110 const char * instMnem, uint64_t setFlags, 111 InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest, 112 uint8_t _dataSize, uint16_t _ext); 113 114 %(BasicExecDeclare)s 115 }; 116}}; 117 118def template MicroRegOpImmDeclare {{ 119 120 class %(class_name)s : public %(base_class)s 121 { 122 public: 123 %(class_name)s(ExtMachInst _machInst, 124 const char * instMnem, uint64_t setFlags, 125 InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest, 126 uint8_t _dataSize, uint16_t _ext); 127 128 %(BasicExecDeclare)s 129 }; 130}}; 131 132def template MicroRegOpConstructor {{ 133 inline %(class_name)s::%(class_name)s( 134 ExtMachInst machInst, const char * instMnem, uint64_t setFlags, 135 InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest, 136 uint8_t _dataSize, uint16_t _ext) : 137 %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags, 138 _src1, _src2, _dest, _dataSize, _ext, 139 %(op_class)s) 140 { 141 %(constructor)s; 142 %(cond_control_flag_init)s; 143 } 144}}; 145 146def template MicroRegOpImmConstructor {{ 147 inline %(class_name)s::%(class_name)s( 148 ExtMachInst machInst, const char * instMnem, uint64_t setFlags, 149 InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest, 150 uint8_t _dataSize, uint16_t _ext) : 151 %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags, 152 _src1, _imm8, _dest, _dataSize, _ext, 153 %(op_class)s) 154 { 155 %(constructor)s; 156 %(cond_control_flag_init)s; 157 } 158}}; 159 160output header {{ 161 void 162 divide(uint64_t dividend, uint64_t divisor, 163 uint64_t "ient, uint64_t &remainder); 164 165 enum SegmentSelectorCheck { 166 SegNoCheck, SegCSCheck, SegCallGateCheck, SegIntGateCheck, 167 SegSoftIntGateCheck, SegSSCheck, SegIretCheck, SegIntCSCheck, 168 SegTRCheck, SegTSSCheck, SegInGDTCheck, SegLDTCheck 169 }; 170 171 enum LongModeDescriptorType { 172 LDT64 = 2, 173 AvailableTSS64 = 9, 174 BusyTSS64 = 0xb, 175 CallGate64 = 0xc, 176 IntGate64 = 0xe, 177 TrapGate64 = 0xf 178 }; 179}}; 180 181output decoder {{ 182 void 183 divide(uint64_t dividend, uint64_t divisor, 184 uint64_t "ient, uint64_t &remainder) 185 { 186 //Check for divide by zero. 187 assert(divisor != 0); 188 //If the divisor is bigger than the dividend, don't do anything. 189 if (divisor <= dividend) { 190 //Shift the divisor so it's msb lines up with the dividend. 191 int dividendMsb = findMsbSet(dividend); 192 int divisorMsb = findMsbSet(divisor); 193 int shift = dividendMsb - divisorMsb; 194 divisor <<= shift; 195 //Compute what we'll add to the quotient if the divisor isn't 196 //now larger than the dividend. 197 uint64_t quotientBit = 1; 198 quotientBit <<= shift; 199 //If we need to step back a bit (no pun intended) because the 200 //divisor got too to large, do that here. This is the "or two" 201 //part of one or two bit division. 202 if (divisor > dividend) { 203 quotientBit >>= 1; 204 divisor >>= 1; 205 } 206 //Decrement the remainder and increment the quotient. 207 quotient += quotientBit; 208 remainder -= divisor; 209 } 210 } 211}}; 212 213let {{ 214 # Make these empty strings so that concatenating onto 215 # them will always work. 216 header_output = "" 217 decoder_output = "" 218 exec_output = "" 219 220 immTemplates = ( 221 MicroRegOpImmDeclare, 222 MicroRegOpImmConstructor, 223 MicroRegOpImmExecute) 224 225 regTemplates = ( 226 MicroRegOpDeclare, 227 MicroRegOpConstructor, 228 MicroRegOpExecute) 229 230 class RegOpMeta(type): 231 def buildCppClasses(self, name, Name, suffix, code, big_code, \ 232 flag_code, cond_check, else_code, cond_control_flag_init, 233 op_class): 234 235 # Globals to stick the output in 236 global header_output 237 global decoder_output 238 global exec_output 239 240 # Stick all the code together so it can be searched at once 241 allCode = "|".join((code, flag_code, cond_check, else_code, 242 cond_control_flag_init)) 243 allBigCode = "|".join((big_code, flag_code, cond_check, else_code, 244 cond_control_flag_init)) 245 246 # If op2 is used anywhere, make register and immediate versions 247 # of this code. 248 matcher = re.compile(r"(?<!\w)(?P<prefix>s?)op2(?P<typeQual>_[^\W_]+)?") 249 match = matcher.search(allCode + allBigCode) 250 if match: 251 typeQual = "" 252 if match.group("typeQual"): 253 typeQual = match.group("typeQual") 254 src2_name = "%spsrc2%s" % (match.group("prefix"), typeQual) 255 self.buildCppClasses(name, Name, suffix, 256 matcher.sub(src2_name, code), 257 matcher.sub(src2_name, big_code), 258 matcher.sub(src2_name, flag_code), 259 matcher.sub(src2_name, cond_check), 260 matcher.sub(src2_name, else_code), 261 matcher.sub(src2_name, cond_control_flag_init), 262 op_class) 263 imm_name = "%simm8" % match.group("prefix") 264 self.buildCppClasses(name + "i", Name, suffix + "Imm", 265 matcher.sub(imm_name, code), 266 matcher.sub(imm_name, big_code), 267 matcher.sub(imm_name, flag_code), 268 matcher.sub(imm_name, cond_check), 269 matcher.sub(imm_name, else_code), 270 matcher.sub(imm_name, cond_control_flag_init), 271 op_class) 272 return 273 274 # If there's something optional to do with flags, generate 275 # a version without it and fix up this version to use it. 276 if flag_code != "" or cond_check != "true": 277 self.buildCppClasses(name, Name, suffix, 278 code, big_code, "", "true", else_code, "", op_class) 279 suffix = "Flags" + suffix 280 281 # If psrc1 or psrc2 is used, we need to actually insert code to 282 # compute it. 283 for (big, all) in ((False, allCode), (True, allBigCode)): 284 prefix = "" 285 for (rex, decl) in ( 286 ("(?<!\w)psrc1(?!\w)", 287 "uint64_t psrc1 = pick(SrcReg1, 0, dataSize);"), 288 ("(?<!\w)psrc2(?!\w)", 289 "uint64_t psrc2 = pick(SrcReg2, 1, dataSize);"), 290 ("(?<!\w)spsrc1(?!\w)", 291 "int64_t spsrc1 = signedPick(SrcReg1, 0, dataSize);"), 292 ("(?<!\w)spsrc2(?!\w)", 293 "int64_t spsrc2 = signedPick(SrcReg2, 1, dataSize);"), 294 ("(?<!\w)simm8(?!\w)", 295 "int8_t simm8 = imm8;")): 296 matcher = re.compile(rex) 297 if matcher.search(all): 298 prefix += decl + "\n" 299 if big: 300 if big_code != "": 301 big_code = prefix + big_code 302 else: 303 code = prefix + code 304 305 base = "X86ISA::RegOp" 306 307 # If imm8 shows up in the code, use the immediate templates, if 308 # not, hopefully the register ones will be correct. 309 templates = regTemplates 310 matcher = re.compile("(?<!\w)s?imm8(?!\w)") 311 if matcher.search(allCode): 312 base += "Imm" 313 templates = immTemplates 314 315 # Get everything ready for the substitution 316 iops = [InstObjParams(name, Name + suffix, base, 317 {"code" : code, 318 "flag_code" : flag_code, 319 "cond_check" : cond_check, 320 "else_code" : else_code, 321 "cond_control_flag_init" : cond_control_flag_init, 322 "op_class" : op_class})] 323 if big_code != "": 324 iops += [InstObjParams(name, Name + suffix + "Big", base, 325 {"code" : big_code, 326 "flag_code" : flag_code, 327 "cond_check" : cond_check, 328 "else_code" : else_code, 329 "cond_control_flag_init" : cond_control_flag_init, 330 "op_class" : op_class})] 331 332 # Generate the actual code (finally!) 333 for iop in iops: 334 header_output += templates[0].subst(iop) 335 decoder_output += templates[1].subst(iop) 336 exec_output += templates[2].subst(iop) 337 338 339 def __new__(mcls, Name, bases, dict): 340 abstract = False 341 name = Name.lower() 342 if "abstract" in dict: 343 abstract = dict['abstract'] 344 del dict['abstract'] 345 346 cls = super(RegOpMeta, mcls).__new__(mcls, Name, bases, dict) 347 if not abstract: 348 cls.className = Name 349 cls.base_mnemonic = name 350 code = cls.code 351 big_code = cls.big_code 352 flag_code = cls.flag_code 353 cond_check = cls.cond_check 354 else_code = cls.else_code 355 cond_control_flag_init = cls.cond_control_flag_init 356 op_class = cls.op_class 357 358 # Set up the C++ classes 359 mcls.buildCppClasses(cls, name, Name, "", code, big_code, 360 flag_code, cond_check, else_code, 361 cond_control_flag_init, op_class) 362 363 # Hook into the microassembler dict 364 global microopClasses 365 microopClasses[name] = cls 366 367 allCode = "|".join((code, flag_code, cond_check, else_code, 368 cond_control_flag_init)) 369 370 # If op2 is used anywhere, make register and immediate versions 371 # of this code. 372 matcher = re.compile(r"op2(?P<typeQual>_[^\W_]+)?") 373 if matcher.search(allCode): 374 microopClasses[name + 'i'] = cls 375 return cls 376 377 378 class RegOp(X86Microop): 379 __metaclass__ = RegOpMeta 380 # This class itself doesn't act as a microop 381 abstract = True 382 383 # Default template parameter values 384 big_code = "" 385 flag_code = "" 386 cond_check = "true" 387 else_code = ";" 388 cond_control_flag_init = "" 389 op_class = "IntAluOp" 390 391 def __init__(self, dest, src1, op2, flags = None, dataSize = "env.dataSize"): 392 self.dest = dest 393 self.src1 = src1 394 self.op2 = op2 395 self.flags = flags 396 self.dataSize = dataSize 397 if flags is None: 398 self.ext = 0 399 else: 400 if not isinstance(flags, (list, tuple)): 401 raise Exception, "flags must be a list or tuple of flags" 402 self.ext = " | ".join(flags) 403 self.className += "Flags" 404 405 def getAllocator(self, microFlags): 406 if self.big_code != "": 407 className = self.className 408 if self.mnemonic == self.base_mnemonic + 'i': 409 className += "Imm" 410 allocString = ''' 411 (%(dataSize)s >= 4) ? 412 (StaticInstPtr)(new %(class_name)sBig(machInst, 413 macrocodeBlock, %(flags)s, %(src1)s, %(op2)s, 414 %(dest)s, %(dataSize)s, %(ext)s)) : 415 (StaticInstPtr)(new %(class_name)s(machInst, 416 macrocodeBlock, %(flags)s, %(src1)s, %(op2)s, 417 %(dest)s, %(dataSize)s, %(ext)s)) 418 ''' 419 allocator = allocString % { 420 "class_name" : className, 421 "flags" : self.microFlagsText(microFlags), 422 "src1" : self.src1, "op2" : self.op2, 423 "dest" : self.dest, 424 "dataSize" : self.dataSize, 425 "ext" : self.ext} 426 return allocator 427 else: 428 className = self.className 429 if self.mnemonic == self.base_mnemonic + 'i': 430 className += "Imm" 431 allocator = '''new %(class_name)s(machInst, macrocodeBlock, 432 %(flags)s, %(src1)s, %(op2)s, %(dest)s, 433 %(dataSize)s, %(ext)s)''' % { 434 "class_name" : className, 435 "flags" : self.microFlagsText(microFlags), 436 "src1" : self.src1, "op2" : self.op2, 437 "dest" : self.dest, 438 "dataSize" : self.dataSize, 439 "ext" : self.ext} 440 return allocator 441 442 class LogicRegOp(RegOp): 443 abstract = True 444 flag_code = ''' 445 //Don't have genFlags handle the OF or CF bits 446 uint64_t mask = CFBit | ECFBit | OFBit; 447 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 448 PredezfBit, ext & ~mask, result, psrc1, op2); 449 PredezfBit = newFlags & EZFBit; 450 PreddfBit = newFlags & DFBit; 451 PredccFlagBits = newFlags & ccFlagMask; 452 453 //If a logic microop wants to set these, it wants to set them to 0. 454 PredcfofBits = PredcfofBits & ~((CFBit | OFBit) & ext); 455 PredecfBit = PredecfBit & ~(ECFBit & ext); 456 ''' 457 458 class FlagRegOp(RegOp): 459 abstract = True 460 flag_code = ''' 461 uint64_t newFlags = genFlags(PredccFlagBits | PredcfofBits | 462 PreddfBit | PredecfBit | PredezfBit, 463 ext, result, psrc1, op2); 464 465 PredcfofBits = newFlags & cfofMask; 466 PredecfBit = newFlags & ECFBit; 467 PredezfBit = newFlags & EZFBit; 468 PreddfBit = newFlags & DFBit; 469 PredccFlagBits = newFlags & ccFlagMask; 470 ''' 471 472 class SubRegOp(RegOp): 473 abstract = True 474 flag_code = ''' 475 uint64_t newFlags = genFlags(PredccFlagBits | PredcfofBits | 476 PreddfBit | PredecfBit | PredezfBit, 477 ext, result, psrc1, ~op2, true); 478 479 PredcfofBits = newFlags & cfofMask; 480 PredecfBit = newFlags & ECFBit; 481 PredezfBit = newFlags & EZFBit; 482 PreddfBit = newFlags & DFBit; 483 PredccFlagBits = newFlags & ccFlagMask; 484 ''' 485 486 class CondRegOp(RegOp): 487 abstract = True 488 cond_check = "checkCondition(ccFlagBits | cfofBits | dfBit | ecfBit | \ 489 ezfBit, ext)" 490 cond_control_flag_init = "flags[IsCondControl] = flags[IsControl];" 491 492 class RdRegOp(RegOp): 493 abstract = True 494 def __init__(self, dest, src1=None, dataSize="env.dataSize"): 495 if not src1: 496 src1 = dest 497 super(RdRegOp, self).__init__(dest, src1, \ 498 "InstRegIndex(NUM_INTREGS)", None, dataSize) 499 500 class WrRegOp(RegOp): 501 abstract = True 502 def __init__(self, src1, src2, flags=None, dataSize="env.dataSize"): 503 super(WrRegOp, self).__init__("InstRegIndex(NUM_INTREGS)", \ 504 src1, src2, flags, dataSize) 505 506 class Add(FlagRegOp): 507 code = 'DestReg = merge(DestReg, result = (psrc1 + op2), dataSize);' 508 big_code = 'DestReg = result = (psrc1 + op2) & mask(dataSize * 8);' 509 510 class Or(LogicRegOp): 511 code = 'DestReg = merge(DestReg, result = (psrc1 | op2), dataSize);' 512 big_code = 'DestReg = result = (psrc1 | op2) & mask(dataSize * 8);' 513 514 class Adc(FlagRegOp): 515 code = ''' 516 CCFlagBits flags = cfofBits; 517 DestReg = merge(DestReg, result = (psrc1 + op2 + flags.cf), dataSize); 518 ''' 519 big_code = ''' 520 CCFlagBits flags = cfofBits; 521 DestReg = result = (psrc1 + op2 + flags.cf) & mask(dataSize * 8); 522 ''' 523 524 class Sbb(SubRegOp): 525 code = ''' 526 CCFlagBits flags = cfofBits; 527 DestReg = merge(DestReg, result = (psrc1 - op2 - flags.cf), dataSize); 528 ''' 529 big_code = ''' 530 CCFlagBits flags = cfofBits; 531 DestReg = result = (psrc1 - op2 - flags.cf) & mask(dataSize * 8); 532 ''' 533 534 class And(LogicRegOp): 535 code = 'DestReg = merge(DestReg, result = (psrc1 & op2), dataSize)' 536 big_code = 'DestReg = result = (psrc1 & op2) & mask(dataSize * 8)' 537 538 class Sub(SubRegOp): 539 code = 'DestReg = merge(DestReg, result = (psrc1 - op2), dataSize)' 540 big_code = 'DestReg = result = (psrc1 - op2) & mask(dataSize * 8)' 541 542 class Xor(LogicRegOp): 543 code = 'DestReg = merge(DestReg, result = (psrc1 ^ op2), dataSize)' 544 big_code = 'DestReg = result = (psrc1 ^ op2) & mask(dataSize * 8)' 545 546 class Mul1s(WrRegOp): 547 op_class = 'IntMultOp' 548 549 code = ''' 550 ProdLow = psrc1 * op2; 551 int halfSize = (dataSize * 8) / 2; 552 uint64_t shifter = (ULL(1) << halfSize); 553 uint64_t hiResult; 554 uint64_t psrc1_h = psrc1 / shifter; 555 uint64_t psrc1_l = psrc1 & mask(halfSize); 556 uint64_t psrc2_h = (op2 / shifter) & mask(halfSize); 557 uint64_t psrc2_l = op2 & mask(halfSize); 558 hiResult = ((psrc1_l * psrc2_h + psrc1_h * psrc2_l + 559 ((psrc1_l * psrc2_l) / shifter)) /shifter) + 560 psrc1_h * psrc2_h; 561 if (bits(psrc1, dataSize * 8 - 1)) 562 hiResult -= op2; 563 if (bits(op2, dataSize * 8 - 1)) 564 hiResult -= psrc1; 565 ProdHi = hiResult; 566 ''' 567 flag_code = ''' 568 if ((-ProdHi & mask(dataSize * 8)) != 569 bits(ProdLow, dataSize * 8 - 1)) { 570 PredcfofBits = PredcfofBits | (ext & (CFBit | OFBit)); 571 PredecfBit = PredecfBit | (ext & ECFBit); 572 } else { 573 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 574 PredecfBit = PredecfBit & ~(ext & ECFBit); 575 } 576 ''' 577 578 class Mul1u(WrRegOp): 579 op_class = 'IntMultOp' 580 581 code = ''' 582 ProdLow = psrc1 * op2; 583 int halfSize = (dataSize * 8) / 2; 584 uint64_t shifter = (ULL(1) << halfSize); 585 uint64_t psrc1_h = psrc1 / shifter; 586 uint64_t psrc1_l = psrc1 & mask(halfSize); 587 uint64_t psrc2_h = (op2 / shifter) & mask(halfSize); 588 uint64_t psrc2_l = op2 & mask(halfSize); 589 ProdHi = ((psrc1_l * psrc2_h + psrc1_h * psrc2_l + 590 ((psrc1_l * psrc2_l) / shifter)) / shifter) + 591 psrc1_h * psrc2_h; 592 ''' 593 flag_code = ''' 594 if (ProdHi) { 595 PredcfofBits = PredcfofBits | (ext & (CFBit | OFBit)); 596 PredecfBit = PredecfBit | (ext & ECFBit); 597 } else { 598 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 599 PredecfBit = PredecfBit & ~(ext & ECFBit); 600 } 601 ''' 602 603 class Mulel(RdRegOp): 604 code = 'DestReg = merge(SrcReg1, ProdLow, dataSize);' 605 big_code = 'DestReg = ProdLow & mask(dataSize * 8);' 606 607 class Muleh(RdRegOp): 608 def __init__(self, dest, src1=None, flags=None, dataSize="env.dataSize"): 609 if not src1: 610 src1 = dest 611 super(RdRegOp, self).__init__(dest, src1, \ 612 "InstRegIndex(NUM_INTREGS)", flags, dataSize) 613 code = 'DestReg = merge(SrcReg1, ProdHi, dataSize);' 614 big_code = 'DestReg = ProdHi & mask(dataSize * 8);' 615 616 # One or two bit divide 617 class Div1(WrRegOp): 618 op_class = 'IntDivOp' 619 620 code = ''' 621 //These are temporaries so that modifying them later won't make 622 //the ISA parser think they're also sources. 623 uint64_t quotient = 0; 624 uint64_t remainder = psrc1; 625 //Similarly, this is a temporary so changing it doesn't make it 626 //a source. 627 uint64_t divisor = op2; 628 //This is a temporary just for consistency and clarity. 629 uint64_t dividend = remainder; 630 //Do the division. 631 if (divisor == 0) { 632 fault = new DivideByZero; 633 } else { 634 divide(dividend, divisor, quotient, remainder); 635 //Record the final results. 636 Remainder = remainder; 637 Quotient = quotient; 638 Divisor = divisor; 639 } 640 ''' 641 642 # Step divide 643 class Div2(RegOp): 644 op_class = 'IntDivOp' 645 646 divCode = ''' 647 uint64_t dividend = Remainder; 648 uint64_t divisor = Divisor; 649 uint64_t quotient = Quotient; 650 uint64_t remainder = dividend; 651 int remaining = op2; 652 //If we overshot, do nothing. This lets us unrool division loops a 653 //little. 654 if (divisor == 0) { 655 fault = new DivideByZero; 656 } else if (remaining) { 657 if (divisor & (ULL(1) << 63)) { 658 while (remaining && !(dividend & (ULL(1) << 63))) { 659 dividend = (dividend << 1) | 660 bits(SrcReg1, remaining - 1); 661 quotient <<= 1; 662 remaining--; 663 } 664 if (dividend & (ULL(1) << 63)) { 665 bool highBit = false; 666 if (dividend < divisor && remaining) { 667 highBit = true; 668 dividend = (dividend << 1) | 669 bits(SrcReg1, remaining - 1); 670 quotient <<= 1; 671 remaining--; 672 } 673 if (highBit || divisor <= dividend) { 674 quotient++; 675 dividend -= divisor; 676 } 677 } 678 remainder = dividend; 679 } else { 680 //Shift in bits from the low order portion of the dividend 681 while (dividend < divisor && remaining) { 682 dividend = (dividend << 1) | 683 bits(SrcReg1, remaining - 1); 684 quotient <<= 1; 685 remaining--; 686 } 687 remainder = dividend; 688 //Do the division. 689 divide(dividend, divisor, quotient, remainder); 690 } 691 } 692 //Keep track of how many bits there are still to pull in. 693 %s 694 //Record the final results 695 Remainder = remainder; 696 Quotient = quotient; 697 ''' 698 code = divCode % "DestReg = merge(DestReg, remaining, dataSize);" 699 big_code = divCode % "DestReg = remaining & mask(dataSize * 8);" 700 flag_code = ''' 701 if (remaining == 0) 702 PredezfBit = PredezfBit | (ext & EZFBit); 703 else 704 PredezfBit = PredezfBit & ~(ext & EZFBit); 705 ''' 706 707 class Divq(RdRegOp): 708 code = 'DestReg = merge(SrcReg1, Quotient, dataSize);' 709 big_code = 'DestReg = Quotient & mask(dataSize * 8);' 710 711 class Divr(RdRegOp): 712 code = 'DestReg = merge(SrcReg1, Remainder, dataSize);' 713 big_code = 'DestReg = Remainder & mask(dataSize * 8);' 714 715 class Mov(CondRegOp): 716 code = 'DestReg = merge(SrcReg1, op2, dataSize)' 717 else_code = 'DestReg = DestReg;' 718 719 # Shift instructions 720 721 class Sll(RegOp): 722 code = ''' 723 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 724 DestReg = merge(DestReg, psrc1 << shiftAmt, dataSize); 725 ''' 726 big_code = ''' 727 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 728 DestReg = (psrc1 << shiftAmt) & mask(dataSize * 8); 729 ''' 730 flag_code = ''' 731 // If the shift amount is zero, no flags should be modified. 732 if (shiftAmt) { 733 //Zero out any flags we might modify. This way we only have to 734 //worry about setting them. 735 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 736 PredecfBit = PredecfBit & ~(ext & ECFBit); 737 738 int CFBits = 0; 739 //Figure out if we -would- set the CF bits if requested. 740 if (shiftAmt <= dataSize * 8 && 741 bits(SrcReg1, dataSize * 8 - shiftAmt)) { 742 CFBits = 1; 743 } 744 745 //If some combination of the CF bits need to be set, set them. 746 if ((ext & (CFBit | ECFBit)) && CFBits) { 747 PredcfofBits = PredcfofBits | (ext & CFBit); 748 PredecfBit = PredecfBit | (ext & ECFBit); 749 } 750 751 //Figure out what the OF bit should be. 752 if ((ext & OFBit) && (CFBits ^ bits(DestReg, dataSize * 8 - 1))) 753 PredcfofBits = PredcfofBits | OFBit; 754 755 //Use the regular mechanisms to calculate the other flags. 756 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 757 PredezfBit, ext & ~(CFBit | ECFBit | OFBit), 758 DestReg, psrc1, op2); 759 760 PredezfBit = newFlags & EZFBit; 761 PreddfBit = newFlags & DFBit; 762 PredccFlagBits = newFlags & ccFlagMask; 763 } 764 ''' 765 766 class Srl(RegOp): 767 # Because what happens to the bits shift -in- on a right shift 768 # is not defined in the C/C++ standard, we have to mask them out 769 # to be sure they're zero. 770 code = ''' 771 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 772 uint64_t logicalMask = mask(dataSize * 8 - shiftAmt); 773 DestReg = merge(DestReg, (psrc1 >> shiftAmt) & logicalMask, dataSize); 774 ''' 775 big_code = ''' 776 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 777 uint64_t logicalMask = mask(dataSize * 8 - shiftAmt); 778 DestReg = (psrc1 >> shiftAmt) & logicalMask; 779 ''' 780 flag_code = ''' 781 // If the shift amount is zero, no flags should be modified. 782 if (shiftAmt) { 783 //Zero out any flags we might modify. This way we only have to 784 //worry about setting them. 785 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 786 PredecfBit = PredecfBit & ~(ext & ECFBit); 787 788 //If some combination of the CF bits need to be set, set them. 789 if ((ext & (CFBit | ECFBit)) && 790 shiftAmt <= dataSize * 8 && 791 bits(SrcReg1, shiftAmt - 1)) { 792 PredcfofBits = PredcfofBits | (ext & CFBit); 793 PredecfBit = PredecfBit | (ext & ECFBit); 794 } 795 796 //Figure out what the OF bit should be. 797 if ((ext & OFBit) && bits(SrcReg1, dataSize * 8 - 1)) 798 PredcfofBits = PredcfofBits | OFBit; 799 800 //Use the regular mechanisms to calculate the other flags. 801 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 802 PredezfBit, ext & ~(CFBit | ECFBit | OFBit), 803 DestReg, psrc1, op2); 804 805 PredezfBit = newFlags & EZFBit; 806 PreddfBit = newFlags & DFBit; 807 PredccFlagBits = newFlags & ccFlagMask; 808 } 809 ''' 810 811 class Sra(RegOp): 812 # Because what happens to the bits shift -in- on a right shift 813 # is not defined in the C/C++ standard, we have to sign extend 814 # them manually to be sure. 815 code = ''' 816 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 817 uint64_t arithMask = (shiftAmt == 0) ? 0 : 818 -bits(psrc1, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt); 819 DestReg = merge(DestReg, (psrc1 >> shiftAmt) | arithMask, dataSize); 820 ''' 821 big_code = ''' 822 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 823 uint64_t arithMask = (shiftAmt == 0) ? 0 : 824 -bits(psrc1, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt); 825 DestReg = ((psrc1 >> shiftAmt) | arithMask) & mask(dataSize * 8); 826 ''' 827 flag_code = ''' 828 // If the shift amount is zero, no flags should be modified. 829 if (shiftAmt) { 830 //Zero out any flags we might modify. This way we only have to 831 //worry about setting them. 832 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 833 PredecfBit = PredecfBit & ~(ext & ECFBit); 834 835 //If some combination of the CF bits need to be set, set them. 836 uint8_t effectiveShift = 837 (shiftAmt <= dataSize * 8) ? shiftAmt : (dataSize * 8); 838 if ((ext & (CFBit | ECFBit)) && 839 bits(SrcReg1, effectiveShift - 1)) { 840 PredcfofBits = PredcfofBits | (ext & CFBit); 841 PredecfBit = PredecfBit | (ext & ECFBit); 842 } 843 844 //Use the regular mechanisms to calculate the other flags. 845 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 846 PredezfBit, ext & ~(CFBit | ECFBit | OFBit), 847 DestReg, psrc1, op2); 848 849 PredezfBit = newFlags & EZFBit; 850 PreddfBit = newFlags & DFBit; 851 PredccFlagBits = newFlags & ccFlagMask; 852 } 853 ''' 854 855 class Ror(RegOp): 856 code = ''' 857 uint8_t shiftAmt = 858 (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 859 uint8_t realShiftAmt = shiftAmt % (dataSize * 8); 860 if (realShiftAmt) { 861 uint64_t top = psrc1 << (dataSize * 8 - realShiftAmt); 862 uint64_t bottom = bits(psrc1, dataSize * 8, realShiftAmt); 863 DestReg = merge(DestReg, top | bottom, dataSize); 864 } else 865 DestReg = merge(DestReg, DestReg, dataSize); 866 ''' 867 flag_code = ''' 868 // If the shift amount is zero, no flags should be modified. 869 if (shiftAmt) { 870 //Zero out any flags we might modify. This way we only have to 871 //worry about setting them. 872 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 873 PredecfBit = PredecfBit & ~(ext & ECFBit); 874 875 //Find the most and second most significant bits of the result. 876 int msb = bits(DestReg, dataSize * 8 - 1); 877 int smsb = bits(DestReg, dataSize * 8 - 2); 878 //If some combination of the CF bits need to be set, set them. 879 if ((ext & (CFBit | ECFBit)) && msb) { 880 PredcfofBits = PredcfofBits | (ext & CFBit); 881 PredecfBit = PredecfBit | (ext & ECFBit); 882 } 883 884 //Figure out what the OF bit should be. 885 if ((ext & OFBit) && (msb ^ smsb)) 886 PredcfofBits = PredcfofBits | OFBit; 887 888 //Use the regular mechanisms to calculate the other flags. 889 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 890 PredezfBit, ext & ~(CFBit | ECFBit | OFBit), 891 DestReg, psrc1, op2); 892 893 PredezfBit = newFlags & EZFBit; 894 PreddfBit = newFlags & DFBit; 895 PredccFlagBits = newFlags & ccFlagMask; 896 } 897 ''' 898 899 class Rcr(RegOp): 900 code = ''' 901 uint8_t shiftAmt = 902 (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 903 uint8_t realShiftAmt = shiftAmt % (dataSize * 8 + 1); 904 if (realShiftAmt) { 905 CCFlagBits flags = cfofBits; 906 uint64_t top = flags.cf << (dataSize * 8 - realShiftAmt); 907 if (realShiftAmt > 1) 908 top |= psrc1 << (dataSize * 8 - realShiftAmt + 1); 909 uint64_t bottom = bits(psrc1, dataSize * 8 - 1, realShiftAmt); 910 DestReg = merge(DestReg, top | bottom, dataSize); 911 } else 912 DestReg = merge(DestReg, DestReg, dataSize); 913 ''' 914 flag_code = ''' 915 // If the shift amount is zero, no flags should be modified. 916 if (shiftAmt) { 917 int origCFBit = (cfofBits & CFBit) ? 1 : 0; 918 //Zero out any flags we might modify. This way we only have to 919 //worry about setting them. 920 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 921 PredecfBit = PredecfBit & ~(ext & ECFBit); 922 923 //Figure out what the OF bit should be. 924 if ((ext & OFBit) && (origCFBit ^ 925 bits(SrcReg1, dataSize * 8 - 1))) { 926 PredcfofBits = PredcfofBits | OFBit; 927 } 928 //If some combination of the CF bits need to be set, set them. 929 if ((ext & (CFBit | ECFBit)) && 930 (realShiftAmt == 0) ? origCFBit : 931 bits(SrcReg1, realShiftAmt - 1)) { 932 PredcfofBits = PredcfofBits | (ext & CFBit); 933 PredecfBit = PredecfBit | (ext & ECFBit); 934 } 935 936 //Use the regular mechanisms to calculate the other flags. 937 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 938 PredezfBit, ext & ~(CFBit | ECFBit | OFBit), 939 DestReg, psrc1, op2); 940 941 PredezfBit = newFlags & EZFBit; 942 PreddfBit = newFlags & DFBit; 943 PredccFlagBits = newFlags & ccFlagMask; 944 } 945 ''' 946 947 class Rol(RegOp): 948 code = ''' 949 uint8_t shiftAmt = 950 (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 951 uint8_t realShiftAmt = shiftAmt % (dataSize * 8); 952 if (realShiftAmt) { 953 uint64_t top = psrc1 << realShiftAmt; 954 uint64_t bottom = 955 bits(psrc1, dataSize * 8 - 1, dataSize * 8 - realShiftAmt); 956 DestReg = merge(DestReg, top | bottom, dataSize); 957 } else 958 DestReg = merge(DestReg, DestReg, dataSize); 959 ''' 960 flag_code = ''' 961 // If the shift amount is zero, no flags should be modified. 962 if (shiftAmt) { 963 //Zero out any flags we might modify. This way we only have to 964 //worry about setting them. 965 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 966 PredecfBit = PredecfBit & ~(ext & ECFBit); 967 968 //The CF bits, if set, would be set to the lsb of the result. 969 int lsb = DestReg & 0x1; 970 int msb = bits(DestReg, dataSize * 8 - 1); 971 //If some combination of the CF bits need to be set, set them. 972 if ((ext & (CFBit | ECFBit)) && lsb) { 973 PredcfofBits = PredcfofBits | (ext & CFBit); 974 PredecfBit = PredecfBit | (ext & ECFBit); 975 } 976 977 //Figure out what the OF bit should be. 978 if ((ext & OFBit) && (msb ^ lsb)) 979 PredcfofBits = PredcfofBits | OFBit; 980 981 //Use the regular mechanisms to calculate the other flags. 982 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 983 PredezfBit, ext & ~(CFBit | ECFBit | OFBit), 984 DestReg, psrc1, op2); 985 986 PredezfBit = newFlags & EZFBit; 987 PreddfBit = newFlags & DFBit; 988 PredccFlagBits = newFlags & ccFlagMask; 989 } 990 ''' 991 992 class Rcl(RegOp): 993 code = ''' 994 uint8_t shiftAmt = 995 (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 996 uint8_t realShiftAmt = shiftAmt % (dataSize * 8 + 1); 997 if (realShiftAmt) { 998 CCFlagBits flags = cfofBits; 999 uint64_t top = psrc1 << realShiftAmt; 1000 uint64_t bottom = flags.cf << (realShiftAmt - 1); 1001 if(shiftAmt > 1) 1002 bottom |= 1003 bits(psrc1, dataSize * 8 - 1, 1004 dataSize * 8 - realShiftAmt + 1); 1005 DestReg = merge(DestReg, top | bottom, dataSize); 1006 } else 1007 DestReg = merge(DestReg, DestReg, dataSize); 1008 ''' 1009 flag_code = ''' 1010 // If the shift amount is zero, no flags should be modified. 1011 if (shiftAmt) { 1012 int origCFBit = (cfofBits & CFBit) ? 1 : 0; 1013 //Zero out any flags we might modify. This way we only have to 1014 //worry about setting them. 1015 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 1016 PredecfBit = PredecfBit & ~(ext & ECFBit); 1017 1018 int msb = bits(DestReg, dataSize * 8 - 1); 1019 int CFBits = bits(SrcReg1, dataSize * 8 - realShiftAmt); 1020 //If some combination of the CF bits need to be set, set them. 1021 if ((ext & (CFBit | ECFBit)) && 1022 (realShiftAmt == 0) ? origCFBit : CFBits) { 1023 PredcfofBits = PredcfofBits | (ext & CFBit); 1024 PredecfBit = PredecfBit | (ext & ECFBit); 1025 } 1026 1027 //Figure out what the OF bit should be. 1028 if ((ext & OFBit) && (msb ^ CFBits)) 1029 PredcfofBits = PredcfofBits | OFBit; 1030 1031 //Use the regular mechanisms to calculate the other flags. 1032 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 1033 PredezfBit, ext & ~(CFBit | ECFBit | OFBit), 1034 DestReg, psrc1, op2); 1035 1036 PredezfBit = newFlags & EZFBit; 1037 PreddfBit = newFlags & DFBit; 1038 PredccFlagBits = newFlags & ccFlagMask; 1039 } 1040 ''' 1041 1042 class Sld(RegOp): 1043 sldCode = ''' 1044 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 1045 uint8_t dataBits = dataSize * 8; 1046 uint8_t realShiftAmt = shiftAmt %% (2 * dataBits); 1047 uint64_t result; 1048 if (realShiftAmt == 0) { 1049 result = psrc1; 1050 } else if (realShiftAmt < dataBits) { 1051 result = (psrc1 << realShiftAmt) | 1052 (DoubleBits >> (dataBits - realShiftAmt)); 1053 } else { 1054 result = (DoubleBits << (realShiftAmt - dataBits)) | 1055 (psrc1 >> (2 * dataBits - realShiftAmt)); 1056 } 1057 %s 1058 ''' 1059 code = sldCode % "DestReg = merge(DestReg, result, dataSize);" 1060 big_code = sldCode % "DestReg = result & mask(dataSize * 8);" 1061 flag_code = ''' 1062 // If the shift amount is zero, no flags should be modified. 1063 if (shiftAmt) { 1064 //Zero out any flags we might modify. This way we only have to 1065 //worry about setting them. 1066 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 1067 PredecfBit = PredecfBit & ~(ext & ECFBit); 1068 int CFBits = 0; 1069 1070 //Figure out if we -would- set the CF bits if requested. 1071 if ((realShiftAmt == 0 && 1072 bits(DoubleBits, 0)) || 1073 (realShiftAmt <= dataBits && 1074 bits(SrcReg1, dataBits - realShiftAmt)) || 1075 (realShiftAmt > dataBits && 1076 bits(DoubleBits, 2 * dataBits - realShiftAmt))) { 1077 CFBits = 1; 1078 } 1079 1080 //If some combination of the CF bits need to be set, set them. 1081 if ((ext & (CFBit | ECFBit)) && CFBits) { 1082 PredcfofBits = PredcfofBits | (ext & CFBit); 1083 PredecfBit = PredecfBit | (ext & ECFBit); 1084 } 1085 1086 //Figure out what the OF bit should be. 1087 if ((ext & OFBit) && (bits(SrcReg1, dataBits - 1) ^ 1088 bits(result, dataBits - 1))) 1089 PredcfofBits = PredcfofBits | OFBit; 1090 1091 //Use the regular mechanisms to calculate the other flags. 1092 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 1093 PredezfBit, ext & ~(CFBit | ECFBit | OFBit), 1094 DestReg, psrc1, op2); 1095 1096 PredezfBit = newFlags & EZFBit; 1097 PreddfBit = newFlags & DFBit; 1098 PredccFlagBits = newFlags & ccFlagMask; 1099 } 1100 ''' 1101 1102 class Srd(RegOp): 1103 srdCode = ''' 1104 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 1105 uint8_t dataBits = dataSize * 8; 1106 uint8_t realShiftAmt = shiftAmt %% (2 * dataBits); 1107 uint64_t result; 1108 if (realShiftAmt == 0) { 1109 result = psrc1; 1110 } else if (realShiftAmt < dataBits) { 1111 // Because what happens to the bits shift -in- on a right 1112 // shift is not defined in the C/C++ standard, we have to 1113 // mask them out to be sure they're zero. 1114 uint64_t logicalMask = mask(dataBits - realShiftAmt); 1115 result = ((psrc1 >> realShiftAmt) & logicalMask) | 1116 (DoubleBits << (dataBits - realShiftAmt)); 1117 } else { 1118 uint64_t logicalMask = mask(2 * dataBits - realShiftAmt); 1119 result = ((DoubleBits >> (realShiftAmt - dataBits)) & 1120 logicalMask) | 1121 (psrc1 << (2 * dataBits - realShiftAmt)); 1122 } 1123 %s 1124 ''' 1125 code = srdCode % "DestReg = merge(DestReg, result, dataSize);" 1126 big_code = srdCode % "DestReg = result & mask(dataSize * 8);" 1127 flag_code = ''' 1128 // If the shift amount is zero, no flags should be modified. 1129 if (shiftAmt) { 1130 //Zero out any flags we might modify. This way we only have to 1131 //worry about setting them. 1132 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 1133 PredecfBit = PredecfBit & ~(ext & ECFBit); 1134 int CFBits = 0; 1135 1136 //If some combination of the CF bits need to be set, set them. 1137 if ((realShiftAmt == 0 && 1138 bits(DoubleBits, dataBits - 1)) || 1139 (realShiftAmt <= dataBits && 1140 bits(SrcReg1, realShiftAmt - 1)) || 1141 (realShiftAmt > dataBits && 1142 bits(DoubleBits, realShiftAmt - dataBits - 1))) { 1143 CFBits = 1; 1144 } 1145 1146 //If some combination of the CF bits need to be set, set them. 1147 if ((ext & (CFBit | ECFBit)) && CFBits) { 1148 PredcfofBits = PredcfofBits | (ext & CFBit); 1149 PredecfBit = PredecfBit | (ext & ECFBit); 1150 } 1151 1152 //Figure out what the OF bit should be. 1153 if ((ext & OFBit) && (bits(SrcReg1, dataBits - 1) ^ 1154 bits(result, dataBits - 1))) 1155 PredcfofBits = PredcfofBits | OFBit; 1156 1157 //Use the regular mechanisms to calculate the other flags. 1158 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 1159 PredezfBit, ext & ~(CFBit | ECFBit | OFBit), 1160 DestReg, psrc1, op2); 1161 1162 PredezfBit = newFlags & EZFBit; 1163 PreddfBit = newFlags & DFBit; 1164 PredccFlagBits = newFlags & ccFlagMask; 1165 } 1166 ''' 1167 1168 class Mdb(WrRegOp): 1169 code = 'DoubleBits = psrc1 ^ op2;' 1170 1171 class Wrip(WrRegOp, CondRegOp): 1172 code = 'NRIP = psrc1 + sop2 + CSBase;' 1173 else_code = "NRIP = NRIP;" 1174 1175 class Wruflags(WrRegOp): 1176 code = ''' 1177 uint64_t newFlags = psrc1 ^ op2; 1178 cfofBits = newFlags & cfofMask; 1179 ecfBit = newFlags & ECFBit; 1180 ezfBit = newFlags & EZFBit; 1181 dfBit = newFlags & DFBit; 1182 ccFlagBits = newFlags & ccFlagMask; 1183 ''' 1184 1185 class Wrflags(WrRegOp): 1186 code = ''' 1187 MiscReg newFlags = psrc1 ^ op2; 1188 MiscReg userFlagMask = 0xDD5; 1189 1190 // Get only the user flags 1191 ccFlagBits = newFlags & ccFlagMask; 1192 dfBit = newFlags & DFBit; 1193 cfofBits = newFlags & cfofMask; 1194 ecfBit = 0; 1195 ezfBit = 0; 1196 1197 // Get everything else 1198 nccFlagBits = newFlags & ~userFlagMask; 1199 ''' 1200 1201 class Rdip(RdRegOp): 1202 code = 'DestReg = NRIP - CSBase;' 1203 1204 class Ruflags(RdRegOp): 1205 code = 'DestReg = ccFlagBits | cfofBits | dfBit | ecfBit | ezfBit;' 1206 1207 class Rflags(RdRegOp): 1208 code = ''' 1209 DestReg = ccFlagBits | cfofBits | dfBit | 1210 ecfBit | ezfBit | nccFlagBits; 1211 ''' 1212 1213 class Ruflag(RegOp): 1214 code = ''' 1215 int flag = bits(ccFlagBits | cfofBits | dfBit | 1216 ecfBit | ezfBit, imm8); 1217 DestReg = merge(DestReg, flag, dataSize); 1218 ezfBit = (flag == 0) ? EZFBit : 0; 1219 ''' 1220 1221 big_code = ''' 1222 int flag = bits(ccFlagBits | cfofBits | dfBit | 1223 ecfBit | ezfBit, imm8); 1224 DestReg = flag & mask(dataSize * 8); 1225 ezfBit = (flag == 0) ? EZFBit : 0; 1226 ''' 1227 1228 def __init__(self, dest, imm, flags=None, \ 1229 dataSize="env.dataSize"): 1230 super(Ruflag, self).__init__(dest, \ 1231 "InstRegIndex(NUM_INTREGS)", imm, flags, dataSize) 1232 1233 class Rflag(RegOp): 1234 code = ''' 1235 MiscReg flagMask = 0x3F7FDD5; 1236 MiscReg flags = (nccFlagBits | ccFlagBits | cfofBits | dfBit | 1237 ecfBit | ezfBit) & flagMask; 1238 1239 int flag = bits(flags, imm8); 1240 DestReg = merge(DestReg, flag, dataSize); 1241 ezfBit = (flag == 0) ? EZFBit : 0; 1242 ''' 1243 1244 big_code = ''' 1245 MiscReg flagMask = 0x3F7FDD5; 1246 MiscReg flags = (nccFlagBits | ccFlagBits | cfofBits | dfBit | 1247 ecfBit | ezfBit) & flagMask; 1248 1249 int flag = bits(flags, imm8); 1250 DestReg = flag & mask(dataSize * 8); 1251 ezfBit = (flag == 0) ? EZFBit : 0; 1252 ''' 1253 1254 def __init__(self, dest, imm, flags=None, \ 1255 dataSize="env.dataSize"): 1256 super(Rflag, self).__init__(dest, \ 1257 "InstRegIndex(NUM_INTREGS)", imm, flags, dataSize) 1258 1259 class Sext(RegOp): 1260 code = ''' 1261 IntReg val = psrc1; 1262 // Mask the bit position so that it wraps. 1263 int bitPos = op2 & (dataSize * 8 - 1); 1264 int sign_bit = bits(val, bitPos, bitPos); 1265 uint64_t maskVal = mask(bitPos+1); 1266 val = sign_bit ? (val | ~maskVal) : (val & maskVal); 1267 DestReg = merge(DestReg, val, dataSize); 1268 ''' 1269 1270 big_code = ''' 1271 IntReg val = psrc1; 1272 // Mask the bit position so that it wraps. 1273 int bitPos = op2 & (dataSize * 8 - 1); 1274 int sign_bit = bits(val, bitPos, bitPos); 1275 uint64_t maskVal = mask(bitPos+1); 1276 val = sign_bit ? (val | ~maskVal) : (val & maskVal); 1277 DestReg = val & mask(dataSize * 8); 1278 ''' 1279 1280 flag_code = ''' 1281 if (!sign_bit) { 1282 PredccFlagBits = PredccFlagBits & ~(ext & (ZFBit)); 1283 PredcfofBits = PredcfofBits & ~(ext & (CFBit)); 1284 PredecfBit = PredecfBit & ~(ext & ECFBit); 1285 PredezfBit = PredezfBit & ~(ext & EZFBit); 1286 } else { 1287 PredccFlagBits = PredccFlagBits | (ext & (ZFBit)); 1288 PredcfofBits = PredcfofBits | (ext & (CFBit)); 1289 PredecfBit = PredecfBit | (ext & ECFBit); 1290 PredezfBit = PredezfBit | (ext & EZFBit); 1291 } 1292 ''' 1293 1294 class Zext(RegOp): 1295 code = 'DestReg = merge(DestReg, bits(psrc1, op2, 0), dataSize);' 1296 big_code = 'DestReg = bits(psrc1, op2, 0) & mask(dataSize * 8);' 1297 1298 class Rddr(RegOp): 1299 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 1300 super(Rddr, self).__init__(dest, \ 1301 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize) 1302 rdrCode = ''' 1303 CR4 cr4 = CR4Op; 1304 DR7 dr7 = DR7Op; 1305 if ((cr4.de == 1 && (src1 == 4 || src1 == 5)) || src1 >= 8) { 1306 fault = new InvalidOpcode(); 1307 } else if (dr7.gd) { 1308 fault = new DebugException(); 1309 } else { 1310 %s 1311 } 1312 ''' 1313 code = rdrCode % "DestReg = merge(DestReg, DebugSrc1, dataSize);" 1314 big_code = rdrCode % "DestReg = DebugSrc1 & mask(dataSize * 8);" 1315 1316 class Wrdr(RegOp): 1317 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 1318 super(Wrdr, self).__init__(dest, \ 1319 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize) 1320 code = ''' 1321 CR4 cr4 = CR4Op; 1322 DR7 dr7 = DR7Op; 1323 if ((cr4.de == 1 && (dest == 4 || dest == 5)) || dest >= 8) { 1324 fault = new InvalidOpcode(); 1325 } else if ((dest == 6 || dest == 7) && bits(psrc1, 63, 32) && 1326 machInst.mode.mode == LongMode) { 1327 fault = new GeneralProtection(0); 1328 } else if (dr7.gd) { 1329 fault = new DebugException(); 1330 } else { 1331 DebugDest = psrc1; 1332 } 1333 ''' 1334 1335 class Rdcr(RegOp): 1336 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 1337 super(Rdcr, self).__init__(dest, \ 1338 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize) 1339 rdcrCode = ''' 1340 if (src1 == 1 || (src1 > 4 && src1 < 8) || (src1 > 8)) { 1341 fault = new InvalidOpcode(); 1342 } else { 1343 %s 1344 } 1345 ''' 1346 code = rdcrCode % "DestReg = merge(DestReg, ControlSrc1, dataSize);" 1347 big_code = rdcrCode % "DestReg = ControlSrc1 & mask(dataSize * 8);" 1348 1349 class Wrcr(RegOp): 1350 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 1351 super(Wrcr, self).__init__(dest, \ 1352 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize) 1353 code = ''' 1354 if (dest == 1 || (dest > 4 && dest < 8) || (dest > 8)) { 1355 fault = new InvalidOpcode(); 1356 } else { 1357 // There are *s in the line below so it doesn't confuse the 1358 // parser. They may be unnecessary. 1359 //Mis*cReg old*Val = pick(Cont*rolDest, 0, dat*aSize); 1360 MiscReg newVal = psrc1; 1361 1362 // Check for any modifications that would cause a fault. 1363 switch(dest) { 1364 case 0: 1365 { 1366 Efer efer = EferOp; 1367 CR0 cr0 = newVal; 1368 CR4 oldCr4 = CR4Op; 1369 if (bits(newVal, 63, 32) || 1370 (!cr0.pe && cr0.pg) || 1371 (!cr0.cd && cr0.nw) || 1372 (cr0.pg && efer.lme && !oldCr4.pae)) 1373 fault = new GeneralProtection(0); 1374 } 1375 break; 1376 case 2: 1377 break; 1378 case 3: 1379 break; 1380 case 4: 1381 { 1382 CR4 cr4 = newVal; 1383 // PAE can't be disabled in long mode. 1384 if (bits(newVal, 63, 11) || 1385 (machInst.mode.mode == LongMode && !cr4.pae)) 1386 fault = new GeneralProtection(0); 1387 } 1388 break; 1389 case 8: 1390 { 1391 if (bits(newVal, 63, 4)) 1392 fault = new GeneralProtection(0); 1393 } 1394 default: 1395 fault = new GenericISA::M5PanicFault( 1396 "Unrecognized control register %d.\\n", dest); 1397 } 1398 ControlDest = newVal; 1399 } 1400 ''' 1401 1402 # Microops for manipulating segmentation registers 1403 class SegOp(CondRegOp): 1404 abstract = True 1405 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 1406 super(SegOp, self).__init__(dest, \ 1407 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize) 1408 1409 class Wrbase(SegOp): 1410 code = ''' 1411 SegBaseDest = psrc1; 1412 ''' 1413 1414 class Wrlimit(SegOp): 1415 code = ''' 1416 SegLimitDest = psrc1; 1417 ''' 1418 1419 class Wrsel(SegOp): 1420 code = ''' 1421 SegSelDest = psrc1; 1422 ''' 1423 1424 class WrAttr(SegOp): 1425 code = ''' 1426 SegAttrDest = psrc1; 1427 ''' 1428 1429 class Rdbase(SegOp): 1430 code = 'DestReg = merge(DestReg, SegBaseSrc1, dataSize);' 1431 big_code = 'DestReg = SegBaseSrc1 & mask(dataSize * 8);' 1432 1433 class Rdlimit(SegOp): 1434 code = 'DestReg = merge(DestReg, SegLimitSrc1, dataSize);' 1435 big_code = 'DestReg = SegLimitSrc1 & mask(dataSize * 8);' 1436 1437 class RdAttr(SegOp): 1438 code = 'DestReg = merge(DestReg, SegAttrSrc1, dataSize);' 1439 big_code = 'DestReg = SegAttrSrc1 & mask(dataSize * 8);' 1440 1441 class Rdsel(SegOp): 1442 code = 'DestReg = merge(DestReg, SegSelSrc1, dataSize);' 1443 big_code = 'DestReg = SegSelSrc1 & mask(dataSize * 8);' 1444 1445 class Rdval(RegOp): 1446 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 1447 super(Rdval, self).__init__(dest, src1, \ 1448 "InstRegIndex(NUM_INTREGS)", flags, dataSize) 1449 code = ''' 1450 DestReg = MiscRegSrc1; 1451 ''' 1452 1453 class Wrval(RegOp): 1454 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 1455 super(Wrval, self).__init__(dest, src1, \ 1456 "InstRegIndex(NUM_INTREGS)", flags, dataSize) 1457 code = ''' 1458 MiscRegDest = SrcReg1; 1459 ''' 1460 1461 class Chks(RegOp): 1462 def __init__(self, dest, src1, src2=0, 1463 flags=None, dataSize="env.dataSize"): 1464 super(Chks, self).__init__(dest, 1465 src1, src2, flags, dataSize) 1466 code = ''' 1467 // The selector is in source 1 and can be at most 16 bits. 1468 SegSelector selector = DestReg; 1469 SegDescriptor desc = SrcReg1; 1470 HandyM5Reg m5reg = M5Reg; 1471 1472 switch (imm8) 1473 { 1474 case SegNoCheck: 1475 break; 1476 case SegCSCheck: 1477 // Make sure it's the right type 1478 if (desc.s == 0 || desc.type.codeOrData != 1) { 1479 fault = new GeneralProtection(0); 1480 } else if (m5reg.cpl != desc.dpl) { 1481 fault = new GeneralProtection(0); 1482 } 1483 break; 1484 case SegCallGateCheck: 1485 fault = new GenericISA::M5PanicFault("CS checks for far " 1486 "calls/jumps through call gates not implemented.\\n"); 1487 break; 1488 case SegSoftIntGateCheck: 1489 // Check permissions. 1490 if (desc.dpl < m5reg.cpl) { 1491 fault = new GeneralProtection(selector); 1492 break; 1493 } 1494 // Fall through on purpose 1495 case SegIntGateCheck: 1496 // Make sure the gate's the right type. 1497 if ((m5reg.mode == LongMode && (desc.type & 0xe) != 0xe) || 1498 ((desc.type & 0x6) != 0x6)) { 1499 fault = new GeneralProtection(0); 1500 } 1501 break; 1502 case SegSSCheck: 1503 if (selector.si || selector.ti) { 1504 if (!desc.p) { 1505 fault = new StackFault(selector); 1506 } else if (!(desc.s == 1 && desc.type.codeOrData == 0 && 1507 desc.type.w) || 1508 (desc.dpl != m5reg.cpl) || 1509 (selector.rpl != m5reg.cpl)) { 1510 fault = new GeneralProtection(selector); 1511 } 1512 } else if (m5reg.submode != SixtyFourBitMode || 1513 m5reg.cpl == 3) { 1514 fault = new GeneralProtection(selector); 1515 } 1516 break; 1517 case SegIretCheck: 1518 { 1519 if ((!selector.si && !selector.ti) || 1520 (selector.rpl < m5reg.cpl) || 1521 !(desc.s == 1 && desc.type.codeOrData == 1) || 1522 (!desc.type.c && desc.dpl != selector.rpl) || 1523 (desc.type.c && desc.dpl > selector.rpl)) { 1524 fault = new GeneralProtection(selector); 1525 } else if (!desc.p) { 1526 fault = new SegmentNotPresent(selector); 1527 } 1528 break; 1529 } 1530 case SegIntCSCheck: 1531 if (m5reg.mode == LongMode) { 1532 if (desc.l != 1 || desc.d != 0) { 1533 fault = new GeneralProtection(selector); 1534 } 1535 } else { 1536 fault = new GenericISA::M5PanicFault("Interrupt CS " 1537 "checks not implemented in legacy mode.\\n"); 1538 } 1539 break; 1540 case SegTRCheck: 1541 if (!selector.si || selector.ti) { 1542 fault = new GeneralProtection(selector); 1543 } 1544 break; 1545 case SegTSSCheck: 1546 if (!desc.p) { 1547 fault = new SegmentNotPresent(selector); 1548 } else if (!(desc.type == 0x9 || 1549 (desc.type == 1 && 1550 m5reg.mode != LongMode))) { 1551 fault = new GeneralProtection(selector); 1552 } 1553 break; 1554 case SegInGDTCheck: 1555 if (selector.ti) { 1556 fault = new GeneralProtection(selector); 1557 } 1558 break; 1559 case SegLDTCheck: 1560 if (!desc.p) { 1561 fault = new SegmentNotPresent(selector); 1562 } else if (desc.type != 0x2) { 1563 fault = new GeneralProtection(selector); 1564 } 1565 break; 1566 default: 1567 fault = new GenericISA::M5PanicFault( 1568 "Undefined segment check type.\\n"); 1569 } 1570 ''' 1571 flag_code = ''' 1572 // Check for a NULL selector and set ZF,EZF appropriately. 1573 PredccFlagBits = PredccFlagBits & ~(ext & ZFBit); 1574 PredezfBit = PredezfBit & ~(ext & EZFBit); 1575 1576 if (!selector.si && !selector.ti) { 1577 PredccFlagBits = PredccFlagBits | (ext & ZFBit); 1578 PredezfBit = PredezfBit | (ext & EZFBit); 1579 } 1580 ''' 1581 1582 class Wrdh(RegOp): 1583 code = ''' 1584 SegDescriptor desc = SrcReg1; 1585 1586 uint64_t target = bits(SrcReg2, 31, 0) << 32; 1587 switch(desc.type) { 1588 case LDT64: 1589 case AvailableTSS64: 1590 case BusyTSS64: 1591 replaceBits(target, 23, 0, desc.baseLow); 1592 replaceBits(target, 31, 24, desc.baseHigh); 1593 break; 1594 case CallGate64: 1595 case IntGate64: 1596 case TrapGate64: 1597 replaceBits(target, 15, 0, bits(desc, 15, 0)); 1598 replaceBits(target, 31, 16, bits(desc, 63, 48)); 1599 break; 1600 default: 1601 fault = new GenericISA::M5PanicFault( 1602 "Wrdh used with wrong descriptor type!\\n"); 1603 } 1604 DestReg = target; 1605 ''' 1606 1607 class Wrtsc(WrRegOp): 1608 code = ''' 1609 TscOp = psrc1; 1610 ''' 1611 1612 class Rdtsc(RdRegOp): 1613 code = ''' 1614 DestReg = TscOp; 1615 ''' 1616 1617 class Rdm5reg(RdRegOp): 1618 code = ''' 1619 DestReg = M5Reg; 1620 ''' 1621 1622 class Wrdl(RegOp): 1623 code = ''' 1624 SegDescriptor desc = SrcReg1; 1625 SegSelector selector = SrcReg2; 1626 // This while loop is so we can use break statements in the code 1627 // below to skip the rest of this section without a bunch of 1628 // nesting. 1629 while (true) { 1630 if (selector.si || selector.ti) { 1631 if (!desc.p) { 1632 fault = new GenericISA::M5PanicFault( 1633 "Segment not present.\\n"); 1634 break; 1635 } 1636 SegAttr attr = 0; 1637 attr.dpl = desc.dpl; 1638 attr.unusable = 0; 1639 attr.defaultSize = desc.d; 1640 attr.longMode = desc.l; 1641 attr.avl = desc.avl; 1642 attr.granularity = desc.g; 1643 attr.present = desc.p; 1644 attr.system = desc.s; 1645 attr.type = desc.type; 1646 if (!desc.s) { 1647 // The expand down bit happens to be set for gates. 1648 if (desc.type.e) { 1649 fault = new GenericISA::M5PanicFault( 1650 "Gate descriptor encountered.\\n"); 1651 break; 1652 } 1653 attr.readable = 1; 1654 attr.writable = 1; 1655 attr.expandDown = 0; 1656 } else { 1657 if (desc.type.codeOrData) { 1658 attr.expandDown = 0; 1659 attr.readable = desc.type.r; 1660 attr.writable = 0; 1661 } else { 1662 attr.expandDown = desc.type.e; 1663 attr.readable = 1; 1664 attr.writable = desc.type.w; 1665 } 1666 } 1667 Addr base = desc.baseLow | (desc.baseHigh << 24); 1668 Addr limit = desc.limitLow | (desc.limitHigh << 16); 1669 if (desc.g) 1670 limit = (limit << 12) | mask(12); 1671 SegBaseDest = base; 1672 SegLimitDest = limit; 1673 SegAttrDest = attr; 1674 } else { 1675 SegBaseDest = SegBaseDest; 1676 SegLimitDest = SegLimitDest; 1677 SegAttrDest = SegAttrDest; 1678 } 1679 break; 1680 } 1681 ''' 1682 1683 class Wrxftw(WrRegOp): 1684 def __init__(self, src1, **kwargs): 1685 super(Wrxftw, self).__init__(src1, "InstRegIndex(NUM_INTREGS)", \ 1686 **kwargs) 1687 1688 code = ''' 1689 FTW = X86ISA::convX87XTagsToTags(SrcReg1); 1690 ''' 1691 1692 class Rdxftw(RdRegOp): 1693 code = ''' 1694 DestReg = X86ISA::convX87TagsToXTags(FTW); 1695 ''' 1696}}; 1697