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(ExecContext *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 RegVal 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(ExecContext *xc, 77 Trace::InstRecord *traceData) const 78 { 79 Fault fault = NoFault; 80 81 %(op_decl)s; 82 %(op_rd)s; 83 84 RegVal 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 Fault execute(ExecContext *, Trace::InstRecord *) const; 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 Fault execute(ExecContext *, Trace::InstRecord *) const; 129 }; 130}}; 131 132def template MicroRegOpConstructor {{ 133 %(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 %(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 # Multiply two values Aa and Bb where Aa = A << p + a, then correct for 550 # negative operands. 551 # Aa * Bb 552 # = (A << p + a) * (B << p + b) 553 # = (A * B) << 2p + (A * b + a * B) << p + a * b 554 code = ''' 555 ProdLow = psrc1 * op2; 556 557 int p = (dataSize * 8) / 2; 558 uint64_t A = bits(psrc1, 2 * p - 1, p); 559 uint64_t a = bits(psrc1, p - 1, 0); 560 uint64_t B = bits<uint64_t>(op2, 2 * p - 1, p); 561 uint64_t b = bits<uint64_t>(op2, p - 1, 0); 562 563 uint64_t c1, c2; // Carry between place values. 564 uint64_t ab = a * b, Ab = A * b, aB = a * B, AB = A * B; 565 566 c1 = ab >> p; 567 568 // Be careful to avoid overflow if p is large. 569 if (p == 32) { 570 c2 = (c1 >> 1) + (Ab >> 1) + (aB >> 1); 571 c2 += ((c1 & 0x1) + (Ab & 0x1) + (aB & 0x1)) >> 1; 572 c2 >>= (p - 1); 573 } else { 574 c2 = (c1 + Ab + aB) >> p; 575 } 576 577 uint64_t hi = AB + c2; 578 579 if (bits(psrc1, dataSize * 8 - 1)) 580 hi -= op2; 581 if (bits(op2, dataSize * 8 - 1)) 582 hi -= psrc1; 583 584 ProdHi = hi; 585 ''' 586 flag_code = ''' 587 if ((-ProdHi & mask(dataSize * 8)) != 588 bits(ProdLow, dataSize * 8 - 1)) { 589 PredcfofBits = PredcfofBits | (ext & (CFBit | OFBit)); 590 PredecfBit = PredecfBit | (ext & ECFBit); 591 } else { 592 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 593 PredecfBit = PredecfBit & ~(ext & ECFBit); 594 } 595 ''' 596 597 class Mul1u(WrRegOp): 598 op_class = 'IntMultOp' 599 600 # Multiply two values Aa and Bb where Aa = A << p + a. 601 # Aa * Bb 602 # = (A << p + a) * (B << p + b) 603 # = (A * B) << 2p + (A * b + a * B) << p + a * b 604 code = ''' 605 ProdLow = psrc1 * op2; 606 607 int p = (dataSize * 8) / 2; 608 uint64_t A = bits(psrc1, 2 * p - 1, p); 609 uint64_t a = bits(psrc1, p - 1, 0); 610 uint64_t B = bits<uint64_t>(op2, 2 * p - 1, p); 611 uint64_t b = bits<uint64_t>(op2, p - 1, 0); 612 613 uint64_t c1, c2; // Carry between place values. 614 uint64_t ab = a * b, Ab = A * b, aB = a * B, AB = A * B; 615 616 c1 = ab >> p; 617 618 // Be careful to avoid overflow if p is large. 619 if (p == 32) { 620 c2 = (c1 >> 1) + (Ab >> 1) + (aB >> 1); 621 c2 += ((c1 & 0x1) + (Ab & 0x1) + (aB & 0x1)) >> 1; 622 c2 >>= (p - 1); 623 } else { 624 c2 = (c1 + Ab + aB) >> p; 625 } 626 627 ProdHi = AB + c2; 628 ''' 629 flag_code = ''' 630 if (ProdHi) { 631 PredcfofBits = PredcfofBits | (ext & (CFBit | OFBit)); 632 PredecfBit = PredecfBit | (ext & ECFBit); 633 } else { 634 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 635 PredecfBit = PredecfBit & ~(ext & ECFBit); 636 } 637 ''' 638 639 class Mulel(RdRegOp): 640 code = 'DestReg = merge(SrcReg1, ProdLow, dataSize);' 641 big_code = 'DestReg = ProdLow & mask(dataSize * 8);' 642 643 class Muleh(RdRegOp): 644 def __init__(self, dest, src1=None, flags=None, dataSize="env.dataSize"): 645 if not src1: 646 src1 = dest 647 super(RdRegOp, self).__init__(dest, src1, \ 648 "InstRegIndex(NUM_INTREGS)", flags, dataSize) 649 code = 'DestReg = merge(SrcReg1, ProdHi, dataSize);' 650 big_code = 'DestReg = ProdHi & mask(dataSize * 8);' 651 652 # One or two bit divide 653 class Div1(WrRegOp): 654 op_class = 'IntDivOp' 655 656 code = ''' 657 //These are temporaries so that modifying them later won't make 658 //the ISA parser think they're also sources. 659 uint64_t quotient = 0; 660 uint64_t remainder = psrc1; 661 //Similarly, this is a temporary so changing it doesn't make it 662 //a source. 663 uint64_t divisor = op2; 664 //This is a temporary just for consistency and clarity. 665 uint64_t dividend = remainder; 666 //Do the division. 667 if (divisor == 0) { 668 fault = std::make_shared<DivideError>(); 669 } else { 670 divide(dividend, divisor, quotient, remainder); 671 //Record the final results. 672 Remainder = remainder; 673 Quotient = quotient; 674 Divisor = divisor; 675 } 676 ''' 677 678 # Step divide 679 class Div2(RegOp): 680 op_class = 'IntDivOp' 681 682 divCode = ''' 683 uint64_t dividend = Remainder; 684 uint64_t divisor = Divisor; 685 uint64_t quotient = Quotient; 686 uint64_t remainder = dividend; 687 int remaining = op2; 688 //If we overshot, do nothing. This lets us unrool division loops a 689 //little. 690 if (divisor == 0) { 691 fault = std::make_shared<DivideError>(); 692 } else if (remaining) { 693 if (divisor & (ULL(1) << 63)) { 694 while (remaining && !(dividend & (ULL(1) << 63))) { 695 dividend = (dividend << 1) | 696 bits(SrcReg1, remaining - 1); 697 quotient <<= 1; 698 remaining--; 699 } 700 if (dividend & (ULL(1) << 63)) { 701 bool highBit = false; 702 if (dividend < divisor && remaining) { 703 highBit = true; 704 dividend = (dividend << 1) | 705 bits(SrcReg1, remaining - 1); 706 quotient <<= 1; 707 remaining--; 708 } 709 if (highBit || divisor <= dividend) { 710 quotient++; 711 dividend -= divisor; 712 } 713 } 714 remainder = dividend; 715 } else { 716 //Shift in bits from the low order portion of the dividend 717 while (dividend < divisor && remaining) { 718 dividend = (dividend << 1) | 719 bits(SrcReg1, remaining - 1); 720 quotient <<= 1; 721 remaining--; 722 } 723 remainder = dividend; 724 //Do the division. 725 divide(dividend, divisor, quotient, remainder); 726 } 727 } 728 //Keep track of how many bits there are still to pull in. 729 %s 730 //Record the final results 731 Remainder = remainder; 732 Quotient = quotient; 733 ''' 734 code = divCode % "DestReg = merge(DestReg, remaining, dataSize);" 735 big_code = divCode % "DestReg = remaining & mask(dataSize * 8);" 736 flag_code = ''' 737 if (remaining == 0) 738 PredezfBit = PredezfBit | (ext & EZFBit); 739 else 740 PredezfBit = PredezfBit & ~(ext & EZFBit); 741 ''' 742 743 class Divq(RdRegOp): 744 code = 'DestReg = merge(SrcReg1, Quotient, dataSize);' 745 big_code = 'DestReg = Quotient & mask(dataSize * 8);' 746 747 class Divr(RdRegOp): 748 code = 'DestReg = merge(SrcReg1, Remainder, dataSize);' 749 big_code = 'DestReg = Remainder & mask(dataSize * 8);' 750 751 class Mov(CondRegOp): 752 code = 'DestReg = merge(SrcReg1, op2, dataSize)' 753 else_code = 'DestReg = DestReg;' 754 755 # Shift instructions 756 757 class Sll(RegOp): 758 code = ''' 759 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 760 DestReg = merge(DestReg, psrc1 << shiftAmt, dataSize); 761 ''' 762 big_code = ''' 763 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 764 DestReg = (psrc1 << shiftAmt) & mask(dataSize * 8); 765 ''' 766 flag_code = ''' 767 // If the shift amount is zero, no flags should be modified. 768 if (shiftAmt) { 769 //Zero out any flags we might modify. This way we only have to 770 //worry about setting them. 771 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 772 PredecfBit = PredecfBit & ~(ext & ECFBit); 773 774 int CFBits = 0; 775 //Figure out if we -would- set the CF bits if requested. 776 if (shiftAmt <= dataSize * 8 && 777 bits(SrcReg1, dataSize * 8 - shiftAmt)) { 778 CFBits = 1; 779 } 780 781 //If some combination of the CF bits need to be set, set them. 782 if ((ext & (CFBit | ECFBit)) && CFBits) { 783 PredcfofBits = PredcfofBits | (ext & CFBit); 784 PredecfBit = PredecfBit | (ext & ECFBit); 785 } 786 787 //Figure out what the OF bit should be. 788 if ((ext & OFBit) && (CFBits ^ bits(DestReg, dataSize * 8 - 1))) 789 PredcfofBits = PredcfofBits | OFBit; 790 791 //Use the regular mechanisms to calculate the other flags. 792 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 793 PredezfBit, ext & ~(CFBit | ECFBit | OFBit), 794 DestReg, psrc1, op2); 795 796 PredezfBit = newFlags & EZFBit; 797 PreddfBit = newFlags & DFBit; 798 PredccFlagBits = newFlags & ccFlagMask; 799 } 800 ''' 801 802 class Srl(RegOp): 803 # Because what happens to the bits shift -in- on a right shift 804 # is not defined in the C/C++ standard, we have to mask them out 805 # to be sure they're zero. 806 code = ''' 807 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 808 uint64_t logicalMask = mask(dataSize * 8 - shiftAmt); 809 DestReg = merge(DestReg, (psrc1 >> shiftAmt) & logicalMask, dataSize); 810 ''' 811 big_code = ''' 812 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 813 uint64_t logicalMask = mask(dataSize * 8 - shiftAmt); 814 DestReg = (psrc1 >> shiftAmt) & logicalMask; 815 ''' 816 flag_code = ''' 817 // If the shift amount is zero, no flags should be modified. 818 if (shiftAmt) { 819 //Zero out any flags we might modify. This way we only have to 820 //worry about setting them. 821 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 822 PredecfBit = PredecfBit & ~(ext & ECFBit); 823 824 //If some combination of the CF bits need to be set, set them. 825 if ((ext & (CFBit | ECFBit)) && 826 shiftAmt <= dataSize * 8 && 827 bits(SrcReg1, shiftAmt - 1)) { 828 PredcfofBits = PredcfofBits | (ext & CFBit); 829 PredecfBit = PredecfBit | (ext & ECFBit); 830 } 831 832 //Figure out what the OF bit should be. 833 if ((ext & OFBit) && bits(SrcReg1, dataSize * 8 - 1)) 834 PredcfofBits = PredcfofBits | OFBit; 835 836 //Use the regular mechanisms to calculate the other flags. 837 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 838 PredezfBit, ext & ~(CFBit | ECFBit | OFBit), 839 DestReg, psrc1, op2); 840 841 PredezfBit = newFlags & EZFBit; 842 PreddfBit = newFlags & DFBit; 843 PredccFlagBits = newFlags & ccFlagMask; 844 } 845 ''' 846 847 class Sra(RegOp): 848 # Because what happens to the bits shift -in- on a right shift 849 # is not defined in the C/C++ standard, we have to sign extend 850 # them manually to be sure. 851 code = ''' 852 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 853 uint64_t arithMask = (shiftAmt == 0) ? 0 : 854 -bits(psrc1, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt); 855 DestReg = merge(DestReg, (psrc1 >> shiftAmt) | arithMask, dataSize); 856 ''' 857 big_code = ''' 858 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 859 uint64_t arithMask = (shiftAmt == 0) ? 0 : 860 -bits(psrc1, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt); 861 DestReg = ((psrc1 >> shiftAmt) | arithMask) & mask(dataSize * 8); 862 ''' 863 flag_code = ''' 864 // If the shift amount is zero, no flags should be modified. 865 if (shiftAmt) { 866 //Zero out any flags we might modify. This way we only have to 867 //worry about setting them. 868 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 869 PredecfBit = PredecfBit & ~(ext & ECFBit); 870 871 //If some combination of the CF bits need to be set, set them. 872 uint8_t effectiveShift = 873 (shiftAmt <= dataSize * 8) ? shiftAmt : (dataSize * 8); 874 if ((ext & (CFBit | ECFBit)) && 875 bits(SrcReg1, effectiveShift - 1)) { 876 PredcfofBits = PredcfofBits | (ext & CFBit); 877 PredecfBit = PredecfBit | (ext & ECFBit); 878 } 879 880 //Use the regular mechanisms to calculate the other flags. 881 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 882 PredezfBit, ext & ~(CFBit | ECFBit | OFBit), 883 DestReg, psrc1, op2); 884 885 PredezfBit = newFlags & EZFBit; 886 PreddfBit = newFlags & DFBit; 887 PredccFlagBits = newFlags & ccFlagMask; 888 } 889 ''' 890 891 class Ror(RegOp): 892 code = ''' 893 uint8_t shiftAmt = 894 (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 895 uint8_t realShiftAmt = shiftAmt % (dataSize * 8); 896 if (realShiftAmt) { 897 uint64_t top = psrc1 << (dataSize * 8 - realShiftAmt); 898 uint64_t bottom = bits(psrc1, dataSize * 8, realShiftAmt); 899 DestReg = merge(DestReg, top | bottom, dataSize); 900 } else 901 DestReg = merge(DestReg, DestReg, dataSize); 902 ''' 903 flag_code = ''' 904 // If the shift amount is zero, no flags should be modified. 905 if (shiftAmt) { 906 //Zero out any flags we might modify. This way we only have to 907 //worry about setting them. 908 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 909 PredecfBit = PredecfBit & ~(ext & ECFBit); 910 911 //Find the most and second most significant bits of the result. 912 int msb = bits(DestReg, dataSize * 8 - 1); 913 int smsb = bits(DestReg, dataSize * 8 - 2); 914 //If some combination of the CF bits need to be set, set them. 915 if ((ext & (CFBit | ECFBit)) && msb) { 916 PredcfofBits = PredcfofBits | (ext & CFBit); 917 PredecfBit = PredecfBit | (ext & ECFBit); 918 } 919 920 //Figure out what the OF bit should be. 921 if ((ext & OFBit) && (msb ^ smsb)) 922 PredcfofBits = PredcfofBits | OFBit; 923 924 //Use the regular mechanisms to calculate the other flags. 925 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 926 PredezfBit, ext & ~(CFBit | ECFBit | OFBit), 927 DestReg, psrc1, op2); 928 929 PredezfBit = newFlags & EZFBit; 930 PreddfBit = newFlags & DFBit; 931 PredccFlagBits = newFlags & ccFlagMask; 932 } 933 ''' 934 935 class Rcr(RegOp): 936 code = ''' 937 uint8_t shiftAmt = 938 (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 939 uint8_t realShiftAmt = shiftAmt % (dataSize * 8 + 1); 940 if (realShiftAmt) { 941 CCFlagBits flags = cfofBits; 942 uint64_t top = flags.cf << (dataSize * 8 - realShiftAmt); 943 if (realShiftAmt > 1) 944 top |= psrc1 << (dataSize * 8 - realShiftAmt + 1); 945 uint64_t bottom = bits(psrc1, dataSize * 8 - 1, realShiftAmt); 946 DestReg = merge(DestReg, top | bottom, dataSize); 947 } else 948 DestReg = merge(DestReg, DestReg, dataSize); 949 ''' 950 flag_code = ''' 951 // If the shift amount is zero, no flags should be modified. 952 if (shiftAmt) { 953 int origCFBit = (cfofBits & CFBit) ? 1 : 0; 954 //Zero out any flags we might modify. This way we only have to 955 //worry about setting them. 956 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 957 PredecfBit = PredecfBit & ~(ext & ECFBit); 958 959 //Figure out what the OF bit should be. 960 if ((ext & OFBit) && (origCFBit ^ 961 bits(SrcReg1, dataSize * 8 - 1))) { 962 PredcfofBits = PredcfofBits | OFBit; 963 } 964 //If some combination of the CF bits need to be set, set them. 965 if ((ext & (CFBit | ECFBit)) && 966 (realShiftAmt == 0) ? origCFBit : 967 bits(SrcReg1, realShiftAmt - 1)) { 968 PredcfofBits = PredcfofBits | (ext & CFBit); 969 PredecfBit = PredecfBit | (ext & ECFBit); 970 } 971 972 //Use the regular mechanisms to calculate the other flags. 973 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 974 PredezfBit, ext & ~(CFBit | ECFBit | OFBit), 975 DestReg, psrc1, op2); 976 977 PredezfBit = newFlags & EZFBit; 978 PreddfBit = newFlags & DFBit; 979 PredccFlagBits = newFlags & ccFlagMask; 980 } 981 ''' 982 983 class Rol(RegOp): 984 code = ''' 985 uint8_t shiftAmt = 986 (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 987 uint8_t realShiftAmt = shiftAmt % (dataSize * 8); 988 if (realShiftAmt) { 989 uint64_t top = psrc1 << realShiftAmt; 990 uint64_t bottom = 991 bits(psrc1, dataSize * 8 - 1, dataSize * 8 - realShiftAmt); 992 DestReg = merge(DestReg, top | bottom, dataSize); 993 } else 994 DestReg = merge(DestReg, DestReg, dataSize); 995 ''' 996 flag_code = ''' 997 // If the shift amount is zero, no flags should be modified. 998 if (shiftAmt) { 999 //Zero out any flags we might modify. This way we only have to 1000 //worry about setting them. 1001 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 1002 PredecfBit = PredecfBit & ~(ext & ECFBit); 1003 1004 //The CF bits, if set, would be set to the lsb of the result. 1005 int lsb = DestReg & 0x1; 1006 int msb = bits(DestReg, dataSize * 8 - 1); 1007 //If some combination of the CF bits need to be set, set them. 1008 if ((ext & (CFBit | ECFBit)) && lsb) { 1009 PredcfofBits = PredcfofBits | (ext & CFBit); 1010 PredecfBit = PredecfBit | (ext & ECFBit); 1011 } 1012 1013 //Figure out what the OF bit should be. 1014 if ((ext & OFBit) && (msb ^ lsb)) 1015 PredcfofBits = PredcfofBits | OFBit; 1016 1017 //Use the regular mechanisms to calculate the other flags. 1018 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 1019 PredezfBit, ext & ~(CFBit | ECFBit | OFBit), 1020 DestReg, psrc1, op2); 1021 1022 PredezfBit = newFlags & EZFBit; 1023 PreddfBit = newFlags & DFBit; 1024 PredccFlagBits = newFlags & ccFlagMask; 1025 } 1026 ''' 1027 1028 class Rcl(RegOp): 1029 code = ''' 1030 uint8_t shiftAmt = 1031 (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 1032 uint8_t realShiftAmt = shiftAmt % (dataSize * 8 + 1); 1033 if (realShiftAmt) { 1034 CCFlagBits flags = cfofBits; 1035 uint64_t top = psrc1 << realShiftAmt; 1036 uint64_t bottom = flags.cf << (realShiftAmt - 1); 1037 if(shiftAmt > 1) 1038 bottom |= 1039 bits(psrc1, dataSize * 8 - 1, 1040 dataSize * 8 - realShiftAmt + 1); 1041 DestReg = merge(DestReg, top | bottom, dataSize); 1042 } else 1043 DestReg = merge(DestReg, DestReg, dataSize); 1044 ''' 1045 flag_code = ''' 1046 // If the shift amount is zero, no flags should be modified. 1047 if (shiftAmt) { 1048 int origCFBit = (cfofBits & CFBit) ? 1 : 0; 1049 //Zero out any flags we might modify. This way we only have to 1050 //worry about setting them. 1051 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 1052 PredecfBit = PredecfBit & ~(ext & ECFBit); 1053 1054 int msb = bits(DestReg, dataSize * 8 - 1); 1055 int CFBits = bits(SrcReg1, dataSize * 8 - realShiftAmt); 1056 //If some combination of the CF bits need to be set, set them. 1057 if ((ext & (CFBit | ECFBit)) && 1058 (realShiftAmt == 0) ? origCFBit : CFBits) { 1059 PredcfofBits = PredcfofBits | (ext & CFBit); 1060 PredecfBit = PredecfBit | (ext & ECFBit); 1061 } 1062 1063 //Figure out what the OF bit should be. 1064 if ((ext & OFBit) && (msb ^ CFBits)) 1065 PredcfofBits = PredcfofBits | OFBit; 1066 1067 //Use the regular mechanisms to calculate the other flags. 1068 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 1069 PredezfBit, ext & ~(CFBit | ECFBit | OFBit), 1070 DestReg, psrc1, op2); 1071 1072 PredezfBit = newFlags & EZFBit; 1073 PreddfBit = newFlags & DFBit; 1074 PredccFlagBits = newFlags & ccFlagMask; 1075 } 1076 ''' 1077 1078 class Sld(RegOp): 1079 sldCode = ''' 1080 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 1081 uint8_t dataBits = dataSize * 8; 1082 uint8_t realShiftAmt = shiftAmt %% (2 * dataBits); 1083 uint64_t result; 1084 if (realShiftAmt == 0) { 1085 result = psrc1; 1086 } else if (realShiftAmt < dataBits) { 1087 result = (psrc1 << realShiftAmt) | 1088 (DoubleBits >> (dataBits - realShiftAmt)); 1089 } else { 1090 result = (DoubleBits << (realShiftAmt - dataBits)) | 1091 (psrc1 >> (2 * dataBits - realShiftAmt)); 1092 } 1093 %s 1094 ''' 1095 code = sldCode % "DestReg = merge(DestReg, result, dataSize);" 1096 big_code = sldCode % "DestReg = result & mask(dataSize * 8);" 1097 flag_code = ''' 1098 // If the shift amount is zero, no flags should be modified. 1099 if (shiftAmt) { 1100 //Zero out any flags we might modify. This way we only have to 1101 //worry about setting them. 1102 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 1103 PredecfBit = PredecfBit & ~(ext & ECFBit); 1104 int CFBits = 0; 1105 1106 //Figure out if we -would- set the CF bits if requested. 1107 if ((realShiftAmt == 0 && 1108 bits(DoubleBits, 0)) || 1109 (realShiftAmt <= dataBits && 1110 bits(SrcReg1, dataBits - realShiftAmt)) || 1111 (realShiftAmt > dataBits && 1112 bits(DoubleBits, 2 * dataBits - realShiftAmt))) { 1113 CFBits = 1; 1114 } 1115 1116 //If some combination of the CF bits need to be set, set them. 1117 if ((ext & (CFBit | ECFBit)) && CFBits) { 1118 PredcfofBits = PredcfofBits | (ext & CFBit); 1119 PredecfBit = PredecfBit | (ext & ECFBit); 1120 } 1121 1122 //Figure out what the OF bit should be. 1123 if ((ext & OFBit) && (bits(SrcReg1, dataBits - 1) ^ 1124 bits(result, dataBits - 1))) 1125 PredcfofBits = PredcfofBits | OFBit; 1126 1127 //Use the regular mechanisms to calculate the other flags. 1128 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 1129 PredezfBit, ext & ~(CFBit | ECFBit | OFBit), 1130 DestReg, psrc1, op2); 1131 1132 PredezfBit = newFlags & EZFBit; 1133 PreddfBit = newFlags & DFBit; 1134 PredccFlagBits = newFlags & ccFlagMask; 1135 } 1136 ''' 1137 1138 class Srd(RegOp): 1139 srdCode = ''' 1140 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); 1141 uint8_t dataBits = dataSize * 8; 1142 uint8_t realShiftAmt = shiftAmt %% (2 * dataBits); 1143 uint64_t result; 1144 if (realShiftAmt == 0) { 1145 result = psrc1; 1146 } else if (realShiftAmt < dataBits) { 1147 // Because what happens to the bits shift -in- on a right 1148 // shift is not defined in the C/C++ standard, we have to 1149 // mask them out to be sure they're zero. 1150 uint64_t logicalMask = mask(dataBits - realShiftAmt); 1151 result = ((psrc1 >> realShiftAmt) & logicalMask) | 1152 (DoubleBits << (dataBits - realShiftAmt)); 1153 } else { 1154 uint64_t logicalMask = mask(2 * dataBits - realShiftAmt); 1155 result = ((DoubleBits >> (realShiftAmt - dataBits)) & 1156 logicalMask) | 1157 (psrc1 << (2 * dataBits - realShiftAmt)); 1158 } 1159 %s 1160 ''' 1161 code = srdCode % "DestReg = merge(DestReg, result, dataSize);" 1162 big_code = srdCode % "DestReg = result & mask(dataSize * 8);" 1163 flag_code = ''' 1164 // If the shift amount is zero, no flags should be modified. 1165 if (shiftAmt) { 1166 //Zero out any flags we might modify. This way we only have to 1167 //worry about setting them. 1168 PredcfofBits = PredcfofBits & ~(ext & (CFBit | OFBit)); 1169 PredecfBit = PredecfBit & ~(ext & ECFBit); 1170 int CFBits = 0; 1171 1172 //If some combination of the CF bits need to be set, set them. 1173 if ((realShiftAmt == 0 && 1174 bits(DoubleBits, dataBits - 1)) || 1175 (realShiftAmt <= dataBits && 1176 bits(SrcReg1, realShiftAmt - 1)) || 1177 (realShiftAmt > dataBits && 1178 bits(DoubleBits, realShiftAmt - dataBits - 1))) { 1179 CFBits = 1; 1180 } 1181 1182 //If some combination of the CF bits need to be set, set them. 1183 if ((ext & (CFBit | ECFBit)) && CFBits) { 1184 PredcfofBits = PredcfofBits | (ext & CFBit); 1185 PredecfBit = PredecfBit | (ext & ECFBit); 1186 } 1187 1188 //Figure out what the OF bit should be. 1189 if ((ext & OFBit) && (bits(SrcReg1, dataBits - 1) ^ 1190 bits(result, dataBits - 1))) 1191 PredcfofBits = PredcfofBits | OFBit; 1192 1193 //Use the regular mechanisms to calculate the other flags. 1194 uint64_t newFlags = genFlags(PredccFlagBits | PreddfBit | 1195 PredezfBit, ext & ~(CFBit | ECFBit | OFBit), 1196 DestReg, psrc1, op2); 1197 1198 PredezfBit = newFlags & EZFBit; 1199 PreddfBit = newFlags & DFBit; 1200 PredccFlagBits = newFlags & ccFlagMask; 1201 } 1202 ''' 1203 1204 class Mdb(WrRegOp): 1205 code = 'DoubleBits = psrc1 ^ op2;' 1206 1207 class Wrip(WrRegOp, CondRegOp): 1208 code = 'NRIP = psrc1 + sop2 + CSBase;' 1209 else_code = "NRIP = NRIP;" 1210 1211 class Wruflags(WrRegOp): 1212 code = ''' 1213 uint64_t newFlags = psrc1 ^ op2; 1214 cfofBits = newFlags & cfofMask; 1215 ecfBit = newFlags & ECFBit; 1216 ezfBit = newFlags & EZFBit; 1217 dfBit = newFlags & DFBit; 1218 ccFlagBits = newFlags & ccFlagMask; 1219 ''' 1220 1221 class Wrflags(WrRegOp): 1222 code = ''' 1223 RegVal newFlags = psrc1 ^ op2; 1224 RegVal userFlagMask = 0xDD5; 1225 1226 // Get only the user flags 1227 ccFlagBits = newFlags & ccFlagMask; 1228 dfBit = newFlags & DFBit; 1229 cfofBits = newFlags & cfofMask; 1230 ecfBit = 0; 1231 ezfBit = 0; 1232 1233 // Get everything else 1234 nccFlagBits = newFlags & ~userFlagMask; 1235 ''' 1236 1237 class Rdip(RdRegOp): 1238 code = 'DestReg = NRIP - CSBase;' 1239 1240 class Ruflags(RdRegOp): 1241 code = 'DestReg = ccFlagBits | cfofBits | dfBit | ecfBit | ezfBit;' 1242 1243 class Rflags(RdRegOp): 1244 code = ''' 1245 DestReg = ccFlagBits | cfofBits | dfBit | 1246 ecfBit | ezfBit | nccFlagBits; 1247 ''' 1248 1249 class Ruflag(RegOp): 1250 code = ''' 1251 int flag = bits(ccFlagBits | cfofBits | dfBit | 1252 ecfBit | ezfBit, imm8); 1253 DestReg = merge(DestReg, flag, dataSize); 1254 ezfBit = (flag == 0) ? EZFBit : 0; 1255 ''' 1256 1257 big_code = ''' 1258 int flag = bits(ccFlagBits | cfofBits | dfBit | 1259 ecfBit | ezfBit, imm8); 1260 DestReg = flag & mask(dataSize * 8); 1261 ezfBit = (flag == 0) ? EZFBit : 0; 1262 ''' 1263 1264 def __init__(self, dest, imm, flags=None, \ 1265 dataSize="env.dataSize"): 1266 super(Ruflag, self).__init__(dest, \ 1267 "InstRegIndex(NUM_INTREGS)", imm, flags, dataSize) 1268 1269 class Rflag(RegOp): 1270 code = ''' 1271 RegVal flagMask = 0x3F7FDD5; 1272 RegVal flags = (nccFlagBits | ccFlagBits | cfofBits | dfBit | 1273 ecfBit | ezfBit) & flagMask; 1274 1275 int flag = bits(flags, imm8); 1276 DestReg = merge(DestReg, flag, dataSize); 1277 ezfBit = (flag == 0) ? EZFBit : 0; 1278 ''' 1279 1280 big_code = ''' 1281 RegVal flagMask = 0x3F7FDD5; 1282 RegVal flags = (nccFlagBits | ccFlagBits | cfofBits | dfBit | 1283 ecfBit | ezfBit) & flagMask; 1284 1285 int flag = bits(flags, imm8); 1286 DestReg = flag & mask(dataSize * 8); 1287 ezfBit = (flag == 0) ? EZFBit : 0; 1288 ''' 1289 1290 def __init__(self, dest, imm, flags=None, \ 1291 dataSize="env.dataSize"): 1292 super(Rflag, self).__init__(dest, \ 1293 "InstRegIndex(NUM_INTREGS)", imm, flags, dataSize) 1294 1295 class Sext(RegOp): 1296 code = ''' 1297 RegVal val = psrc1; 1298 // Mask the bit position so that it wraps. 1299 int bitPos = op2 & (dataSize * 8 - 1); 1300 int sign_bit = bits(val, bitPos, bitPos); 1301 uint64_t maskVal = mask(bitPos+1); 1302 val = sign_bit ? (val | ~maskVal) : (val & maskVal); 1303 DestReg = merge(DestReg, val, dataSize); 1304 ''' 1305 1306 big_code = ''' 1307 RegVal val = psrc1; 1308 // Mask the bit position so that it wraps. 1309 int bitPos = op2 & (dataSize * 8 - 1); 1310 int sign_bit = bits(val, bitPos, bitPos); 1311 uint64_t maskVal = mask(bitPos+1); 1312 val = sign_bit ? (val | ~maskVal) : (val & maskVal); 1313 DestReg = val & mask(dataSize * 8); 1314 ''' 1315 1316 flag_code = ''' 1317 if (!sign_bit) { 1318 PredccFlagBits = PredccFlagBits & ~(ext & (ZFBit)); 1319 PredcfofBits = PredcfofBits & ~(ext & (CFBit)); 1320 PredecfBit = PredecfBit & ~(ext & ECFBit); 1321 PredezfBit = PredezfBit & ~(ext & EZFBit); 1322 } else { 1323 PredccFlagBits = PredccFlagBits | (ext & (ZFBit)); 1324 PredcfofBits = PredcfofBits | (ext & (CFBit)); 1325 PredecfBit = PredecfBit | (ext & ECFBit); 1326 PredezfBit = PredezfBit | (ext & EZFBit); 1327 } 1328 ''' 1329 1330 class Zext(RegOp): 1331 code = 'DestReg = merge(DestReg, bits(psrc1, op2, 0), dataSize);' 1332 big_code = 'DestReg = bits(psrc1, op2, 0) & mask(dataSize * 8);' 1333 1334 class Rddr(RegOp): 1335 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 1336 super(Rddr, self).__init__(dest, \ 1337 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize) 1338 rdrCode = ''' 1339 CR4 cr4 = CR4Op; 1340 DR7 dr7 = DR7Op; 1341 if ((cr4.de == 1 && (src1 == 4 || src1 == 5)) || src1 >= 8) { 1342 fault = std::make_shared<InvalidOpcode>(); 1343 } else if (dr7.gd) { 1344 fault = std::make_shared<DebugException>(); 1345 } else { 1346 %s 1347 } 1348 ''' 1349 code = rdrCode % "DestReg = merge(DestReg, DebugSrc1, dataSize);" 1350 big_code = rdrCode % "DestReg = DebugSrc1 & mask(dataSize * 8);" 1351 1352 class Wrdr(RegOp): 1353 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 1354 super(Wrdr, self).__init__(dest, \ 1355 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize) 1356 code = ''' 1357 CR4 cr4 = CR4Op; 1358 DR7 dr7 = DR7Op; 1359 if ((cr4.de == 1 && (dest == 4 || dest == 5)) || dest >= 8) { 1360 fault = std::make_shared<InvalidOpcode>(); 1361 } else if ((dest == 6 || dest == 7) && bits(psrc1, 63, 32) && 1362 machInst.mode.mode == LongMode) { 1363 fault = std::make_shared<GeneralProtection>(0); 1364 } else if (dr7.gd) { 1365 fault = std::make_shared<DebugException>(); 1366 } else { 1367 DebugDest = psrc1; 1368 } 1369 ''' 1370 1371 class Rdcr(RegOp): 1372 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 1373 super(Rdcr, self).__init__(dest, \ 1374 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize) 1375 rdcrCode = ''' 1376 if (src1 == 1 || (src1 > 4 && src1 < 8) || (src1 > 8)) { 1377 fault = std::make_shared<InvalidOpcode>(); 1378 } else { 1379 %s 1380 } 1381 ''' 1382 code = rdcrCode % "DestReg = merge(DestReg, ControlSrc1, dataSize);" 1383 big_code = rdcrCode % "DestReg = ControlSrc1 & mask(dataSize * 8);" 1384 1385 class Wrcr(RegOp): 1386 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 1387 super(Wrcr, self).__init__(dest, \ 1388 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize) 1389 code = ''' 1390 if (dest == 1 || (dest > 4 && dest < 8) || (dest > 8)) { 1391 fault = std::make_shared<InvalidOpcode>(); 1392 } else { 1393 RegVal newVal = psrc1; 1394 1395 // Check for any modifications that would cause a fault. 1396 switch(dest) { 1397 case 0: 1398 { 1399 Efer efer = EferOp; 1400 CR0 cr0 = newVal; 1401 CR4 oldCr4 = CR4Op; 1402 if (bits(newVal, 63, 32) || 1403 (!cr0.pe && cr0.pg) || 1404 (!cr0.cd && cr0.nw) || 1405 (cr0.pg && efer.lme && !oldCr4.pae)) 1406 fault = std::make_shared<GeneralProtection>(0); 1407 } 1408 break; 1409 case 2: 1410 break; 1411 case 3: 1412 break; 1413 case 4: 1414 { 1415 CR4 cr4 = newVal; 1416 // PAE can't be disabled in long mode. 1417 if (bits(newVal, 63, 11) || 1418 (machInst.mode.mode == LongMode && !cr4.pae)) 1419 fault = std::make_shared<GeneralProtection>(0); 1420 } 1421 break; 1422 case 8: 1423 { 1424 if (bits(newVal, 63, 4)) 1425 fault = std::make_shared<GeneralProtection>(0); 1426 } 1427 break; 1428 default: 1429 fault = std::make_shared<GenericISA::M5PanicFault>( 1430 "Unrecognized control register %d.\\n", dest); 1431 } 1432 ControlDest = newVal; 1433 } 1434 ''' 1435 1436 # Microops for manipulating segmentation registers 1437 class SegOp(CondRegOp): 1438 abstract = True 1439 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 1440 super(SegOp, self).__init__(dest, \ 1441 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize) 1442 1443 class Wrbase(SegOp): 1444 code = ''' 1445 SegBaseDest = psrc1; 1446 ''' 1447 1448 class Wrlimit(SegOp): 1449 code = ''' 1450 SegLimitDest = psrc1; 1451 ''' 1452 1453 class Wrsel(SegOp): 1454 code = ''' 1455 SegSelDest = psrc1; 1456 ''' 1457 1458 class WrAttr(SegOp): 1459 code = ''' 1460 SegAttrDest = psrc1; 1461 ''' 1462 1463 class Rdbase(SegOp): 1464 code = 'DestReg = merge(DestReg, SegBaseSrc1, dataSize);' 1465 big_code = 'DestReg = SegBaseSrc1 & mask(dataSize * 8);' 1466 1467 class Rdlimit(SegOp): 1468 code = 'DestReg = merge(DestReg, SegLimitSrc1, dataSize);' 1469 big_code = 'DestReg = SegLimitSrc1 & mask(dataSize * 8);' 1470 1471 class RdAttr(SegOp): 1472 code = 'DestReg = merge(DestReg, SegAttrSrc1, dataSize);' 1473 big_code = 'DestReg = SegAttrSrc1 & mask(dataSize * 8);' 1474 1475 class Rdsel(SegOp): 1476 code = 'DestReg = merge(DestReg, SegSelSrc1, dataSize);' 1477 big_code = 'DestReg = SegSelSrc1 & mask(dataSize * 8);' 1478 1479 class Rdval(RegOp): 1480 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 1481 super(Rdval, self).__init__(dest, src1, \ 1482 "InstRegIndex(NUM_INTREGS)", flags, dataSize) 1483 code = ''' 1484 DestReg = MiscRegSrc1; 1485 ''' 1486 1487 class Wrval(RegOp): 1488 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 1489 super(Wrval, self).__init__(dest, src1, \ 1490 "InstRegIndex(NUM_INTREGS)", flags, dataSize) 1491 code = ''' 1492 MiscRegDest = SrcReg1; 1493 ''' 1494 1495 class Chks(RegOp): 1496 def __init__(self, dest, src1, src2=0, 1497 flags=None, dataSize="env.dataSize"): 1498 super(Chks, self).__init__(dest, 1499 src1, src2, flags, dataSize) 1500 code = ''' 1501 // The selector is in source 1 and can be at most 16 bits. 1502 SegSelector selector = DestReg; 1503 SegDescriptor desc = SrcReg1; 1504 HandyM5Reg m5reg = M5Reg; 1505 1506 switch (imm8) 1507 { 1508 case SegNoCheck: 1509 break; 1510 case SegCSCheck: 1511 // Make sure it's the right type 1512 if (desc.s == 0 || desc.type.codeOrData != 1) { 1513 fault = std::make_shared<GeneralProtection>(0); 1514 } else if (m5reg.cpl != desc.dpl) { 1515 fault = std::make_shared<GeneralProtection>(0); 1516 } 1517 break; 1518 case SegCallGateCheck: 1519 fault = std::make_shared<GenericISA::M5PanicFault>( 1520 "CS checks for far " 1521 "calls/jumps through call gates not implemented.\\n"); 1522 break; 1523 case SegSoftIntGateCheck: 1524 // Check permissions. 1525 if (desc.dpl < m5reg.cpl) { 1526 fault = std::make_shared<GeneralProtection>(selector); 1527 break; 1528 } 1529 M5_FALLTHROUGH; 1530 case SegIntGateCheck: 1531 // Make sure the gate's the right type. 1532 if ((m5reg.mode == LongMode && (desc.type & 0xe) != 0xe) || 1533 ((desc.type & 0x6) != 0x6)) { 1534 fault = std::make_shared<GeneralProtection>(0); 1535 } 1536 break; 1537 case SegSSCheck: 1538 if (selector.si || selector.ti) { 1539 if (!desc.p) { 1540 fault = std::make_shared<StackFault>(selector); 1541 } else if (!(desc.s == 1 && desc.type.codeOrData == 0 && 1542 desc.type.w) || 1543 (desc.dpl != m5reg.cpl) || 1544 (selector.rpl != m5reg.cpl)) { 1545 fault = std::make_shared<GeneralProtection>(selector); 1546 } 1547 } else if (m5reg.submode != SixtyFourBitMode || 1548 m5reg.cpl == 3) { 1549 fault = std::make_shared<GeneralProtection>(selector); 1550 } 1551 break; 1552 case SegIretCheck: 1553 { 1554 if ((!selector.si && !selector.ti) || 1555 (selector.rpl < m5reg.cpl) || 1556 !(desc.s == 1 && desc.type.codeOrData == 1) || 1557 (!desc.type.c && desc.dpl != selector.rpl) || 1558 (desc.type.c && desc.dpl > selector.rpl)) { 1559 fault = std::make_shared<GeneralProtection>(selector); 1560 } else if (!desc.p) { 1561 fault = std::make_shared<SegmentNotPresent>(selector); 1562 } 1563 break; 1564 } 1565 case SegIntCSCheck: 1566 if (m5reg.mode == LongMode) { 1567 if (desc.l != 1 || desc.d != 0) { 1568 fault = std::make_shared<GeneralProtection>(selector); 1569 } 1570 } else { 1571 fault = std::make_shared<GenericISA::M5PanicFault>( 1572 "Interrupt CS " 1573 "checks not implemented in legacy mode.\\n"); 1574 } 1575 break; 1576 case SegTRCheck: 1577 if (!selector.si || selector.ti) { 1578 fault = std::make_shared<GeneralProtection>(selector); 1579 } 1580 break; 1581 case SegTSSCheck: 1582 if (!desc.p) { 1583 fault = std::make_shared<SegmentNotPresent>(selector); 1584 } else if (!(desc.type == 0x9 || 1585 (desc.type == 1 && 1586 m5reg.mode != LongMode))) { 1587 fault = std::make_shared<GeneralProtection>(selector); 1588 } 1589 break; 1590 case SegInGDTCheck: 1591 if (selector.ti) { 1592 fault = std::make_shared<GeneralProtection>(selector); 1593 } 1594 break; 1595 case SegLDTCheck: 1596 if (!desc.p) { 1597 fault = std::make_shared<SegmentNotPresent>(selector); 1598 } else if (desc.type != 0x2) { 1599 fault = std::make_shared<GeneralProtection>(selector); 1600 } 1601 break; 1602 default: 1603 fault = std::make_shared<GenericISA::M5PanicFault>( 1604 "Undefined segment check type.\\n"); 1605 } 1606 ''' 1607 flag_code = ''' 1608 // Check for a NULL selector and set ZF,EZF appropriately. 1609 PredccFlagBits = PredccFlagBits & ~(ext & ZFBit); 1610 PredezfBit = PredezfBit & ~(ext & EZFBit); 1611 1612 if (!selector.si && !selector.ti) { 1613 PredccFlagBits = PredccFlagBits | (ext & ZFBit); 1614 PredezfBit = PredezfBit | (ext & EZFBit); 1615 } 1616 ''' 1617 1618 class Wrdh(RegOp): 1619 code = ''' 1620 SegDescriptor desc = SrcReg1; 1621 1622 uint64_t target = bits(SrcReg2, 31, 0) << 32; 1623 switch(desc.type) { 1624 case LDT64: 1625 case AvailableTSS64: 1626 case BusyTSS64: 1627 replaceBits(target, 31, 0, desc.base); 1628 break; 1629 case CallGate64: 1630 case IntGate64: 1631 case TrapGate64: 1632 replaceBits(target, 15, 0, bits(desc, 15, 0)); 1633 replaceBits(target, 31, 16, bits(desc, 63, 48)); 1634 break; 1635 default: 1636 fault = std::make_shared<GenericISA::M5PanicFault>( 1637 "Wrdh used with wrong descriptor type!\\n"); 1638 } 1639 DestReg = target; 1640 ''' 1641 1642 class Wrtsc(WrRegOp): 1643 code = ''' 1644 TscOp = psrc1; 1645 ''' 1646 1647 class Rdtsc(RdRegOp): 1648 code = ''' 1649 DestReg = TscOp; 1650 ''' 1651 1652 class Rdm5reg(RdRegOp): 1653 code = ''' 1654 DestReg = M5Reg; 1655 ''' 1656 1657 class Wrdl(RegOp): 1658 code = ''' 1659 SegDescriptor desc = SrcReg1; 1660 SegSelector selector = SrcReg2; 1661 // This while loop is so we can use break statements in the code 1662 // below to skip the rest of this section without a bunch of 1663 // nesting. 1664 while (true) { 1665 if (selector.si || selector.ti) { 1666 if (!desc.p) { 1667 fault = std::make_shared<GenericISA::M5PanicFault>( 1668 "Segment not present.\\n"); 1669 break; 1670 } 1671 SegAttr attr = 0; 1672 attr.dpl = desc.dpl; 1673 attr.unusable = 0; 1674 attr.defaultSize = desc.d; 1675 attr.longMode = desc.l; 1676 attr.avl = desc.avl; 1677 attr.granularity = desc.g; 1678 attr.present = desc.p; 1679 attr.system = desc.s; 1680 attr.type = desc.type; 1681 if (!desc.s) { 1682 // The expand down bit happens to be set for gates. 1683 if (desc.type.e) { 1684 fault = std::make_shared<GenericISA::M5PanicFault>( 1685 "Gate descriptor encountered.\\n"); 1686 break; 1687 } 1688 attr.readable = 1; 1689 attr.writable = 1; 1690 attr.expandDown = 0; 1691 } else { 1692 if (desc.type.codeOrData) { 1693 attr.expandDown = 0; 1694 attr.readable = desc.type.r; 1695 attr.writable = 0; 1696 } else { 1697 attr.expandDown = desc.type.e; 1698 attr.readable = 1; 1699 attr.writable = desc.type.w; 1700 } 1701 } 1702 SegBaseDest = desc.base; 1703 SegLimitDest = desc.limit; 1704 SegAttrDest = attr; 1705 } else { 1706 SegBaseDest = SegBaseDest; 1707 SegLimitDest = SegLimitDest; 1708 SegAttrDest = SegAttrDest; 1709 } 1710 break; 1711 } 1712 ''' 1713 1714 class Wrxftw(WrRegOp): 1715 def __init__(self, src1, **kwargs): 1716 super(Wrxftw, self).__init__(src1, "InstRegIndex(NUM_INTREGS)", \ 1717 **kwargs) 1718 1719 code = ''' 1720 FTW = X86ISA::convX87XTagsToTags(SrcReg1); 1721 ''' 1722 1723 class Rdxftw(RdRegOp): 1724 code = ''' 1725 DestReg = X86ISA::convX87TagsToXTags(FTW); 1726 ''' 1727}}; 1728