regop.isa revision 12588:c007da6c777a
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 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(ExecContext *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 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 MiscReg newFlags = psrc1 ^ op2; 1224 MiscReg 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 MiscReg flagMask = 0x3F7FDD5; 1272 MiscReg 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 MiscReg flagMask = 0x3F7FDD5; 1282 MiscReg 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 IntReg 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 IntReg 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 // There are *s in the line below so it doesn't confuse the 1394 // parser. They may be unnecessary. 1395 //Mis*cReg old*Val = pick(Cont*rolDest, 0, dat*aSize); 1396 MiscReg newVal = psrc1; 1397 1398 // Check for any modifications that would cause a fault. 1399 switch(dest) { 1400 case 0: 1401 { 1402 Efer efer = EferOp; 1403 CR0 cr0 = newVal; 1404 CR4 oldCr4 = CR4Op; 1405 if (bits(newVal, 63, 32) || 1406 (!cr0.pe && cr0.pg) || 1407 (!cr0.cd && cr0.nw) || 1408 (cr0.pg && efer.lme && !oldCr4.pae)) 1409 fault = std::make_shared<GeneralProtection>(0); 1410 } 1411 break; 1412 case 2: 1413 break; 1414 case 3: 1415 break; 1416 case 4: 1417 { 1418 CR4 cr4 = newVal; 1419 // PAE can't be disabled in long mode. 1420 if (bits(newVal, 63, 11) || 1421 (machInst.mode.mode == LongMode && !cr4.pae)) 1422 fault = std::make_shared<GeneralProtection>(0); 1423 } 1424 break; 1425 case 8: 1426 { 1427 if (bits(newVal, 63, 4)) 1428 fault = std::make_shared<GeneralProtection>(0); 1429 } 1430 break; 1431 default: 1432 fault = std::make_shared<GenericISA::M5PanicFault>( 1433 "Unrecognized control register %d.\\n", dest); 1434 } 1435 ControlDest = newVal; 1436 } 1437 ''' 1438 1439 # Microops for manipulating segmentation registers 1440 class SegOp(CondRegOp): 1441 abstract = True 1442 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 1443 super(SegOp, self).__init__(dest, \ 1444 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize) 1445 1446 class Wrbase(SegOp): 1447 code = ''' 1448 SegBaseDest = psrc1; 1449 ''' 1450 1451 class Wrlimit(SegOp): 1452 code = ''' 1453 SegLimitDest = psrc1; 1454 ''' 1455 1456 class Wrsel(SegOp): 1457 code = ''' 1458 SegSelDest = psrc1; 1459 ''' 1460 1461 class WrAttr(SegOp): 1462 code = ''' 1463 SegAttrDest = psrc1; 1464 ''' 1465 1466 class Rdbase(SegOp): 1467 code = 'DestReg = merge(DestReg, SegBaseSrc1, dataSize);' 1468 big_code = 'DestReg = SegBaseSrc1 & mask(dataSize * 8);' 1469 1470 class Rdlimit(SegOp): 1471 code = 'DestReg = merge(DestReg, SegLimitSrc1, dataSize);' 1472 big_code = 'DestReg = SegLimitSrc1 & mask(dataSize * 8);' 1473 1474 class RdAttr(SegOp): 1475 code = 'DestReg = merge(DestReg, SegAttrSrc1, dataSize);' 1476 big_code = 'DestReg = SegAttrSrc1 & mask(dataSize * 8);' 1477 1478 class Rdsel(SegOp): 1479 code = 'DestReg = merge(DestReg, SegSelSrc1, dataSize);' 1480 big_code = 'DestReg = SegSelSrc1 & mask(dataSize * 8);' 1481 1482 class Rdval(RegOp): 1483 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 1484 super(Rdval, self).__init__(dest, src1, \ 1485 "InstRegIndex(NUM_INTREGS)", flags, dataSize) 1486 code = ''' 1487 DestReg = MiscRegSrc1; 1488 ''' 1489 1490 class Wrval(RegOp): 1491 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"): 1492 super(Wrval, self).__init__(dest, src1, \ 1493 "InstRegIndex(NUM_INTREGS)", flags, dataSize) 1494 code = ''' 1495 MiscRegDest = SrcReg1; 1496 ''' 1497 1498 class Chks(RegOp): 1499 def __init__(self, dest, src1, src2=0, 1500 flags=None, dataSize="env.dataSize"): 1501 super(Chks, self).__init__(dest, 1502 src1, src2, flags, dataSize) 1503 code = ''' 1504 // The selector is in source 1 and can be at most 16 bits. 1505 SegSelector selector = DestReg; 1506 SegDescriptor desc = SrcReg1; 1507 HandyM5Reg m5reg = M5Reg; 1508 1509 switch (imm8) 1510 { 1511 case SegNoCheck: 1512 break; 1513 case SegCSCheck: 1514 // Make sure it's the right type 1515 if (desc.s == 0 || desc.type.codeOrData != 1) { 1516 fault = std::make_shared<GeneralProtection>(0); 1517 } else if (m5reg.cpl != desc.dpl) { 1518 fault = std::make_shared<GeneralProtection>(0); 1519 } 1520 break; 1521 case SegCallGateCheck: 1522 fault = std::make_shared<GenericISA::M5PanicFault>( 1523 "CS checks for far " 1524 "calls/jumps through call gates not implemented.\\n"); 1525 break; 1526 case SegSoftIntGateCheck: 1527 // Check permissions. 1528 if (desc.dpl < m5reg.cpl) { 1529 fault = std::make_shared<GeneralProtection>(selector); 1530 break; 1531 } 1532 M5_FALLTHROUGH; 1533 case SegIntGateCheck: 1534 // Make sure the gate's the right type. 1535 if ((m5reg.mode == LongMode && (desc.type & 0xe) != 0xe) || 1536 ((desc.type & 0x6) != 0x6)) { 1537 fault = std::make_shared<GeneralProtection>(0); 1538 } 1539 break; 1540 case SegSSCheck: 1541 if (selector.si || selector.ti) { 1542 if (!desc.p) { 1543 fault = std::make_shared<StackFault>(selector); 1544 } else if (!(desc.s == 1 && desc.type.codeOrData == 0 && 1545 desc.type.w) || 1546 (desc.dpl != m5reg.cpl) || 1547 (selector.rpl != m5reg.cpl)) { 1548 fault = std::make_shared<GeneralProtection>(selector); 1549 } 1550 } else if (m5reg.submode != SixtyFourBitMode || 1551 m5reg.cpl == 3) { 1552 fault = std::make_shared<GeneralProtection>(selector); 1553 } 1554 break; 1555 case SegIretCheck: 1556 { 1557 if ((!selector.si && !selector.ti) || 1558 (selector.rpl < m5reg.cpl) || 1559 !(desc.s == 1 && desc.type.codeOrData == 1) || 1560 (!desc.type.c && desc.dpl != selector.rpl) || 1561 (desc.type.c && desc.dpl > selector.rpl)) { 1562 fault = std::make_shared<GeneralProtection>(selector); 1563 } else if (!desc.p) { 1564 fault = std::make_shared<SegmentNotPresent>(selector); 1565 } 1566 break; 1567 } 1568 case SegIntCSCheck: 1569 if (m5reg.mode == LongMode) { 1570 if (desc.l != 1 || desc.d != 0) { 1571 fault = std::make_shared<GeneralProtection>(selector); 1572 } 1573 } else { 1574 fault = std::make_shared<GenericISA::M5PanicFault>( 1575 "Interrupt CS " 1576 "checks not implemented in legacy mode.\\n"); 1577 } 1578 break; 1579 case SegTRCheck: 1580 if (!selector.si || selector.ti) { 1581 fault = std::make_shared<GeneralProtection>(selector); 1582 } 1583 break; 1584 case SegTSSCheck: 1585 if (!desc.p) { 1586 fault = std::make_shared<SegmentNotPresent>(selector); 1587 } else if (!(desc.type == 0x9 || 1588 (desc.type == 1 && 1589 m5reg.mode != LongMode))) { 1590 fault = std::make_shared<GeneralProtection>(selector); 1591 } 1592 break; 1593 case SegInGDTCheck: 1594 if (selector.ti) { 1595 fault = std::make_shared<GeneralProtection>(selector); 1596 } 1597 break; 1598 case SegLDTCheck: 1599 if (!desc.p) { 1600 fault = std::make_shared<SegmentNotPresent>(selector); 1601 } else if (desc.type != 0x2) { 1602 fault = std::make_shared<GeneralProtection>(selector); 1603 } 1604 break; 1605 default: 1606 fault = std::make_shared<GenericISA::M5PanicFault>( 1607 "Undefined segment check type.\\n"); 1608 } 1609 ''' 1610 flag_code = ''' 1611 // Check for a NULL selector and set ZF,EZF appropriately. 1612 PredccFlagBits = PredccFlagBits & ~(ext & ZFBit); 1613 PredezfBit = PredezfBit & ~(ext & EZFBit); 1614 1615 if (!selector.si && !selector.ti) { 1616 PredccFlagBits = PredccFlagBits | (ext & ZFBit); 1617 PredezfBit = PredezfBit | (ext & EZFBit); 1618 } 1619 ''' 1620 1621 class Wrdh(RegOp): 1622 code = ''' 1623 SegDescriptor desc = SrcReg1; 1624 1625 uint64_t target = bits(SrcReg2, 31, 0) << 32; 1626 switch(desc.type) { 1627 case LDT64: 1628 case AvailableTSS64: 1629 case BusyTSS64: 1630 replaceBits(target, 31, 0, desc.base); 1631 break; 1632 case CallGate64: 1633 case IntGate64: 1634 case TrapGate64: 1635 replaceBits(target, 15, 0, bits(desc, 15, 0)); 1636 replaceBits(target, 31, 16, bits(desc, 63, 48)); 1637 break; 1638 default: 1639 fault = std::make_shared<GenericISA::M5PanicFault>( 1640 "Wrdh used with wrong descriptor type!\\n"); 1641 } 1642 DestReg = target; 1643 ''' 1644 1645 class Wrtsc(WrRegOp): 1646 code = ''' 1647 TscOp = psrc1; 1648 ''' 1649 1650 class Rdtsc(RdRegOp): 1651 code = ''' 1652 DestReg = TscOp; 1653 ''' 1654 1655 class Rdm5reg(RdRegOp): 1656 code = ''' 1657 DestReg = M5Reg; 1658 ''' 1659 1660 class Wrdl(RegOp): 1661 code = ''' 1662 SegDescriptor desc = SrcReg1; 1663 SegSelector selector = SrcReg2; 1664 // This while loop is so we can use break statements in the code 1665 // below to skip the rest of this section without a bunch of 1666 // nesting. 1667 while (true) { 1668 if (selector.si || selector.ti) { 1669 if (!desc.p) { 1670 fault = std::make_shared<GenericISA::M5PanicFault>( 1671 "Segment not present.\\n"); 1672 break; 1673 } 1674 SegAttr attr = 0; 1675 attr.dpl = desc.dpl; 1676 attr.unusable = 0; 1677 attr.defaultSize = desc.d; 1678 attr.longMode = desc.l; 1679 attr.avl = desc.avl; 1680 attr.granularity = desc.g; 1681 attr.present = desc.p; 1682 attr.system = desc.s; 1683 attr.type = desc.type; 1684 if (!desc.s) { 1685 // The expand down bit happens to be set for gates. 1686 if (desc.type.e) { 1687 fault = std::make_shared<GenericISA::M5PanicFault>( 1688 "Gate descriptor encountered.\\n"); 1689 break; 1690 } 1691 attr.readable = 1; 1692 attr.writable = 1; 1693 attr.expandDown = 0; 1694 } else { 1695 if (desc.type.codeOrData) { 1696 attr.expandDown = 0; 1697 attr.readable = desc.type.r; 1698 attr.writable = 0; 1699 } else { 1700 attr.expandDown = desc.type.e; 1701 attr.readable = 1; 1702 attr.writable = desc.type.w; 1703 } 1704 } 1705 SegBaseDest = desc.base; 1706 SegLimitDest = desc.limit; 1707 SegAttrDest = attr; 1708 } else { 1709 SegBaseDest = SegBaseDest; 1710 SegLimitDest = SegLimitDest; 1711 SegAttrDest = SegAttrDest; 1712 } 1713 break; 1714 } 1715 ''' 1716 1717 class Wrxftw(WrRegOp): 1718 def __init__(self, src1, **kwargs): 1719 super(Wrxftw, self).__init__(src1, "InstRegIndex(NUM_INTREGS)", \ 1720 **kwargs) 1721 1722 code = ''' 1723 FTW = X86ISA::convX87XTagsToTags(SrcReg1); 1724 ''' 1725 1726 class Rdxftw(RdRegOp): 1727 code = ''' 1728 DestReg = X86ISA::convX87TagsToXTags(FTW); 1729 ''' 1730}}; 1731