regop.isa revision 12236:126ac9da6050
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 &quotient, 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 &quotient, 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                  default:
1431                    fault = std::make_shared<GenericISA::M5PanicFault>(
1432                            "Unrecognized control register %d.\\n", dest);
1433                }
1434                ControlDest = newVal;
1435            }
1436            '''
1437
1438    # Microops for manipulating segmentation registers
1439    class SegOp(CondRegOp):
1440        abstract = True
1441        def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1442            super(SegOp, self).__init__(dest, \
1443                    src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1444
1445    class Wrbase(SegOp):
1446        code = '''
1447            SegBaseDest = psrc1;
1448        '''
1449
1450    class Wrlimit(SegOp):
1451        code = '''
1452            SegLimitDest = psrc1;
1453        '''
1454
1455    class Wrsel(SegOp):
1456        code = '''
1457            SegSelDest = psrc1;
1458        '''
1459
1460    class WrAttr(SegOp):
1461        code = '''
1462            SegAttrDest = psrc1;
1463        '''
1464
1465    class Rdbase(SegOp):
1466        code = 'DestReg = merge(DestReg, SegBaseSrc1, dataSize);'
1467        big_code = 'DestReg = SegBaseSrc1 & mask(dataSize * 8);'
1468
1469    class Rdlimit(SegOp):
1470        code = 'DestReg = merge(DestReg, SegLimitSrc1, dataSize);'
1471        big_code = 'DestReg = SegLimitSrc1 & mask(dataSize * 8);'
1472
1473    class RdAttr(SegOp):
1474        code = 'DestReg = merge(DestReg, SegAttrSrc1, dataSize);'
1475        big_code = 'DestReg = SegAttrSrc1 & mask(dataSize * 8);'
1476
1477    class Rdsel(SegOp):
1478        code = 'DestReg = merge(DestReg, SegSelSrc1, dataSize);'
1479        big_code = 'DestReg = SegSelSrc1 & mask(dataSize * 8);'
1480
1481    class Rdval(RegOp):
1482        def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1483            super(Rdval, self).__init__(dest, src1, \
1484                    "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1485        code = '''
1486            DestReg = MiscRegSrc1;
1487        '''
1488
1489    class Wrval(RegOp):
1490        def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1491            super(Wrval, self).__init__(dest, src1, \
1492                    "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1493        code = '''
1494            MiscRegDest = SrcReg1;
1495        '''
1496
1497    class Chks(RegOp):
1498        def __init__(self, dest, src1, src2=0,
1499                flags=None, dataSize="env.dataSize"):
1500            super(Chks, self).__init__(dest,
1501                    src1, src2, flags, dataSize)
1502        code = '''
1503            // The selector is in source 1 and can be at most 16 bits.
1504            SegSelector selector = DestReg;
1505            SegDescriptor desc = SrcReg1;
1506            HandyM5Reg m5reg = M5Reg;
1507
1508            switch (imm8)
1509            {
1510              case SegNoCheck:
1511                break;
1512              case SegCSCheck:
1513                // Make sure it's the right type
1514                if (desc.s == 0 || desc.type.codeOrData != 1) {
1515                    fault = std::make_shared<GeneralProtection>(0);
1516                } else if (m5reg.cpl != desc.dpl) {
1517                    fault = std::make_shared<GeneralProtection>(0);
1518                }
1519                break;
1520              case SegCallGateCheck:
1521                fault = std::make_shared<GenericISA::M5PanicFault>(
1522                        "CS checks for far "
1523                        "calls/jumps through call gates not implemented.\\n");
1524                break;
1525              case SegSoftIntGateCheck:
1526                // Check permissions.
1527                if (desc.dpl < m5reg.cpl) {
1528                    fault = std::make_shared<GeneralProtection>(selector);
1529                    break;
1530                }
1531                // Fall through on purpose
1532              case SegIntGateCheck:
1533                // Make sure the gate's the right type.
1534                if ((m5reg.mode == LongMode && (desc.type & 0xe) != 0xe) ||
1535                        ((desc.type & 0x6) != 0x6)) {
1536                    fault = std::make_shared<GeneralProtection>(0);
1537                }
1538                break;
1539              case SegSSCheck:
1540                if (selector.si || selector.ti) {
1541                    if (!desc.p) {
1542                        fault = std::make_shared<StackFault>(selector);
1543                    } else if (!(desc.s == 1 && desc.type.codeOrData == 0 &&
1544                                desc.type.w) ||
1545                            (desc.dpl != m5reg.cpl) ||
1546                            (selector.rpl != m5reg.cpl)) {
1547                        fault = std::make_shared<GeneralProtection>(selector);
1548                    }
1549                } else if (m5reg.submode != SixtyFourBitMode ||
1550                        m5reg.cpl == 3) {
1551                    fault = std::make_shared<GeneralProtection>(selector);
1552                }
1553                break;
1554              case SegIretCheck:
1555                {
1556                    if ((!selector.si && !selector.ti) ||
1557                            (selector.rpl < m5reg.cpl) ||
1558                            !(desc.s == 1 && desc.type.codeOrData == 1) ||
1559                            (!desc.type.c && desc.dpl != selector.rpl) ||
1560                            (desc.type.c && desc.dpl > selector.rpl)) {
1561                        fault = std::make_shared<GeneralProtection>(selector);
1562                    } else if (!desc.p) {
1563                        fault = std::make_shared<SegmentNotPresent>(selector);
1564                    }
1565                    break;
1566                }
1567              case SegIntCSCheck:
1568                if (m5reg.mode == LongMode) {
1569                    if (desc.l != 1 || desc.d != 0) {
1570                        fault = std::make_shared<GeneralProtection>(selector);
1571                    }
1572                } else {
1573                    fault = std::make_shared<GenericISA::M5PanicFault>(
1574                            "Interrupt CS "
1575                            "checks not implemented in legacy mode.\\n");
1576                }
1577                break;
1578              case SegTRCheck:
1579                if (!selector.si || selector.ti) {
1580                    fault = std::make_shared<GeneralProtection>(selector);
1581                }
1582                break;
1583              case SegTSSCheck:
1584                if (!desc.p) {
1585                    fault = std::make_shared<SegmentNotPresent>(selector);
1586                } else if (!(desc.type == 0x9 ||
1587                        (desc.type == 1 &&
1588                         m5reg.mode != LongMode))) {
1589                    fault = std::make_shared<GeneralProtection>(selector);
1590                }
1591                break;
1592              case SegInGDTCheck:
1593                if (selector.ti) {
1594                    fault = std::make_shared<GeneralProtection>(selector);
1595                }
1596                break;
1597              case SegLDTCheck:
1598                if (!desc.p) {
1599                    fault = std::make_shared<SegmentNotPresent>(selector);
1600                } else if (desc.type != 0x2) {
1601                    fault = std::make_shared<GeneralProtection>(selector);
1602                }
1603                break;
1604              default:
1605                fault = std::make_shared<GenericISA::M5PanicFault>(
1606                        "Undefined segment check type.\\n");
1607            }
1608        '''
1609        flag_code = '''
1610            // Check for a NULL selector and set ZF,EZF appropriately.
1611            PredccFlagBits = PredccFlagBits & ~(ext & ZFBit);
1612            PredezfBit = PredezfBit & ~(ext & EZFBit);
1613
1614            if (!selector.si && !selector.ti) {
1615                PredccFlagBits = PredccFlagBits | (ext & ZFBit);
1616                PredezfBit = PredezfBit | (ext & EZFBit);
1617            }
1618        '''
1619
1620    class Wrdh(RegOp):
1621        code = '''
1622            SegDescriptor desc = SrcReg1;
1623
1624            uint64_t target = bits(SrcReg2, 31, 0) << 32;
1625            switch(desc.type) {
1626              case LDT64:
1627              case AvailableTSS64:
1628              case BusyTSS64:
1629                replaceBits(target, 23, 0, desc.baseLow);
1630                replaceBits(target, 31, 24, desc.baseHigh);
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                    Addr base = desc.baseLow | (desc.baseHigh << 24);
1706                    Addr limit = desc.limitLow | (desc.limitHigh << 16);
1707                    if (desc.g)
1708                        limit = (limit << 12) | mask(12);
1709                    SegBaseDest = base;
1710                    SegLimitDest = limit;
1711                    SegAttrDest = attr;
1712                } else {
1713                    SegBaseDest = SegBaseDest;
1714                    SegLimitDest = SegLimitDest;
1715                    SegAttrDest = SegAttrDest;
1716                }
1717                break;
1718            }
1719        '''
1720
1721    class Wrxftw(WrRegOp):
1722        def __init__(self, src1, **kwargs):
1723            super(Wrxftw, self).__init__(src1, "InstRegIndex(NUM_INTREGS)", \
1724                                         **kwargs)
1725
1726        code = '''
1727            FTW = X86ISA::convX87XTagsToTags(SrcReg1);
1728        '''
1729
1730    class Rdxftw(RdRegOp):
1731        code = '''
1732            DestReg = X86ISA::convX87TagsToXTags(FTW);
1733        '''
1734}};
1735