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