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