regop.isa revision 7087:fb8d5786ff30
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            if(%(cond_check)s)
55            {
56                %(code)s;
57                %(flag_code)s;
58            }
59            else
60            {
61                %(else_code)s;
62            }
63
64            //Write the resulting state to the execution context
65            if(fault == NoFault)
66            {
67                %(op_wb)s;
68            }
69            return fault;
70        }
71}};
72
73def template MicroRegOpImmExecute {{
74        Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
75                Trace::InstRecord *traceData) const
76        {
77            Fault fault = NoFault;
78
79            %(op_decl)s;
80            %(op_rd)s;
81
82            if(%(cond_check)s)
83            {
84                %(code)s;
85                %(flag_code)s;
86            }
87            else
88            {
89                %(else_code)s;
90            }
91
92            //Write the resulting state to the execution context
93            if(fault == NoFault)
94            {
95                %(op_wb)s;
96            }
97            return fault;
98        }
99}};
100
101def template MicroRegOpDeclare {{
102    class %(class_name)s : public %(base_class)s
103    {
104      protected:
105        void buildMe();
106
107      public:
108        %(class_name)s(ExtMachInst _machInst,
109                const char * instMnem,
110                bool isMicro, bool isDelayed, bool isFirst, bool isLast,
111                InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
112                uint8_t _dataSize, uint16_t _ext);
113
114        %(class_name)s(ExtMachInst _machInst,
115                const char * instMnem,
116                InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
117                uint8_t _dataSize, uint16_t _ext);
118
119        %(BasicExecDeclare)s
120    };
121}};
122
123def template MicroRegOpImmDeclare {{
124
125    class %(class_name)s : public %(base_class)s
126    {
127      protected:
128        void buildMe();
129
130      public:
131        %(class_name)s(ExtMachInst _machInst,
132                const char * instMnem,
133                bool isMicro, bool isDelayed, bool isFirst, bool isLast,
134                InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest,
135                uint8_t _dataSize, uint16_t _ext);
136
137        %(class_name)s(ExtMachInst _machInst,
138                const char * instMnem,
139                InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest,
140                uint8_t _dataSize, uint16_t _ext);
141
142        %(BasicExecDeclare)s
143    };
144}};
145
146def template MicroRegOpConstructor {{
147
148    inline void %(class_name)s::buildMe()
149    {
150        %(constructor)s;
151    }
152
153    inline %(class_name)s::%(class_name)s(
154            ExtMachInst machInst, const char * instMnem,
155            InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
156            uint8_t _dataSize, uint16_t _ext) :
157        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
158                false, false, false, false,
159                _src1, _src2, _dest, _dataSize, _ext,
160                %(op_class)s)
161    {
162        buildMe();
163    }
164
165    inline %(class_name)s::%(class_name)s(
166            ExtMachInst machInst, const char * instMnem,
167            bool isMicro, bool isDelayed, bool isFirst, bool isLast,
168            InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
169            uint8_t _dataSize, uint16_t _ext) :
170        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
171                isMicro, isDelayed, isFirst, isLast,
172                _src1, _src2, _dest, _dataSize, _ext,
173                %(op_class)s)
174    {
175        buildMe();
176    }
177}};
178
179def template MicroRegOpImmConstructor {{
180
181    inline void %(class_name)s::buildMe()
182    {
183        %(constructor)s;
184    }
185
186    inline %(class_name)s::%(class_name)s(
187            ExtMachInst machInst, const char * instMnem,
188            InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest,
189            uint8_t _dataSize, uint16_t _ext) :
190        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
191                false, false, false, false,
192                _src1, _imm8, _dest, _dataSize, _ext,
193                %(op_class)s)
194    {
195        buildMe();
196    }
197
198    inline %(class_name)s::%(class_name)s(
199            ExtMachInst machInst, const char * instMnem,
200            bool isMicro, bool isDelayed, bool isFirst, bool isLast,
201            InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest,
202            uint8_t _dataSize, uint16_t _ext) :
203        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
204                isMicro, isDelayed, isFirst, isLast,
205                _src1, _imm8, _dest, _dataSize, _ext,
206                %(op_class)s)
207    {
208        buildMe();
209    }
210}};
211
212output header {{
213    void
214    divide(uint64_t dividend, uint64_t divisor,
215            uint64_t &quotient, uint64_t &remainder);
216
217    enum SegmentSelectorCheck {
218      SegNoCheck, SegCSCheck, SegCallGateCheck, SegIntGateCheck,
219      SegSoftIntGateCheck, SegSSCheck, SegIretCheck, SegIntCSCheck,
220      SegTRCheck, SegTSSCheck, SegInGDTCheck, SegLDTCheck
221    };
222
223    enum LongModeDescriptorType {
224        LDT64 = 2,
225        AvailableTSS64 = 9,
226        BusyTSS64 = 0xb,
227        CallGate64 = 0xc,
228        IntGate64 = 0xe,
229        TrapGate64 = 0xf
230    };
231}};
232
233output decoder {{
234    void
235    divide(uint64_t dividend, uint64_t divisor,
236            uint64_t &quotient, uint64_t &remainder)
237    {
238        //Check for divide by zero.
239        if (divisor == 0)
240            panic("Divide by zero!\\n");
241        //If the divisor is bigger than the dividend, don't do anything.
242        if (divisor <= dividend) {
243            //Shift the divisor so it's msb lines up with the dividend.
244            int dividendMsb = findMsbSet(dividend);
245            int divisorMsb = findMsbSet(divisor);
246            int shift = dividendMsb - divisorMsb;
247            divisor <<= shift;
248            //Compute what we'll add to the quotient if the divisor isn't
249            //now larger than the dividend.
250            uint64_t quotientBit = 1;
251            quotientBit <<= shift;
252            //If we need to step back a bit (no pun intended) because the
253            //divisor got too to large, do that here. This is the "or two"
254            //part of one or two bit division.
255            if (divisor > dividend) {
256                quotientBit >>= 1;
257                divisor >>= 1;
258            }
259            //Decrement the remainder and increment the quotient.
260            quotient += quotientBit;
261            remainder -= divisor;
262        }
263    }
264}};
265
266let {{
267    # Make these empty strings so that concatenating onto
268    # them will always work.
269    header_output = ""
270    decoder_output = ""
271    exec_output = ""
272
273    immTemplates = (
274            MicroRegOpImmDeclare,
275            MicroRegOpImmConstructor,
276            MicroRegOpImmExecute)
277
278    regTemplates = (
279            MicroRegOpDeclare,
280            MicroRegOpConstructor,
281            MicroRegOpExecute)
282
283    class RegOpMeta(type):
284        def buildCppClasses(self, name, Name, suffix, \
285                code, flag_code, cond_check, else_code):
286
287            # Globals to stick the output in
288            global header_output
289            global decoder_output
290            global exec_output
291
292            # Stick all the code together so it can be searched at once
293            allCode = "|".join((code, flag_code, cond_check, else_code))
294
295            # If op2 is used anywhere, make register and immediate versions
296            # of this code.
297            matcher = re.compile("(?<!\\w)(?P<prefix>s?)op2(?P<typeQual>\\.\\w+)?")
298            match = matcher.search(allCode)
299            if match:
300                typeQual = ""
301                if match.group("typeQual"):
302                    typeQual = match.group("typeQual")
303                src2_name = "%spsrc2%s" % (match.group("prefix"), typeQual)
304                self.buildCppClasses(name, Name, suffix,
305                        matcher.sub(src2_name, code),
306                        matcher.sub(src2_name, flag_code),
307                        matcher.sub(src2_name, cond_check),
308                        matcher.sub(src2_name, else_code))
309                imm_name = "%simm8" % match.group("prefix")
310                self.buildCppClasses(name + "i", Name, suffix + "Imm",
311                        matcher.sub(imm_name, code),
312                        matcher.sub(imm_name, flag_code),
313                        matcher.sub(imm_name, cond_check),
314                        matcher.sub(imm_name, else_code))
315                return
316
317            # If there's something optional to do with flags, generate
318            # a version without it and fix up this version to use it.
319            if flag_code != "" or cond_check != "true":
320                self.buildCppClasses(name, Name, suffix,
321                        code, "", "true", else_code)
322                suffix = "Flags" + suffix
323
324            # If psrc1 or psrc2 is used, we need to actually insert code to
325            # compute it.
326            matcher = re.compile("(?<!\w)psrc1(?!\w)")
327            if matcher.search(allCode):
328                code = "uint64_t psrc1 = pick(SrcReg1, 0, dataSize);" + code
329            matcher = re.compile("(?<!\w)psrc2(?!\w)")
330            if matcher.search(allCode):
331                code = "uint64_t psrc2 = pick(SrcReg2, 1, dataSize);" + code
332            # Also make available versions which do sign extension
333            matcher = re.compile("(?<!\w)spsrc1(?!\w)")
334            if matcher.search(allCode):
335                code = "int64_t spsrc1 = signedPick(SrcReg1, 0, dataSize);" + code
336            matcher = re.compile("(?<!\w)spsrc2(?!\w)")
337            if matcher.search(allCode):
338                code = "int64_t spsrc2 = signedPick(SrcReg2, 1, dataSize);" + code
339            matcher = re.compile("(?<!\w)simm8(?!\w)")
340            if matcher.search(allCode):
341                code = "int8_t simm8 = imm8;" + code
342
343            base = "X86ISA::RegOp"
344
345            # If imm8 shows up in the code, use the immediate templates, if
346            # not, hopefully the register ones will be correct.
347            templates = regTemplates
348            matcher = re.compile("(?<!\w)s?imm8(?!\w)")
349            if matcher.search(allCode):
350                base += "Imm"
351                templates = immTemplates
352
353            # Get everything ready for the substitution
354            iop = InstObjParams(name, Name + suffix, base,
355                    {"code" : code,
356                     "flag_code" : flag_code,
357                     "cond_check" : cond_check,
358                     "else_code" : else_code})
359
360            # Generate the actual code (finally!)
361            header_output += templates[0].subst(iop)
362            decoder_output += templates[1].subst(iop)
363            exec_output += templates[2].subst(iop)
364
365
366        def __new__(mcls, Name, bases, dict):
367            abstract = False
368            name = Name.lower()
369            if "abstract" in dict:
370                abstract = dict['abstract']
371                del dict['abstract']
372
373            cls = super(RegOpMeta, mcls).__new__(mcls, Name, bases, dict)
374            if not abstract:
375                cls.className = Name
376                cls.base_mnemonic = name
377                code = cls.code
378                flag_code = cls.flag_code
379                cond_check = cls.cond_check
380                else_code = cls.else_code
381
382                # Set up the C++ classes
383                mcls.buildCppClasses(cls, name, Name, "",
384                        code, flag_code, cond_check, else_code)
385
386                # Hook into the microassembler dict
387                global microopClasses
388                microopClasses[name] = cls
389
390                allCode = "|".join((code, flag_code, cond_check, else_code))
391
392                # If op2 is used anywhere, make register and immediate versions
393                # of this code.
394                matcher = re.compile("op2(?P<typeQual>\\.\\w+)?")
395                if matcher.search(allCode):
396                    microopClasses[name + 'i'] = cls
397            return cls
398
399
400    class RegOp(X86Microop):
401        __metaclass__ = RegOpMeta
402        # This class itself doesn't act as a microop
403        abstract = True
404
405        # Default template parameter values
406        flag_code = ""
407        cond_check = "true"
408        else_code = ";"
409
410        def __init__(self, dest, src1, op2, flags = None, dataSize = "env.dataSize"):
411            self.dest = dest
412            self.src1 = src1
413            self.op2 = op2
414            self.flags = flags
415            self.dataSize = dataSize
416            if flags is None:
417                self.ext = 0
418            else:
419                if not isinstance(flags, (list, tuple)):
420                    raise Exception, "flags must be a list or tuple of flags"
421                self.ext = " | ".join(flags)
422                self.className += "Flags"
423
424        def getAllocator(self, *microFlags):
425            className = self.className
426            if self.mnemonic == self.base_mnemonic + 'i':
427                className += "Imm"
428            allocator = '''new %(class_name)s(machInst, macrocodeBlock
429                    %(flags)s, %(src1)s, %(op2)s, %(dest)s,
430                    %(dataSize)s, %(ext)s)''' % {
431                "class_name" : className,
432                "flags" : self.microFlagsText(microFlags),
433                "src1" : self.src1, "op2" : self.op2,
434                "dest" : self.dest,
435                "dataSize" : self.dataSize,
436                "ext" : self.ext}
437            return allocator
438
439    class LogicRegOp(RegOp):
440        abstract = True
441        flag_code = '''
442            //Don't have genFlags handle the OF or CF bits
443            uint64_t mask = CFBit | ECFBit | OFBit;
444            ccFlagBits = genFlags(ccFlagBits, ext & ~mask, DestReg, psrc1, op2);
445            //If a logic microop wants to set these, it wants to set them to 0.
446            ccFlagBits &= ~(CFBit & ext);
447            ccFlagBits &= ~(ECFBit & ext);
448            ccFlagBits &= ~(OFBit & ext);
449        '''
450
451    class FlagRegOp(RegOp):
452        abstract = True
453        flag_code = \
454            "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, op2);"
455
456    class SubRegOp(RegOp):
457        abstract = True
458        flag_code = \
459            "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, ~op2, true);"
460
461    class CondRegOp(RegOp):
462        abstract = True
463        cond_check = "checkCondition(ccFlagBits, ext)"
464
465    class RdRegOp(RegOp):
466        abstract = True
467        def __init__(self, dest, src1=None, dataSize="env.dataSize"):
468            if not src1:
469                src1 = dest
470            super(RdRegOp, self).__init__(dest, src1, \
471                    "InstRegIndex(NUM_INTREGS)", None, dataSize)
472
473    class WrRegOp(RegOp):
474        abstract = True
475        def __init__(self, src1, src2, flags=None, dataSize="env.dataSize"):
476            super(WrRegOp, self).__init__("InstRegIndex(NUM_INTREGS)", \
477                    src1, src2, flags, dataSize)
478
479    class Add(FlagRegOp):
480        code = 'DestReg = merge(DestReg, psrc1 + op2, dataSize);'
481
482    class Or(LogicRegOp):
483        code = 'DestReg = merge(DestReg, psrc1 | op2, dataSize);'
484
485    class Adc(FlagRegOp):
486        code = '''
487            CCFlagBits flags = ccFlagBits;
488            DestReg = merge(DestReg, psrc1 + op2 + flags.cf, dataSize);
489            '''
490
491    class Sbb(SubRegOp):
492        code = '''
493            CCFlagBits flags = ccFlagBits;
494            DestReg = merge(DestReg, psrc1 - op2 - flags.cf, dataSize);
495            '''
496
497    class And(LogicRegOp):
498        code = 'DestReg = merge(DestReg, psrc1 & op2, dataSize)'
499
500    class Sub(SubRegOp):
501        code = 'DestReg = merge(DestReg, psrc1 - op2, dataSize)'
502
503    class Xor(LogicRegOp):
504        code = 'DestReg = merge(DestReg, psrc1 ^ op2, dataSize)'
505
506    class Mul1s(WrRegOp):
507        code = '''
508            ProdLow = psrc1 * op2;
509            int halfSize = (dataSize * 8) / 2;
510            uint64_t shifter = (ULL(1) << halfSize);
511            uint64_t hiResult;
512            uint64_t psrc1_h = psrc1 / shifter;
513            uint64_t psrc1_l = psrc1 & mask(halfSize);
514            uint64_t psrc2_h = (op2 / shifter) & mask(halfSize);
515            uint64_t psrc2_l = op2 & mask(halfSize);
516            hiResult = ((psrc1_l * psrc2_h + psrc1_h * psrc2_l +
517                        ((psrc1_l * psrc2_l) / shifter)) /shifter) +
518                       psrc1_h * psrc2_h;
519            if (bits(psrc1, dataSize * 8 - 1))
520                hiResult -= op2;
521            if (bits(op2, dataSize * 8 - 1))
522                hiResult -= psrc1;
523            ProdHi = hiResult;
524            '''
525        flag_code = '''
526            if ((-ProdHi & mask(dataSize * 8)) !=
527                    bits(ProdLow, dataSize * 8 - 1)) {
528                ccFlagBits = ccFlagBits | (ext & (CFBit | OFBit | ECFBit));
529            } else {
530                ccFlagBits = ccFlagBits & ~(ext & (CFBit | OFBit | ECFBit));
531            }
532        '''
533
534    class Mul1u(WrRegOp):
535        code = '''
536            ProdLow = psrc1 * op2;
537            int halfSize = (dataSize * 8) / 2;
538            uint64_t shifter = (ULL(1) << halfSize);
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            ProdHi = ((psrc1_l * psrc2_h + psrc1_h * psrc2_l +
544                      ((psrc1_l * psrc2_l) / shifter)) / shifter) +
545                     psrc1_h * psrc2_h;
546            '''
547        flag_code = '''
548            if (ProdHi) {
549                ccFlagBits = ccFlagBits | (ext & (CFBit | OFBit | ECFBit));
550            } else {
551                ccFlagBits = ccFlagBits & ~(ext & (CFBit | OFBit | ECFBit));
552            }
553        '''
554
555    class Mulel(RdRegOp):
556        code = 'DestReg = merge(SrcReg1, ProdLow, dataSize);'
557
558    class Muleh(RdRegOp):
559        def __init__(self, dest, src1=None, flags=None, dataSize="env.dataSize"):
560            if not src1:
561                src1 = dest
562            super(RdRegOp, self).__init__(dest, src1, \
563                    "InstRegIndex(NUM_INTREGS)", flags, dataSize)
564        code = 'DestReg = merge(SrcReg1, ProdHi, dataSize);'
565
566    # One or two bit divide
567    class Div1(WrRegOp):
568        code = '''
569            //These are temporaries so that modifying them later won't make
570            //the ISA parser think they're also sources.
571            uint64_t quotient = 0;
572            uint64_t remainder = psrc1;
573            //Similarly, this is a temporary so changing it doesn't make it
574            //a source.
575            uint64_t divisor = op2;
576            //This is a temporary just for consistency and clarity.
577            uint64_t dividend = remainder;
578            //Do the division.
579            divide(dividend, divisor, quotient, remainder);
580            //Record the final results.
581            Remainder = remainder;
582            Quotient = quotient;
583            Divisor = divisor;
584            '''
585
586    # Step divide
587    class Div2(RegOp):
588        code = '''
589            uint64_t dividend = Remainder;
590            uint64_t divisor = Divisor;
591            uint64_t quotient = Quotient;
592            uint64_t remainder = dividend;
593            int remaining = op2;
594            //If we overshot, do nothing. This lets us unrool division loops a
595            //little.
596            if (remaining) {
597                if (divisor & (ULL(1) << 63)) {
598                    while (remaining && !(dividend & (ULL(1) << 63))) {
599                        dividend = (dividend << 1) |
600                            bits(SrcReg1, remaining - 1);
601                        quotient <<= 1;
602                        remaining--;
603                    }
604                    if (dividend & (ULL(1) << 63)) {
605                        bool highBit = false;
606                        if (dividend < divisor && remaining) {
607                            highBit = true;
608                            dividend = (dividend << 1) |
609                                bits(SrcReg1, remaining - 1);
610                            quotient <<= 1;
611                            remaining--;
612                        }
613                        if (highBit || divisor <= dividend) {
614                            quotient++;
615                            dividend -= divisor;
616                        }
617                    }
618                    remainder = dividend;
619                } else {
620                    //Shift in bits from the low order portion of the dividend
621                    while (dividend < divisor && remaining) {
622                        dividend = (dividend << 1) |
623                            bits(SrcReg1, remaining - 1);
624                        quotient <<= 1;
625                        remaining--;
626                    }
627                    remainder = dividend;
628                    //Do the division.
629                    divide(dividend, divisor, quotient, remainder);
630                }
631            }
632            //Keep track of how many bits there are still to pull in.
633            DestReg = merge(DestReg, remaining, dataSize);
634            //Record the final results
635            Remainder = remainder;
636            Quotient = quotient;
637        '''
638        flag_code = '''
639            if (DestReg == 0)
640                ccFlagBits = ccFlagBits | (ext & EZFBit);
641            else
642                ccFlagBits = ccFlagBits & ~(ext & EZFBit);
643        '''
644
645    class Divq(RdRegOp):
646        code = 'DestReg = merge(SrcReg1, Quotient, dataSize);'
647
648    class Divr(RdRegOp):
649        code = 'DestReg = merge(SrcReg1, Remainder, dataSize);'
650
651    class Mov(CondRegOp):
652        code = 'DestReg = merge(SrcReg1, op2, dataSize)'
653        else_code = 'DestReg = DestReg;'
654
655    # Shift instructions
656
657    class Sll(RegOp):
658        code = '''
659            uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
660            DestReg = merge(DestReg, psrc1 << shiftAmt, dataSize);
661            '''
662        flag_code = '''
663            // If the shift amount is zero, no flags should be modified.
664            if (shiftAmt) {
665                //Zero out any flags we might modify. This way we only have to
666                //worry about setting them.
667                ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
668                int CFBits = 0;
669                //Figure out if we -would- set the CF bits if requested.
670                if (shiftAmt <= dataSize * 8 &&
671                        bits(SrcReg1, dataSize * 8 - shiftAmt)) {
672                    CFBits = 1;
673                }
674                //If some combination of the CF bits need to be set, set them.
675                if ((ext & (CFBit | ECFBit)) && CFBits)
676                    ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
677                //Figure out what the OF bit should be.
678                if ((ext & OFBit) && (CFBits ^ bits(DestReg, dataSize * 8 - 1)))
679                    ccFlagBits = ccFlagBits | OFBit;
680                //Use the regular mechanisms to calculate the other flags.
681                ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
682                        DestReg, psrc1, op2);
683            }
684        '''
685
686    class Srl(RegOp):
687        code = '''
688            uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
689            // Because what happens to the bits shift -in- on a right shift
690            // is not defined in the C/C++ standard, we have to mask them out
691            // to be sure they're zero.
692            uint64_t logicalMask = mask(dataSize * 8 - shiftAmt);
693            DestReg = merge(DestReg, (psrc1 >> shiftAmt) & logicalMask, dataSize);
694            '''
695        flag_code = '''
696            // If the shift amount is zero, no flags should be modified.
697            if (shiftAmt) {
698                //Zero out any flags we might modify. This way we only have to
699                //worry about setting them.
700                ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
701                //If some combination of the CF bits need to be set, set them.
702                if ((ext & (CFBit | ECFBit)) && 
703                        shiftAmt <= dataSize * 8 &&
704                        bits(SrcReg1, shiftAmt - 1)) {
705                    ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
706                }
707                //Figure out what the OF bit should be.
708                if ((ext & OFBit) && bits(SrcReg1, dataSize * 8 - 1))
709                    ccFlagBits = ccFlagBits | OFBit;
710                //Use the regular mechanisms to calculate the other flags.
711                ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
712                        DestReg, psrc1, op2);
713            }
714        '''
715
716    class Sra(RegOp):
717        code = '''
718            uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
719            // Because what happens to the bits shift -in- on a right shift
720            // is not defined in the C/C++ standard, we have to sign extend
721            // them manually to be sure.
722            uint64_t arithMask = (shiftAmt == 0) ? 0 :
723                -bits(psrc1, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt);
724            DestReg = merge(DestReg, (psrc1 >> shiftAmt) | arithMask, dataSize);
725            '''
726        flag_code = '''
727            // If the shift amount is zero, no flags should be modified.
728            if (shiftAmt) {
729                //Zero out any flags we might modify. This way we only have to
730                //worry about setting them.
731                ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
732                //If some combination of the CF bits need to be set, set them.
733                uint8_t effectiveShift =
734                    (shiftAmt <= dataSize * 8) ? shiftAmt : (dataSize * 8);
735                if ((ext & (CFBit | ECFBit)) &&
736                        bits(SrcReg1, effectiveShift - 1)) {
737                    ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
738                }
739                //Use the regular mechanisms to calculate the other flags.
740                ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
741                        DestReg, psrc1, op2);
742            }
743        '''
744
745    class Ror(RegOp):
746        code = '''
747            uint8_t shiftAmt =
748                (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
749            uint8_t realShiftAmt = shiftAmt % (dataSize * 8);
750            if(realShiftAmt)
751            {
752                uint64_t top = psrc1 << (dataSize * 8 - realShiftAmt);
753                uint64_t bottom = bits(psrc1, dataSize * 8, realShiftAmt);
754                DestReg = merge(DestReg, top | bottom, dataSize);
755            }
756            else
757                DestReg = merge(DestReg, DestReg, dataSize);
758            '''
759        flag_code = '''
760            // If the shift amount is zero, no flags should be modified.
761            if (shiftAmt) {
762                //Zero out any flags we might modify. This way we only have to
763                //worry about setting them.
764                ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
765                //Find the most and second most significant bits of the result.
766                int msb = bits(DestReg, dataSize * 8 - 1);
767                int smsb = bits(DestReg, dataSize * 8 - 2);
768                //If some combination of the CF bits need to be set, set them.
769                if ((ext & (CFBit | ECFBit)) && msb)
770                    ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
771                //Figure out what the OF bit should be.
772                if ((ext & OFBit) && (msb ^ smsb))
773                    ccFlagBits = ccFlagBits | OFBit;
774                //Use the regular mechanisms to calculate the other flags.
775                ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
776                        DestReg, psrc1, op2);
777            }
778        '''
779
780    class Rcr(RegOp):
781        code = '''
782            uint8_t shiftAmt =
783                (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
784            uint8_t realShiftAmt = shiftAmt % (dataSize * 8 + 1);
785            if(realShiftAmt)
786            {
787                CCFlagBits flags = ccFlagBits;
788                uint64_t top = flags.cf << (dataSize * 8 - realShiftAmt);
789                if (realShiftAmt > 1)
790                    top |= psrc1 << (dataSize * 8 - realShiftAmt + 1);
791                uint64_t bottom = bits(psrc1, dataSize * 8 - 1, realShiftAmt);
792                DestReg = merge(DestReg, top | bottom, dataSize);
793            }
794            else
795                DestReg = merge(DestReg, DestReg, dataSize);
796            '''
797        flag_code = '''
798            // If the shift amount is zero, no flags should be modified.
799            if (shiftAmt) {
800                int origCFBit = (ccFlagBits & CFBit) ? 1 : 0;
801                //Zero out any flags we might modify. This way we only have to
802                //worry about setting them.
803                ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
804                //Figure out what the OF bit should be.
805                if ((ext & OFBit) && (origCFBit ^
806                                      bits(SrcReg1, dataSize * 8 - 1))) {
807                    ccFlagBits = ccFlagBits | OFBit;
808                }
809                //If some combination of the CF bits need to be set, set them.
810                if ((ext & (CFBit | ECFBit)) &&
811                        (realShiftAmt == 0) ? origCFBit :
812                        bits(SrcReg1, realShiftAmt - 1)) {
813                    ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
814                }
815                //Use the regular mechanisms to calculate the other flags.
816                ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
817                        DestReg, psrc1, op2);
818            }
819        '''
820
821    class Rol(RegOp):
822        code = '''
823            uint8_t shiftAmt =
824                (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
825            uint8_t realShiftAmt = shiftAmt % (dataSize * 8);
826            if(realShiftAmt)
827            {
828                uint64_t top = psrc1 << realShiftAmt;
829                uint64_t bottom =
830                    bits(psrc1, dataSize * 8 - 1, dataSize * 8 - realShiftAmt);
831                DestReg = merge(DestReg, top | bottom, dataSize);
832            }
833            else
834                DestReg = merge(DestReg, DestReg, dataSize);
835            '''
836        flag_code = '''
837            // If the shift amount is zero, no flags should be modified.
838            if (shiftAmt) {
839                //Zero out any flags we might modify. This way we only have to
840                //worry about setting them.
841                ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
842                //The CF bits, if set, would be set to the lsb of the result.
843                int lsb = DestReg & 0x1;
844                int msb = bits(DestReg, dataSize * 8 - 1);
845                //If some combination of the CF bits need to be set, set them.
846                if ((ext & (CFBit | ECFBit)) && lsb)
847                    ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
848                //Figure out what the OF bit should be.
849                if ((ext & OFBit) && (msb ^ lsb))
850                    ccFlagBits = ccFlagBits | OFBit;
851                //Use the regular mechanisms to calculate the other flags.
852                ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
853                        DestReg, psrc1, op2);
854            }
855        '''
856
857    class Rcl(RegOp):
858        code = '''
859            uint8_t shiftAmt =
860                (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
861            uint8_t realShiftAmt = shiftAmt % (dataSize * 8 + 1);
862            if(realShiftAmt)
863            {
864                CCFlagBits flags = ccFlagBits;
865                uint64_t top = psrc1 << realShiftAmt;
866                uint64_t bottom = flags.cf << (realShiftAmt - 1);
867                if(shiftAmt > 1)
868                    bottom |=
869                        bits(psrc1, dataSize * 8 - 1,
870                                   dataSize * 8 - realShiftAmt + 1);
871                DestReg = merge(DestReg, top | bottom, dataSize);
872            }
873            else
874                DestReg = merge(DestReg, DestReg, dataSize);
875            '''
876        flag_code = '''
877            // If the shift amount is zero, no flags should be modified.
878            if (shiftAmt) {
879                int origCFBit = (ccFlagBits & CFBit) ? 1 : 0;
880                //Zero out any flags we might modify. This way we only have to
881                //worry about setting them.
882                ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
883                int msb = bits(DestReg, dataSize * 8 - 1);
884                int CFBits = bits(SrcReg1, dataSize * 8 - realShiftAmt);
885                //If some combination of the CF bits need to be set, set them.
886                if ((ext & (CFBit | ECFBit)) && 
887                        (realShiftAmt == 0) ? origCFBit : CFBits)
888                    ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
889                //Figure out what the OF bit should be.
890                if ((ext & OFBit) && (msb ^ CFBits))
891                    ccFlagBits = ccFlagBits | OFBit;
892                //Use the regular mechanisms to calculate the other flags.
893                ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
894                        DestReg, psrc1, op2);
895            }
896        '''
897
898    class Sld(RegOp):
899        code = '''
900            uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
901            uint8_t dataBits = dataSize * 8;
902            uint8_t realShiftAmt = shiftAmt % (2 * dataBits);
903            uint64_t result;
904            if (realShiftAmt == 0) {
905                result = psrc1;
906            } else if (realShiftAmt < dataBits) {
907                result = (psrc1 << realShiftAmt) |
908                         (DoubleBits >> (dataBits - realShiftAmt));
909            } else {
910                result = (DoubleBits << (realShiftAmt - dataBits)) |
911                         (psrc1 >> (2 * dataBits - realShiftAmt));
912            }
913            DestReg = merge(DestReg, result, dataSize);
914            '''
915        flag_code = '''
916            // If the shift amount is zero, no flags should be modified.
917            if (shiftAmt) {
918                //Zero out any flags we might modify. This way we only have to
919                //worry about setting them.
920                ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
921                int CFBits = 0;
922                //Figure out if we -would- set the CF bits if requested.
923                if ((realShiftAmt == 0 &&
924                        bits(DoubleBits, 0)) ||
925                    (realShiftAmt <= dataBits &&
926                     bits(SrcReg1, dataBits - realShiftAmt)) ||
927                    (realShiftAmt > dataBits &&
928                     bits(DoubleBits, 2 * dataBits - realShiftAmt))) {
929                    CFBits = 1;
930                }
931                //If some combination of the CF bits need to be set, set them.
932                if ((ext & (CFBit | ECFBit)) && CFBits)
933                    ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
934                //Figure out what the OF bit should be.
935                if ((ext & OFBit) && (bits(SrcReg1, dataBits - 1) ^
936                                      bits(result, dataBits - 1)))
937                    ccFlagBits = ccFlagBits | OFBit;
938                //Use the regular mechanisms to calculate the other flags.
939                ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
940                        DestReg, psrc1, op2);
941            }
942        '''
943
944    class Srd(RegOp):
945        code = '''
946            uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
947            uint8_t dataBits = dataSize * 8;
948            uint8_t realShiftAmt = shiftAmt % (2 * dataBits);
949            uint64_t result;
950            if (realShiftAmt == 0) {
951                result = psrc1;
952            } else if (realShiftAmt < dataBits) {
953                // Because what happens to the bits shift -in- on a right
954                // shift is not defined in the C/C++ standard, we have to
955                // mask them out to be sure they're zero.
956                uint64_t logicalMask = mask(dataBits - realShiftAmt);
957                result = ((psrc1 >> realShiftAmt) & logicalMask) |
958                         (DoubleBits << (dataBits - realShiftAmt));
959            } else {
960                uint64_t logicalMask = mask(2 * dataBits - realShiftAmt);
961                result = ((DoubleBits >> (realShiftAmt - dataBits)) &
962                          logicalMask) |
963                         (psrc1 << (2 * dataBits - realShiftAmt));
964            }
965            DestReg = merge(DestReg, result, dataSize);
966            '''
967        flag_code = '''
968            // If the shift amount is zero, no flags should be modified.
969            if (shiftAmt) {
970                //Zero out any flags we might modify. This way we only have to
971                //worry about setting them.
972                ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
973                int CFBits = 0;
974                //If some combination of the CF bits need to be set, set them.
975                if ((realShiftAmt == 0 &&
976                            bits(DoubleBits, dataBits - 1)) ||
977                        (realShiftAmt <= dataBits &&
978                         bits(SrcReg1, realShiftAmt - 1)) ||
979                        (realShiftAmt > dataBits &&
980                         bits(DoubleBits, realShiftAmt - dataBits - 1))) {
981                    CFBits = 1;
982                }
983                //If some combination of the CF bits need to be set, set them.
984                if ((ext & (CFBit | ECFBit)) && CFBits)
985                    ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
986                //Figure out what the OF bit should be.
987                if ((ext & OFBit) && (bits(SrcReg1, dataBits - 1) ^
988                                      bits(result, dataBits - 1)))
989                    ccFlagBits = ccFlagBits | OFBit;
990                //Use the regular mechanisms to calculate the other flags.
991                ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
992                        DestReg, psrc1, op2);
993            }
994        '''
995
996    class Mdb(WrRegOp):
997        code = 'DoubleBits = psrc1 ^ op2;'
998
999    class Wrip(WrRegOp, CondRegOp):
1000        code = 'RIP = psrc1 + sop2 + CSBase'
1001        else_code="RIP = RIP;"
1002
1003    class Wruflags(WrRegOp):
1004        code = 'ccFlagBits = psrc1 ^ op2'
1005
1006    class Wrflags(WrRegOp):
1007        code = '''
1008            MiscReg newFlags = psrc1 ^ op2;
1009            MiscReg userFlagMask = 0xDD5;
1010            // Get only the user flags
1011            ccFlagBits = newFlags & userFlagMask;
1012            // Get everything else
1013            nccFlagBits = newFlags & ~userFlagMask;
1014        '''
1015
1016    class Rdip(RdRegOp):
1017        code = 'DestReg = RIP - CSBase'
1018
1019    class Ruflags(RdRegOp):
1020        code = 'DestReg = ccFlagBits'
1021
1022    class Rflags(RdRegOp):
1023        code = 'DestReg = ccFlagBits | nccFlagBits'
1024
1025    class Ruflag(RegOp):
1026        code = '''
1027            int flag = bits(ccFlagBits, imm8);
1028            DestReg = merge(DestReg, flag, dataSize);
1029            ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) :
1030                                       (ccFlagBits & ~EZFBit);
1031            '''
1032        def __init__(self, dest, imm, flags=None, \
1033                dataSize="env.dataSize"):
1034            super(Ruflag, self).__init__(dest, \
1035                    "InstRegIndex(NUM_INTREGS)", imm, flags, dataSize)
1036
1037    class Rflag(RegOp):
1038        code = '''
1039            MiscReg flagMask = 0x3F7FDD5;
1040            MiscReg flags = (nccFlagBits | ccFlagBits) & flagMask;
1041            int flag = bits(flags, imm8);
1042            DestReg = merge(DestReg, flag, dataSize);
1043            ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) :
1044                                       (ccFlagBits & ~EZFBit);
1045            '''
1046        def __init__(self, dest, imm, flags=None, \
1047                dataSize="env.dataSize"):
1048            super(Rflag, self).__init__(dest, \
1049                    "InstRegIndex(NUM_INTREGS)", imm, flags, dataSize)
1050
1051    class Sext(RegOp):
1052        code = '''
1053            IntReg val = psrc1;
1054            // Mask the bit position so that it wraps.
1055            int bitPos = op2 & (dataSize * 8 - 1);
1056            int sign_bit = bits(val, bitPos, bitPos);
1057            uint64_t maskVal = mask(bitPos+1);
1058            val = sign_bit ? (val | ~maskVal) : (val & maskVal);
1059            DestReg = merge(DestReg, val, dataSize);
1060            '''
1061        flag_code = '''
1062            if (!sign_bit)
1063                ccFlagBits = ccFlagBits &
1064                    ~(ext & (CFBit | ECFBit | ZFBit | EZFBit));
1065            else
1066                ccFlagBits = ccFlagBits |
1067                    (ext & (CFBit | ECFBit | ZFBit | EZFBit));
1068            '''
1069
1070    class Zext(RegOp):
1071        code = 'DestReg = merge(DestReg, bits(psrc1, op2, 0), dataSize);'
1072
1073    class Rddr(RegOp):
1074        def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1075            super(Rddr, self).__init__(dest, \
1076                    src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1077        code = '''
1078            CR4 cr4 = CR4Op;
1079            DR7 dr7 = DR7Op;
1080            if ((cr4.de == 1 && (src1 == 4 || src1 == 5)) || src1 >= 8) {
1081                fault = new InvalidOpcode();
1082            } else if (dr7.gd) {
1083                fault = new DebugException();
1084            } else {
1085                DestReg = merge(DestReg, DebugSrc1, dataSize);
1086            }
1087        '''
1088
1089    class Wrdr(RegOp):
1090        def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1091            super(Wrdr, self).__init__(dest, \
1092                    src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1093        code = '''
1094            CR4 cr4 = CR4Op;
1095            DR7 dr7 = DR7Op;
1096            if ((cr4.de == 1 && (dest == 4 || dest == 5)) || dest >= 8) {
1097                fault = new InvalidOpcode();
1098            } else if ((dest == 6 || dest == 7) && bits(psrc1, 63, 32) &&
1099                    machInst.mode.mode == LongMode) {
1100                fault = new GeneralProtection(0);
1101            } else if (dr7.gd) {
1102                fault = new DebugException();
1103            } else {
1104                DebugDest = psrc1;
1105            }
1106        '''
1107
1108    class Rdcr(RegOp):
1109        def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1110            super(Rdcr, self).__init__(dest, \
1111                    src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1112        code = '''
1113            if (src1 == 1 || (src1 > 4 && src1 < 8) || (src1 > 8)) {
1114                fault = new InvalidOpcode();
1115            } else {
1116                DestReg = merge(DestReg, ControlSrc1, dataSize);
1117            }
1118        '''
1119
1120    class Wrcr(RegOp):
1121        def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1122            super(Wrcr, self).__init__(dest, \
1123                    src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1124        code = '''
1125            if (dest == 1 || (dest > 4 && dest < 8) || (dest > 8)) {
1126                fault = new InvalidOpcode();
1127            } else {
1128                // There are *s in the line below so it doesn't confuse the
1129                // parser. They may be unnecessary.
1130                //Mis*cReg old*Val = pick(Cont*rolDest, 0, dat*aSize);
1131                MiscReg newVal = psrc1;
1132
1133                // Check for any modifications that would cause a fault.
1134                switch(dest) {
1135                  case 0:
1136                    {
1137                        Efer efer = EferOp;
1138                        CR0 cr0 = newVal;
1139                        CR4 oldCr4 = CR4Op;
1140                        if (bits(newVal, 63, 32) ||
1141                                (!cr0.pe && cr0.pg) ||
1142                                (!cr0.cd && cr0.nw) ||
1143                                (cr0.pg && efer.lme && !oldCr4.pae))
1144                            fault = new GeneralProtection(0);
1145                    }
1146                    break;
1147                  case 2:
1148                    break;
1149                  case 3:
1150                    break;
1151                  case 4:
1152                    {
1153                        CR4 cr4 = newVal;
1154                        // PAE can't be disabled in long mode.
1155                        if (bits(newVal, 63, 11) ||
1156                                (machInst.mode.mode == LongMode && !cr4.pae))
1157                            fault = new GeneralProtection(0);
1158                    }
1159                    break;
1160                  case 8:
1161                    {
1162                        if (bits(newVal, 63, 4))
1163                            fault = new GeneralProtection(0);
1164                    }
1165                  default:
1166                    panic("Unrecognized control register %d.\\n", dest);
1167                }
1168                ControlDest = newVal;
1169            }
1170            '''
1171
1172    # Microops for manipulating segmentation registers
1173    class SegOp(CondRegOp):
1174        abstract = True
1175        def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1176            super(SegOp, self).__init__(dest, \
1177                    src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1178
1179    class Wrbase(SegOp):
1180        code = '''
1181            SegBaseDest = psrc1;
1182        '''
1183
1184    class Wrlimit(SegOp):
1185        code = '''
1186            SegLimitDest = psrc1;
1187        '''
1188
1189    class Wrsel(SegOp):
1190        code = '''
1191            SegSelDest = psrc1;
1192        '''
1193
1194    class WrAttr(SegOp):
1195        code = '''
1196            SegAttrDest = psrc1;
1197        '''
1198
1199    class Rdbase(SegOp):
1200        code = '''
1201            DestReg = merge(DestReg, SegBaseSrc1, dataSize);
1202        '''
1203
1204    class Rdlimit(SegOp):
1205        code = '''
1206            DestReg = merge(DestReg, SegLimitSrc1, dataSize);
1207        '''
1208
1209    class RdAttr(SegOp):
1210        code = '''
1211            DestReg = merge(DestReg, SegAttrSrc1, dataSize);
1212        '''
1213
1214    class Rdsel(SegOp):
1215        code = '''
1216            DestReg = merge(DestReg, SegSelSrc1, dataSize);
1217        '''
1218
1219    class Rdval(RegOp):
1220        def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1221            super(Rdval, self).__init__(dest, src1, \
1222                    "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1223        code = '''
1224            DestReg = MiscRegSrc1;
1225        '''
1226
1227    class Wrval(RegOp):
1228        def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1229            super(Wrval, self).__init__(dest, src1, \
1230                    "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1231        code = '''
1232            MiscRegDest = SrcReg1;
1233        '''
1234
1235    class Chks(RegOp):
1236        def __init__(self, dest, src1, src2=0,
1237                flags=None, dataSize="env.dataSize"):
1238            super(Chks, self).__init__(dest,
1239                    src1, src2, flags, dataSize)
1240        code = '''
1241            // The selector is in source 1 and can be at most 16 bits.
1242            SegSelector selector = DestReg;
1243            SegDescriptor desc = SrcReg1;
1244            HandyM5Reg m5reg = M5Reg;
1245
1246            switch (imm8)
1247            {
1248              case SegNoCheck:
1249                break;
1250              case SegCSCheck:
1251                // Make sure it's the right type
1252                if (desc.s == 0 || desc.type.codeOrData != 1) {
1253                    fault = new GeneralProtection(0);
1254                } else if (m5reg.cpl != desc.dpl) {
1255                    fault = new GeneralProtection(0);
1256                }
1257                break;
1258              case SegCallGateCheck:
1259                panic("CS checks for far calls/jumps through call gates"
1260                        "not implemented.\\n");
1261                break;
1262              case SegSoftIntGateCheck:
1263                // Check permissions.
1264                if (desc.dpl < m5reg.cpl) {
1265                    fault = new GeneralProtection(selector);
1266                    break;
1267                }
1268                // Fall through on purpose
1269              case SegIntGateCheck:
1270                // Make sure the gate's the right type.
1271                if ((m5reg.mode == LongMode && (desc.type & 0xe) != 0xe) ||
1272                        ((desc.type & 0x6) != 0x6)) {
1273                    fault = new GeneralProtection(0);
1274                }
1275                break;
1276              case SegSSCheck:
1277                if (selector.si || selector.ti) {
1278                    if (!desc.p) {
1279                        fault = new StackFault(selector);
1280                    }
1281                } else {
1282                    if ((m5reg.submode != SixtyFourBitMode ||
1283                                m5reg.cpl == 3) ||
1284                            !(desc.s == 1 &&
1285                            desc.type.codeOrData == 0 && desc.type.w) ||
1286                            (desc.dpl != m5reg.cpl) ||
1287                            (selector.rpl != m5reg.cpl)) {
1288                        fault = new GeneralProtection(selector);
1289                    }
1290                }
1291                break;
1292              case SegIretCheck:
1293                {
1294                    if ((!selector.si && !selector.ti) ||
1295                            (selector.rpl < m5reg.cpl) ||
1296                            !(desc.s == 1 && desc.type.codeOrData == 1) ||
1297                            (!desc.type.c && desc.dpl != selector.rpl) ||
1298                            (desc.type.c && desc.dpl > selector.rpl)) {
1299                        fault = new GeneralProtection(selector);
1300                    } else if (!desc.p) {
1301                        fault = new SegmentNotPresent(selector);
1302                    }
1303                    break;
1304                }
1305              case SegIntCSCheck:
1306                if (m5reg.mode == LongMode) {
1307                    if (desc.l != 1 || desc.d != 0) {
1308                        fault = new GeneralProtection(selector);
1309                    }
1310                } else {
1311                    panic("Interrupt CS checks not implemented "
1312                            "in legacy mode.\\n");
1313                }
1314                break;
1315              case SegTRCheck:
1316                if (!selector.si || selector.ti) {
1317                    fault = new GeneralProtection(selector);
1318                }
1319                break;
1320              case SegTSSCheck:
1321                if (!desc.p) {
1322                    fault = new SegmentNotPresent(selector);
1323                } else if (!(desc.type == 0x9 ||
1324                        (desc.type == 1 &&
1325                         m5reg.mode != LongMode))) {
1326                    fault = new GeneralProtection(selector);
1327                }
1328                break;
1329              case SegInGDTCheck:
1330                if (selector.ti) {
1331                    fault = new GeneralProtection(selector);
1332                }
1333                break;
1334              case SegLDTCheck:
1335                if (!desc.p) {
1336                    fault = new SegmentNotPresent(selector);
1337                } else if (desc.type != 0x2) {
1338                    fault = new GeneralProtection(selector);
1339                }
1340                break;
1341              default:
1342                panic("Undefined segment check type.\\n");
1343            }
1344        '''
1345        flag_code = '''
1346            // Check for a NULL selector and set ZF,EZF appropriately.
1347            ccFlagBits = ccFlagBits & ~(ext & (ZFBit | EZFBit));
1348            if (!selector.si && !selector.ti)
1349                ccFlagBits = ccFlagBits | (ext & (ZFBit | EZFBit));
1350        '''
1351
1352    class Wrdh(RegOp):
1353        code = '''
1354            SegDescriptor desc = SrcReg1;
1355
1356            uint64_t target = bits(SrcReg2, 31, 0) << 32;
1357            switch(desc.type) {
1358              case LDT64:
1359              case AvailableTSS64:
1360              case BusyTSS64:
1361                replaceBits(target, 23, 0, desc.baseLow);
1362                replaceBits(target, 31, 24, desc.baseHigh);
1363                break;
1364              case CallGate64:
1365              case IntGate64:
1366              case TrapGate64:
1367                replaceBits(target, 15, 0, bits(desc, 15, 0));
1368                replaceBits(target, 31, 16, bits(desc, 63, 48));
1369                break;
1370              default:
1371                panic("Wrdh used with wrong descriptor type!\\n");
1372            }
1373            DestReg = target;
1374        '''
1375
1376    class Wrtsc(WrRegOp):
1377        code = '''
1378            TscOp = psrc1;
1379        '''
1380
1381    class Rdtsc(RdRegOp):
1382        code = '''
1383            DestReg = TscOp;
1384        '''
1385
1386    class Rdm5reg(RdRegOp):
1387        code = '''
1388            DestReg = M5Reg;
1389        '''
1390
1391    class Wrdl(RegOp):
1392        code = '''
1393            SegDescriptor desc = SrcReg1;
1394            SegSelector selector = SrcReg2;
1395            if (selector.si || selector.ti) {
1396                if (!desc.p)
1397                    panic("Segment not present.\\n");
1398                SegAttr attr = 0;
1399                attr.dpl = desc.dpl;
1400                attr.unusable = 0;
1401                attr.defaultSize = desc.d;
1402                attr.longMode = desc.l;
1403                attr.avl = desc.avl;
1404                attr.granularity = desc.g;
1405                attr.present = desc.p;
1406                attr.system = desc.s;
1407                attr.type = desc.type;
1408                if (!desc.s) {
1409                    // The expand down bit happens to be set for gates.
1410                    if (desc.type.e) {
1411                        panic("Gate descriptor encountered.\\n");
1412                    }
1413                    attr.readable = 1;
1414                    attr.writable = 1;
1415                    attr.expandDown = 0;
1416                } else {
1417                    if (desc.type.codeOrData) {
1418                        attr.expandDown = 0;
1419                        attr.readable = desc.type.r;
1420                        attr.writable = 0;
1421                    } else {
1422                        attr.expandDown = desc.type.e;
1423                        attr.readable = 1;
1424                        attr.writable = desc.type.w;
1425                    }
1426                }
1427                Addr base = desc.baseLow | (desc.baseHigh << 24);
1428                Addr limit = desc.limitLow | (desc.limitHigh << 16);
1429                if (desc.g)
1430                    limit = (limit << 12) | mask(12);
1431                SegBaseDest = base;
1432                SegLimitDest = limit;
1433                SegAttrDest = attr;
1434            } else {
1435                SegBaseDest = SegBaseDest;
1436                SegLimitDest = SegLimitDest;
1437                SegAttrDest = SegAttrDest;
1438            }
1439        '''
1440}};
1441