1 // Copyright (c) 2007-2008 The Hewlett-Packard Development Company
2 // All rights reserved.
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.
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.
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.
36 // Authors: Gabe Black
38 //////////////////////////////////////////////////////////////////////////
40 // RegOp Microop templates
42 //////////////////////////////////////////////////////////////////////////
44 def template MicroRegOpExecute {{
45 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
46 Trace::InstRecord *traceData) const
48 Fault fault = NoFault;
50 DPRINTF(X86, "The data size is %d\n", dataSize);
64 //Write the resulting state to the execution context
73 def template MicroRegOpImmExecute {{
74 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
75 Trace::InstRecord *traceData) const
77 Fault fault = NoFault;
92 //Write the resulting state to the execution context
101 def template MicroRegOpDeclare {{
102 class %(class_name)s : public %(base_class)s
105 %(class_name)s(ExtMachInst _machInst,
106 const char * instMnem, uint64_t setFlags,
107 InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
108 uint8_t _dataSize, uint16_t _ext);
114 def template MicroRegOpImmDeclare {{
116 class %(class_name)s : public %(base_class)s
119 %(class_name)s(ExtMachInst _machInst,
120 const char * instMnem, uint64_t setFlags,
121 InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest,
122 uint8_t _dataSize, uint16_t _ext);
128 def template MicroRegOpConstructor {{
129 inline %(class_name)s::%(class_name)s(
130 ExtMachInst machInst, const char * instMnem, uint64_t setFlags,
131 InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
132 uint8_t _dataSize, uint16_t _ext) :
133 %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags,
134 _src1, _src2, _dest, _dataSize, _ext,
141 def template MicroRegOpImmConstructor {{
142 inline %(class_name)s::%(class_name)s(
143 ExtMachInst machInst, const char * instMnem, uint64_t setFlags,
144 InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest,
145 uint8_t _dataSize, uint16_t _ext) :
146 %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags,
147 _src1, _imm8, _dest, _dataSize, _ext,
156 divide(uint64_t dividend, uint64_t divisor,
157 uint64_t "ient, uint64_t &remainder);
159 enum SegmentSelectorCheck {
160 SegNoCheck, SegCSCheck, SegCallGateCheck, SegIntGateCheck,
161 SegSoftIntGateCheck, SegSSCheck, SegIretCheck, SegIntCSCheck,
162 SegTRCheck, SegTSSCheck, SegInGDTCheck, SegLDTCheck
165 enum LongModeDescriptorType {
177 divide(uint64_t dividend, uint64_t divisor,
178 uint64_t "ient, uint64_t &remainder)
180 //Check for divide by zero.
181 assert(divisor != 0);
182 //If the divisor is bigger than the dividend, don't do anything.
183 if (divisor <= dividend) {
184 //Shift the divisor so it's msb lines up with the dividend.
185 int dividendMsb = findMsbSet(dividend);
186 int divisorMsb = findMsbSet(divisor);
187 int shift = dividendMsb - divisorMsb;
189 //Compute what we'll add to the quotient if the divisor isn't
190 //now larger than the dividend.
191 uint64_t quotientBit = 1;
192 quotientBit <<= shift;
193 //If we need to step back a bit (no pun intended) because the
194 //divisor got too to large, do that here. This is the "or two"
195 //part of one or two bit division.
196 if (divisor > dividend) {
200 //Decrement the remainder and increment the quotient.
201 quotient += quotientBit;
202 remainder -= divisor;
208 # Make these empty strings so that concatenating onto
209 # them will always work.
215 MicroRegOpImmDeclare,
216 MicroRegOpImmConstructor,
217 MicroRegOpImmExecute)
221 MicroRegOpConstructor,
224 class RegOpMeta(type):
225 def buildCppClasses(self, name, Name, suffix, \
226 code, flag_code, cond_check, else_code):
228 # Globals to stick the output in
230 global decoder_output
233 # Stick all the code together so it can be searched at once
234 allCode = "|".join((code, flag_code, cond_check, else_code))
236 # If op2 is used anywhere, make register and immediate versions
238 matcher = re.compile("(?<!\\w)(?P<prefix>s?)op2(?P<typeQual>\\.\\w+)?")
239 match = matcher.search(allCode)
242 if match.group("typeQual"):
243 typeQual = match.group("typeQual")
244 src2_name = "%spsrc2%s" % (match.group("prefix"), typeQual)
245 self.buildCppClasses(name, Name, suffix,
246 matcher.sub(src2_name, code),
247 matcher.sub(src2_name, flag_code),
248 matcher.sub(src2_name, cond_check),
249 matcher.sub(src2_name, else_code))
250 imm_name = "%simm8" % match.group("prefix")
251 self.buildCppClasses(name + "i", Name, suffix + "Imm",
252 matcher.sub(imm_name, code),
253 matcher.sub(imm_name, flag_code),
254 matcher.sub(imm_name, cond_check),
255 matcher.sub(imm_name, else_code))
258 # If there's something optional to do with flags, generate
259 # a version without it and fix up this version to use it.
260 if flag_code != "" or cond_check != "true":
261 self.buildCppClasses(name, Name, suffix,
262 code, "", "true", else_code)
263 suffix = "Flags" + suffix
265 # If psrc1 or psrc2 is used, we need to actually insert code to
267 matcher = re.compile("(?<!\w)psrc1(?!\w)")
268 if matcher.search(allCode):
269 code = "uint64_t psrc1 = pick(SrcReg1, 0, dataSize);" + code
270 matcher = re.compile("(?<!\w)psrc2(?!\w)")
271 if matcher.search(allCode):
272 code = "uint64_t psrc2 = pick(SrcReg2, 1, dataSize);" + code
273 # Also make available versions which do sign extension
274 matcher = re.compile("(?<!\w)spsrc1(?!\w)")
275 if matcher.search(allCode):
276 code = "int64_t spsrc1 = signedPick(SrcReg1, 0, dataSize);" + code
277 matcher = re.compile("(?<!\w)spsrc2(?!\w)")
278 if matcher.search(allCode):
279 code = "int64_t spsrc2 = signedPick(SrcReg2, 1, dataSize);" + code
280 matcher = re.compile("(?<!\w)simm8(?!\w)")
281 if matcher.search(allCode):
282 code = "int8_t simm8 = imm8;" + code
284 base = "X86ISA::RegOp"
286 # If imm8 shows up in the code, use the immediate templates, if
287 # not, hopefully the register ones will be correct.
288 templates = regTemplates
289 matcher = re.compile("(?<!\w)s?imm8(?!\w)")
290 if matcher.search(allCode):
292 templates = immTemplates
294 # Get everything ready for the substitution
295 iop = InstObjParams(name, Name + suffix, base,
297 "flag_code" : flag_code,
298 "cond_check" : cond_check,
299 "else_code" : else_code})
301 # Generate the actual code (finally!)
302 header_output += templates[0].subst(iop)
303 decoder_output += templates[1].subst(iop)
304 exec_output += templates[2].subst(iop)
307 def __new__(mcls, Name, bases, dict):
310 if "abstract" in dict:
311 abstract = dict['abstract']
314 cls = super(RegOpMeta, mcls).__new__(mcls, Name, bases, dict)
317 cls.base_mnemonic = name
319 flag_code = cls.flag_code
320 cond_check = cls.cond_check
321 else_code = cls.else_code
323 # Set up the C++ classes
324 mcls.buildCppClasses(cls, name, Name, "",
325 code, flag_code, cond_check, else_code)
327 # Hook into the microassembler dict
328 global microopClasses
329 microopClasses[name] = cls
331 allCode = "|".join((code, flag_code, cond_check, else_code))
333 # If op2 is used anywhere, make register and immediate versions
335 matcher = re.compile("op2(?P<typeQual>\\.\\w+)?")
336 if matcher.search(allCode):
337 microopClasses[name + 'i'] = cls
341 class RegOp(X86Microop):
342 __metaclass__ = RegOpMeta
343 # This class itself doesn't act as a microop
346 # Default template parameter values
351 def __init__(self, dest, src1, op2, flags = None, dataSize = "env.dataSize"):
356 self.dataSize = dataSize
360 if not isinstance(flags, (list, tuple)):
361 raise Exception, "flags must be a list or tuple of flags"
362 self.ext = " | ".join(flags)
363 self.className += "Flags"
365 def getAllocator(self, microFlags):
366 className = self.className
367 if self.mnemonic == self.base_mnemonic + 'i':
369 allocator = '''new %(class_name)s(machInst, macrocodeBlock,
370 %(flags)s, %(src1)s, %(op2)s, %(dest)s,
371 %(dataSize)s, %(ext)s)''' % {
372 "class_name" : className,
373 "flags" : self.microFlagsText(microFlags),
374 "src1" : self.src1, "op2" : self.op2,
376 "dataSize" : self.dataSize,
380 class LogicRegOp(RegOp):
383 //Don't have genFlags handle the OF or CF bits
384 uint64_t mask = CFBit | ECFBit | OFBit;
385 ccFlagBits = genFlags(ccFlagBits, ext & ~mask, DestReg, psrc1, op2);
386 //If a logic microop wants to set these, it wants to set them to 0.
387 ccFlagBits &= ~(CFBit & ext);
388 ccFlagBits &= ~(ECFBit & ext);
389 ccFlagBits &= ~(OFBit & ext);
392 class FlagRegOp(RegOp):
395 "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, op2);"
397 class SubRegOp(RegOp):
400 "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, ~op2, true);"
402 class CondRegOp(RegOp):
404 cond_check = "checkCondition(ccFlagBits, ext)"
406 class RdRegOp(RegOp):
408 def __init__(self, dest, src1=None, dataSize="env.dataSize"):
411 super(RdRegOp, self).__init__(dest, src1, \
412 "InstRegIndex(NUM_INTREGS)", None, dataSize)
414 class WrRegOp(RegOp):
416 def __init__(self, src1, src2, flags=None, dataSize="env.dataSize"):
417 super(WrRegOp, self).__init__("InstRegIndex(NUM_INTREGS)", \
418 src1, src2, flags, dataSize)
420 class Add(FlagRegOp):
421 code = 'DestReg = merge(DestReg, psrc1 + op2, dataSize);'
423 class Or(LogicRegOp):
424 code = 'DestReg = merge(DestReg, psrc1 | op2, dataSize);'
426 class Adc(FlagRegOp):
428 CCFlagBits flags = ccFlagBits;
429 DestReg = merge(DestReg, psrc1 + op2 + flags.cf, dataSize);
434 CCFlagBits flags = ccFlagBits;
435 DestReg = merge(DestReg, psrc1 - op2 - flags.cf, dataSize);
438 class And(LogicRegOp):
439 code = 'DestReg = merge(DestReg, psrc1 & op2, dataSize)'
442 code = 'DestReg = merge(DestReg, psrc1 - op2, dataSize)'
444 class Xor(LogicRegOp):
445 code = 'DestReg = merge(DestReg, psrc1 ^ op2, dataSize)'
447 class Mul1s(WrRegOp):
449 ProdLow = psrc1 * op2;
450 int halfSize = (dataSize * 8) / 2;
451 uint64_t shifter = (ULL(1) << halfSize);
453 uint64_t psrc1_h = psrc1 / shifter;
454 uint64_t psrc1_l = psrc1 & mask(halfSize);
455 uint64_t psrc2_h = (op2 / shifter) & mask(halfSize);
456 uint64_t psrc2_l = op2 & mask(halfSize);
457 hiResult = ((psrc1_l * psrc2_h + psrc1_h * psrc2_l +
458 ((psrc1_l * psrc2_l) / shifter)) /shifter) +
460 if (bits(psrc1, dataSize * 8 - 1))
462 if (bits(op2, dataSize * 8 - 1))
467 if ((-ProdHi & mask(dataSize * 8)) !=
468 bits(ProdLow, dataSize * 8 - 1)) {
469 ccFlagBits = ccFlagBits | (ext & (CFBit | OFBit | ECFBit));
471 ccFlagBits = ccFlagBits & ~(ext & (CFBit | OFBit | ECFBit));
475 class Mul1u(WrRegOp):
477 ProdLow = psrc1 * op2;
478 int halfSize = (dataSize * 8) / 2;
479 uint64_t shifter = (ULL(1) << halfSize);
480 uint64_t psrc1_h = psrc1 / shifter;
481 uint64_t psrc1_l = psrc1 & mask(halfSize);
482 uint64_t psrc2_h = (op2 / shifter) & mask(halfSize);
483 uint64_t psrc2_l = op2 & mask(halfSize);
484 ProdHi = ((psrc1_l * psrc2_h + psrc1_h * psrc2_l +
485 ((psrc1_l * psrc2_l) / shifter)) / shifter) +
490 ccFlagBits = ccFlagBits | (ext & (CFBit | OFBit | ECFBit));
492 ccFlagBits = ccFlagBits & ~(ext & (CFBit | OFBit | ECFBit));
496 class Mulel(RdRegOp):
497 code = 'DestReg = merge(SrcReg1, ProdLow, dataSize);'
499 class Muleh(RdRegOp):
500 def __init__(self, dest, src1=None, flags=None, dataSize="env.dataSize"):
503 super(RdRegOp, self).__init__(dest, src1, \
504 "InstRegIndex(NUM_INTREGS)", flags, dataSize)
505 code = 'DestReg = merge(SrcReg1, ProdHi, dataSize);'
507 # One or two bit divide
510 //These are temporaries so that modifying them later won't make
511 //the ISA parser think they're also sources.
512 uint64_t quotient = 0;
513 uint64_t remainder = psrc1;
514 //Similarly, this is a temporary so changing it doesn't make it
516 uint64_t divisor = op2;
517 //This is a temporary just for consistency and clarity.
518 uint64_t dividend = remainder;
521 fault = new DivideByZero;
523 divide(dividend, divisor, quotient, remainder);
524 //Record the final results.
525 Remainder = remainder;
534 uint64_t dividend = Remainder;
535 uint64_t divisor = Divisor;
536 uint64_t quotient = Quotient;
537 uint64_t remainder = dividend;
539 //If we overshot, do nothing. This lets us unrool division loops a
542 fault = new DivideByZero;
543 } else if (remaining) {
544 if (divisor & (ULL(1) << 63)) {
545 while (remaining && !(dividend & (ULL(1) << 63))) {
546 dividend = (dividend << 1) |
547 bits(SrcReg1, remaining - 1);
551 if (dividend & (ULL(1) << 63)) {
552 bool highBit = false;
553 if (dividend < divisor && remaining) {
555 dividend = (dividend << 1) |
556 bits(SrcReg1, remaining - 1);
560 if (highBit || divisor <= dividend) {
565 remainder = dividend;
567 //Shift in bits from the low order portion of the dividend
568 while (dividend < divisor && remaining) {
569 dividend = (dividend << 1) |
570 bits(SrcReg1, remaining - 1);
574 remainder = dividend;
576 divide(dividend, divisor, quotient, remainder);
579 //Keep track of how many bits there are still to pull in.
580 DestReg = merge(DestReg, remaining, dataSize);
581 //Record the final results
582 Remainder = remainder;
587 ccFlagBits = ccFlagBits | (ext & EZFBit);
589 ccFlagBits = ccFlagBits & ~(ext & EZFBit);
593 code = 'DestReg = merge(SrcReg1, Quotient, dataSize);'
596 code = 'DestReg = merge(SrcReg1, Remainder, dataSize);'
598 class Mov(CondRegOp):
599 code = 'DestReg = merge(SrcReg1, op2, dataSize)'
600 else_code = 'DestReg = DestReg;'
606 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
607 DestReg = merge(DestReg, psrc1 << shiftAmt, dataSize);
610 // If the shift amount is zero, no flags should be modified.
612 //Zero out any flags we might modify. This way we only have to
613 //worry about setting them.
614 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
616 //Figure out if we -would- set the CF bits if requested.
617 if (shiftAmt <= dataSize * 8 &&
618 bits(SrcReg1, dataSize * 8 - shiftAmt)) {
621 //If some combination of the CF bits need to be set, set them.
622 if ((ext & (CFBit | ECFBit)) && CFBits)
623 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
624 //Figure out what the OF bit should be.
625 if ((ext & OFBit) && (CFBits ^ bits(DestReg, dataSize * 8 - 1)))
626 ccFlagBits = ccFlagBits | OFBit;
627 //Use the regular mechanisms to calculate the other flags.
628 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
629 DestReg, psrc1, op2);
635 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
636 // Because what happens to the bits shift -in- on a right shift
637 // is not defined in the C/C++ standard, we have to mask them out
638 // to be sure they're zero.
639 uint64_t logicalMask = mask(dataSize * 8 - shiftAmt);
640 DestReg = merge(DestReg, (psrc1 >> shiftAmt) & logicalMask, dataSize);
643 // If the shift amount is zero, no flags should be modified.
645 //Zero out any flags we might modify. This way we only have to
646 //worry about setting them.
647 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
648 //If some combination of the CF bits need to be set, set them.
649 if ((ext & (CFBit | ECFBit)) &&
650 shiftAmt <= dataSize * 8 &&
651 bits(SrcReg1, shiftAmt - 1)) {
652 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
654 //Figure out what the OF bit should be.
655 if ((ext & OFBit) && bits(SrcReg1, dataSize * 8 - 1))
656 ccFlagBits = ccFlagBits | OFBit;
657 //Use the regular mechanisms to calculate the other flags.
658 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
659 DestReg, psrc1, op2);
665 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
666 // Because what happens to the bits shift -in- on a right shift
667 // is not defined in the C/C++ standard, we have to sign extend
668 // them manually to be sure.
669 uint64_t arithMask = (shiftAmt == 0) ? 0 :
670 -bits(psrc1, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt);
671 DestReg = merge(DestReg, (psrc1 >> shiftAmt) | arithMask, dataSize);
674 // If the shift amount is zero, no flags should be modified.
676 //Zero out any flags we might modify. This way we only have to
677 //worry about setting them.
678 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
679 //If some combination of the CF bits need to be set, set them.
680 uint8_t effectiveShift =
681 (shiftAmt <= dataSize * 8) ? shiftAmt : (dataSize * 8);
682 if ((ext & (CFBit | ECFBit)) &&
683 bits(SrcReg1, effectiveShift - 1)) {
684 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
686 //Use the regular mechanisms to calculate the other flags.
687 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
688 DestReg, psrc1, op2);
695 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
696 uint8_t realShiftAmt = shiftAmt % (dataSize * 8);
699 uint64_t top = psrc1 << (dataSize * 8 - realShiftAmt);
700 uint64_t bottom = bits(psrc1, dataSize * 8, realShiftAmt);
701 DestReg = merge(DestReg, top | bottom, dataSize);
704 DestReg = merge(DestReg, DestReg, dataSize);
707 // If the shift amount is zero, no flags should be modified.
709 //Zero out any flags we might modify. This way we only have to
710 //worry about setting them.
711 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
712 //Find the most and second most significant bits of the result.
713 int msb = bits(DestReg, dataSize * 8 - 1);
714 int smsb = bits(DestReg, dataSize * 8 - 2);
715 //If some combination of the CF bits need to be set, set them.
716 if ((ext & (CFBit | ECFBit)) && msb)
717 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
718 //Figure out what the OF bit should be.
719 if ((ext & OFBit) && (msb ^ smsb))
720 ccFlagBits = ccFlagBits | OFBit;
721 //Use the regular mechanisms to calculate the other flags.
722 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
723 DestReg, psrc1, op2);
730 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
731 uint8_t realShiftAmt = shiftAmt % (dataSize * 8 + 1);
734 CCFlagBits flags = ccFlagBits;
735 uint64_t top = flags.cf << (dataSize * 8 - realShiftAmt);
736 if (realShiftAmt > 1)
737 top |= psrc1 << (dataSize * 8 - realShiftAmt + 1);
738 uint64_t bottom = bits(psrc1, dataSize * 8 - 1, realShiftAmt);
739 DestReg = merge(DestReg, top | bottom, dataSize);
742 DestReg = merge(DestReg, DestReg, dataSize);
745 // If the shift amount is zero, no flags should be modified.
747 int origCFBit = (ccFlagBits & CFBit) ? 1 : 0;
748 //Zero out any flags we might modify. This way we only have to
749 //worry about setting them.
750 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
751 //Figure out what the OF bit should be.
752 if ((ext & OFBit) && (origCFBit ^
753 bits(SrcReg1, dataSize * 8 - 1))) {
754 ccFlagBits = ccFlagBits | OFBit;
756 //If some combination of the CF bits need to be set, set them.
757 if ((ext & (CFBit | ECFBit)) &&
758 (realShiftAmt == 0) ? origCFBit :
759 bits(SrcReg1, realShiftAmt - 1)) {
760 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
762 //Use the regular mechanisms to calculate the other flags.
763 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
764 DestReg, psrc1, op2);
771 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
772 uint8_t realShiftAmt = shiftAmt % (dataSize * 8);
775 uint64_t top = psrc1 << realShiftAmt;
777 bits(psrc1, dataSize * 8 - 1, dataSize * 8 - realShiftAmt);
778 DestReg = merge(DestReg, top | bottom, dataSize);
781 DestReg = merge(DestReg, DestReg, dataSize);
784 // If the shift amount is zero, no flags should be modified.
786 //Zero out any flags we might modify. This way we only have to
787 //worry about setting them.
788 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
789 //The CF bits, if set, would be set to the lsb of the result.
790 int lsb = DestReg & 0x1;
791 int msb = bits(DestReg, dataSize * 8 - 1);
792 //If some combination of the CF bits need to be set, set them.
793 if ((ext & (CFBit | ECFBit)) && lsb)
794 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
795 //Figure out what the OF bit should be.
796 if ((ext & OFBit) && (msb ^ lsb))
797 ccFlagBits = ccFlagBits | OFBit;
798 //Use the regular mechanisms to calculate the other flags.
799 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
800 DestReg, psrc1, op2);
807 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
808 uint8_t realShiftAmt = shiftAmt % (dataSize * 8 + 1);
811 CCFlagBits flags = ccFlagBits;
812 uint64_t top = psrc1 << realShiftAmt;
813 uint64_t bottom = flags.cf << (realShiftAmt - 1);
816 bits(psrc1, dataSize * 8 - 1,
817 dataSize * 8 - realShiftAmt + 1);
818 DestReg = merge(DestReg, top | bottom, dataSize);
821 DestReg = merge(DestReg, DestReg, dataSize);
824 // If the shift amount is zero, no flags should be modified.
826 int origCFBit = (ccFlagBits & CFBit) ? 1 : 0;
827 //Zero out any flags we might modify. This way we only have to
828 //worry about setting them.
829 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
830 int msb = bits(DestReg, dataSize * 8 - 1);
831 int CFBits = bits(SrcReg1, dataSize * 8 - realShiftAmt);
832 //If some combination of the CF bits need to be set, set them.
833 if ((ext & (CFBit | ECFBit)) &&
834 (realShiftAmt == 0) ? origCFBit : CFBits)
835 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
836 //Figure out what the OF bit should be.
837 if ((ext & OFBit) && (msb ^ CFBits))
838 ccFlagBits = ccFlagBits | OFBit;
839 //Use the regular mechanisms to calculate the other flags.
840 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
841 DestReg, psrc1, op2);
847 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
848 uint8_t dataBits = dataSize * 8;
849 uint8_t realShiftAmt = shiftAmt % (2 * dataBits);
851 if (realShiftAmt == 0) {
853 } else if (realShiftAmt < dataBits) {
854 result = (psrc1 << realShiftAmt) |
855 (DoubleBits >> (dataBits - realShiftAmt));
857 result = (DoubleBits << (realShiftAmt - dataBits)) |
858 (psrc1 >> (2 * dataBits - realShiftAmt));
860 DestReg = merge(DestReg, result, dataSize);
863 // If the shift amount is zero, no flags should be modified.
865 //Zero out any flags we might modify. This way we only have to
866 //worry about setting them.
867 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
869 //Figure out if we -would- set the CF bits if requested.
870 if ((realShiftAmt == 0 &&
871 bits(DoubleBits, 0)) ||
872 (realShiftAmt <= dataBits &&
873 bits(SrcReg1, dataBits - realShiftAmt)) ||
874 (realShiftAmt > dataBits &&
875 bits(DoubleBits, 2 * dataBits - realShiftAmt))) {
878 //If some combination of the CF bits need to be set, set them.
879 if ((ext & (CFBit | ECFBit)) && CFBits)
880 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
881 //Figure out what the OF bit should be.
882 if ((ext & OFBit) && (bits(SrcReg1, dataBits - 1) ^
883 bits(result, dataBits - 1)))
884 ccFlagBits = ccFlagBits | OFBit;
885 //Use the regular mechanisms to calculate the other flags.
886 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
887 DestReg, psrc1, op2);
893 uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
894 uint8_t dataBits = dataSize * 8;
895 uint8_t realShiftAmt = shiftAmt % (2 * dataBits);
897 if (realShiftAmt == 0) {
899 } else if (realShiftAmt < dataBits) {
900 // Because what happens to the bits shift -in- on a right
901 // shift is not defined in the C/C++ standard, we have to
902 // mask them out to be sure they're zero.
903 uint64_t logicalMask = mask(dataBits - realShiftAmt);
904 result = ((psrc1 >> realShiftAmt) & logicalMask) |
905 (DoubleBits << (dataBits - realShiftAmt));
907 uint64_t logicalMask = mask(2 * dataBits - realShiftAmt);
908 result = ((DoubleBits >> (realShiftAmt - dataBits)) &
910 (psrc1 << (2 * dataBits - realShiftAmt));
912 DestReg = merge(DestReg, result, dataSize);
915 // If the shift amount is zero, no flags should be modified.
917 //Zero out any flags we might modify. This way we only have to
918 //worry about setting them.
919 ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
921 //If some combination of the CF bits need to be set, set them.
922 if ((realShiftAmt == 0 &&
923 bits(DoubleBits, dataBits - 1)) ||
924 (realShiftAmt <= dataBits &&
925 bits(SrcReg1, realShiftAmt - 1)) ||
926 (realShiftAmt > dataBits &&
927 bits(DoubleBits, realShiftAmt - dataBits - 1))) {
930 //If some combination of the CF bits need to be set, set them.
931 if ((ext & (CFBit | ECFBit)) && CFBits)
932 ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
933 //Figure out what the OF bit should be.
934 if ((ext & OFBit) && (bits(SrcReg1, dataBits - 1) ^
935 bits(result, dataBits - 1)))
936 ccFlagBits = ccFlagBits | OFBit;
937 //Use the regular mechanisms to calculate the other flags.
938 ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
939 DestReg, psrc1, op2);
944 code = 'DoubleBits = psrc1 ^ op2;'
946 class Wrip(WrRegOp, CondRegOp):
947 code = 'NRIP = psrc1 + sop2 + CSBase;'
948 else_code = "NRIP = NRIP;"
950 class Wruflags(WrRegOp):
951 code = 'ccFlagBits = psrc1 ^ op2'
953 class Wrflags(WrRegOp):
955 MiscReg newFlags = psrc1 ^ op2;
956 MiscReg userFlagMask = 0xDD5;
957 // Get only the user flags
958 ccFlagBits = newFlags & userFlagMask;
959 // Get everything else
960 nccFlagBits = newFlags & ~userFlagMask;
964 code = 'DestReg = NRIP - CSBase;'
966 class Ruflags(RdRegOp):
967 code = 'DestReg = ccFlagBits'
969 class Rflags(RdRegOp):
970 code = 'DestReg = ccFlagBits | nccFlagBits'
974 int flag = bits(ccFlagBits, imm8);
975 DestReg = merge(DestReg, flag, dataSize);
976 ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) :
977 (ccFlagBits & ~EZFBit);
979 def __init__(self, dest, imm, flags=None, \
980 dataSize="env.dataSize"):
981 super(Ruflag, self).__init__(dest, \
982 "InstRegIndex(NUM_INTREGS)", imm, flags, dataSize)
986 MiscReg flagMask = 0x3F7FDD5;
987 MiscReg flags = (nccFlagBits | ccFlagBits) & flagMask;
988 int flag = bits(flags, imm8);
989 DestReg = merge(DestReg, flag, dataSize);
990 ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) :
991 (ccFlagBits & ~EZFBit);
993 def __init__(self, dest, imm, flags=None, \
994 dataSize="env.dataSize"):
995 super(Rflag, self).__init__(dest, \
996 "InstRegIndex(NUM_INTREGS)", imm, flags, dataSize)
1001 // Mask the bit position so that it wraps.
1002 int bitPos = op2 & (dataSize * 8 - 1);
1003 int sign_bit = bits(val, bitPos, bitPos);
1004 uint64_t maskVal = mask(bitPos+1);
1005 val = sign_bit ? (val | ~maskVal) : (val & maskVal);
1006 DestReg = merge(DestReg, val, dataSize);
1010 ccFlagBits = ccFlagBits &
1011 ~(ext & (CFBit | ECFBit | ZFBit | EZFBit));
1013 ccFlagBits = ccFlagBits |
1014 (ext & (CFBit | ECFBit | ZFBit | EZFBit));
1018 code = 'DestReg = merge(DestReg, bits(psrc1, op2, 0), dataSize);'
1021 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1022 super(Rddr, self).__init__(dest, \
1023 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1027 if ((cr4.de == 1 && (src1 == 4 || src1 == 5)) || src1 >= 8) {
1028 fault = new InvalidOpcode();
1029 } else if (dr7.gd) {
1030 fault = new DebugException();
1032 DestReg = merge(DestReg, DebugSrc1, dataSize);
1037 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1038 super(Wrdr, self).__init__(dest, \
1039 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1043 if ((cr4.de == 1 && (dest == 4 || dest == 5)) || dest >= 8) {
1044 fault = new InvalidOpcode();
1045 } else if ((dest == 6 || dest == 7) && bits(psrc1, 63, 32) &&
1046 machInst.mode.mode == LongMode) {
1047 fault = new GeneralProtection(0);
1048 } else if (dr7.gd) {
1049 fault = new DebugException();
1056 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1057 super(Rdcr, self).__init__(dest, \
1058 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1060 if (src1 == 1 || (src1 > 4 && src1 < 8) || (src1 > 8)) {
1061 fault = new InvalidOpcode();
1063 DestReg = merge(DestReg, ControlSrc1, dataSize);
1068 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1069 super(Wrcr, self).__init__(dest, \
1070 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1072 if (dest == 1 || (dest > 4 && dest < 8) || (dest > 8)) {
1073 fault = new InvalidOpcode();
1075 // There are *s in the line below so it doesn't confuse the
1076 // parser. They may be unnecessary.
1077 //Mis*cReg old*Val = pick(Cont*rolDest, 0, dat*aSize);
1078 MiscReg newVal = psrc1;
1080 // Check for any modifications that would cause a fault.
1087 if (bits(newVal, 63, 32) ||
1088 (!cr0.pe && cr0.pg) ||
1089 (!cr0.cd && cr0.nw) ||
1090 (cr0.pg && efer.lme && !oldCr4.pae))
1091 fault = new GeneralProtection(0);
1101 // PAE can't be disabled in long mode.
1102 if (bits(newVal, 63, 11) ||
1103 (machInst.mode.mode == LongMode && !cr4.pae))
1104 fault = new GeneralProtection(0);
1109 if (bits(newVal, 63, 4))
1110 fault = new GeneralProtection(0);
1113 panic("Unrecognized control register %d.\\n", dest);
1115 ControlDest = newVal;
1119 # Microops for manipulating segmentation registers
1120 class SegOp(CondRegOp):
1122 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1123 super(SegOp, self).__init__(dest, \
1124 src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1126 class Wrbase(SegOp):
1128 SegBaseDest = psrc1;
1131 class Wrlimit(SegOp):
1133 SegLimitDest = psrc1;
1141 class WrAttr(SegOp):
1143 SegAttrDest = psrc1;
1146 class Rdbase(SegOp):
1148 DestReg = merge(DestReg, SegBaseSrc1, dataSize);
1151 class Rdlimit(SegOp):
1153 DestReg = merge(DestReg, SegLimitSrc1, dataSize);
1156 class RdAttr(SegOp):
1158 DestReg = merge(DestReg, SegAttrSrc1, dataSize);
1163 DestReg = merge(DestReg, SegSelSrc1, dataSize);
1167 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1168 super(Rdval, self).__init__(dest, src1, \
1169 "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1171 DestReg = MiscRegSrc1;
1175 def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1176 super(Wrval, self).__init__(dest, src1, \
1177 "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1179 MiscRegDest = SrcReg1;
1183 def __init__(self, dest, src1, src2=0,
1184 flags=None, dataSize="env.dataSize"):
1185 super(Chks, self).__init__(dest,
1186 src1, src2, flags, dataSize)
1188 // The selector is in source 1 and can be at most 16 bits.
1189 SegSelector selector = DestReg;
1190 SegDescriptor desc = SrcReg1;
1191 HandyM5Reg m5reg = M5Reg;
1198 // Make sure it's the right type
1199 if (desc.s == 0 || desc.type.codeOrData != 1) {
1200 fault = new GeneralProtection(0);
1201 } else if (m5reg.cpl != desc.dpl) {
1202 fault = new GeneralProtection(0);
1205 case SegCallGateCheck:
1206 panic("CS checks for far calls/jumps through call gates"
1207 "not implemented.\\n");
1209 case SegSoftIntGateCheck:
1210 // Check permissions.
1211 if (desc.dpl < m5reg.cpl) {
1212 fault = new GeneralProtection(selector);
1215 // Fall through on purpose
1216 case SegIntGateCheck:
1217 // Make sure the gate's the right type.
1218 if ((m5reg.mode == LongMode && (desc.type & 0xe) != 0xe) ||
1219 ((desc.type & 0x6) != 0x6)) {
1220 fault = new GeneralProtection(0);
1224 if (selector.si || selector.ti) {
1226 fault = new StackFault(selector);
1229 if ((m5reg.submode != SixtyFourBitMode ||
1232 desc.type.codeOrData == 0 && desc.type.w) ||
1233 (desc.dpl != m5reg.cpl) ||
1234 (selector.rpl != m5reg.cpl)) {
1235 fault = new GeneralProtection(selector);
1241 if ((!selector.si && !selector.ti) ||
1242 (selector.rpl < m5reg.cpl) ||
1243 !(desc.s == 1 && desc.type.codeOrData == 1) ||
1244 (!desc.type.c && desc.dpl != selector.rpl) ||
1245 (desc.type.c && desc.dpl > selector.rpl)) {
1246 fault = new GeneralProtection(selector);
1247 } else if (!desc.p) {
1248 fault = new SegmentNotPresent(selector);
1253 if (m5reg.mode == LongMode) {
1254 if (desc.l != 1 || desc.d != 0) {
1255 fault = new GeneralProtection(selector);
1258 panic("Interrupt CS checks not implemented "
1259 "in legacy mode.\\n");
1263 if (!selector.si || selector.ti) {
1264 fault = new GeneralProtection(selector);
1269 fault = new SegmentNotPresent(selector);
1270 } else if (!(desc.type == 0x9 ||
1272 m5reg.mode != LongMode))) {
1273 fault = new GeneralProtection(selector);
1278 fault = new GeneralProtection(selector);
1283 fault = new SegmentNotPresent(selector);
1284 } else if (desc.type != 0x2) {
1285 fault = new GeneralProtection(selector);
1289 panic("Undefined segment check type.\\n");
1293 // Check for a NULL selector and set ZF,EZF appropriately.
1294 ccFlagBits = ccFlagBits & ~(ext & (ZFBit | EZFBit));
1295 if (!selector.si && !selector.ti)
1296 ccFlagBits = ccFlagBits | (ext & (ZFBit | EZFBit));
1301 SegDescriptor desc = SrcReg1;
1303 uint64_t target = bits(SrcReg2, 31, 0) << 32;
1306 case AvailableTSS64:
1308 replaceBits(target, 23, 0, desc.baseLow);
1309 replaceBits(target, 31, 24, desc.baseHigh);
1314 replaceBits(target, 15, 0, bits(desc, 15, 0));
1315 replaceBits(target, 31, 16, bits(desc, 63, 48));
1318 panic("Wrdh used with wrong descriptor type!\\n");
1323 class Wrtsc(WrRegOp):
1328 class Rdtsc(RdRegOp):
1333 class Rdm5reg(RdRegOp):
1340 SegDescriptor desc = SrcReg1;
1341 SegSelector selector = SrcReg2;
1342 if (selector.si || selector.ti) {
1344 panic("Segment not present.\\n");
1346 attr.dpl = desc.dpl;
1348 attr.defaultSize = desc.d;
1349 attr.longMode = desc.l;
1350 attr.avl = desc.avl;
1351 attr.granularity = desc.g;
1352 attr.present = desc.p;
1353 attr.system = desc.s;
1354 attr.type = desc.type;
1356 // The expand down bit happens to be set for gates.
1358 panic("Gate descriptor encountered.\\n");
1362 attr.expandDown = 0;
1364 if (desc.type.codeOrData) {
1365 attr.expandDown = 0;
1366 attr.readable = desc.type.r;
1369 attr.expandDown = desc.type.e;
1371 attr.writable = desc.type.w;
1374 Addr base = desc.baseLow | (desc.baseHigh << 24);
1375 Addr limit = desc.limitLow | (desc.limitHigh << 16);
1377 limit = (limit << 12) | mask(12);
1379 SegLimitDest = limit;
1382 SegBaseDest = SegBaseDest;
1383 SegLimitDest = SegLimitDest;
1384 SegAttrDest = SegAttrDest;