regop.isa revision 7967
12914SN/A// Copyright (c) 2007-2008 The Hewlett-Packard Development Company
210713Sandreas.hansson@arm.com// All rights reserved.
38856SN/A//
48856SN/A// The license below extends only to copyright in the software and shall
58856SN/A// not be construed as granting a license to any other intellectual
68856SN/A// property including but not limited to intellectual property relating
78856SN/A// to a hardware implementation of the functionality of the software
88856SN/A// licensed hereunder.  You may use the software subject to the license
98856SN/A// terms below provided that you ensure that this notice is replicated
108856SN/A// unmodified and in its entirety in all distributions of the software,
118856SN/A// modified or unmodified, in source code or in binary form.
128856SN/A//
138856SN/A// Redistribution and use in source and binary forms, with or without
142914SN/A// modification, are permitted provided that the following conditions are
152914SN/A// met: redistributions of source code must retain the above copyright
162914SN/A// notice, this list of conditions and the following disclaimer;
172914SN/A// redistributions in binary form must reproduce the above copyright
182914SN/A// notice, this list of conditions and the following disclaimer in the
192914SN/A// documentation and/or other materials provided with the distribution;
202914SN/A// neither the name of the copyright holders nor the names of its
212914SN/A// contributors may be used to endorse or promote products derived from
222914SN/A// this software without specific prior written permission.
232914SN/A//
242914SN/A// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
252914SN/A// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
262914SN/A// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
272914SN/A// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
282914SN/A// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
292914SN/A// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
302914SN/A// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
312914SN/A// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
322914SN/A// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
332914SN/A// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
342914SN/A// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
352914SN/A//
362914SN/A// Authors: Gabe Black
372914SN/A
382914SN/A//////////////////////////////////////////////////////////////////////////
392914SN/A//
402914SN/A// RegOp Microop templates
418856SN/A//
422914SN/A//////////////////////////////////////////////////////////////////////////
432914SN/A
449356Snilay@cs.wisc.edudef template MicroRegOpExecute {{
459152Satgutier@umich.edu        Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
468914Sandreas.hansson@arm.com                Trace::InstRecord *traceData) const
478914Sandreas.hansson@arm.com        {
482914SN/A            Fault fault = NoFault;
495740SN/A
505740SN/A            DPRINTF(X86, "The data size is %d\n", dataSize);
5111207SBrad.Beckmann@amd.com            %(op_decl)s;
5211207SBrad.Beckmann@amd.com            %(op_rd)s;
5311207SBrad.Beckmann@amd.com
5411207SBrad.Beckmann@amd.com            if(%(cond_check)s)
555740SN/A            {
565740SN/A                %(code)s;
575740SN/A                %(flag_code)s;
588914Sandreas.hansson@arm.com            }
595740SN/A            else
605740SN/A            {
615740SN/A                %(else_code)s;
628914Sandreas.hansson@arm.com            }
638914Sandreas.hansson@arm.com
648914Sandreas.hansson@arm.com            //Write the resulting state to the execution context
658914Sandreas.hansson@arm.com            if(fault == NoFault)
668914Sandreas.hansson@arm.com            {
6710713Sandreas.hansson@arm.com                %(op_wb)s;
688914Sandreas.hansson@arm.com            }
698914Sandreas.hansson@arm.com            return fault;
708914Sandreas.hansson@arm.com        }
714929SN/A}};
7210713Sandreas.hansson@arm.com
7310713Sandreas.hansson@arm.comdef template MicroRegOpImmExecute {{
7410713Sandreas.hansson@arm.com        Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
7510713Sandreas.hansson@arm.com                Trace::InstRecord *traceData) const
7610713Sandreas.hansson@arm.com        {
7710713Sandreas.hansson@arm.com            Fault fault = NoFault;
7810713Sandreas.hansson@arm.com
7910713Sandreas.hansson@arm.com            %(op_decl)s;
8010713Sandreas.hansson@arm.com            %(op_rd)s;
8110713Sandreas.hansson@arm.com
8210713Sandreas.hansson@arm.com            if(%(cond_check)s)
8310713Sandreas.hansson@arm.com            {
848914Sandreas.hansson@arm.com                %(code)s;
853091SN/A                %(flag_code)s;
868856SN/A            }
878856SN/A            else
8810322Sandreas.hansson@arm.com            {
898856SN/A                %(else_code)s;
903296SN/A            }
9110322Sandreas.hansson@arm.com
928856SN/A            //Write the resulting state to the execution context
938856SN/A            if(fault == NoFault)
948856SN/A            {
958856SN/A                %(op_wb)s;
963284SN/A            }
974929SN/A            return fault;
988856SN/A        }
998856SN/A}};
1008856SN/A
1014490SN/Adef template MicroRegOpDeclare {{
1023342SN/A    class %(class_name)s : public %(base_class)s
1034490SN/A    {
10410722Sstephan.diestelhorst@arm.com      public:
1053403SN/A        %(class_name)s(ExtMachInst _machInst,
10610722Sstephan.diestelhorst@arm.com                const char * instMnem, uint64_t setFlags,
10710722Sstephan.diestelhorst@arm.com                InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
10810722Sstephan.diestelhorst@arm.com                uint8_t _dataSize, uint16_t _ext);
10910713Sandreas.hansson@arm.com
1109160Sandreas.hansson@arm.com        %(BasicExecDeclare)s
1119160Sandreas.hansson@arm.com    };
1124492SN/A}};
1139163Sandreas.hansson@arm.com
1149163Sandreas.hansson@arm.comdef template MicroRegOpImmDeclare {{
1159163Sandreas.hansson@arm.com
1169390Sandreas.hansson@arm.com    class %(class_name)s : public %(base_class)s
1179390Sandreas.hansson@arm.com    {
11811207SBrad.Beckmann@amd.com      public:
1199390Sandreas.hansson@arm.com        %(class_name)s(ExtMachInst _machInst,
1209390Sandreas.hansson@arm.com                const char * instMnem, uint64_t setFlags,
1219390Sandreas.hansson@arm.com                InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest,
1229390Sandreas.hansson@arm.com                uint8_t _dataSize, uint16_t _ext);
12311195Sandreas.hansson@arm.com
12411195Sandreas.hansson@arm.com        %(BasicExecDeclare)s
12510922Sandreas.hansson@arm.com    };
1264666SN/A}};
1274666SN/A
1284666SN/Adef template MicroRegOpConstructor {{
1294666SN/A    inline %(class_name)s::%(class_name)s(
13010713Sandreas.hansson@arm.com            ExtMachInst machInst, const char * instMnem, uint64_t setFlags,
13110713Sandreas.hansson@arm.com            InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
13210713Sandreas.hansson@arm.com            uint8_t _dataSize, uint16_t _ext) :
13310713Sandreas.hansson@arm.com        %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags,
13410713Sandreas.hansson@arm.com                _src1, _src2, _dest, _dataSize, _ext,
13510713Sandreas.hansson@arm.com                %(op_class)s)
13610713Sandreas.hansson@arm.com    {
13710713Sandreas.hansson@arm.com        %(constructor)s;
13811195Sandreas.hansson@arm.com        %(cond_control_flag_init)s;
13911195Sandreas.hansson@arm.com    }
14011195Sandreas.hansson@arm.com}};
14111195Sandreas.hansson@arm.com
14211195Sandreas.hansson@arm.comdef template MicroRegOpImmConstructor {{
14311195Sandreas.hansson@arm.com    inline %(class_name)s::%(class_name)s(
14411195Sandreas.hansson@arm.com            ExtMachInst machInst, const char * instMnem, uint64_t setFlags,
14511195Sandreas.hansson@arm.com            InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest,
14611195Sandreas.hansson@arm.com            uint8_t _dataSize, uint16_t _ext) :
1473450SN/A        %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags,
14811195Sandreas.hansson@arm.com                _src1, _imm8, _dest, _dataSize, _ext,
14911195Sandreas.hansson@arm.com                %(op_class)s)
15011195Sandreas.hansson@arm.com    {
1518856SN/A        %(constructor)s;
1528856SN/A        %(cond_control_flag_init)s;
1538856SN/A    }
15410713Sandreas.hansson@arm.com}};
1558856SN/A
15610713Sandreas.hansson@arm.comoutput header {{
15710713Sandreas.hansson@arm.com    void
15810713Sandreas.hansson@arm.com    divide(uint64_t dividend, uint64_t divisor,
15910713Sandreas.hansson@arm.com            uint64_t &quotient, uint64_t &remainder);
16010713Sandreas.hansson@arm.com
16110713Sandreas.hansson@arm.com    enum SegmentSelectorCheck {
1628914Sandreas.hansson@arm.com      SegNoCheck, SegCSCheck, SegCallGateCheck, SegIntGateCheck,
16310713Sandreas.hansson@arm.com      SegSoftIntGateCheck, SegSSCheck, SegIretCheck, SegIntCSCheck,
16410713Sandreas.hansson@arm.com      SegTRCheck, SegTSSCheck, SegInGDTCheck, SegLDTCheck
16510713Sandreas.hansson@arm.com    };
16610713Sandreas.hansson@arm.com
16710713Sandreas.hansson@arm.com    enum LongModeDescriptorType {
16810713Sandreas.hansson@arm.com        LDT64 = 2,
16910423Sandreas.hansson@arm.com        AvailableTSS64 = 9,
17010713Sandreas.hansson@arm.com        BusyTSS64 = 0xb,
17110713Sandreas.hansson@arm.com        CallGate64 = 0xc,
17210423Sandreas.hansson@arm.com        IntGate64 = 0xe,
17310423Sandreas.hansson@arm.com        TrapGate64 = 0xf
17410713Sandreas.hansson@arm.com    };
17510423Sandreas.hansson@arm.com}};
1768856SN/A
17710713Sandreas.hansson@arm.comoutput decoder {{
17810713Sandreas.hansson@arm.com    void
17910913Sandreas.sandberg@arm.com    divide(uint64_t dividend, uint64_t divisor,
18010913Sandreas.sandberg@arm.com            uint64_t &quotient, uint64_t &remainder)
18110913Sandreas.sandberg@arm.com    {
1829152Satgutier@umich.edu        //Check for divide by zero.
1839152Satgutier@umich.edu        assert(divisor != 0);
18410913Sandreas.sandberg@arm.com        //If the divisor is bigger than the dividend, don't do anything.
1858856SN/A        if (divisor <= dividend) {
1868856SN/A            //Shift the divisor so it's msb lines up with the dividend.
1878856SN/A            int dividendMsb = findMsbSet(dividend);
1884492SN/A            int divisorMsb = findMsbSet(divisor);
1893403SN/A            int shift = dividendMsb - divisorMsb;
1908914Sandreas.hansson@arm.com            divisor <<= shift;
1912914SN/A            //Compute what we'll add to the quotient if the divisor isn't
19210713Sandreas.hansson@arm.com            //now larger than the dividend.
19310713Sandreas.hansson@arm.com            uint64_t quotientBit = 1;
19410713Sandreas.hansson@arm.com            quotientBit <<= shift;
19510713Sandreas.hansson@arm.com            //If we need to step back a bit (no pun intended) because the
19610713Sandreas.hansson@arm.com            //divisor got too to large, do that here. This is the "or two"
19710713Sandreas.hansson@arm.com            //part of one or two bit division.
19810713Sandreas.hansson@arm.com            if (divisor > dividend) {
19910713Sandreas.hansson@arm.com                quotientBit >>= 1;
20010713Sandreas.hansson@arm.com                divisor >>= 1;
20110713Sandreas.hansson@arm.com            }
20210713Sandreas.hansson@arm.com            //Decrement the remainder and increment the quotient.
20310713Sandreas.hansson@arm.com            quotient += quotientBit;
20410713Sandreas.hansson@arm.com            remainder -= divisor;
20510713Sandreas.hansson@arm.com        }
20610713Sandreas.hansson@arm.com    }
20710713Sandreas.hansson@arm.com}};
2084492SN/A
2098856SN/Alet {{
2108856SN/A    # Make these empty strings so that concatenating onto
2118856SN/A    # them will always work.
21210713Sandreas.hansson@arm.com    header_output = ""
21310713Sandreas.hansson@arm.com    decoder_output = ""
21410713Sandreas.hansson@arm.com    exec_output = ""
21510745Sandreas.hansson@arm.com
2164492SN/A    immTemplates = (
2174492SN/A            MicroRegOpImmDeclare,
2184492SN/A            MicroRegOpImmConstructor,
2194492SN/A            MicroRegOpImmExecute)
2208914Sandreas.hansson@arm.com
2214492SN/A    regTemplates = (
2224492SN/A            MicroRegOpDeclare,
2234492SN/A            MicroRegOpConstructor,
2242914SN/A            MicroRegOpExecute)
2252914SN/A
22610913Sandreas.sandberg@arm.com    class RegOpMeta(type):
22710913Sandreas.sandberg@arm.com        def buildCppClasses(self, name, Name, suffix, code, big_code, \
2282914SN/A                flag_code, cond_check, else_code, cond_control_flag_init):
22910913Sandreas.sandberg@arm.com
23010913Sandreas.sandberg@arm.com            # Globals to stick the output in
23110913Sandreas.sandberg@arm.com            global header_output
23210913Sandreas.sandberg@arm.com            global decoder_output
23310913Sandreas.sandberg@arm.com            global exec_output
23410913Sandreas.sandberg@arm.com
2352914SN/A            # Stick all the code together so it can be searched at once
2368975Sandreas.hansson@arm.com            allCode = "|".join((code, flag_code, cond_check, else_code, 
23710713Sandreas.hansson@arm.com                                cond_control_flag_init))
23810713Sandreas.hansson@arm.com            allBigCode = "|".join((big_code, flag_code, cond_check, else_code,
2398975Sandreas.hansson@arm.com                                   cond_control_flag_init))
2408975Sandreas.hansson@arm.com
2418975Sandreas.hansson@arm.com            # If op2 is used anywhere, make register and immediate versions
2428975Sandreas.hansson@arm.com            # of this code.
2438975Sandreas.hansson@arm.com            matcher = re.compile("(?<!\\w)(?P<prefix>s?)op2(?P<typeQual>\\.\\w+)?")
24410713Sandreas.hansson@arm.com            match = matcher.search(allCode + allBigCode)
2458975Sandreas.hansson@arm.com            if match:
24610713Sandreas.hansson@arm.com                typeQual = ""
2478975Sandreas.hansson@arm.com                if match.group("typeQual"):
2488975Sandreas.hansson@arm.com                    typeQual = match.group("typeQual")
24910713Sandreas.hansson@arm.com                src2_name = "%spsrc2%s" % (match.group("prefix"), typeQual)
25010713Sandreas.hansson@arm.com                self.buildCppClasses(name, Name, suffix,
25110713Sandreas.hansson@arm.com                        matcher.sub(src2_name, code),
25210713Sandreas.hansson@arm.com                        matcher.sub(src2_name, big_code),
25310713Sandreas.hansson@arm.com                        matcher.sub(src2_name, flag_code),
25410713Sandreas.hansson@arm.com                        matcher.sub(src2_name, cond_check),
25510713Sandreas.hansson@arm.com                        matcher.sub(src2_name, else_code),
25610713Sandreas.hansson@arm.com                        matcher.sub(src2_name, cond_control_flag_init))
25710713Sandreas.hansson@arm.com                imm_name = "%simm8" % match.group("prefix")
25810713Sandreas.hansson@arm.com                self.buildCppClasses(name + "i", Name, suffix + "Imm",
25910713Sandreas.hansson@arm.com                        matcher.sub(imm_name, code),
26010713Sandreas.hansson@arm.com                        matcher.sub(imm_name, big_code),
26110713Sandreas.hansson@arm.com                        matcher.sub(imm_name, flag_code),
26210713Sandreas.hansson@arm.com                        matcher.sub(imm_name, cond_check),
26310713Sandreas.hansson@arm.com                        matcher.sub(imm_name, else_code),
2648975Sandreas.hansson@arm.com                        matcher.sub(imm_name, cond_control_flag_init))
2658975Sandreas.hansson@arm.com                return
2668975Sandreas.hansson@arm.com
2678975Sandreas.hansson@arm.com            # If there's something optional to do with flags, generate
2688975Sandreas.hansson@arm.com            # a version without it and fix up this version to use it.
26910713Sandreas.hansson@arm.com            if flag_code != "" or cond_check != "true":
2708975Sandreas.hansson@arm.com                self.buildCppClasses(name, Name, suffix,
2718975Sandreas.hansson@arm.com                        code, big_code, "", "true", else_code, "")
2728975Sandreas.hansson@arm.com                suffix = "Flags" + suffix
273
274            # If psrc1 or psrc2 is used, we need to actually insert code to
275            # compute it.
276            for (big, all) in ((False, allCode), (True, allBigCode)):
277                prefix = ""
278                for (rex, decl) in (
279                        ("(?<!\w)psrc1(?!\w)",
280                         "uint64_t psrc1 = pick(SrcReg1, 0, dataSize);"),
281                        ("(?<!\w)psrc2(?!\w)",
282                         "uint64_t psrc2 = pick(SrcReg2, 1, dataSize);"),
283                        ("(?<!\w)spsrc1(?!\w)",
284                         "int64_t spsrc1 = signedPick(SrcReg1, 0, dataSize);"),
285                        ("(?<!\w)spsrc2(?!\w)",
286                         "int64_t spsrc2 = signedPick(SrcReg2, 1, dataSize);"),
287                        ("(?<!\w)simm8(?!\w)",
288                         "int8_t simm8 = imm8;")):
289                    matcher = re.compile(rex)
290                    if matcher.search(all):
291                        prefix += decl + "\n"
292                if big:
293                    if big_code != "":
294                        big_code = prefix + big_code
295                else:
296                    code = prefix + code
297
298            base = "X86ISA::RegOp"
299
300            # If imm8 shows up in the code, use the immediate templates, if
301            # not, hopefully the register ones will be correct.
302            templates = regTemplates
303            matcher = re.compile("(?<!\w)s?imm8(?!\w)")
304            if matcher.search(allCode):
305                base += "Imm"
306                templates = immTemplates
307
308            # Get everything ready for the substitution
309            iops = [InstObjParams(name, Name + suffix, base,
310                    {"code" : code,
311                     "flag_code" : flag_code,
312                     "cond_check" : cond_check,
313                     "else_code" : else_code,
314                     "cond_control_flag_init" : cond_control_flag_init})]
315            if big_code != "":
316                iops += [InstObjParams(name, Name + suffix + "Big", base,
317                         {"code" : big_code,
318                          "flag_code" : flag_code,
319                          "cond_check" : cond_check,
320                          "else_code" : else_code,
321                          "cond_control_flag_init" :
322                              cond_control_flag_init})]
323
324            # Generate the actual code (finally!)
325            for iop in iops:
326                header_output += templates[0].subst(iop)
327                decoder_output += templates[1].subst(iop)
328                exec_output += templates[2].subst(iop)
329
330
331        def __new__(mcls, Name, bases, dict):
332            abstract = False
333            name = Name.lower()
334            if "abstract" in dict:
335                abstract = dict['abstract']
336                del dict['abstract']
337
338            cls = super(RegOpMeta, mcls).__new__(mcls, Name, bases, dict)
339            if not abstract:
340                cls.className = Name
341                cls.base_mnemonic = name
342                code = cls.code
343                big_code = cls.big_code
344                flag_code = cls.flag_code
345                cond_check = cls.cond_check
346                else_code = cls.else_code
347                cond_control_flag_init = cls.cond_control_flag_init
348
349                # Set up the C++ classes
350                mcls.buildCppClasses(cls, name, Name, "", code, big_code,
351                        flag_code, cond_check, else_code,
352                        cond_control_flag_init)
353
354                # Hook into the microassembler dict
355                global microopClasses
356                microopClasses[name] = cls
357
358                allCode = "|".join((code, flag_code, cond_check, else_code,
359                                    cond_control_flag_init))
360
361                # If op2 is used anywhere, make register and immediate versions
362                # of this code.
363                matcher = re.compile("op2(?P<typeQual>\\.\\w+)?")
364                if matcher.search(allCode):
365                    microopClasses[name + 'i'] = cls
366            return cls
367
368
369    class RegOp(X86Microop):
370        __metaclass__ = RegOpMeta
371        # This class itself doesn't act as a microop
372        abstract = True
373
374        # Default template parameter values
375        big_code = ""
376        flag_code = ""
377        cond_check = "true"
378        else_code = ";"
379        cond_control_flag_init = ""
380
381        def __init__(self, dest, src1, op2, flags = None, dataSize = "env.dataSize"):
382            self.dest = dest
383            self.src1 = src1
384            self.op2 = op2
385            self.flags = flags
386            self.dataSize = dataSize
387            if flags is None:
388                self.ext = 0
389            else:
390                if not isinstance(flags, (list, tuple)):
391                    raise Exception, "flags must be a list or tuple of flags"
392                self.ext = " | ".join(flags)
393                self.className += "Flags"
394
395        def getAllocator(self, microFlags):
396            if self.big_code != "":
397                className = self.className
398                if self.mnemonic == self.base_mnemonic + 'i':
399                    className += "Imm"
400                allocString = '''
401                    (%(dataSize)s >= 4) ?
402                        (StaticInstPtr)(new %(class_name)sBig(machInst,
403                            macrocodeBlock, %(flags)s, %(src1)s, %(op2)s,
404                            %(dest)s, %(dataSize)s, %(ext)s)) :
405                        (StaticInstPtr)(new %(class_name)s(machInst,
406                            macrocodeBlock, %(flags)s, %(src1)s, %(op2)s,
407                            %(dest)s, %(dataSize)s, %(ext)s))
408                    '''
409                allocator = allocString % {
410                    "class_name" : className,
411                    "flags" : self.microFlagsText(microFlags),
412                    "src1" : self.src1, "op2" : self.op2,
413                    "dest" : self.dest,
414                    "dataSize" : self.dataSize,
415                    "ext" : self.ext}
416                return allocator
417            else:
418                className = self.className
419                if self.mnemonic == self.base_mnemonic + 'i':
420                    className += "Imm"
421                allocator = '''new %(class_name)s(machInst, macrocodeBlock,
422                        %(flags)s, %(src1)s, %(op2)s, %(dest)s,
423                        %(dataSize)s, %(ext)s)''' % {
424                    "class_name" : className,
425                    "flags" : self.microFlagsText(microFlags),
426                    "src1" : self.src1, "op2" : self.op2,
427                    "dest" : self.dest,
428                    "dataSize" : self.dataSize,
429                    "ext" : self.ext}
430                return allocator
431
432    class LogicRegOp(RegOp):
433        abstract = True
434        flag_code = '''
435            //Don't have genFlags handle the OF or CF bits
436            uint64_t mask = CFBit | ECFBit | OFBit;
437            ccFlagBits = genFlags(ccFlagBits, ext & ~mask, DestReg, psrc1, op2);
438            //If a logic microop wants to set these, it wants to set them to 0.
439            ccFlagBits &= ~(CFBit & ext);
440            ccFlagBits &= ~(ECFBit & ext);
441            ccFlagBits &= ~(OFBit & ext);
442        '''
443
444    class FlagRegOp(RegOp):
445        abstract = True
446        flag_code = \
447            "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, op2);"
448
449    class SubRegOp(RegOp):
450        abstract = True
451        flag_code = \
452            "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, ~op2, true);"
453
454    class CondRegOp(RegOp):
455        abstract = True
456        cond_check = "checkCondition(ccFlagBits, ext)"
457        cond_control_flag_init = "flags[IsCondControl] = flags[IsControl];"
458
459    class RdRegOp(RegOp):
460        abstract = True
461        def __init__(self, dest, src1=None, dataSize="env.dataSize"):
462            if not src1:
463                src1 = dest
464            super(RdRegOp, self).__init__(dest, src1, \
465                    "InstRegIndex(NUM_INTREGS)", None, dataSize)
466
467    class WrRegOp(RegOp):
468        abstract = True
469        def __init__(self, src1, src2, flags=None, dataSize="env.dataSize"):
470            super(WrRegOp, self).__init__("InstRegIndex(NUM_INTREGS)", \
471                    src1, src2, flags, dataSize)
472
473    class Add(FlagRegOp):
474        code = 'DestReg = merge(DestReg, psrc1 + op2, dataSize);'
475        big_code = 'DestReg = (psrc1 + op2) & mask(dataSize * 8);'
476
477    class Or(LogicRegOp):
478        code = 'DestReg = merge(DestReg, psrc1 | op2, dataSize);'
479        big_code = 'DestReg = (psrc1 | op2) & mask(dataSize * 8);'
480
481    class Adc(FlagRegOp):
482        code = '''
483            CCFlagBits flags = ccFlagBits;
484            DestReg = merge(DestReg, psrc1 + op2 + flags.cf, dataSize);
485            '''
486        big_code = '''
487            CCFlagBits flags = ccFlagBits;
488            DestReg = (psrc1 + op2 + flags.cf) & mask(dataSize * 8);
489            '''
490
491    class Sbb(SubRegOp):
492        code = '''
493            CCFlagBits flags = ccFlagBits;
494            DestReg = merge(DestReg, psrc1 - op2 - flags.cf, dataSize);
495            '''
496        big_code = '''
497            CCFlagBits flags = ccFlagBits;
498            DestReg = (psrc1 - op2 - flags.cf) & mask(dataSize * 8);
499            '''
500
501    class And(LogicRegOp):
502        code = 'DestReg = merge(DestReg, psrc1 & op2, dataSize)'
503        big_code = 'DestReg = (psrc1 & op2) & mask(dataSize * 8)'
504
505    class Sub(SubRegOp):
506        code = 'DestReg = merge(DestReg, psrc1 - op2, dataSize)'
507        big_code = 'DestReg = (psrc1 - op2) & mask(dataSize * 8)'
508
509    class Xor(LogicRegOp):
510        code = 'DestReg = merge(DestReg, psrc1 ^ op2, dataSize)'
511        big_code = 'DestReg = (psrc1 ^ op2) & mask(dataSize * 8)'
512
513    class Mul1s(WrRegOp):
514        code = '''
515            ProdLow = psrc1 * op2;
516            int halfSize = (dataSize * 8) / 2;
517            uint64_t shifter = (ULL(1) << halfSize);
518            uint64_t hiResult;
519            uint64_t psrc1_h = psrc1 / shifter;
520            uint64_t psrc1_l = psrc1 & mask(halfSize);
521            uint64_t psrc2_h = (op2 / shifter) & mask(halfSize);
522            uint64_t psrc2_l = op2 & mask(halfSize);
523            hiResult = ((psrc1_l * psrc2_h + psrc1_h * psrc2_l +
524                        ((psrc1_l * psrc2_l) / shifter)) /shifter) +
525                       psrc1_h * psrc2_h;
526            if (bits(psrc1, dataSize * 8 - 1))
527                hiResult -= op2;
528            if (bits(op2, dataSize * 8 - 1))
529                hiResult -= psrc1;
530            ProdHi = hiResult;
531            '''
532        flag_code = '''
533            if ((-ProdHi & mask(dataSize * 8)) !=
534                    bits(ProdLow, dataSize * 8 - 1)) {
535                ccFlagBits = ccFlagBits | (ext & (CFBit | OFBit | ECFBit));
536            } else {
537                ccFlagBits = ccFlagBits & ~(ext & (CFBit | OFBit | ECFBit));
538            }
539        '''
540
541    class Mul1u(WrRegOp):
542        code = '''
543            ProdLow = psrc1 * op2;
544            int halfSize = (dataSize * 8) / 2;
545            uint64_t shifter = (ULL(1) << halfSize);
546            uint64_t psrc1_h = psrc1 / shifter;
547            uint64_t psrc1_l = psrc1 & mask(halfSize);
548            uint64_t psrc2_h = (op2 / shifter) & mask(halfSize);
549            uint64_t psrc2_l = op2 & mask(halfSize);
550            ProdHi = ((psrc1_l * psrc2_h + psrc1_h * psrc2_l +
551                      ((psrc1_l * psrc2_l) / shifter)) / shifter) +
552                     psrc1_h * psrc2_h;
553            '''
554        flag_code = '''
555            if (ProdHi) {
556                ccFlagBits = ccFlagBits | (ext & (CFBit | OFBit | ECFBit));
557            } else {
558                ccFlagBits = ccFlagBits & ~(ext & (CFBit | OFBit | ECFBit));
559            }
560        '''
561
562    class Mulel(RdRegOp):
563        code = 'DestReg = merge(SrcReg1, ProdLow, dataSize);'
564        big_code = 'DestReg = ProdLow & mask(dataSize * 8);'
565
566    class Muleh(RdRegOp):
567        def __init__(self, dest, src1=None, flags=None, dataSize="env.dataSize"):
568            if not src1:
569                src1 = dest
570            super(RdRegOp, self).__init__(dest, src1, \
571                    "InstRegIndex(NUM_INTREGS)", flags, dataSize)
572        code = 'DestReg = merge(SrcReg1, ProdHi, dataSize);'
573        big_code = 'DestReg = ProdHi & mask(dataSize * 8);'
574
575    # One or two bit divide
576    class Div1(WrRegOp):
577        code = '''
578            //These are temporaries so that modifying them later won't make
579            //the ISA parser think they're also sources.
580            uint64_t quotient = 0;
581            uint64_t remainder = psrc1;
582            //Similarly, this is a temporary so changing it doesn't make it
583            //a source.
584            uint64_t divisor = op2;
585            //This is a temporary just for consistency and clarity.
586            uint64_t dividend = remainder;
587            //Do the division.
588            if (divisor == 0) {
589                fault = new DivideByZero;
590            } else {
591                divide(dividend, divisor, quotient, remainder);
592                //Record the final results.
593                Remainder = remainder;
594                Quotient = quotient;
595                Divisor = divisor;
596            }
597            '''
598
599    # Step divide
600    class Div2(RegOp):
601        divCode = '''
602            uint64_t dividend = Remainder;
603            uint64_t divisor = Divisor;
604            uint64_t quotient = Quotient;
605            uint64_t remainder = dividend;
606            int remaining = op2;
607            //If we overshot, do nothing. This lets us unrool division loops a
608            //little.
609            if (divisor == 0) {
610                fault = new DivideByZero;
611            } else if (remaining) {
612                if (divisor & (ULL(1) << 63)) {
613                    while (remaining && !(dividend & (ULL(1) << 63))) {
614                        dividend = (dividend << 1) |
615                            bits(SrcReg1, remaining - 1);
616                        quotient <<= 1;
617                        remaining--;
618                    }
619                    if (dividend & (ULL(1) << 63)) {
620                        bool highBit = false;
621                        if (dividend < divisor && remaining) {
622                            highBit = true;
623                            dividend = (dividend << 1) |
624                                bits(SrcReg1, remaining - 1);
625                            quotient <<= 1;
626                            remaining--;
627                        }
628                        if (highBit || divisor <= dividend) {
629                            quotient++;
630                            dividend -= divisor;
631                        }
632                    }
633                    remainder = dividend;
634                } else {
635                    //Shift in bits from the low order portion of the dividend
636                    while (dividend < divisor && remaining) {
637                        dividend = (dividend << 1) |
638                            bits(SrcReg1, remaining - 1);
639                        quotient <<= 1;
640                        remaining--;
641                    }
642                    remainder = dividend;
643                    //Do the division.
644                    divide(dividend, divisor, quotient, remainder);
645                }
646            }
647            //Keep track of how many bits there are still to pull in.
648            %s
649            //Record the final results
650            Remainder = remainder;
651            Quotient = quotient;
652        '''
653        code = divCode % "DestReg = merge(DestReg, remaining, dataSize);"
654        big_code = divCode % "DestReg = remaining & mask(dataSize * 8);"
655        flag_code = '''
656            if (remaining == 0)
657                ccFlagBits = ccFlagBits | (ext & EZFBit);
658            else
659                ccFlagBits = ccFlagBits & ~(ext & EZFBit);
660        '''
661
662    class Divq(RdRegOp):
663        code = 'DestReg = merge(SrcReg1, Quotient, dataSize);'
664        big_code = 'DestReg = Quotient & mask(dataSize * 8);'
665
666    class Divr(RdRegOp):
667        code = 'DestReg = merge(SrcReg1, Remainder, dataSize);'
668        big_code = 'DestReg = Remainder & mask(dataSize * 8);'
669
670    class Mov(CondRegOp):
671        code = 'DestReg = merge(SrcReg1, op2, dataSize)'
672        else_code = 'DestReg = DestReg;'
673
674    # Shift instructions
675
676    class Sll(RegOp):
677        code = '''
678            uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
679            DestReg = merge(DestReg, psrc1 << shiftAmt, dataSize);
680            '''
681        big_code = '''
682            uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
683            DestReg = (psrc1 << shiftAmt) & mask(dataSize * 8);
684            '''
685        flag_code = '''
686            // If the shift amount is zero, no flags should be modified.
687            if (shiftAmt) {
688                //Zero out any flags we might modify. This way we only have to
689                //worry about setting them.
690                ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
691                int CFBits = 0;
692                //Figure out if we -would- set the CF bits if requested.
693                if (shiftAmt <= dataSize * 8 &&
694                        bits(SrcReg1, dataSize * 8 - shiftAmt)) {
695                    CFBits = 1;
696                }
697                //If some combination of the CF bits need to be set, set them.
698                if ((ext & (CFBit | ECFBit)) && CFBits)
699                    ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
700                //Figure out what the OF bit should be.
701                if ((ext & OFBit) && (CFBits ^ bits(DestReg, dataSize * 8 - 1)))
702                    ccFlagBits = ccFlagBits | OFBit;
703                //Use the regular mechanisms to calculate the other flags.
704                ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
705                        DestReg, psrc1, op2);
706            }
707        '''
708
709    class Srl(RegOp):
710        # Because what happens to the bits shift -in- on a right shift
711        # is not defined in the C/C++ standard, we have to mask them out
712        # to be sure they're zero.
713        code = '''
714            uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
715            uint64_t logicalMask = mask(dataSize * 8 - shiftAmt);
716            DestReg = merge(DestReg, (psrc1 >> shiftAmt) & logicalMask, dataSize);
717            '''
718        big_code = '''
719            uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
720            uint64_t logicalMask = mask(dataSize * 8 - shiftAmt);
721            DestReg = (psrc1 >> shiftAmt) & logicalMask;
722            '''
723        flag_code = '''
724            // If the shift amount is zero, no flags should be modified.
725            if (shiftAmt) {
726                //Zero out any flags we might modify. This way we only have to
727                //worry about setting them.
728                ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
729                //If some combination of the CF bits need to be set, set them.
730                if ((ext & (CFBit | ECFBit)) && 
731                        shiftAmt <= dataSize * 8 &&
732                        bits(SrcReg1, shiftAmt - 1)) {
733                    ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
734                }
735                //Figure out what the OF bit should be.
736                if ((ext & OFBit) && bits(SrcReg1, dataSize * 8 - 1))
737                    ccFlagBits = ccFlagBits | OFBit;
738                //Use the regular mechanisms to calculate the other flags.
739                ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
740                        DestReg, psrc1, op2);
741            }
742        '''
743
744    class Sra(RegOp):
745        # Because what happens to the bits shift -in- on a right shift
746        # is not defined in the C/C++ standard, we have to sign extend
747        # them manually to be sure.
748        code = '''
749            uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
750            uint64_t arithMask = (shiftAmt == 0) ? 0 :
751                -bits(psrc1, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt);
752            DestReg = merge(DestReg, (psrc1 >> shiftAmt) | arithMask, dataSize);
753            '''
754        big_code = '''
755            uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
756            uint64_t arithMask = (shiftAmt == 0) ? 0 :
757                -bits(psrc1, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt);
758            DestReg = ((psrc1 >> shiftAmt) | arithMask) & mask(dataSize * 8);
759            '''
760        flag_code = '''
761            // If the shift amount is zero, no flags should be modified.
762            if (shiftAmt) {
763                //Zero out any flags we might modify. This way we only have to
764                //worry about setting them.
765                ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
766                //If some combination of the CF bits need to be set, set them.
767                uint8_t effectiveShift =
768                    (shiftAmt <= dataSize * 8) ? shiftAmt : (dataSize * 8);
769                if ((ext & (CFBit | ECFBit)) &&
770                        bits(SrcReg1, effectiveShift - 1)) {
771                    ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
772                }
773                //Use the regular mechanisms to calculate the other flags.
774                ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
775                        DestReg, psrc1, op2);
776            }
777        '''
778
779    class Ror(RegOp):
780        code = '''
781            uint8_t shiftAmt =
782                (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
783            uint8_t realShiftAmt = shiftAmt % (dataSize * 8);
784            if (realShiftAmt) {
785                uint64_t top = psrc1 << (dataSize * 8 - realShiftAmt);
786                uint64_t bottom = bits(psrc1, dataSize * 8, realShiftAmt);
787                DestReg = merge(DestReg, top | bottom, dataSize);
788            } else
789                DestReg = merge(DestReg, DestReg, dataSize);
790            '''
791        flag_code = '''
792            // If the shift amount is zero, no flags should be modified.
793            if (shiftAmt) {
794                //Zero out any flags we might modify. This way we only have to
795                //worry about setting them.
796                ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
797                //Find the most and second most significant bits of the result.
798                int msb = bits(DestReg, dataSize * 8 - 1);
799                int smsb = bits(DestReg, dataSize * 8 - 2);
800                //If some combination of the CF bits need to be set, set them.
801                if ((ext & (CFBit | ECFBit)) && msb)
802                    ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
803                //Figure out what the OF bit should be.
804                if ((ext & OFBit) && (msb ^ smsb))
805                    ccFlagBits = ccFlagBits | OFBit;
806                //Use the regular mechanisms to calculate the other flags.
807                ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
808                        DestReg, psrc1, op2);
809            }
810        '''
811
812    class Rcr(RegOp):
813        code = '''
814            uint8_t shiftAmt =
815                (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
816            uint8_t realShiftAmt = shiftAmt % (dataSize * 8 + 1);
817            if (realShiftAmt) {
818                CCFlagBits flags = ccFlagBits;
819                uint64_t top = flags.cf << (dataSize * 8 - realShiftAmt);
820                if (realShiftAmt > 1)
821                    top |= psrc1 << (dataSize * 8 - realShiftAmt + 1);
822                uint64_t bottom = bits(psrc1, dataSize * 8 - 1, realShiftAmt);
823                DestReg = merge(DestReg, top | bottom, dataSize);
824            } else
825                DestReg = merge(DestReg, DestReg, dataSize);
826            '''
827        flag_code = '''
828            // If the shift amount is zero, no flags should be modified.
829            if (shiftAmt) {
830                int origCFBit = (ccFlagBits & CFBit) ? 1 : 0;
831                //Zero out any flags we might modify. This way we only have to
832                //worry about setting them.
833                ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
834                //Figure out what the OF bit should be.
835                if ((ext & OFBit) && (origCFBit ^
836                                      bits(SrcReg1, dataSize * 8 - 1))) {
837                    ccFlagBits = ccFlagBits | OFBit;
838                }
839                //If some combination of the CF bits need to be set, set them.
840                if ((ext & (CFBit | ECFBit)) &&
841                        (realShiftAmt == 0) ? origCFBit :
842                        bits(SrcReg1, realShiftAmt - 1)) {
843                    ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
844                }
845                //Use the regular mechanisms to calculate the other flags.
846                ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
847                        DestReg, psrc1, op2);
848            }
849        '''
850
851    class Rol(RegOp):
852        code = '''
853            uint8_t shiftAmt =
854                (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
855            uint8_t realShiftAmt = shiftAmt % (dataSize * 8);
856            if (realShiftAmt) {
857                uint64_t top = psrc1 << realShiftAmt;
858                uint64_t bottom =
859                    bits(psrc1, dataSize * 8 - 1, dataSize * 8 - realShiftAmt);
860                DestReg = merge(DestReg, top | bottom, dataSize);
861            } else
862                DestReg = merge(DestReg, DestReg, dataSize);
863            '''
864        flag_code = '''
865            // If the shift amount is zero, no flags should be modified.
866            if (shiftAmt) {
867                //Zero out any flags we might modify. This way we only have to
868                //worry about setting them.
869                ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
870                //The CF bits, if set, would be set to the lsb of the result.
871                int lsb = DestReg & 0x1;
872                int msb = bits(DestReg, dataSize * 8 - 1);
873                //If some combination of the CF bits need to be set, set them.
874                if ((ext & (CFBit | ECFBit)) && lsb)
875                    ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
876                //Figure out what the OF bit should be.
877                if ((ext & OFBit) && (msb ^ lsb))
878                    ccFlagBits = ccFlagBits | OFBit;
879                //Use the regular mechanisms to calculate the other flags.
880                ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
881                        DestReg, psrc1, op2);
882            }
883        '''
884
885    class Rcl(RegOp):
886        code = '''
887            uint8_t shiftAmt =
888                (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
889            uint8_t realShiftAmt = shiftAmt % (dataSize * 8 + 1);
890            if (realShiftAmt) {
891                CCFlagBits flags = ccFlagBits;
892                uint64_t top = psrc1 << realShiftAmt;
893                uint64_t bottom = flags.cf << (realShiftAmt - 1);
894                if(shiftAmt > 1)
895                    bottom |=
896                        bits(psrc1, dataSize * 8 - 1,
897                                   dataSize * 8 - realShiftAmt + 1);
898                DestReg = merge(DestReg, top | bottom, dataSize);
899            } else
900                DestReg = merge(DestReg, DestReg, dataSize);
901            '''
902        flag_code = '''
903            // If the shift amount is zero, no flags should be modified.
904            if (shiftAmt) {
905                int origCFBit = (ccFlagBits & CFBit) ? 1 : 0;
906                //Zero out any flags we might modify. This way we only have to
907                //worry about setting them.
908                ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
909                int msb = bits(DestReg, dataSize * 8 - 1);
910                int CFBits = bits(SrcReg1, dataSize * 8 - realShiftAmt);
911                //If some combination of the CF bits need to be set, set them.
912                if ((ext & (CFBit | ECFBit)) && 
913                        (realShiftAmt == 0) ? origCFBit : CFBits)
914                    ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
915                //Figure out what the OF bit should be.
916                if ((ext & OFBit) && (msb ^ CFBits))
917                    ccFlagBits = ccFlagBits | OFBit;
918                //Use the regular mechanisms to calculate the other flags.
919                ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
920                        DestReg, psrc1, op2);
921            }
922        '''
923
924    class Sld(RegOp):
925        sldCode = '''
926            uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
927            uint8_t dataBits = dataSize * 8;
928            uint8_t realShiftAmt = shiftAmt %% (2 * dataBits);
929            uint64_t result;
930            if (realShiftAmt == 0) {
931                result = psrc1;
932            } else if (realShiftAmt < dataBits) {
933                result = (psrc1 << realShiftAmt) |
934                         (DoubleBits >> (dataBits - realShiftAmt));
935            } else {
936                result = (DoubleBits << (realShiftAmt - dataBits)) |
937                         (psrc1 >> (2 * dataBits - realShiftAmt));
938            }
939            %s
940            '''
941        code = sldCode % "DestReg = merge(DestReg, result, dataSize);"
942        big_code = sldCode % "DestReg = result & mask(dataSize * 8);"
943        flag_code = '''
944            // If the shift amount is zero, no flags should be modified.
945            if (shiftAmt) {
946                //Zero out any flags we might modify. This way we only have to
947                //worry about setting them.
948                ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
949                int CFBits = 0;
950                //Figure out if we -would- set the CF bits if requested.
951                if ((realShiftAmt == 0 &&
952                        bits(DoubleBits, 0)) ||
953                    (realShiftAmt <= dataBits &&
954                     bits(SrcReg1, dataBits - realShiftAmt)) ||
955                    (realShiftAmt > dataBits &&
956                     bits(DoubleBits, 2 * dataBits - realShiftAmt))) {
957                    CFBits = 1;
958                }
959                //If some combination of the CF bits need to be set, set them.
960                if ((ext & (CFBit | ECFBit)) && CFBits)
961                    ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
962                //Figure out what the OF bit should be.
963                if ((ext & OFBit) && (bits(SrcReg1, dataBits - 1) ^
964                                      bits(result, dataBits - 1)))
965                    ccFlagBits = ccFlagBits | OFBit;
966                //Use the regular mechanisms to calculate the other flags.
967                ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
968                        DestReg, psrc1, op2);
969            }
970        '''
971
972    class Srd(RegOp):
973        srdCode = '''
974            uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
975            uint8_t dataBits = dataSize * 8;
976            uint8_t realShiftAmt = shiftAmt %% (2 * dataBits);
977            uint64_t result;
978            if (realShiftAmt == 0) {
979                result = psrc1;
980            } else if (realShiftAmt < dataBits) {
981                // Because what happens to the bits shift -in- on a right
982                // shift is not defined in the C/C++ standard, we have to
983                // mask them out to be sure they're zero.
984                uint64_t logicalMask = mask(dataBits - realShiftAmt);
985                result = ((psrc1 >> realShiftAmt) & logicalMask) |
986                         (DoubleBits << (dataBits - realShiftAmt));
987            } else {
988                uint64_t logicalMask = mask(2 * dataBits - realShiftAmt);
989                result = ((DoubleBits >> (realShiftAmt - dataBits)) &
990                          logicalMask) |
991                         (psrc1 << (2 * dataBits - realShiftAmt));
992            }
993            %s
994            '''
995        code = srdCode % "DestReg = merge(DestReg, result, dataSize);"
996        big_code = srdCode % "DestReg = result & mask(dataSize * 8);"
997        flag_code = '''
998            // If the shift amount is zero, no flags should be modified.
999            if (shiftAmt) {
1000                //Zero out any flags we might modify. This way we only have to
1001                //worry about setting them.
1002                ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
1003                int CFBits = 0;
1004                //If some combination of the CF bits need to be set, set them.
1005                if ((realShiftAmt == 0 &&
1006                            bits(DoubleBits, dataBits - 1)) ||
1007                        (realShiftAmt <= dataBits &&
1008                         bits(SrcReg1, realShiftAmt - 1)) ||
1009                        (realShiftAmt > dataBits &&
1010                         bits(DoubleBits, realShiftAmt - dataBits - 1))) {
1011                    CFBits = 1;
1012                }
1013                //If some combination of the CF bits need to be set, set them.
1014                if ((ext & (CFBit | ECFBit)) && CFBits)
1015                    ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
1016                //Figure out what the OF bit should be.
1017                if ((ext & OFBit) && (bits(SrcReg1, dataBits - 1) ^
1018                                      bits(result, dataBits - 1)))
1019                    ccFlagBits = ccFlagBits | OFBit;
1020                //Use the regular mechanisms to calculate the other flags.
1021                ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
1022                        DestReg, psrc1, op2);
1023            }
1024        '''
1025
1026    class Mdb(WrRegOp):
1027        code = 'DoubleBits = psrc1 ^ op2;'
1028
1029    class Wrip(WrRegOp, CondRegOp):
1030        code = 'NRIP = psrc1 + sop2 + CSBase;'
1031        else_code = "NRIP = NRIP;"
1032
1033    class Wruflags(WrRegOp):
1034        code = 'ccFlagBits = psrc1 ^ op2'
1035
1036    class Wrflags(WrRegOp):
1037        code = '''
1038            MiscReg newFlags = psrc1 ^ op2;
1039            MiscReg userFlagMask = 0xDD5;
1040            // Get only the user flags
1041            ccFlagBits = newFlags & userFlagMask;
1042            // Get everything else
1043            nccFlagBits = newFlags & ~userFlagMask;
1044        '''
1045
1046    class Rdip(RdRegOp):
1047        code = 'DestReg = NRIP - CSBase;'
1048
1049    class Ruflags(RdRegOp):
1050        code = 'DestReg = ccFlagBits'
1051
1052    class Rflags(RdRegOp):
1053        code = 'DestReg = ccFlagBits | nccFlagBits'
1054
1055    class Ruflag(RegOp):
1056        code = '''
1057            int flag = bits(ccFlagBits, imm8);
1058            DestReg = merge(DestReg, flag, dataSize);
1059            ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) :
1060                                       (ccFlagBits & ~EZFBit);
1061            '''
1062        big_code = '''
1063            int flag = bits(ccFlagBits, imm8);
1064            DestReg = flag & mask(dataSize * 8);
1065            ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) :
1066                                       (ccFlagBits & ~EZFBit);
1067            '''
1068        def __init__(self, dest, imm, flags=None, \
1069                dataSize="env.dataSize"):
1070            super(Ruflag, self).__init__(dest, \
1071                    "InstRegIndex(NUM_INTREGS)", imm, flags, dataSize)
1072
1073    class Rflag(RegOp):
1074        code = '''
1075            MiscReg flagMask = 0x3F7FDD5;
1076            MiscReg flags = (nccFlagBits | ccFlagBits) & flagMask;
1077            int flag = bits(flags, imm8);
1078            DestReg = merge(DestReg, flag, dataSize);
1079            ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) :
1080                                       (ccFlagBits & ~EZFBit);
1081            '''
1082        big_code = '''
1083            MiscReg flagMask = 0x3F7FDD5;
1084            MiscReg flags = (nccFlagBits | ccFlagBits) & flagMask;
1085            int flag = bits(flags, imm8);
1086            DestReg = flag & mask(dataSize * 8);
1087            ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) :
1088                                       (ccFlagBits & ~EZFBit);
1089            '''
1090        def __init__(self, dest, imm, flags=None, \
1091                dataSize="env.dataSize"):
1092            super(Rflag, self).__init__(dest, \
1093                    "InstRegIndex(NUM_INTREGS)", imm, flags, dataSize)
1094
1095    class Sext(RegOp):
1096        code = '''
1097            IntReg val = psrc1;
1098            // Mask the bit position so that it wraps.
1099            int bitPos = op2 & (dataSize * 8 - 1);
1100            int sign_bit = bits(val, bitPos, bitPos);
1101            uint64_t maskVal = mask(bitPos+1);
1102            val = sign_bit ? (val | ~maskVal) : (val & maskVal);
1103            DestReg = merge(DestReg, val, dataSize);
1104            '''
1105        big_code = '''
1106            IntReg val = psrc1;
1107            // Mask the bit position so that it wraps.
1108            int bitPos = op2 & (dataSize * 8 - 1);
1109            int sign_bit = bits(val, bitPos, bitPos);
1110            uint64_t maskVal = mask(bitPos+1);
1111            val = sign_bit ? (val | ~maskVal) : (val & maskVal);
1112            DestReg = val & mask(dataSize * 8);
1113            '''
1114        flag_code = '''
1115            if (!sign_bit)
1116                ccFlagBits = ccFlagBits &
1117                    ~(ext & (CFBit | ECFBit | ZFBit | EZFBit));
1118            else
1119                ccFlagBits = ccFlagBits |
1120                    (ext & (CFBit | ECFBit | ZFBit | EZFBit));
1121            '''
1122
1123    class Zext(RegOp):
1124        code = 'DestReg = merge(DestReg, bits(psrc1, op2, 0), dataSize);'
1125        big_code = 'DestReg = bits(psrc1, op2, 0) & mask(dataSize * 8);'
1126
1127    class Rddr(RegOp):
1128        def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1129            super(Rddr, self).__init__(dest, \
1130                    src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1131        rdrCode = '''
1132            CR4 cr4 = CR4Op;
1133            DR7 dr7 = DR7Op;
1134            if ((cr4.de == 1 && (src1 == 4 || src1 == 5)) || src1 >= 8) {
1135                fault = new InvalidOpcode();
1136            } else if (dr7.gd) {
1137                fault = new DebugException();
1138            } else {
1139                %s
1140            }
1141        '''
1142        code = rdrCode % "DestReg = merge(DestReg, DebugSrc1, dataSize);"
1143        big_code = rdrCode % "DestReg = DebugSrc1 & mask(dataSize * 8);"
1144
1145    class Wrdr(RegOp):
1146        def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1147            super(Wrdr, self).__init__(dest, \
1148                    src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1149        code = '''
1150            CR4 cr4 = CR4Op;
1151            DR7 dr7 = DR7Op;
1152            if ((cr4.de == 1 && (dest == 4 || dest == 5)) || dest >= 8) {
1153                fault = new InvalidOpcode();
1154            } else if ((dest == 6 || dest == 7) && bits(psrc1, 63, 32) &&
1155                    machInst.mode.mode == LongMode) {
1156                fault = new GeneralProtection(0);
1157            } else if (dr7.gd) {
1158                fault = new DebugException();
1159            } else {
1160                DebugDest = psrc1;
1161            }
1162        '''
1163
1164    class Rdcr(RegOp):
1165        def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1166            super(Rdcr, self).__init__(dest, \
1167                    src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1168        rdcrCode = '''
1169            if (src1 == 1 || (src1 > 4 && src1 < 8) || (src1 > 8)) {
1170                fault = new InvalidOpcode();
1171            } else {
1172                %s
1173            }
1174        '''
1175        code = rdcrCode % "DestReg = merge(DestReg, ControlSrc1, dataSize);"
1176        big_code = rdcrCode % "DestReg = ControlSrc1 & mask(dataSize * 8);"
1177
1178    class Wrcr(RegOp):
1179        def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1180            super(Wrcr, self).__init__(dest, \
1181                    src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1182        code = '''
1183            if (dest == 1 || (dest > 4 && dest < 8) || (dest > 8)) {
1184                fault = new InvalidOpcode();
1185            } else {
1186                // There are *s in the line below so it doesn't confuse the
1187                // parser. They may be unnecessary.
1188                //Mis*cReg old*Val = pick(Cont*rolDest, 0, dat*aSize);
1189                MiscReg newVal = psrc1;
1190
1191                // Check for any modifications that would cause a fault.
1192                switch(dest) {
1193                  case 0:
1194                    {
1195                        Efer efer = EferOp;
1196                        CR0 cr0 = newVal;
1197                        CR4 oldCr4 = CR4Op;
1198                        if (bits(newVal, 63, 32) ||
1199                                (!cr0.pe && cr0.pg) ||
1200                                (!cr0.cd && cr0.nw) ||
1201                                (cr0.pg && efer.lme && !oldCr4.pae))
1202                            fault = new GeneralProtection(0);
1203                    }
1204                    break;
1205                  case 2:
1206                    break;
1207                  case 3:
1208                    break;
1209                  case 4:
1210                    {
1211                        CR4 cr4 = newVal;
1212                        // PAE can't be disabled in long mode.
1213                        if (bits(newVal, 63, 11) ||
1214                                (machInst.mode.mode == LongMode && !cr4.pae))
1215                            fault = new GeneralProtection(0);
1216                    }
1217                    break;
1218                  case 8:
1219                    {
1220                        if (bits(newVal, 63, 4))
1221                            fault = new GeneralProtection(0);
1222                    }
1223                  default:
1224                    panic("Unrecognized control register %d.\\n", dest);
1225                }
1226                ControlDest = newVal;
1227            }
1228            '''
1229
1230    # Microops for manipulating segmentation registers
1231    class SegOp(CondRegOp):
1232        abstract = True
1233        def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1234            super(SegOp, self).__init__(dest, \
1235                    src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1236
1237    class Wrbase(SegOp):
1238        code = '''
1239            SegBaseDest = psrc1;
1240        '''
1241
1242    class Wrlimit(SegOp):
1243        code = '''
1244            SegLimitDest = psrc1;
1245        '''
1246
1247    class Wrsel(SegOp):
1248        code = '''
1249            SegSelDest = psrc1;
1250        '''
1251
1252    class WrAttr(SegOp):
1253        code = '''
1254            SegAttrDest = psrc1;
1255        '''
1256
1257    class Rdbase(SegOp):
1258        code = 'DestReg = merge(DestReg, SegBaseSrc1, dataSize);'
1259        big_code = 'DestReg = SegBaseSrc1 & mask(dataSize * 8);'
1260
1261    class Rdlimit(SegOp):
1262        code = 'DestReg = merge(DestReg, SegLimitSrc1, dataSize);'
1263        big_code = 'DestReg = SegLimitSrc1 & mask(dataSize * 8);'
1264
1265    class RdAttr(SegOp):
1266        code = 'DestReg = merge(DestReg, SegAttrSrc1, dataSize);'
1267        big_code = 'DestReg = SegAttrSrc1 & mask(dataSize * 8);'
1268
1269    class Rdsel(SegOp):
1270        code = 'DestReg = merge(DestReg, SegSelSrc1, dataSize);'
1271        big_code = 'DestReg = SegSelSrc1 & mask(dataSize * 8);'
1272
1273    class Rdval(RegOp):
1274        def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1275            super(Rdval, self).__init__(dest, src1, \
1276                    "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1277        code = '''
1278            DestReg = MiscRegSrc1;
1279        '''
1280
1281    class Wrval(RegOp):
1282        def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1283            super(Wrval, self).__init__(dest, src1, \
1284                    "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1285        code = '''
1286            MiscRegDest = SrcReg1;
1287        '''
1288
1289    class Chks(RegOp):
1290        def __init__(self, dest, src1, src2=0,
1291                flags=None, dataSize="env.dataSize"):
1292            super(Chks, self).__init__(dest,
1293                    src1, src2, flags, dataSize)
1294        code = '''
1295            // The selector is in source 1 and can be at most 16 bits.
1296            SegSelector selector = DestReg;
1297            SegDescriptor desc = SrcReg1;
1298            HandyM5Reg m5reg = M5Reg;
1299
1300            switch (imm8)
1301            {
1302              case SegNoCheck:
1303                break;
1304              case SegCSCheck:
1305                // Make sure it's the right type
1306                if (desc.s == 0 || desc.type.codeOrData != 1) {
1307                    fault = new GeneralProtection(0);
1308                } else if (m5reg.cpl != desc.dpl) {
1309                    fault = new GeneralProtection(0);
1310                }
1311                break;
1312              case SegCallGateCheck:
1313                panic("CS checks for far calls/jumps through call gates"
1314                        "not implemented.\\n");
1315                break;
1316              case SegSoftIntGateCheck:
1317                // Check permissions.
1318                if (desc.dpl < m5reg.cpl) {
1319                    fault = new GeneralProtection(selector);
1320                    break;
1321                }
1322                // Fall through on purpose
1323              case SegIntGateCheck:
1324                // Make sure the gate's the right type.
1325                if ((m5reg.mode == LongMode && (desc.type & 0xe) != 0xe) ||
1326                        ((desc.type & 0x6) != 0x6)) {
1327                    fault = new GeneralProtection(0);
1328                }
1329                break;
1330              case SegSSCheck:
1331                if (selector.si || selector.ti) {
1332                    if (!desc.p) {
1333                        fault = new StackFault(selector);
1334                    }
1335                } else {
1336                    if ((m5reg.submode != SixtyFourBitMode ||
1337                                m5reg.cpl == 3) ||
1338                            !(desc.s == 1 &&
1339                            desc.type.codeOrData == 0 && desc.type.w) ||
1340                            (desc.dpl != m5reg.cpl) ||
1341                            (selector.rpl != m5reg.cpl)) {
1342                        fault = new GeneralProtection(selector);
1343                    }
1344                }
1345                break;
1346              case SegIretCheck:
1347                {
1348                    if ((!selector.si && !selector.ti) ||
1349                            (selector.rpl < m5reg.cpl) ||
1350                            !(desc.s == 1 && desc.type.codeOrData == 1) ||
1351                            (!desc.type.c && desc.dpl != selector.rpl) ||
1352                            (desc.type.c && desc.dpl > selector.rpl)) {
1353                        fault = new GeneralProtection(selector);
1354                    } else if (!desc.p) {
1355                        fault = new SegmentNotPresent(selector);
1356                    }
1357                    break;
1358                }
1359              case SegIntCSCheck:
1360                if (m5reg.mode == LongMode) {
1361                    if (desc.l != 1 || desc.d != 0) {
1362                        fault = new GeneralProtection(selector);
1363                    }
1364                } else {
1365                    panic("Interrupt CS checks not implemented "
1366                            "in legacy mode.\\n");
1367                }
1368                break;
1369              case SegTRCheck:
1370                if (!selector.si || selector.ti) {
1371                    fault = new GeneralProtection(selector);
1372                }
1373                break;
1374              case SegTSSCheck:
1375                if (!desc.p) {
1376                    fault = new SegmentNotPresent(selector);
1377                } else if (!(desc.type == 0x9 ||
1378                        (desc.type == 1 &&
1379                         m5reg.mode != LongMode))) {
1380                    fault = new GeneralProtection(selector);
1381                }
1382                break;
1383              case SegInGDTCheck:
1384                if (selector.ti) {
1385                    fault = new GeneralProtection(selector);
1386                }
1387                break;
1388              case SegLDTCheck:
1389                if (!desc.p) {
1390                    fault = new SegmentNotPresent(selector);
1391                } else if (desc.type != 0x2) {
1392                    fault = new GeneralProtection(selector);
1393                }
1394                break;
1395              default:
1396                panic("Undefined segment check type.\\n");
1397            }
1398        '''
1399        flag_code = '''
1400            // Check for a NULL selector and set ZF,EZF appropriately.
1401            ccFlagBits = ccFlagBits & ~(ext & (ZFBit | EZFBit));
1402            if (!selector.si && !selector.ti)
1403                ccFlagBits = ccFlagBits | (ext & (ZFBit | EZFBit));
1404        '''
1405
1406    class Wrdh(RegOp):
1407        code = '''
1408            SegDescriptor desc = SrcReg1;
1409
1410            uint64_t target = bits(SrcReg2, 31, 0) << 32;
1411            switch(desc.type) {
1412              case LDT64:
1413              case AvailableTSS64:
1414              case BusyTSS64:
1415                replaceBits(target, 23, 0, desc.baseLow);
1416                replaceBits(target, 31, 24, desc.baseHigh);
1417                break;
1418              case CallGate64:
1419              case IntGate64:
1420              case TrapGate64:
1421                replaceBits(target, 15, 0, bits(desc, 15, 0));
1422                replaceBits(target, 31, 16, bits(desc, 63, 48));
1423                break;
1424              default:
1425                panic("Wrdh used with wrong descriptor type!\\n");
1426            }
1427            DestReg = target;
1428        '''
1429
1430    class Wrtsc(WrRegOp):
1431        code = '''
1432            TscOp = psrc1;
1433        '''
1434
1435    class Rdtsc(RdRegOp):
1436        code = '''
1437            DestReg = TscOp;
1438        '''
1439
1440    class Rdm5reg(RdRegOp):
1441        code = '''
1442            DestReg = M5Reg;
1443        '''
1444
1445    class Wrdl(RegOp):
1446        code = '''
1447            SegDescriptor desc = SrcReg1;
1448            SegSelector selector = SrcReg2;
1449            if (selector.si || selector.ti) {
1450                if (!desc.p)
1451                    panic("Segment not present.\\n");
1452                SegAttr attr = 0;
1453                attr.dpl = desc.dpl;
1454                attr.unusable = 0;
1455                attr.defaultSize = desc.d;
1456                attr.longMode = desc.l;
1457                attr.avl = desc.avl;
1458                attr.granularity = desc.g;
1459                attr.present = desc.p;
1460                attr.system = desc.s;
1461                attr.type = desc.type;
1462                if (!desc.s) {
1463                    // The expand down bit happens to be set for gates.
1464                    if (desc.type.e) {
1465                        panic("Gate descriptor encountered.\\n");
1466                    }
1467                    attr.readable = 1;
1468                    attr.writable = 1;
1469                    attr.expandDown = 0;
1470                } else {
1471                    if (desc.type.codeOrData) {
1472                        attr.expandDown = 0;
1473                        attr.readable = desc.type.r;
1474                        attr.writable = 0;
1475                    } else {
1476                        attr.expandDown = desc.type.e;
1477                        attr.readable = 1;
1478                        attr.writable = desc.type.w;
1479                    }
1480                }
1481                Addr base = desc.baseLow | (desc.baseHigh << 24);
1482                Addr limit = desc.limitLow | (desc.limitHigh << 16);
1483                if (desc.g)
1484                    limit = (limit << 12) | mask(12);
1485                SegBaseDest = base;
1486                SegLimitDest = limit;
1487                SegAttrDest = attr;
1488            } else {
1489                SegBaseDest = SegBaseDest;
1490                SegLimitDest = SegLimitDest;
1491                SegAttrDest = SegAttrDest;
1492            }
1493        '''
1494}};
1495