regop.isa revision 8857
15409Sgblack@eecs.umich.edu// Copyright (c) 2007-2008 The Hewlett-Packard Development Company
24519Sgblack@eecs.umich.edu// All rights reserved.
34519Sgblack@eecs.umich.edu//
44519Sgblack@eecs.umich.edu// The license below extends only to copyright in the software and shall
54519Sgblack@eecs.umich.edu// not be construed as granting a license to any other intellectual
64519Sgblack@eecs.umich.edu// property including but not limited to intellectual property relating
74519Sgblack@eecs.umich.edu// to a hardware implementation of the functionality of the software
84519Sgblack@eecs.umich.edu// licensed hereunder.  You may use the software subject to the license
94519Sgblack@eecs.umich.edu// terms below provided that you ensure that this notice is replicated
104519Sgblack@eecs.umich.edu// unmodified and in its entirety in all distributions of the software,
114519Sgblack@eecs.umich.edu// modified or unmodified, in source code or in binary form.
124519Sgblack@eecs.umich.edu//
134519Sgblack@eecs.umich.edu// Redistribution and use in source and binary forms, with or without
144519Sgblack@eecs.umich.edu// modification, are permitted provided that the following conditions are
154519Sgblack@eecs.umich.edu// met: redistributions of source code must retain the above copyright
164519Sgblack@eecs.umich.edu// notice, this list of conditions and the following disclaimer;
174519Sgblack@eecs.umich.edu// redistributions in binary form must reproduce the above copyright
184519Sgblack@eecs.umich.edu// notice, this list of conditions and the following disclaimer in the
194519Sgblack@eecs.umich.edu// documentation and/or other materials provided with the distribution;
204519Sgblack@eecs.umich.edu// neither the name of the copyright holders nor the names of its
214519Sgblack@eecs.umich.edu// contributors may be used to endorse or promote products derived from
224519Sgblack@eecs.umich.edu// this software without specific prior written permission.
234519Sgblack@eecs.umich.edu//
244519Sgblack@eecs.umich.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
254519Sgblack@eecs.umich.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
264519Sgblack@eecs.umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
274519Sgblack@eecs.umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
284519Sgblack@eecs.umich.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
294519Sgblack@eecs.umich.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
304519Sgblack@eecs.umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
314519Sgblack@eecs.umich.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
324519Sgblack@eecs.umich.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
334519Sgblack@eecs.umich.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
344519Sgblack@eecs.umich.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
354519Sgblack@eecs.umich.edu//
364519Sgblack@eecs.umich.edu// Authors: Gabe Black
374519Sgblack@eecs.umich.edu
384519Sgblack@eecs.umich.edu//////////////////////////////////////////////////////////////////////////
394519Sgblack@eecs.umich.edu//
404519Sgblack@eecs.umich.edu// RegOp Microop templates
414519Sgblack@eecs.umich.edu//
424519Sgblack@eecs.umich.edu//////////////////////////////////////////////////////////////////////////
434519Sgblack@eecs.umich.edu
444519Sgblack@eecs.umich.edudef template MicroRegOpExecute {{
454519Sgblack@eecs.umich.edu        Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
464519Sgblack@eecs.umich.edu                Trace::InstRecord *traceData) const
474519Sgblack@eecs.umich.edu        {
484519Sgblack@eecs.umich.edu            Fault fault = NoFault;
494519Sgblack@eecs.umich.edu
504519Sgblack@eecs.umich.edu            DPRINTF(X86, "The data size is %d\n", dataSize);
514519Sgblack@eecs.umich.edu            %(op_decl)s;
524519Sgblack@eecs.umich.edu            %(op_rd)s;
534519Sgblack@eecs.umich.edu
544519Sgblack@eecs.umich.edu            IntReg result M5_VAR_USED;
554519Sgblack@eecs.umich.edu
564519Sgblack@eecs.umich.edu            if(%(cond_check)s)
574519Sgblack@eecs.umich.edu            {
584519Sgblack@eecs.umich.edu                %(code)s;
594519Sgblack@eecs.umich.edu                %(flag_code)s;
604519Sgblack@eecs.umich.edu            }
614519Sgblack@eecs.umich.edu            else
624519Sgblack@eecs.umich.edu            {
634519Sgblack@eecs.umich.edu                %(else_code)s;
644519Sgblack@eecs.umich.edu            }
654519Sgblack@eecs.umich.edu
664519Sgblack@eecs.umich.edu            //Write the resulting state to the execution context
674519Sgblack@eecs.umich.edu            if(fault == NoFault)
684809Sgblack@eecs.umich.edu            {
694519Sgblack@eecs.umich.edu                %(op_wb)s;
704519Sgblack@eecs.umich.edu            }
714688Sgblack@eecs.umich.edu            return fault;
724688Sgblack@eecs.umich.edu        }
734688Sgblack@eecs.umich.edu}};
744688Sgblack@eecs.umich.edu
754688Sgblack@eecs.umich.edudef template MicroRegOpImmExecute {{
764688Sgblack@eecs.umich.edu        Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
774708Sgblack@eecs.umich.edu                Trace::InstRecord *traceData) const
784708Sgblack@eecs.umich.edu        {
794708Sgblack@eecs.umich.edu            Fault fault = NoFault;
804708Sgblack@eecs.umich.edu
814519Sgblack@eecs.umich.edu            %(op_decl)s;
824519Sgblack@eecs.umich.edu            %(op_rd)s;
834519Sgblack@eecs.umich.edu
844519Sgblack@eecs.umich.edu            IntReg result M5_VAR_USED;
854519Sgblack@eecs.umich.edu
864519Sgblack@eecs.umich.edu            if(%(cond_check)s)
874519Sgblack@eecs.umich.edu            {
884519Sgblack@eecs.umich.edu                %(code)s;
894519Sgblack@eecs.umich.edu                %(flag_code)s;
904519Sgblack@eecs.umich.edu            }
914519Sgblack@eecs.umich.edu            else
924951Sgblack@eecs.umich.edu            {
934519Sgblack@eecs.umich.edu                %(else_code)s;
944519Sgblack@eecs.umich.edu            }
954519Sgblack@eecs.umich.edu
964519Sgblack@eecs.umich.edu            //Write the resulting state to the execution context
974519Sgblack@eecs.umich.edu            if(fault == NoFault)
984519Sgblack@eecs.umich.edu            {
994688Sgblack@eecs.umich.edu                %(op_wb)s;
1004688Sgblack@eecs.umich.edu            }
1014688Sgblack@eecs.umich.edu            return fault;
1024688Sgblack@eecs.umich.edu        }
1034688Sgblack@eecs.umich.edu}};
1044688Sgblack@eecs.umich.edu
1054708Sgblack@eecs.umich.edudef template MicroRegOpDeclare {{
1064708Sgblack@eecs.umich.edu    class %(class_name)s : public %(base_class)s
1074708Sgblack@eecs.umich.edu    {
1084708Sgblack@eecs.umich.edu      public:
1094519Sgblack@eecs.umich.edu        %(class_name)s(ExtMachInst _machInst,
1104519Sgblack@eecs.umich.edu                const char * instMnem, uint64_t setFlags,
1114519Sgblack@eecs.umich.edu                InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
1124519Sgblack@eecs.umich.edu                uint8_t _dataSize, uint16_t _ext);
1134519Sgblack@eecs.umich.edu
1144519Sgblack@eecs.umich.edu        %(BasicExecDeclare)s
1154519Sgblack@eecs.umich.edu    };
1164519Sgblack@eecs.umich.edu}};
1174519Sgblack@eecs.umich.edu
1184519Sgblack@eecs.umich.edudef template MicroRegOpImmDeclare {{
1194519Sgblack@eecs.umich.edu
1204519Sgblack@eecs.umich.edu    class %(class_name)s : public %(base_class)s
1214519Sgblack@eecs.umich.edu    {
1224519Sgblack@eecs.umich.edu      public:
1234519Sgblack@eecs.umich.edu        %(class_name)s(ExtMachInst _machInst,
1244519Sgblack@eecs.umich.edu                const char * instMnem, uint64_t setFlags,
1254519Sgblack@eecs.umich.edu                InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest,
1264519Sgblack@eecs.umich.edu                uint8_t _dataSize, uint16_t _ext);
1274519Sgblack@eecs.umich.edu
1284519Sgblack@eecs.umich.edu        %(BasicExecDeclare)s
1294519Sgblack@eecs.umich.edu    };
1304712Sgblack@eecs.umich.edu}};
1314519Sgblack@eecs.umich.edu
1324519Sgblack@eecs.umich.edudef template MicroRegOpConstructor {{
1334519Sgblack@eecs.umich.edu    inline %(class_name)s::%(class_name)s(
1344519Sgblack@eecs.umich.edu            ExtMachInst machInst, const char * instMnem, uint64_t setFlags,
1354712Sgblack@eecs.umich.edu            InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
1364519Sgblack@eecs.umich.edu            uint8_t _dataSize, uint16_t _ext) :
1374519Sgblack@eecs.umich.edu        %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags,
1384519Sgblack@eecs.umich.edu                _src1, _src2, _dest, _dataSize, _ext,
1394519Sgblack@eecs.umich.edu                %(op_class)s)
1404519Sgblack@eecs.umich.edu    {
1414519Sgblack@eecs.umich.edu        %(constructor)s;
1424519Sgblack@eecs.umich.edu        %(cond_control_flag_init)s;
1434951Sgblack@eecs.umich.edu    }
1444519Sgblack@eecs.umich.edu}};
1454519Sgblack@eecs.umich.edu
1464519Sgblack@eecs.umich.edudef template MicroRegOpImmConstructor {{
1474519Sgblack@eecs.umich.edu    inline %(class_name)s::%(class_name)s(
1484519Sgblack@eecs.umich.edu            ExtMachInst machInst, const char * instMnem, uint64_t setFlags,
1494951Sgblack@eecs.umich.edu            InstRegIndex _src1, uint8_t _imm8, InstRegIndex _dest,
1504519Sgblack@eecs.umich.edu            uint8_t _dataSize, uint16_t _ext) :
1514519Sgblack@eecs.umich.edu        %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags,
1524951Sgblack@eecs.umich.edu                _src1, _imm8, _dest, _dataSize, _ext,
1534712Sgblack@eecs.umich.edu                %(op_class)s)
1544519Sgblack@eecs.umich.edu    {
1554951Sgblack@eecs.umich.edu        %(constructor)s;
1564519Sgblack@eecs.umich.edu        %(cond_control_flag_init)s;
1574951Sgblack@eecs.umich.edu    }
1584712Sgblack@eecs.umich.edu}};
1594519Sgblack@eecs.umich.edu
1604519Sgblack@eecs.umich.eduoutput header {{
1614519Sgblack@eecs.umich.edu    void
1624519Sgblack@eecs.umich.edu    divide(uint64_t dividend, uint64_t divisor,
1634519Sgblack@eecs.umich.edu            uint64_t &quotient, uint64_t &remainder);
1644519Sgblack@eecs.umich.edu
1654519Sgblack@eecs.umich.edu    enum SegmentSelectorCheck {
1664519Sgblack@eecs.umich.edu      SegNoCheck, SegCSCheck, SegCallGateCheck, SegIntGateCheck,
1674519Sgblack@eecs.umich.edu      SegSoftIntGateCheck, SegSSCheck, SegIretCheck, SegIntCSCheck,
1684519Sgblack@eecs.umich.edu      SegTRCheck, SegTSSCheck, SegInGDTCheck, SegLDTCheck
1694519Sgblack@eecs.umich.edu    };
1704519Sgblack@eecs.umich.edu
1714519Sgblack@eecs.umich.edu    enum LongModeDescriptorType {
1724519Sgblack@eecs.umich.edu        LDT64 = 2,
1734519Sgblack@eecs.umich.edu        AvailableTSS64 = 9,
1744712Sgblack@eecs.umich.edu        BusyTSS64 = 0xb,
1754519Sgblack@eecs.umich.edu        CallGate64 = 0xc,
1764581Sgblack@eecs.umich.edu        IntGate64 = 0xe,
1774688Sgblack@eecs.umich.edu        TrapGate64 = 0xf
1784581Sgblack@eecs.umich.edu    };
1794519Sgblack@eecs.umich.edu}};
1804519Sgblack@eecs.umich.edu
1814519Sgblack@eecs.umich.eduoutput decoder {{
1824519Sgblack@eecs.umich.edu    void
1834519Sgblack@eecs.umich.edu    divide(uint64_t dividend, uint64_t divisor,
1844519Sgblack@eecs.umich.edu            uint64_t &quotient, uint64_t &remainder)
1854519Sgblack@eecs.umich.edu    {
1864519Sgblack@eecs.umich.edu        //Check for divide by zero.
1874712Sgblack@eecs.umich.edu        assert(divisor != 0);
1884519Sgblack@eecs.umich.edu        //If the divisor is bigger than the dividend, don't do anything.
1894581Sgblack@eecs.umich.edu        if (divisor <= dividend) {
1904688Sgblack@eecs.umich.edu            //Shift the divisor so it's msb lines up with the dividend.
1914581Sgblack@eecs.umich.edu            int dividendMsb = findMsbSet(dividend);
1924519Sgblack@eecs.umich.edu            int divisorMsb = findMsbSet(divisor);
1934519Sgblack@eecs.umich.edu            int shift = dividendMsb - divisorMsb;
1944519Sgblack@eecs.umich.edu            divisor <<= shift;
1954519Sgblack@eecs.umich.edu            //Compute what we'll add to the quotient if the divisor isn't
1964519Sgblack@eecs.umich.edu            //now larger than the dividend.
1974519Sgblack@eecs.umich.edu            uint64_t quotientBit = 1;
1984519Sgblack@eecs.umich.edu            quotientBit <<= shift;
1994951Sgblack@eecs.umich.edu            //If we need to step back a bit (no pun intended) because the
2004519Sgblack@eecs.umich.edu            //divisor got too to large, do that here. This is the "or two"
2014519Sgblack@eecs.umich.edu            //part of one or two bit division.
2024519Sgblack@eecs.umich.edu            if (divisor > dividend) {
2034519Sgblack@eecs.umich.edu                quotientBit >>= 1;
2044951Sgblack@eecs.umich.edu                divisor >>= 1;
2054519Sgblack@eecs.umich.edu            }
2064951Sgblack@eecs.umich.edu            //Decrement the remainder and increment the quotient.
2074712Sgblack@eecs.umich.edu            quotient += quotientBit;
2084519Sgblack@eecs.umich.edu            remainder -= divisor;
2094581Sgblack@eecs.umich.edu        }
2104688Sgblack@eecs.umich.edu    }
2114581Sgblack@eecs.umich.edu}};
2124519Sgblack@eecs.umich.edu
2134519Sgblack@eecs.umich.edulet {{
2144519Sgblack@eecs.umich.edu    # Make these empty strings so that concatenating onto
2154519Sgblack@eecs.umich.edu    # them will always work.
2164951Sgblack@eecs.umich.edu    header_output = ""
2174519Sgblack@eecs.umich.edu    decoder_output = ""
2184519Sgblack@eecs.umich.edu    exec_output = ""
2194951Sgblack@eecs.umich.edu
2204712Sgblack@eecs.umich.edu    immTemplates = (
2214519Sgblack@eecs.umich.edu            MicroRegOpImmDeclare,
2224581Sgblack@eecs.umich.edu            MicroRegOpImmConstructor,
2234688Sgblack@eecs.umich.edu            MicroRegOpImmExecute)
2244581Sgblack@eecs.umich.edu
2254519Sgblack@eecs.umich.edu    regTemplates = (
2264519Sgblack@eecs.umich.edu            MicroRegOpDeclare,
2274519Sgblack@eecs.umich.edu            MicroRegOpConstructor,
2284519Sgblack@eecs.umich.edu            MicroRegOpExecute)
2294519Sgblack@eecs.umich.edu
2305075Sgblack@eecs.umich.edu    class RegOpMeta(type):
2315075Sgblack@eecs.umich.edu        def buildCppClasses(self, name, Name, suffix, code, big_code, \
2325075Sgblack@eecs.umich.edu                flag_code, cond_check, else_code, cond_control_flag_init):
2335075Sgblack@eecs.umich.edu
2345075Sgblack@eecs.umich.edu            # Globals to stick the output in
2355075Sgblack@eecs.umich.edu            global header_output
2365075Sgblack@eecs.umich.edu            global decoder_output
2375075Sgblack@eecs.umich.edu            global exec_output
2385075Sgblack@eecs.umich.edu
2395075Sgblack@eecs.umich.edu            # Stick all the code together so it can be searched at once
2405075Sgblack@eecs.umich.edu            allCode = "|".join((code, flag_code, cond_check, else_code, 
2415075Sgblack@eecs.umich.edu                                cond_control_flag_init))
2425075Sgblack@eecs.umich.edu            allBigCode = "|".join((big_code, flag_code, cond_check, else_code,
2435075Sgblack@eecs.umich.edu                                   cond_control_flag_init))
2445075Sgblack@eecs.umich.edu
2455075Sgblack@eecs.umich.edu            # If op2 is used anywhere, make register and immediate versions
2465075Sgblack@eecs.umich.edu            # of this code.
2475075Sgblack@eecs.umich.edu            matcher = re.compile(r"(?<!\w)(?P<prefix>s?)op2(?P<typeQual>_[^\W_]+)?")
2485075Sgblack@eecs.umich.edu            match = matcher.search(allCode + allBigCode)
2495075Sgblack@eecs.umich.edu            if match:
2505075Sgblack@eecs.umich.edu                typeQual = ""
2515075Sgblack@eecs.umich.edu                if match.group("typeQual"):
2525075Sgblack@eecs.umich.edu                    typeQual = match.group("typeQual")
2535075Sgblack@eecs.umich.edu                src2_name = "%spsrc2%s" % (match.group("prefix"), typeQual)
2545075Sgblack@eecs.umich.edu                self.buildCppClasses(name, Name, suffix,
2555075Sgblack@eecs.umich.edu                        matcher.sub(src2_name, code),
2565075Sgblack@eecs.umich.edu                        matcher.sub(src2_name, big_code),
2575075Sgblack@eecs.umich.edu                        matcher.sub(src2_name, flag_code),
2585075Sgblack@eecs.umich.edu                        matcher.sub(src2_name, cond_check),
2595075Sgblack@eecs.umich.edu                        matcher.sub(src2_name, else_code),
2605075Sgblack@eecs.umich.edu                        matcher.sub(src2_name, cond_control_flag_init))
2615075Sgblack@eecs.umich.edu                imm_name = "%simm8" % match.group("prefix")
2625075Sgblack@eecs.umich.edu                self.buildCppClasses(name + "i", Name, suffix + "Imm",
2635075Sgblack@eecs.umich.edu                        matcher.sub(imm_name, code),
2645075Sgblack@eecs.umich.edu                        matcher.sub(imm_name, big_code),
2655075Sgblack@eecs.umich.edu                        matcher.sub(imm_name, flag_code),
2665075Sgblack@eecs.umich.edu                        matcher.sub(imm_name, cond_check),
2675075Sgblack@eecs.umich.edu                        matcher.sub(imm_name, else_code),
2685075Sgblack@eecs.umich.edu                        matcher.sub(imm_name, cond_control_flag_init))
2694519Sgblack@eecs.umich.edu                return
2705040Sgblack@eecs.umich.edu
2715040Sgblack@eecs.umich.edu            # If there's something optional to do with flags, generate
2725040Sgblack@eecs.umich.edu            # a version without it and fix up this version to use it.
2735040Sgblack@eecs.umich.edu            if flag_code != "" or cond_check != "true":
2745040Sgblack@eecs.umich.edu                self.buildCppClasses(name, Name, suffix,
2755040Sgblack@eecs.umich.edu                        code, big_code, "", "true", else_code, "")
2765040Sgblack@eecs.umich.edu                suffix = "Flags" + suffix
2775040Sgblack@eecs.umich.edu
2785040Sgblack@eecs.umich.edu            # If psrc1 or psrc2 is used, we need to actually insert code to
2795040Sgblack@eecs.umich.edu            # compute it.
2805040Sgblack@eecs.umich.edu            for (big, all) in ((False, allCode), (True, allBigCode)):
2815040Sgblack@eecs.umich.edu                prefix = ""
2825040Sgblack@eecs.umich.edu                for (rex, decl) in (
2835040Sgblack@eecs.umich.edu                        ("(?<!\w)psrc1(?!\w)",
2845040Sgblack@eecs.umich.edu                         "uint64_t psrc1 = pick(SrcReg1, 0, dataSize);"),
2855040Sgblack@eecs.umich.edu                        ("(?<!\w)psrc2(?!\w)",
2865040Sgblack@eecs.umich.edu                         "uint64_t psrc2 = pick(SrcReg2, 1, dataSize);"),
2875040Sgblack@eecs.umich.edu                        ("(?<!\w)spsrc1(?!\w)",
2885040Sgblack@eecs.umich.edu                         "int64_t spsrc1 = signedPick(SrcReg1, 0, dataSize);"),
2895040Sgblack@eecs.umich.edu                        ("(?<!\w)spsrc2(?!\w)",
2905040Sgblack@eecs.umich.edu                         "int64_t spsrc2 = signedPick(SrcReg2, 1, dataSize);"),
2915040Sgblack@eecs.umich.edu                        ("(?<!\w)simm8(?!\w)",
2925040Sgblack@eecs.umich.edu                         "int8_t simm8 = imm8;")):
2935040Sgblack@eecs.umich.edu                    matcher = re.compile(rex)
2945040Sgblack@eecs.umich.edu                    if matcher.search(all):
2955040Sgblack@eecs.umich.edu                        prefix += decl + "\n"
2965040Sgblack@eecs.umich.edu                if big:
2975040Sgblack@eecs.umich.edu                    if big_code != "":
2985040Sgblack@eecs.umich.edu                        big_code = prefix + big_code
2995040Sgblack@eecs.umich.edu                else:
3005062Sgblack@eecs.umich.edu                    code = prefix + code
3015062Sgblack@eecs.umich.edu
3025062Sgblack@eecs.umich.edu            base = "X86ISA::RegOp"
3035062Sgblack@eecs.umich.edu
3045062Sgblack@eecs.umich.edu            # If imm8 shows up in the code, use the immediate templates, if
3055062Sgblack@eecs.umich.edu            # not, hopefully the register ones will be correct.
3065062Sgblack@eecs.umich.edu            templates = regTemplates
3075040Sgblack@eecs.umich.edu            matcher = re.compile("(?<!\w)s?imm8(?!\w)")
3085062Sgblack@eecs.umich.edu            if matcher.search(allCode):
3095062Sgblack@eecs.umich.edu                base += "Imm"
3105062Sgblack@eecs.umich.edu                templates = immTemplates
3115062Sgblack@eecs.umich.edu
3125040Sgblack@eecs.umich.edu            # Get everything ready for the substitution
3135040Sgblack@eecs.umich.edu            iops = [InstObjParams(name, Name + suffix, base,
3145040Sgblack@eecs.umich.edu                    {"code" : code,
3155040Sgblack@eecs.umich.edu                     "flag_code" : flag_code,
3165040Sgblack@eecs.umich.edu                     "cond_check" : cond_check,
3175040Sgblack@eecs.umich.edu                     "else_code" : else_code,
3185040Sgblack@eecs.umich.edu                     "cond_control_flag_init" : cond_control_flag_init})]
3195040Sgblack@eecs.umich.edu            if big_code != "":
3205040Sgblack@eecs.umich.edu                iops += [InstObjParams(name, Name + suffix + "Big", base,
3215239Sgblack@eecs.umich.edu                         {"code" : big_code,
3225040Sgblack@eecs.umich.edu                          "flag_code" : flag_code,
3235040Sgblack@eecs.umich.edu                          "cond_check" : cond_check,
3245040Sgblack@eecs.umich.edu                          "else_code" : else_code,
3255040Sgblack@eecs.umich.edu                          "cond_control_flag_init" :
3265040Sgblack@eecs.umich.edu                              cond_control_flag_init})]
3275040Sgblack@eecs.umich.edu
3285040Sgblack@eecs.umich.edu            # Generate the actual code (finally!)
3295040Sgblack@eecs.umich.edu            for iop in iops:
3305061Sgblack@eecs.umich.edu                header_output += templates[0].subst(iop)
3315040Sgblack@eecs.umich.edu                decoder_output += templates[1].subst(iop)
3325040Sgblack@eecs.umich.edu                exec_output += templates[2].subst(iop)
3335061Sgblack@eecs.umich.edu
3345061Sgblack@eecs.umich.edu
3355061Sgblack@eecs.umich.edu        def __new__(mcls, Name, bases, dict):
3365061Sgblack@eecs.umich.edu            abstract = False
3375061Sgblack@eecs.umich.edu            name = Name.lower()
3385061Sgblack@eecs.umich.edu            if "abstract" in dict:
3395061Sgblack@eecs.umich.edu                abstract = dict['abstract']
3405061Sgblack@eecs.umich.edu                del dict['abstract']
3415040Sgblack@eecs.umich.edu
3425040Sgblack@eecs.umich.edu            cls = super(RegOpMeta, mcls).__new__(mcls, Name, bases, dict)
3435040Sgblack@eecs.umich.edu            if not abstract:
3445040Sgblack@eecs.umich.edu                cls.className = Name
3455040Sgblack@eecs.umich.edu                cls.base_mnemonic = name
3465040Sgblack@eecs.umich.edu                code = cls.code
3475040Sgblack@eecs.umich.edu                big_code = cls.big_code
3485040Sgblack@eecs.umich.edu                flag_code = cls.flag_code
3495040Sgblack@eecs.umich.edu                cond_check = cls.cond_check
3505040Sgblack@eecs.umich.edu                else_code = cls.else_code
3515040Sgblack@eecs.umich.edu                cond_control_flag_init = cls.cond_control_flag_init
3525040Sgblack@eecs.umich.edu
3535040Sgblack@eecs.umich.edu                # Set up the C++ classes
3545040Sgblack@eecs.umich.edu                mcls.buildCppClasses(cls, name, Name, "", code, big_code,
3555040Sgblack@eecs.umich.edu                        flag_code, cond_check, else_code,
3565040Sgblack@eecs.umich.edu                        cond_control_flag_init)
3575040Sgblack@eecs.umich.edu
3585040Sgblack@eecs.umich.edu                # Hook into the microassembler dict
3595040Sgblack@eecs.umich.edu                global microopClasses
3605040Sgblack@eecs.umich.edu                microopClasses[name] = cls
3615040Sgblack@eecs.umich.edu
3625040Sgblack@eecs.umich.edu                allCode = "|".join((code, flag_code, cond_check, else_code,
3635040Sgblack@eecs.umich.edu                                    cond_control_flag_init))
3645040Sgblack@eecs.umich.edu
3655040Sgblack@eecs.umich.edu                # If op2 is used anywhere, make register and immediate versions
3664688Sgblack@eecs.umich.edu                # of this code.
3675040Sgblack@eecs.umich.edu                matcher = re.compile(r"op2(?P<typeQual>_[^\W_]+)?")
3684688Sgblack@eecs.umich.edu                if matcher.search(allCode):
3694688Sgblack@eecs.umich.edu                    microopClasses[name + 'i'] = cls
3704688Sgblack@eecs.umich.edu            return cls
3714688Sgblack@eecs.umich.edu
3725040Sgblack@eecs.umich.edu
3734688Sgblack@eecs.umich.edu    class RegOp(X86Microop):
3745040Sgblack@eecs.umich.edu        __metaclass__ = RegOpMeta
3755040Sgblack@eecs.umich.edu        # This class itself doesn't act as a microop
3765040Sgblack@eecs.umich.edu        abstract = True
3775040Sgblack@eecs.umich.edu
3785040Sgblack@eecs.umich.edu        # Default template parameter values
3795040Sgblack@eecs.umich.edu        big_code = ""
3805040Sgblack@eecs.umich.edu        flag_code = ""
3815040Sgblack@eecs.umich.edu        cond_check = "true"
3825040Sgblack@eecs.umich.edu        else_code = ";"
3835040Sgblack@eecs.umich.edu        cond_control_flag_init = ""
3845040Sgblack@eecs.umich.edu
3855040Sgblack@eecs.umich.edu        def __init__(self, dest, src1, op2, flags = None, dataSize = "env.dataSize"):
3865040Sgblack@eecs.umich.edu            self.dest = dest
3875040Sgblack@eecs.umich.edu            self.src1 = src1
3885040Sgblack@eecs.umich.edu            self.op2 = op2
3895040Sgblack@eecs.umich.edu            self.flags = flags
3905040Sgblack@eecs.umich.edu            self.dataSize = dataSize
3915040Sgblack@eecs.umich.edu            if flags is None:
3925040Sgblack@eecs.umich.edu                self.ext = 0
3935040Sgblack@eecs.umich.edu            else:
3945040Sgblack@eecs.umich.edu                if not isinstance(flags, (list, tuple)):
3955040Sgblack@eecs.umich.edu                    raise Exception, "flags must be a list or tuple of flags"
3964688Sgblack@eecs.umich.edu                self.ext = " | ".join(flags)
3974688Sgblack@eecs.umich.edu                self.className += "Flags"
3985040Sgblack@eecs.umich.edu
3995040Sgblack@eecs.umich.edu        def getAllocator(self, microFlags):
4005040Sgblack@eecs.umich.edu            if self.big_code != "":
4015040Sgblack@eecs.umich.edu                className = self.className
4024688Sgblack@eecs.umich.edu                if self.mnemonic == self.base_mnemonic + 'i':
4034688Sgblack@eecs.umich.edu                    className += "Imm"
4045040Sgblack@eecs.umich.edu                allocString = '''
4055040Sgblack@eecs.umich.edu                    (%(dataSize)s >= 4) ?
4065040Sgblack@eecs.umich.edu                        (StaticInstPtr)(new %(class_name)sBig(machInst,
4075040Sgblack@eecs.umich.edu                            macrocodeBlock, %(flags)s, %(src1)s, %(op2)s,
4085040Sgblack@eecs.umich.edu                            %(dest)s, %(dataSize)s, %(ext)s)) :
4095040Sgblack@eecs.umich.edu                        (StaticInstPtr)(new %(class_name)s(machInst,
4104519Sgblack@eecs.umich.edu                            macrocodeBlock, %(flags)s, %(src1)s, %(op2)s,
4114519Sgblack@eecs.umich.edu                            %(dest)s, %(dataSize)s, %(ext)s))
4125040Sgblack@eecs.umich.edu                    '''
4134688Sgblack@eecs.umich.edu                allocator = allocString % {
4144701Sgblack@eecs.umich.edu                    "class_name" : className,
4154688Sgblack@eecs.umich.edu                    "flags" : self.microFlagsText(microFlags),
4164688Sgblack@eecs.umich.edu                    "src1" : self.src1, "op2" : self.op2,
4174688Sgblack@eecs.umich.edu                    "dest" : self.dest,
4184688Sgblack@eecs.umich.edu                    "dataSize" : self.dataSize,
4194688Sgblack@eecs.umich.edu                    "ext" : self.ext}
4204688Sgblack@eecs.umich.edu                return allocator
4214688Sgblack@eecs.umich.edu            else:
4224519Sgblack@eecs.umich.edu                className = self.className
4234519Sgblack@eecs.umich.edu                if self.mnemonic == self.base_mnemonic + 'i':
4245040Sgblack@eecs.umich.edu                    className += "Imm"
4255040Sgblack@eecs.umich.edu                allocator = '''new %(class_name)s(machInst, macrocodeBlock,
4265040Sgblack@eecs.umich.edu                        %(flags)s, %(src1)s, %(op2)s, %(dest)s,
4274560Sgblack@eecs.umich.edu                        %(dataSize)s, %(ext)s)''' % {
4285040Sgblack@eecs.umich.edu                    "class_name" : className,
4294688Sgblack@eecs.umich.edu                    "flags" : self.microFlagsText(microFlags),
4305040Sgblack@eecs.umich.edu                    "src1" : self.src1, "op2" : self.op2,
4314519Sgblack@eecs.umich.edu                    "dest" : self.dest,
4325040Sgblack@eecs.umich.edu                    "dataSize" : self.dataSize,
4334519Sgblack@eecs.umich.edu                    "ext" : self.ext}
4344519Sgblack@eecs.umich.edu                return allocator
4354519Sgblack@eecs.umich.edu
4364539Sgblack@eecs.umich.edu    class LogicRegOp(RegOp):
4374519Sgblack@eecs.umich.edu        abstract = True
4385040Sgblack@eecs.umich.edu        flag_code = '''
4394688Sgblack@eecs.umich.edu            //Don't have genFlags handle the OF or CF bits
4405040Sgblack@eecs.umich.edu            uint64_t mask = CFBit | ECFBit | OFBit;
4415040Sgblack@eecs.umich.edu            ccFlagBits = genFlags(ccFlagBits, ext & ~mask, result, psrc1, op2);
4425115Sgblack@eecs.umich.edu            //If a logic microop wants to set these, it wants to set them to 0.
4435040Sgblack@eecs.umich.edu            ccFlagBits &= ~(CFBit & ext);
4445040Sgblack@eecs.umich.edu            ccFlagBits &= ~(ECFBit & ext);
4455040Sgblack@eecs.umich.edu            ccFlagBits &= ~(OFBit & ext);
4465115Sgblack@eecs.umich.edu        '''
4475040Sgblack@eecs.umich.edu
4485040Sgblack@eecs.umich.edu    class FlagRegOp(RegOp):
4494519Sgblack@eecs.umich.edu        abstract = True
4505040Sgblack@eecs.umich.edu        flag_code = \
4515040Sgblack@eecs.umich.edu            "ccFlagBits = genFlags(ccFlagBits, ext, result, psrc1, op2);"
4525040Sgblack@eecs.umich.edu
4535040Sgblack@eecs.umich.edu    class SubRegOp(RegOp):
4544519Sgblack@eecs.umich.edu        abstract = True
4555040Sgblack@eecs.umich.edu        flag_code = \
4565040Sgblack@eecs.umich.edu            "ccFlagBits = genFlags(ccFlagBits, ext, result, psrc1, ~op2, true);"
4575040Sgblack@eecs.umich.edu
4585040Sgblack@eecs.umich.edu    class CondRegOp(RegOp):
4594519Sgblack@eecs.umich.edu        abstract = True
4605040Sgblack@eecs.umich.edu        cond_check = "checkCondition(ccFlagBits, ext)"
4615040Sgblack@eecs.umich.edu        cond_control_flag_init = "flags[IsCondControl] = flags[IsControl];"
4625083Sgblack@eecs.umich.edu
4634519Sgblack@eecs.umich.edu    class RdRegOp(RegOp):
4645063Sgblack@eecs.umich.edu        abstract = True
4655063Sgblack@eecs.umich.edu        def __init__(self, dest, src1=None, dataSize="env.dataSize"):
4665063Sgblack@eecs.umich.edu            if not src1:
4675063Sgblack@eecs.umich.edu                src1 = dest
4685063Sgblack@eecs.umich.edu            super(RdRegOp, self).__init__(dest, src1, \
4695063Sgblack@eecs.umich.edu                    "InstRegIndex(NUM_INTREGS)", None, dataSize)
4705063Sgblack@eecs.umich.edu
4715063Sgblack@eecs.umich.edu    class WrRegOp(RegOp):
4725063Sgblack@eecs.umich.edu        abstract = True
4735063Sgblack@eecs.umich.edu        def __init__(self, src1, src2, flags=None, dataSize="env.dataSize"):
4745063Sgblack@eecs.umich.edu            super(WrRegOp, self).__init__("InstRegIndex(NUM_INTREGS)", \
4755063Sgblack@eecs.umich.edu                    src1, src2, flags, dataSize)
4765040Sgblack@eecs.umich.edu
4775040Sgblack@eecs.umich.edu    class Add(FlagRegOp):
4784595Sgblack@eecs.umich.edu        code = 'DestReg = merge(DestReg, result = (psrc1 + op2), dataSize);'
4795040Sgblack@eecs.umich.edu        big_code = 'DestReg = result = (psrc1 + op2) & mask(dataSize * 8);'
4805040Sgblack@eecs.umich.edu
4814595Sgblack@eecs.umich.edu    class Or(LogicRegOp):
4825040Sgblack@eecs.umich.edu        code = 'DestReg = merge(DestReg, result = (psrc1 | op2), dataSize);'
4835040Sgblack@eecs.umich.edu        big_code = 'DestReg = result = (psrc1 | op2) & mask(dataSize * 8);'
4844732Sgblack@eecs.umich.edu
4855138Sgblack@eecs.umich.edu    class Adc(FlagRegOp):
4865040Sgblack@eecs.umich.edu        code = '''
4875040Sgblack@eecs.umich.edu            CCFlagBits flags = ccFlagBits;
4885040Sgblack@eecs.umich.edu            DestReg = merge(DestReg, result = (psrc1 + op2 + flags.cf), dataSize);
4895040Sgblack@eecs.umich.edu            '''
4904732Sgblack@eecs.umich.edu        big_code = '''
4915138Sgblack@eecs.umich.edu            CCFlagBits flags = ccFlagBits;
4925040Sgblack@eecs.umich.edu            DestReg = result = (psrc1 + op2 + flags.cf) & mask(dataSize * 8);
4935040Sgblack@eecs.umich.edu            '''
4945040Sgblack@eecs.umich.edu
4955040Sgblack@eecs.umich.edu    class Sbb(SubRegOp):
4965040Sgblack@eecs.umich.edu        code = '''
4975040Sgblack@eecs.umich.edu            CCFlagBits flags = ccFlagBits;
4985040Sgblack@eecs.umich.edu            DestReg = merge(DestReg, result = (psrc1 - op2 - flags.cf), dataSize);
4995040Sgblack@eecs.umich.edu            '''
5005040Sgblack@eecs.umich.edu        big_code = '''
5015040Sgblack@eecs.umich.edu            CCFlagBits flags = ccFlagBits;
5025040Sgblack@eecs.umich.edu            DestReg = result = (psrc1 - op2 - flags.cf) & mask(dataSize * 8);
5035065Sgblack@eecs.umich.edu            '''
5045065Sgblack@eecs.umich.edu
5055065Sgblack@eecs.umich.edu    class And(LogicRegOp):
5065065Sgblack@eecs.umich.edu        code = 'DestReg = merge(DestReg, result = (psrc1 & op2), dataSize)'
5075065Sgblack@eecs.umich.edu        big_code = 'DestReg = result = (psrc1 & op2) & mask(dataSize * 8)'
5085063Sgblack@eecs.umich.edu
5095040Sgblack@eecs.umich.edu    class Sub(SubRegOp):
5105063Sgblack@eecs.umich.edu        code = 'DestReg = merge(DestReg, result = (psrc1 - op2), dataSize)'
5115063Sgblack@eecs.umich.edu        big_code = 'DestReg = result = (psrc1 - op2) & mask(dataSize * 8)'
5125063Sgblack@eecs.umich.edu
5135063Sgblack@eecs.umich.edu    class Xor(LogicRegOp):
5145063Sgblack@eecs.umich.edu        code = 'DestReg = merge(DestReg, result = (psrc1 ^ op2), dataSize)'
5155063Sgblack@eecs.umich.edu        big_code = 'DestReg = result = (psrc1 ^ op2) & mask(dataSize * 8)'
5165063Sgblack@eecs.umich.edu
5175063Sgblack@eecs.umich.edu    class Mul1s(WrRegOp):
5185063Sgblack@eecs.umich.edu        code = '''
5195040Sgblack@eecs.umich.edu            ProdLow = psrc1 * op2;
5205040Sgblack@eecs.umich.edu            int halfSize = (dataSize * 8) / 2;
5215063Sgblack@eecs.umich.edu            uint64_t shifter = (ULL(1) << halfSize);
5225040Sgblack@eecs.umich.edu            uint64_t hiResult;
5235063Sgblack@eecs.umich.edu            uint64_t psrc1_h = psrc1 / shifter;
5244809Sgblack@eecs.umich.edu            uint64_t psrc1_l = psrc1 & mask(halfSize);
5255063Sgblack@eecs.umich.edu            uint64_t psrc2_h = (op2 / shifter) & mask(halfSize);
5265063Sgblack@eecs.umich.edu            uint64_t psrc2_l = op2 & mask(halfSize);
5275063Sgblack@eecs.umich.edu            hiResult = ((psrc1_l * psrc2_h + psrc1_h * psrc2_l +
5285063Sgblack@eecs.umich.edu                        ((psrc1_l * psrc2_l) / shifter)) /shifter) +
5295063Sgblack@eecs.umich.edu                       psrc1_h * psrc2_h;
5305063Sgblack@eecs.umich.edu            if (bits(psrc1, dataSize * 8 - 1))
5315063Sgblack@eecs.umich.edu                hiResult -= op2;
5325040Sgblack@eecs.umich.edu            if (bits(op2, dataSize * 8 - 1))
5335040Sgblack@eecs.umich.edu                hiResult -= psrc1;
5345063Sgblack@eecs.umich.edu            ProdHi = hiResult;
5355063Sgblack@eecs.umich.edu            '''
5365040Sgblack@eecs.umich.edu        flag_code = '''
5375063Sgblack@eecs.umich.edu            if ((-ProdHi & mask(dataSize * 8)) !=
5385063Sgblack@eecs.umich.edu                    bits(ProdLow, dataSize * 8 - 1)) {
5395063Sgblack@eecs.umich.edu                ccFlagBits = ccFlagBits | (ext & (CFBit | OFBit | ECFBit));
5405063Sgblack@eecs.umich.edu            } else {
5415063Sgblack@eecs.umich.edu                ccFlagBits = ccFlagBits & ~(ext & (CFBit | OFBit | ECFBit));
5425063Sgblack@eecs.umich.edu            }
5435063Sgblack@eecs.umich.edu        '''
5445063Sgblack@eecs.umich.edu
5455063Sgblack@eecs.umich.edu    class Mul1u(WrRegOp):
5465063Sgblack@eecs.umich.edu        code = '''
5475063Sgblack@eecs.umich.edu            ProdLow = psrc1 * op2;
5485063Sgblack@eecs.umich.edu            int halfSize = (dataSize * 8) / 2;
5495062Sgblack@eecs.umich.edu            uint64_t shifter = (ULL(1) << halfSize);
5505075Sgblack@eecs.umich.edu            uint64_t psrc1_h = psrc1 / shifter;
5515075Sgblack@eecs.umich.edu            uint64_t psrc1_l = psrc1 & mask(halfSize);
5525040Sgblack@eecs.umich.edu            uint64_t psrc2_h = (op2 / shifter) & mask(halfSize);
5535075Sgblack@eecs.umich.edu            uint64_t psrc2_l = op2 & mask(halfSize);
5545075Sgblack@eecs.umich.edu            ProdHi = ((psrc1_l * psrc2_h + psrc1_h * psrc2_l +
5555075Sgblack@eecs.umich.edu                      ((psrc1_l * psrc2_l) / shifter)) / shifter) +
5565075Sgblack@eecs.umich.edu                     psrc1_h * psrc2_h;
5575075Sgblack@eecs.umich.edu            '''
5585075Sgblack@eecs.umich.edu        flag_code = '''
5595075Sgblack@eecs.umich.edu            if (ProdHi) {
5605075Sgblack@eecs.umich.edu                ccFlagBits = ccFlagBits | (ext & (CFBit | OFBit | ECFBit));
5615075Sgblack@eecs.umich.edu            } else {
5625075Sgblack@eecs.umich.edu                ccFlagBits = ccFlagBits & ~(ext & (CFBit | OFBit | ECFBit));
5635075Sgblack@eecs.umich.edu            }
5645075Sgblack@eecs.umich.edu        '''
5655075Sgblack@eecs.umich.edu
5665075Sgblack@eecs.umich.edu    class Mulel(RdRegOp):
5675075Sgblack@eecs.umich.edu        code = 'DestReg = merge(SrcReg1, ProdLow, dataSize);'
5685040Sgblack@eecs.umich.edu        big_code = 'DestReg = ProdLow & mask(dataSize * 8);'
5694823Sgblack@eecs.umich.edu
5705075Sgblack@eecs.umich.edu    class Muleh(RdRegOp):
5715075Sgblack@eecs.umich.edu        def __init__(self, dest, src1=None, flags=None, dataSize="env.dataSize"):
5725075Sgblack@eecs.umich.edu            if not src1:
5735075Sgblack@eecs.umich.edu                src1 = dest
5745075Sgblack@eecs.umich.edu            super(RdRegOp, self).__init__(dest, src1, \
5755075Sgblack@eecs.umich.edu                    "InstRegIndex(NUM_INTREGS)", flags, dataSize)
5765075Sgblack@eecs.umich.edu        code = 'DestReg = merge(SrcReg1, ProdHi, dataSize);'
5775075Sgblack@eecs.umich.edu        big_code = 'DestReg = ProdHi & mask(dataSize * 8);'
5785075Sgblack@eecs.umich.edu
5795075Sgblack@eecs.umich.edu    # One or two bit divide
5805075Sgblack@eecs.umich.edu    class Div1(WrRegOp):
5815075Sgblack@eecs.umich.edu        code = '''
5825075Sgblack@eecs.umich.edu            //These are temporaries so that modifying them later won't make
5835075Sgblack@eecs.umich.edu            //the ISA parser think they're also sources.
5845075Sgblack@eecs.umich.edu            uint64_t quotient = 0;
5855075Sgblack@eecs.umich.edu            uint64_t remainder = psrc1;
5865075Sgblack@eecs.umich.edu            //Similarly, this is a temporary so changing it doesn't make it
5875075Sgblack@eecs.umich.edu            //a source.
5885075Sgblack@eecs.umich.edu            uint64_t divisor = op2;
5895075Sgblack@eecs.umich.edu            //This is a temporary just for consistency and clarity.
5905075Sgblack@eecs.umich.edu            uint64_t dividend = remainder;
5915075Sgblack@eecs.umich.edu            //Do the division.
5925075Sgblack@eecs.umich.edu            if (divisor == 0) {
5935075Sgblack@eecs.umich.edu                fault = new DivideByZero;
5945075Sgblack@eecs.umich.edu            } else {
5955075Sgblack@eecs.umich.edu                divide(dividend, divisor, quotient, remainder);
5965075Sgblack@eecs.umich.edu                //Record the final results.
5975075Sgblack@eecs.umich.edu                Remainder = remainder;
5985075Sgblack@eecs.umich.edu                Quotient = quotient;
5995075Sgblack@eecs.umich.edu                Divisor = divisor;
6005075Sgblack@eecs.umich.edu            }
6015075Sgblack@eecs.umich.edu            '''
6025075Sgblack@eecs.umich.edu
6034732Sgblack@eecs.umich.edu    # Step divide
6045075Sgblack@eecs.umich.edu    class Div2(RegOp):
6055075Sgblack@eecs.umich.edu        divCode = '''
6065075Sgblack@eecs.umich.edu            uint64_t dividend = Remainder;
6075075Sgblack@eecs.umich.edu            uint64_t divisor = Divisor;
6085075Sgblack@eecs.umich.edu            uint64_t quotient = Quotient;
6095040Sgblack@eecs.umich.edu            uint64_t remainder = dividend;
6105040Sgblack@eecs.umich.edu            int remaining = op2;
6115040Sgblack@eecs.umich.edu            //If we overshot, do nothing. This lets us unrool division loops a
6125040Sgblack@eecs.umich.edu            //little.
6135040Sgblack@eecs.umich.edu            if (divisor == 0) {
6144732Sgblack@eecs.umich.edu                fault = new DivideByZero;
6155040Sgblack@eecs.umich.edu            } else if (remaining) {
6165076Sgblack@eecs.umich.edu                if (divisor & (ULL(1) << 63)) {
6175040Sgblack@eecs.umich.edu                    while (remaining && !(dividend & (ULL(1) << 63))) {
6184756Sgblack@eecs.umich.edu                        dividend = (dividend << 1) |
6194823Sgblack@eecs.umich.edu                            bits(SrcReg1, remaining - 1);
6205040Sgblack@eecs.umich.edu                        quotient <<= 1;
6215076Sgblack@eecs.umich.edu                        remaining--;
6225076Sgblack@eecs.umich.edu                    }
6235076Sgblack@eecs.umich.edu                    if (dividend & (ULL(1) << 63)) {
6245076Sgblack@eecs.umich.edu                        bool highBit = false;
6255076Sgblack@eecs.umich.edu                        if (dividend < divisor && remaining) {
6265076Sgblack@eecs.umich.edu                            highBit = true;
6275076Sgblack@eecs.umich.edu                            dividend = (dividend << 1) |
6285076Sgblack@eecs.umich.edu                                bits(SrcReg1, remaining - 1);
6295076Sgblack@eecs.umich.edu                            quotient <<= 1;
6305076Sgblack@eecs.umich.edu                            remaining--;
6315076Sgblack@eecs.umich.edu                        }
6325076Sgblack@eecs.umich.edu                        if (highBit || divisor <= dividend) {
6335076Sgblack@eecs.umich.edu                            quotient++;
6345076Sgblack@eecs.umich.edu                            dividend -= divisor;
6355076Sgblack@eecs.umich.edu                        }
6365076Sgblack@eecs.umich.edu                    }
6375076Sgblack@eecs.umich.edu                    remainder = dividend;
6385076Sgblack@eecs.umich.edu                } else {
6395076Sgblack@eecs.umich.edu                    //Shift in bits from the low order portion of the dividend
6405076Sgblack@eecs.umich.edu                    while (dividend < divisor && remaining) {
6415076Sgblack@eecs.umich.edu                        dividend = (dividend << 1) |
6425040Sgblack@eecs.umich.edu                            bits(SrcReg1, remaining - 1);
6435076Sgblack@eecs.umich.edu                        quotient <<= 1;
6445040Sgblack@eecs.umich.edu                        remaining--;
6454756Sgblack@eecs.umich.edu                    }
6464732Sgblack@eecs.umich.edu                    remainder = dividend;
6474732Sgblack@eecs.umich.edu                    //Do the division.
6484732Sgblack@eecs.umich.edu                    divide(dividend, divisor, quotient, remainder);
6494732Sgblack@eecs.umich.edu                }
6504823Sgblack@eecs.umich.edu            }
6515040Sgblack@eecs.umich.edu            //Keep track of how many bits there are still to pull in.
6525076Sgblack@eecs.umich.edu            %s
6535076Sgblack@eecs.umich.edu            //Record the final results
6545076Sgblack@eecs.umich.edu            Remainder = remainder;
6555076Sgblack@eecs.umich.edu            Quotient = quotient;
6565076Sgblack@eecs.umich.edu        '''
6575076Sgblack@eecs.umich.edu        code = divCode % "DestReg = merge(DestReg, remaining, dataSize);"
6585076Sgblack@eecs.umich.edu        big_code = divCode % "DestReg = remaining & mask(dataSize * 8);"
6595076Sgblack@eecs.umich.edu        flag_code = '''
6605076Sgblack@eecs.umich.edu            if (remaining == 0)
6615076Sgblack@eecs.umich.edu                ccFlagBits = ccFlagBits | (ext & EZFBit);
6625076Sgblack@eecs.umich.edu            else
6635076Sgblack@eecs.umich.edu                ccFlagBits = ccFlagBits & ~(ext & EZFBit);
6645076Sgblack@eecs.umich.edu        '''
6655076Sgblack@eecs.umich.edu
6665076Sgblack@eecs.umich.edu    class Divq(RdRegOp):
6675076Sgblack@eecs.umich.edu        code = 'DestReg = merge(SrcReg1, Quotient, dataSize);'
6685076Sgblack@eecs.umich.edu        big_code = 'DestReg = Quotient & mask(dataSize * 8);'
6695040Sgblack@eecs.umich.edu
6705076Sgblack@eecs.umich.edu    class Divr(RdRegOp):
6715040Sgblack@eecs.umich.edu        code = 'DestReg = merge(SrcReg1, Remainder, dataSize);'
6724756Sgblack@eecs.umich.edu        big_code = 'DestReg = Remainder & mask(dataSize * 8);'
6734732Sgblack@eecs.umich.edu
6744732Sgblack@eecs.umich.edu    class Mov(CondRegOp):
6754732Sgblack@eecs.umich.edu        code = 'DestReg = merge(SrcReg1, op2, dataSize)'
6764732Sgblack@eecs.umich.edu        else_code = 'DestReg = DestReg;'
6775032Sgblack@eecs.umich.edu
6784823Sgblack@eecs.umich.edu    # Shift instructions
6795040Sgblack@eecs.umich.edu
6805076Sgblack@eecs.umich.edu    class Sll(RegOp):
6815076Sgblack@eecs.umich.edu        code = '''
6825076Sgblack@eecs.umich.edu            uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
6835076Sgblack@eecs.umich.edu            DestReg = merge(DestReg, psrc1 << shiftAmt, dataSize);
6845076Sgblack@eecs.umich.edu            '''
6855076Sgblack@eecs.umich.edu        big_code = '''
6865076Sgblack@eecs.umich.edu            uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
6875076Sgblack@eecs.umich.edu            DestReg = (psrc1 << shiftAmt) & mask(dataSize * 8);
6885076Sgblack@eecs.umich.edu            '''
6895076Sgblack@eecs.umich.edu        flag_code = '''
6905076Sgblack@eecs.umich.edu            // If the shift amount is zero, no flags should be modified.
6915076Sgblack@eecs.umich.edu            if (shiftAmt) {
6925076Sgblack@eecs.umich.edu                //Zero out any flags we might modify. This way we only have to
6935076Sgblack@eecs.umich.edu                //worry about setting them.
6945040Sgblack@eecs.umich.edu                ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
6955076Sgblack@eecs.umich.edu                int CFBits = 0;
6965040Sgblack@eecs.umich.edu                //Figure out if we -would- set the CF bits if requested.
6974732Sgblack@eecs.umich.edu                if (shiftAmt <= dataSize * 8 &&
6984756Sgblack@eecs.umich.edu                        bits(SrcReg1, dataSize * 8 - shiftAmt)) {
6994732Sgblack@eecs.umich.edu                    CFBits = 1;
7004732Sgblack@eecs.umich.edu                }
7014823Sgblack@eecs.umich.edu                //If some combination of the CF bits need to be set, set them.
7024823Sgblack@eecs.umich.edu                if ((ext & (CFBit | ECFBit)) && CFBits)
7034732Sgblack@eecs.umich.edu                    ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
7044732Sgblack@eecs.umich.edu                //Figure out what the OF bit should be.
7054732Sgblack@eecs.umich.edu                if ((ext & OFBit) && (CFBits ^ bits(DestReg, dataSize * 8 - 1)))
7064732Sgblack@eecs.umich.edu                    ccFlagBits = ccFlagBits | OFBit;
7075040Sgblack@eecs.umich.edu                //Use the regular mechanisms to calculate the other flags.
7085076Sgblack@eecs.umich.edu                ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
7095076Sgblack@eecs.umich.edu                        DestReg, psrc1, op2);
7105076Sgblack@eecs.umich.edu            }
7115076Sgblack@eecs.umich.edu        '''
7125076Sgblack@eecs.umich.edu
7135076Sgblack@eecs.umich.edu    class Srl(RegOp):
7145076Sgblack@eecs.umich.edu        # Because what happens to the bits shift -in- on a right shift
7155076Sgblack@eecs.umich.edu        # is not defined in the C/C++ standard, we have to mask them out
7165076Sgblack@eecs.umich.edu        # to be sure they're zero.
7175076Sgblack@eecs.umich.edu        code = '''
7185076Sgblack@eecs.umich.edu            uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
7195076Sgblack@eecs.umich.edu            uint64_t logicalMask = mask(dataSize * 8 - shiftAmt);
7205076Sgblack@eecs.umich.edu            DestReg = merge(DestReg, (psrc1 >> shiftAmt) & logicalMask, dataSize);
7215076Sgblack@eecs.umich.edu            '''
7225076Sgblack@eecs.umich.edu        big_code = '''
7235076Sgblack@eecs.umich.edu            uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
7245076Sgblack@eecs.umich.edu            uint64_t logicalMask = mask(dataSize * 8 - shiftAmt);
7255076Sgblack@eecs.umich.edu            DestReg = (psrc1 >> shiftAmt) & logicalMask;
7265076Sgblack@eecs.umich.edu            '''
7275076Sgblack@eecs.umich.edu        flag_code = '''
7285040Sgblack@eecs.umich.edu            // If the shift amount is zero, no flags should be modified.
7295076Sgblack@eecs.umich.edu            if (shiftAmt) {
7305040Sgblack@eecs.umich.edu                //Zero out any flags we might modify. This way we only have to
7314733Sgblack@eecs.umich.edu                //worry about setting them.
7324756Sgblack@eecs.umich.edu                ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
7334733Sgblack@eecs.umich.edu                //If some combination of the CF bits need to be set, set them.
7344733Sgblack@eecs.umich.edu                if ((ext & (CFBit | ECFBit)) && 
7354733Sgblack@eecs.umich.edu                        shiftAmt <= dataSize * 8 &&
7365138Sgblack@eecs.umich.edu                        bits(SrcReg1, shiftAmt - 1)) {
7374733Sgblack@eecs.umich.edu                    ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
7384823Sgblack@eecs.umich.edu                }
7394823Sgblack@eecs.umich.edu                //Figure out what the OF bit should be.
7404733Sgblack@eecs.umich.edu                if ((ext & OFBit) && bits(SrcReg1, dataSize * 8 - 1))
7414733Sgblack@eecs.umich.edu                    ccFlagBits = ccFlagBits | OFBit;
7424733Sgblack@eecs.umich.edu                //Use the regular mechanisms to calculate the other flags.
7434733Sgblack@eecs.umich.edu                ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
7445040Sgblack@eecs.umich.edu                        DestReg, psrc1, op2);
7455076Sgblack@eecs.umich.edu            }
7465076Sgblack@eecs.umich.edu        '''
7475076Sgblack@eecs.umich.edu
7485076Sgblack@eecs.umich.edu    class Sra(RegOp):
7495076Sgblack@eecs.umich.edu        # Because what happens to the bits shift -in- on a right shift
7505076Sgblack@eecs.umich.edu        # is not defined in the C/C++ standard, we have to sign extend
7515076Sgblack@eecs.umich.edu        # them manually to be sure.
7525076Sgblack@eecs.umich.edu        code = '''
7535076Sgblack@eecs.umich.edu            uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
7545076Sgblack@eecs.umich.edu            uint64_t arithMask = (shiftAmt == 0) ? 0 :
7555076Sgblack@eecs.umich.edu                -bits(psrc1, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt);
7565076Sgblack@eecs.umich.edu            DestReg = merge(DestReg, (psrc1 >> shiftAmt) | arithMask, dataSize);
7575076Sgblack@eecs.umich.edu            '''
7585076Sgblack@eecs.umich.edu        big_code = '''
7595076Sgblack@eecs.umich.edu            uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
7605076Sgblack@eecs.umich.edu            uint64_t arithMask = (shiftAmt == 0) ? 0 :
7615076Sgblack@eecs.umich.edu                -bits(psrc1, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt);
7625076Sgblack@eecs.umich.edu            DestReg = ((psrc1 >> shiftAmt) | arithMask) & mask(dataSize * 8);
7635040Sgblack@eecs.umich.edu            '''
7645076Sgblack@eecs.umich.edu        flag_code = '''
7655040Sgblack@eecs.umich.edu            // If the shift amount is zero, no flags should be modified.
7664732Sgblack@eecs.umich.edu            if (shiftAmt) {
7674756Sgblack@eecs.umich.edu                //Zero out any flags we might modify. This way we only have to
7684732Sgblack@eecs.umich.edu                //worry about setting them.
7694732Sgblack@eecs.umich.edu                ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
7704823Sgblack@eecs.umich.edu                //If some combination of the CF bits need to be set, set them.
7714732Sgblack@eecs.umich.edu                uint8_t effectiveShift =
7724823Sgblack@eecs.umich.edu                    (shiftAmt <= dataSize * 8) ? shiftAmt : (dataSize * 8);
7734732Sgblack@eecs.umich.edu                if ((ext & (CFBit | ECFBit)) &&
7744732Sgblack@eecs.umich.edu                        bits(SrcReg1, effectiveShift - 1)) {
7754732Sgblack@eecs.umich.edu                    ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
7764732Sgblack@eecs.umich.edu                }
7775040Sgblack@eecs.umich.edu                //Use the regular mechanisms to calculate the other flags.
7785076Sgblack@eecs.umich.edu                ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
7795076Sgblack@eecs.umich.edu                        DestReg, psrc1, op2);
7805076Sgblack@eecs.umich.edu            }
7815076Sgblack@eecs.umich.edu        '''
7825076Sgblack@eecs.umich.edu
7835076Sgblack@eecs.umich.edu    class Ror(RegOp):
7845076Sgblack@eecs.umich.edu        code = '''
7855076Sgblack@eecs.umich.edu            uint8_t shiftAmt =
7865076Sgblack@eecs.umich.edu                (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
7875076Sgblack@eecs.umich.edu            uint8_t realShiftAmt = shiftAmt % (dataSize * 8);
7885076Sgblack@eecs.umich.edu            if (realShiftAmt) {
7895076Sgblack@eecs.umich.edu                uint64_t top = psrc1 << (dataSize * 8 - realShiftAmt);
7905076Sgblack@eecs.umich.edu                uint64_t bottom = bits(psrc1, dataSize * 8, realShiftAmt);
7915076Sgblack@eecs.umich.edu                DestReg = merge(DestReg, top | bottom, dataSize);
7925076Sgblack@eecs.umich.edu            } else
7935076Sgblack@eecs.umich.edu                DestReg = merge(DestReg, DestReg, dataSize);
7945076Sgblack@eecs.umich.edu            '''
7955076Sgblack@eecs.umich.edu        flag_code = '''
7965076Sgblack@eecs.umich.edu            // If the shift amount is zero, no flags should be modified.
7975076Sgblack@eecs.umich.edu            if (shiftAmt) {
7985040Sgblack@eecs.umich.edu                //Zero out any flags we might modify. This way we only have to
7995076Sgblack@eecs.umich.edu                //worry about setting them.
8005040Sgblack@eecs.umich.edu                ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
8014733Sgblack@eecs.umich.edu                //Find the most and second most significant bits of the result.
8024756Sgblack@eecs.umich.edu                int msb = bits(DestReg, dataSize * 8 - 1);
8034733Sgblack@eecs.umich.edu                int smsb = bits(DestReg, dataSize * 8 - 2);
8044733Sgblack@eecs.umich.edu                //If some combination of the CF bits need to be set, set them.
8054733Sgblack@eecs.umich.edu                if ((ext & (CFBit | ECFBit)) && msb)
8064823Sgblack@eecs.umich.edu                    ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
8075138Sgblack@eecs.umich.edu                //Figure out what the OF bit should be.
8084733Sgblack@eecs.umich.edu                if ((ext & OFBit) && (msb ^ smsb))
8094733Sgblack@eecs.umich.edu                    ccFlagBits = ccFlagBits | OFBit;
8104823Sgblack@eecs.umich.edu                //Use the regular mechanisms to calculate the other flags.
8114809Sgblack@eecs.umich.edu                ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
8124733Sgblack@eecs.umich.edu                        DestReg, psrc1, op2);
8134733Sgblack@eecs.umich.edu            }
8144733Sgblack@eecs.umich.edu        '''
8154733Sgblack@eecs.umich.edu
8165040Sgblack@eecs.umich.edu    class Rcr(RegOp):
8175076Sgblack@eecs.umich.edu        code = '''
8185076Sgblack@eecs.umich.edu            uint8_t shiftAmt =
8195076Sgblack@eecs.umich.edu                (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
8205076Sgblack@eecs.umich.edu            uint8_t realShiftAmt = shiftAmt % (dataSize * 8 + 1);
8215076Sgblack@eecs.umich.edu            if (realShiftAmt) {
8225076Sgblack@eecs.umich.edu                CCFlagBits flags = ccFlagBits;
8235076Sgblack@eecs.umich.edu                uint64_t top = flags.cf << (dataSize * 8 - realShiftAmt);
8245076Sgblack@eecs.umich.edu                if (realShiftAmt > 1)
8255076Sgblack@eecs.umich.edu                    top |= psrc1 << (dataSize * 8 - realShiftAmt + 1);
8265076Sgblack@eecs.umich.edu                uint64_t bottom = bits(psrc1, dataSize * 8 - 1, realShiftAmt);
8275076Sgblack@eecs.umich.edu                DestReg = merge(DestReg, top | bottom, dataSize);
8285076Sgblack@eecs.umich.edu            } else
8295076Sgblack@eecs.umich.edu                DestReg = merge(DestReg, DestReg, dataSize);
8305076Sgblack@eecs.umich.edu            '''
8315076Sgblack@eecs.umich.edu        flag_code = '''
8325076Sgblack@eecs.umich.edu            // If the shift amount is zero, no flags should be modified.
8335076Sgblack@eecs.umich.edu            if (shiftAmt) {
8345076Sgblack@eecs.umich.edu                int origCFBit = (ccFlagBits & CFBit) ? 1 : 0;
8355076Sgblack@eecs.umich.edu                //Zero out any flags we might modify. This way we only have to
8364732Sgblack@eecs.umich.edu                //worry about setting them.
8375040Sgblack@eecs.umich.edu                ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
8385246Sgblack@eecs.umich.edu                //Figure out what the OF bit should be.
8395040Sgblack@eecs.umich.edu                if ((ext & OFBit) && (origCFBit ^
8405040Sgblack@eecs.umich.edu                                      bits(SrcReg1, dataSize * 8 - 1))) {
8415040Sgblack@eecs.umich.edu                    ccFlagBits = ccFlagBits | OFBit;
8425040Sgblack@eecs.umich.edu                }
8435040Sgblack@eecs.umich.edu                //If some combination of the CF bits need to be set, set them.
8445040Sgblack@eecs.umich.edu                if ((ext & (CFBit | ECFBit)) &&
8455040Sgblack@eecs.umich.edu                        (realShiftAmt == 0) ? origCFBit :
8465040Sgblack@eecs.umich.edu                        bits(SrcReg1, realShiftAmt - 1)) {
8475040Sgblack@eecs.umich.edu                    ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
8485040Sgblack@eecs.umich.edu                }
8495246Sgblack@eecs.umich.edu                //Use the regular mechanisms to calculate the other flags.
8505040Sgblack@eecs.umich.edu                ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
8515040Sgblack@eecs.umich.edu                        DestReg, psrc1, op2);
8525040Sgblack@eecs.umich.edu            }
8535040Sgblack@eecs.umich.edu        '''
8545040Sgblack@eecs.umich.edu
8555040Sgblack@eecs.umich.edu    class Rol(RegOp):
8565116Sgblack@eecs.umich.edu        code = '''
8574951Sgblack@eecs.umich.edu            uint8_t shiftAmt =
8585011Sgblack@eecs.umich.edu                (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
8595011Sgblack@eecs.umich.edu            uint8_t realShiftAmt = shiftAmt % (dataSize * 8);
8605040Sgblack@eecs.umich.edu            if (realShiftAmt) {
8615040Sgblack@eecs.umich.edu                uint64_t top = psrc1 << realShiftAmt;
8625040Sgblack@eecs.umich.edu                uint64_t bottom =
8635040Sgblack@eecs.umich.edu                    bits(psrc1, dataSize * 8 - 1, dataSize * 8 - realShiftAmt);
8645040Sgblack@eecs.umich.edu                DestReg = merge(DestReg, top | bottom, dataSize);
8654732Sgblack@eecs.umich.edu            } else
8665040Sgblack@eecs.umich.edu                DestReg = merge(DestReg, DestReg, dataSize);
8675040Sgblack@eecs.umich.edu            '''
8684823Sgblack@eecs.umich.edu        flag_code = '''
8695239Sgblack@eecs.umich.edu            // If the shift amount is zero, no flags should be modified.
8705239Sgblack@eecs.umich.edu            if (shiftAmt) {
8715239Sgblack@eecs.umich.edu                //Zero out any flags we might modify. This way we only have to
8725239Sgblack@eecs.umich.edu                //worry about setting them.
8735007Sgblack@eecs.umich.edu                ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
8745007Sgblack@eecs.umich.edu                //The CF bits, if set, would be set to the lsb of the result.
8755040Sgblack@eecs.umich.edu                int lsb = DestReg & 0x1;
8765239Sgblack@eecs.umich.edu                int msb = bits(DestReg, dataSize * 8 - 1);
8775239Sgblack@eecs.umich.edu                //If some combination of the CF bits need to be set, set them.
8785239Sgblack@eecs.umich.edu                if ((ext & (CFBit | ECFBit)) && lsb)
8795239Sgblack@eecs.umich.edu                    ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
8805239Sgblack@eecs.umich.edu                //Figure out what the OF bit should be.
8815239Sgblack@eecs.umich.edu                if ((ext & OFBit) && (msb ^ lsb))
8825239Sgblack@eecs.umich.edu                    ccFlagBits = ccFlagBits | OFBit;
8835239Sgblack@eecs.umich.edu                //Use the regular mechanisms to calculate the other flags.
8844714Sgblack@eecs.umich.edu                ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
8855040Sgblack@eecs.umich.edu                        DestReg, psrc1, op2);
8865239Sgblack@eecs.umich.edu            }
8875241Sgblack@eecs.umich.edu        '''
8885296Sgblack@eecs.umich.edu
8895296Sgblack@eecs.umich.edu    class Rcl(RegOp):
8905296Sgblack@eecs.umich.edu        code = '''
8915296Sgblack@eecs.umich.edu            uint8_t shiftAmt =
8925296Sgblack@eecs.umich.edu                (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
8935296Sgblack@eecs.umich.edu            uint8_t realShiftAmt = shiftAmt % (dataSize * 8 + 1);
8945296Sgblack@eecs.umich.edu            if (realShiftAmt) {
8955296Sgblack@eecs.umich.edu                CCFlagBits flags = ccFlagBits;
8965296Sgblack@eecs.umich.edu                uint64_t top = psrc1 << realShiftAmt;
8975296Sgblack@eecs.umich.edu                uint64_t bottom = flags.cf << (realShiftAmt - 1);
8985296Sgblack@eecs.umich.edu                if(shiftAmt > 1)
8995296Sgblack@eecs.umich.edu                    bottom |=
9005241Sgblack@eecs.umich.edu                        bits(psrc1, dataSize * 8 - 1,
9015241Sgblack@eecs.umich.edu                                   dataSize * 8 - realShiftAmt + 1);
9025241Sgblack@eecs.umich.edu                DestReg = merge(DestReg, top | bottom, dataSize);
9035241Sgblack@eecs.umich.edu            } else
9045241Sgblack@eecs.umich.edu                DestReg = merge(DestReg, DestReg, dataSize);
9055241Sgblack@eecs.umich.edu            '''
9065241Sgblack@eecs.umich.edu        flag_code = '''
9075241Sgblack@eecs.umich.edu            // If the shift amount is zero, no flags should be modified.
9085241Sgblack@eecs.umich.edu            if (shiftAmt) {
9095241Sgblack@eecs.umich.edu                int origCFBit = (ccFlagBits & CFBit) ? 1 : 0;
9105241Sgblack@eecs.umich.edu                //Zero out any flags we might modify. This way we only have to
9115241Sgblack@eecs.umich.edu                //worry about setting them.
9125241Sgblack@eecs.umich.edu                ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
9135241Sgblack@eecs.umich.edu                int msb = bits(DestReg, dataSize * 8 - 1);
9145241Sgblack@eecs.umich.edu                int CFBits = bits(SrcReg1, dataSize * 8 - realShiftAmt);
9155241Sgblack@eecs.umich.edu                //If some combination of the CF bits need to be set, set them.
9165241Sgblack@eecs.umich.edu                if ((ext & (CFBit | ECFBit)) && 
9175241Sgblack@eecs.umich.edu                        (realShiftAmt == 0) ? origCFBit : CFBits)
9185241Sgblack@eecs.umich.edu                    ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
9195241Sgblack@eecs.umich.edu                //Figure out what the OF bit should be.
9205241Sgblack@eecs.umich.edu                if ((ext & OFBit) && (msb ^ CFBits))
9215241Sgblack@eecs.umich.edu                    ccFlagBits = ccFlagBits | OFBit;
9225241Sgblack@eecs.umich.edu                //Use the regular mechanisms to calculate the other flags.
9235241Sgblack@eecs.umich.edu                ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
9245241Sgblack@eecs.umich.edu                        DestReg, psrc1, op2);
9255241Sgblack@eecs.umich.edu            }
9265241Sgblack@eecs.umich.edu        '''
9275241Sgblack@eecs.umich.edu
9285241Sgblack@eecs.umich.edu    class Sld(RegOp):
9295241Sgblack@eecs.umich.edu        sldCode = '''
9305241Sgblack@eecs.umich.edu            uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
9315241Sgblack@eecs.umich.edu            uint8_t dataBits = dataSize * 8;
9325241Sgblack@eecs.umich.edu            uint8_t realShiftAmt = shiftAmt %% (2 * dataBits);
9335241Sgblack@eecs.umich.edu            uint64_t result;
9345241Sgblack@eecs.umich.edu            if (realShiftAmt == 0) {
9355241Sgblack@eecs.umich.edu                result = psrc1;
9365241Sgblack@eecs.umich.edu            } else if (realShiftAmt < dataBits) {
9375241Sgblack@eecs.umich.edu                result = (psrc1 << realShiftAmt) |
9385241Sgblack@eecs.umich.edu                         (DoubleBits >> (dataBits - realShiftAmt));
9395241Sgblack@eecs.umich.edu            } else {
9405241Sgblack@eecs.umich.edu                result = (DoubleBits << (realShiftAmt - dataBits)) |
9415241Sgblack@eecs.umich.edu                         (psrc1 >> (2 * dataBits - realShiftAmt));
9425241Sgblack@eecs.umich.edu            }
9435241Sgblack@eecs.umich.edu            %s
9445241Sgblack@eecs.umich.edu            '''
9455241Sgblack@eecs.umich.edu        code = sldCode % "DestReg = merge(DestReg, result, dataSize);"
9465241Sgblack@eecs.umich.edu        big_code = sldCode % "DestReg = result & mask(dataSize * 8);"
9475241Sgblack@eecs.umich.edu        flag_code = '''
9485241Sgblack@eecs.umich.edu            // If the shift amount is zero, no flags should be modified.
9495241Sgblack@eecs.umich.edu            if (shiftAmt) {
9505241Sgblack@eecs.umich.edu                //Zero out any flags we might modify. This way we only have to
9515290Sgblack@eecs.umich.edu                //worry about setting them.
9525294Sgblack@eecs.umich.edu                ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
9535294Sgblack@eecs.umich.edu                int CFBits = 0;
9545294Sgblack@eecs.umich.edu                //Figure out if we -would- set the CF bits if requested.
9555290Sgblack@eecs.umich.edu                if ((realShiftAmt == 0 &&
9565294Sgblack@eecs.umich.edu                        bits(DoubleBits, 0)) ||
9575290Sgblack@eecs.umich.edu                    (realShiftAmt <= dataBits &&
9585294Sgblack@eecs.umich.edu                     bits(SrcReg1, dataBits - realShiftAmt)) ||
9595294Sgblack@eecs.umich.edu                    (realShiftAmt > dataBits &&
9605290Sgblack@eecs.umich.edu                     bits(DoubleBits, 2 * dataBits - realShiftAmt))) {
9615294Sgblack@eecs.umich.edu                    CFBits = 1;
9625290Sgblack@eecs.umich.edu                }
9635290Sgblack@eecs.umich.edu                //If some combination of the CF bits need to be set, set them.
9645294Sgblack@eecs.umich.edu                if ((ext & (CFBit | ECFBit)) && CFBits)
9655290Sgblack@eecs.umich.edu                    ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
9665294Sgblack@eecs.umich.edu                //Figure out what the OF bit should be.
9675294Sgblack@eecs.umich.edu                if ((ext & OFBit) && (bits(SrcReg1, dataBits - 1) ^
9685294Sgblack@eecs.umich.edu                                      bits(result, dataBits - 1)))
9695294Sgblack@eecs.umich.edu                    ccFlagBits = ccFlagBits | OFBit;
9705294Sgblack@eecs.umich.edu                //Use the regular mechanisms to calculate the other flags.
9715294Sgblack@eecs.umich.edu                ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
9725294Sgblack@eecs.umich.edu                        DestReg, psrc1, op2);
9735294Sgblack@eecs.umich.edu            }
9745294Sgblack@eecs.umich.edu        '''
9755294Sgblack@eecs.umich.edu
9765294Sgblack@eecs.umich.edu    class Srd(RegOp):
9775294Sgblack@eecs.umich.edu        srdCode = '''
9785294Sgblack@eecs.umich.edu            uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
9795294Sgblack@eecs.umich.edu            uint8_t dataBits = dataSize * 8;
9805294Sgblack@eecs.umich.edu            uint8_t realShiftAmt = shiftAmt %% (2 * dataBits);
9815294Sgblack@eecs.umich.edu            uint64_t result;
9825294Sgblack@eecs.umich.edu            if (realShiftAmt == 0) {
9835294Sgblack@eecs.umich.edu                result = psrc1;
9845294Sgblack@eecs.umich.edu            } else if (realShiftAmt < dataBits) {
9855294Sgblack@eecs.umich.edu                // Because what happens to the bits shift -in- on a right
9865294Sgblack@eecs.umich.edu                // shift is not defined in the C/C++ standard, we have to
9875294Sgblack@eecs.umich.edu                // mask them out to be sure they're zero.
9885294Sgblack@eecs.umich.edu                uint64_t logicalMask = mask(dataBits - realShiftAmt);
9895294Sgblack@eecs.umich.edu                result = ((psrc1 >> realShiftAmt) & logicalMask) |
9905294Sgblack@eecs.umich.edu                         (DoubleBits << (dataBits - realShiftAmt));
9915424Sgblack@eecs.umich.edu            } else {
9925294Sgblack@eecs.umich.edu                uint64_t logicalMask = mask(2 * dataBits - realShiftAmt);
9935294Sgblack@eecs.umich.edu                result = ((DoubleBits >> (realShiftAmt - dataBits)) &
9945294Sgblack@eecs.umich.edu                          logicalMask) |
9955294Sgblack@eecs.umich.edu                         (psrc1 << (2 * dataBits - realShiftAmt));
9965294Sgblack@eecs.umich.edu            }
9975424Sgblack@eecs.umich.edu            %s
9985424Sgblack@eecs.umich.edu            '''
9995294Sgblack@eecs.umich.edu        code = srdCode % "DestReg = merge(DestReg, result, dataSize);"
10005294Sgblack@eecs.umich.edu        big_code = srdCode % "DestReg = result & mask(dataSize * 8);"
10015294Sgblack@eecs.umich.edu        flag_code = '''
10025294Sgblack@eecs.umich.edu            // If the shift amount is zero, no flags should be modified.
10035424Sgblack@eecs.umich.edu            if (shiftAmt) {
10045424Sgblack@eecs.umich.edu                //Zero out any flags we might modify. This way we only have to
10055294Sgblack@eecs.umich.edu                //worry about setting them.
10065294Sgblack@eecs.umich.edu                ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit));
10075294Sgblack@eecs.umich.edu                int CFBits = 0;
10085294Sgblack@eecs.umich.edu                //If some combination of the CF bits need to be set, set them.
10095294Sgblack@eecs.umich.edu                if ((realShiftAmt == 0 &&
10105294Sgblack@eecs.umich.edu                            bits(DoubleBits, dataBits - 1)) ||
10115294Sgblack@eecs.umich.edu                        (realShiftAmt <= dataBits &&
10125424Sgblack@eecs.umich.edu                         bits(SrcReg1, realShiftAmt - 1)) ||
10135294Sgblack@eecs.umich.edu                        (realShiftAmt > dataBits &&
10145294Sgblack@eecs.umich.edu                         bits(DoubleBits, realShiftAmt - dataBits - 1))) {
10155294Sgblack@eecs.umich.edu                    CFBits = 1;
10165294Sgblack@eecs.umich.edu                }
10175294Sgblack@eecs.umich.edu                //If some combination of the CF bits need to be set, set them.
10185294Sgblack@eecs.umich.edu                if ((ext & (CFBit | ECFBit)) && CFBits)
10195294Sgblack@eecs.umich.edu                    ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit));
10205294Sgblack@eecs.umich.edu                //Figure out what the OF bit should be.
10215409Sgblack@eecs.umich.edu                if ((ext & OFBit) && (bits(SrcReg1, dataBits - 1) ^
10225409Sgblack@eecs.umich.edu                                      bits(result, dataBits - 1)))
10235409Sgblack@eecs.umich.edu                    ccFlagBits = ccFlagBits | OFBit;
10245409Sgblack@eecs.umich.edu                //Use the regular mechanisms to calculate the other flags.
10255409Sgblack@eecs.umich.edu                ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit),
10265409Sgblack@eecs.umich.edu                        DestReg, psrc1, op2);
10275409Sgblack@eecs.umich.edu            }
10285409Sgblack@eecs.umich.edu        '''
10295409Sgblack@eecs.umich.edu
10305409Sgblack@eecs.umich.edu    class Mdb(WrRegOp):
10315294Sgblack@eecs.umich.edu        code = 'DoubleBits = psrc1 ^ op2;'
10325294Sgblack@eecs.umich.edu
10335294Sgblack@eecs.umich.edu    class Wrip(WrRegOp, CondRegOp):
10345294Sgblack@eecs.umich.edu        code = 'NRIP = psrc1 + sop2 + CSBase;'
10355294Sgblack@eecs.umich.edu        else_code = "NRIP = NRIP;"
10365294Sgblack@eecs.umich.edu
10375295Sgblack@eecs.umich.edu    class Wruflags(WrRegOp):
10385295Sgblack@eecs.umich.edu        code = 'ccFlagBits = psrc1 ^ op2'
10395295Sgblack@eecs.umich.edu
10405295Sgblack@eecs.umich.edu    class Wrflags(WrRegOp):
10415294Sgblack@eecs.umich.edu        code = '''
10425294Sgblack@eecs.umich.edu            MiscReg newFlags = psrc1 ^ op2;
10435295Sgblack@eecs.umich.edu            MiscReg userFlagMask = 0xDD5;
10445295Sgblack@eecs.umich.edu            // Get only the user flags
10455295Sgblack@eecs.umich.edu            ccFlagBits = newFlags & userFlagMask;
10465295Sgblack@eecs.umich.edu            // Get everything else
10475295Sgblack@eecs.umich.edu            nccFlagBits = newFlags & ~userFlagMask;
10485295Sgblack@eecs.umich.edu        '''
10495295Sgblack@eecs.umich.edu
10505295Sgblack@eecs.umich.edu    class Rdip(RdRegOp):
10515295Sgblack@eecs.umich.edu        code = 'DestReg = NRIP - CSBase;'
10525295Sgblack@eecs.umich.edu
10535295Sgblack@eecs.umich.edu    class Ruflags(RdRegOp):
10545295Sgblack@eecs.umich.edu        code = 'DestReg = ccFlagBits'
10555294Sgblack@eecs.umich.edu
10565294Sgblack@eecs.umich.edu    class Rflags(RdRegOp):
10575295Sgblack@eecs.umich.edu        code = 'DestReg = ccFlagBits | nccFlagBits'
10585295Sgblack@eecs.umich.edu
10595295Sgblack@eecs.umich.edu    class Ruflag(RegOp):
10605294Sgblack@eecs.umich.edu        code = '''
10615290Sgblack@eecs.umich.edu            int flag = bits(ccFlagBits, imm8);
10624519Sgblack@eecs.umich.edu            DestReg = merge(DestReg, flag, dataSize);
1063            ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) :
1064                                       (ccFlagBits & ~EZFBit);
1065            '''
1066        big_code = '''
1067            int flag = bits(ccFlagBits, imm8);
1068            DestReg = flag & mask(dataSize * 8);
1069            ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) :
1070                                       (ccFlagBits & ~EZFBit);
1071            '''
1072        def __init__(self, dest, imm, flags=None, \
1073                dataSize="env.dataSize"):
1074            super(Ruflag, self).__init__(dest, \
1075                    "InstRegIndex(NUM_INTREGS)", imm, flags, dataSize)
1076
1077    class Rflag(RegOp):
1078        code = '''
1079            MiscReg flagMask = 0x3F7FDD5;
1080            MiscReg flags = (nccFlagBits | ccFlagBits) & flagMask;
1081            int flag = bits(flags, imm8);
1082            DestReg = merge(DestReg, flag, dataSize);
1083            ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) :
1084                                       (ccFlagBits & ~EZFBit);
1085            '''
1086        big_code = '''
1087            MiscReg flagMask = 0x3F7FDD5;
1088            MiscReg flags = (nccFlagBits | ccFlagBits) & flagMask;
1089            int flag = bits(flags, imm8);
1090            DestReg = flag & mask(dataSize * 8);
1091            ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) :
1092                                       (ccFlagBits & ~EZFBit);
1093            '''
1094        def __init__(self, dest, imm, flags=None, \
1095                dataSize="env.dataSize"):
1096            super(Rflag, self).__init__(dest, \
1097                    "InstRegIndex(NUM_INTREGS)", imm, flags, dataSize)
1098
1099    class Sext(RegOp):
1100        code = '''
1101            IntReg val = psrc1;
1102            // Mask the bit position so that it wraps.
1103            int bitPos = op2 & (dataSize * 8 - 1);
1104            int sign_bit = bits(val, bitPos, bitPos);
1105            uint64_t maskVal = mask(bitPos+1);
1106            val = sign_bit ? (val | ~maskVal) : (val & maskVal);
1107            DestReg = merge(DestReg, val, dataSize);
1108            '''
1109        big_code = '''
1110            IntReg val = psrc1;
1111            // Mask the bit position so that it wraps.
1112            int bitPos = op2 & (dataSize * 8 - 1);
1113            int sign_bit = bits(val, bitPos, bitPos);
1114            uint64_t maskVal = mask(bitPos+1);
1115            val = sign_bit ? (val | ~maskVal) : (val & maskVal);
1116            DestReg = val & mask(dataSize * 8);
1117            '''
1118        flag_code = '''
1119            if (!sign_bit)
1120                ccFlagBits = ccFlagBits &
1121                    ~(ext & (CFBit | ECFBit | ZFBit | EZFBit));
1122            else
1123                ccFlagBits = ccFlagBits |
1124                    (ext & (CFBit | ECFBit | ZFBit | EZFBit));
1125            '''
1126
1127    class Zext(RegOp):
1128        code = 'DestReg = merge(DestReg, bits(psrc1, op2, 0), dataSize);'
1129        big_code = 'DestReg = bits(psrc1, op2, 0) & mask(dataSize * 8);'
1130
1131    class Rddr(RegOp):
1132        def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1133            super(Rddr, self).__init__(dest, \
1134                    src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1135        rdrCode = '''
1136            CR4 cr4 = CR4Op;
1137            DR7 dr7 = DR7Op;
1138            if ((cr4.de == 1 && (src1 == 4 || src1 == 5)) || src1 >= 8) {
1139                fault = new InvalidOpcode();
1140            } else if (dr7.gd) {
1141                fault = new DebugException();
1142            } else {
1143                %s
1144            }
1145        '''
1146        code = rdrCode % "DestReg = merge(DestReg, DebugSrc1, dataSize);"
1147        big_code = rdrCode % "DestReg = DebugSrc1 & mask(dataSize * 8);"
1148
1149    class Wrdr(RegOp):
1150        def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1151            super(Wrdr, self).__init__(dest, \
1152                    src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1153        code = '''
1154            CR4 cr4 = CR4Op;
1155            DR7 dr7 = DR7Op;
1156            if ((cr4.de == 1 && (dest == 4 || dest == 5)) || dest >= 8) {
1157                fault = new InvalidOpcode();
1158            } else if ((dest == 6 || dest == 7) && bits(psrc1, 63, 32) &&
1159                    machInst.mode.mode == LongMode) {
1160                fault = new GeneralProtection(0);
1161            } else if (dr7.gd) {
1162                fault = new DebugException();
1163            } else {
1164                DebugDest = psrc1;
1165            }
1166        '''
1167
1168    class Rdcr(RegOp):
1169        def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1170            super(Rdcr, self).__init__(dest, \
1171                    src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1172        rdcrCode = '''
1173            if (src1 == 1 || (src1 > 4 && src1 < 8) || (src1 > 8)) {
1174                fault = new InvalidOpcode();
1175            } else {
1176                %s
1177            }
1178        '''
1179        code = rdcrCode % "DestReg = merge(DestReg, ControlSrc1, dataSize);"
1180        big_code = rdcrCode % "DestReg = ControlSrc1 & mask(dataSize * 8);"
1181
1182    class Wrcr(RegOp):
1183        def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1184            super(Wrcr, self).__init__(dest, \
1185                    src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1186        code = '''
1187            if (dest == 1 || (dest > 4 && dest < 8) || (dest > 8)) {
1188                fault = new InvalidOpcode();
1189            } else {
1190                // There are *s in the line below so it doesn't confuse the
1191                // parser. They may be unnecessary.
1192                //Mis*cReg old*Val = pick(Cont*rolDest, 0, dat*aSize);
1193                MiscReg newVal = psrc1;
1194
1195                // Check for any modifications that would cause a fault.
1196                switch(dest) {
1197                  case 0:
1198                    {
1199                        Efer efer = EferOp;
1200                        CR0 cr0 = newVal;
1201                        CR4 oldCr4 = CR4Op;
1202                        if (bits(newVal, 63, 32) ||
1203                                (!cr0.pe && cr0.pg) ||
1204                                (!cr0.cd && cr0.nw) ||
1205                                (cr0.pg && efer.lme && !oldCr4.pae))
1206                            fault = new GeneralProtection(0);
1207                    }
1208                    break;
1209                  case 2:
1210                    break;
1211                  case 3:
1212                    break;
1213                  case 4:
1214                    {
1215                        CR4 cr4 = newVal;
1216                        // PAE can't be disabled in long mode.
1217                        if (bits(newVal, 63, 11) ||
1218                                (machInst.mode.mode == LongMode && !cr4.pae))
1219                            fault = new GeneralProtection(0);
1220                    }
1221                    break;
1222                  case 8:
1223                    {
1224                        if (bits(newVal, 63, 4))
1225                            fault = new GeneralProtection(0);
1226                    }
1227                  default:
1228                    fault = new GenericISA::M5PanicFault(
1229                            "Unrecognized control register %d.\\n", dest);
1230                }
1231                ControlDest = newVal;
1232            }
1233            '''
1234
1235    # Microops for manipulating segmentation registers
1236    class SegOp(CondRegOp):
1237        abstract = True
1238        def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1239            super(SegOp, self).__init__(dest, \
1240                    src1, "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1241
1242    class Wrbase(SegOp):
1243        code = '''
1244            SegBaseDest = psrc1;
1245        '''
1246
1247    class Wrlimit(SegOp):
1248        code = '''
1249            SegLimitDest = psrc1;
1250        '''
1251
1252    class Wrsel(SegOp):
1253        code = '''
1254            SegSelDest = psrc1;
1255        '''
1256
1257    class WrAttr(SegOp):
1258        code = '''
1259            SegAttrDest = psrc1;
1260        '''
1261
1262    class Rdbase(SegOp):
1263        code = 'DestReg = merge(DestReg, SegBaseSrc1, dataSize);'
1264        big_code = 'DestReg = SegBaseSrc1 & mask(dataSize * 8);'
1265
1266    class Rdlimit(SegOp):
1267        code = 'DestReg = merge(DestReg, SegLimitSrc1, dataSize);'
1268        big_code = 'DestReg = SegLimitSrc1 & mask(dataSize * 8);'
1269
1270    class RdAttr(SegOp):
1271        code = 'DestReg = merge(DestReg, SegAttrSrc1, dataSize);'
1272        big_code = 'DestReg = SegAttrSrc1 & mask(dataSize * 8);'
1273
1274    class Rdsel(SegOp):
1275        code = 'DestReg = merge(DestReg, SegSelSrc1, dataSize);'
1276        big_code = 'DestReg = SegSelSrc1 & mask(dataSize * 8);'
1277
1278    class Rdval(RegOp):
1279        def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1280            super(Rdval, self).__init__(dest, src1, \
1281                    "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1282        code = '''
1283            DestReg = MiscRegSrc1;
1284        '''
1285
1286    class Wrval(RegOp):
1287        def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
1288            super(Wrval, self).__init__(dest, src1, \
1289                    "InstRegIndex(NUM_INTREGS)", flags, dataSize)
1290        code = '''
1291            MiscRegDest = SrcReg1;
1292        '''
1293
1294    class Chks(RegOp):
1295        def __init__(self, dest, src1, src2=0,
1296                flags=None, dataSize="env.dataSize"):
1297            super(Chks, self).__init__(dest,
1298                    src1, src2, flags, dataSize)
1299        code = '''
1300            // The selector is in source 1 and can be at most 16 bits.
1301            SegSelector selector = DestReg;
1302            SegDescriptor desc = SrcReg1;
1303            HandyM5Reg m5reg = M5Reg;
1304
1305            switch (imm8)
1306            {
1307              case SegNoCheck:
1308                break;
1309              case SegCSCheck:
1310                // Make sure it's the right type
1311                if (desc.s == 0 || desc.type.codeOrData != 1) {
1312                    fault = new GeneralProtection(0);
1313                } else if (m5reg.cpl != desc.dpl) {
1314                    fault = new GeneralProtection(0);
1315                }
1316                break;
1317              case SegCallGateCheck:
1318                fault = new GenericISA::M5PanicFault("CS checks for far "
1319                        "calls/jumps through call gates not implemented.\\n");
1320                break;
1321              case SegSoftIntGateCheck:
1322                // Check permissions.
1323                if (desc.dpl < m5reg.cpl) {
1324                    fault = new GeneralProtection(selector);
1325                    break;
1326                }
1327                // Fall through on purpose
1328              case SegIntGateCheck:
1329                // Make sure the gate's the right type.
1330                if ((m5reg.mode == LongMode && (desc.type & 0xe) != 0xe) ||
1331                        ((desc.type & 0x6) != 0x6)) {
1332                    fault = new GeneralProtection(0);
1333                }
1334                break;
1335              case SegSSCheck:
1336                if (selector.si || selector.ti) {
1337                    if (!desc.p) {
1338                        fault = new StackFault(selector);
1339                    } else if (!(desc.s == 1 && desc.type.codeOrData == 0 &&
1340                                desc.type.w) ||
1341                            (desc.dpl != m5reg.cpl) ||
1342                            (selector.rpl != m5reg.cpl)) {
1343                        fault = new GeneralProtection(selector);
1344                    }
1345                } else if (m5reg.submode != SixtyFourBitMode ||
1346                        m5reg.cpl == 3) {
1347                    fault = new GeneralProtection(selector);
1348                }
1349                break;
1350              case SegIretCheck:
1351                {
1352                    if ((!selector.si && !selector.ti) ||
1353                            (selector.rpl < m5reg.cpl) ||
1354                            !(desc.s == 1 && desc.type.codeOrData == 1) ||
1355                            (!desc.type.c && desc.dpl != selector.rpl) ||
1356                            (desc.type.c && desc.dpl > selector.rpl)) {
1357                        fault = new GeneralProtection(selector);
1358                    } else if (!desc.p) {
1359                        fault = new SegmentNotPresent(selector);
1360                    }
1361                    break;
1362                }
1363              case SegIntCSCheck:
1364                if (m5reg.mode == LongMode) {
1365                    if (desc.l != 1 || desc.d != 0) {
1366                        fault = new GeneralProtection(selector);
1367                    }
1368                } else {
1369                    fault = new GenericISA::M5PanicFault("Interrupt CS "
1370                            "checks not implemented in legacy mode.\\n");
1371                }
1372                break;
1373              case SegTRCheck:
1374                if (!selector.si || selector.ti) {
1375                    fault = new GeneralProtection(selector);
1376                }
1377                break;
1378              case SegTSSCheck:
1379                if (!desc.p) {
1380                    fault = new SegmentNotPresent(selector);
1381                } else if (!(desc.type == 0x9 ||
1382                        (desc.type == 1 &&
1383                         m5reg.mode != LongMode))) {
1384                    fault = new GeneralProtection(selector);
1385                }
1386                break;
1387              case SegInGDTCheck:
1388                if (selector.ti) {
1389                    fault = new GeneralProtection(selector);
1390                }
1391                break;
1392              case SegLDTCheck:
1393                if (!desc.p) {
1394                    fault = new SegmentNotPresent(selector);
1395                } else if (desc.type != 0x2) {
1396                    fault = new GeneralProtection(selector);
1397                }
1398                break;
1399              default:
1400                fault = new GenericISA::M5PanicFault(
1401                        "Undefined segment check type.\\n");
1402            }
1403        '''
1404        flag_code = '''
1405            // Check for a NULL selector and set ZF,EZF appropriately.
1406            ccFlagBits = ccFlagBits & ~(ext & (ZFBit | EZFBit));
1407            if (!selector.si && !selector.ti)
1408                ccFlagBits = ccFlagBits | (ext & (ZFBit | EZFBit));
1409        '''
1410
1411    class Wrdh(RegOp):
1412        code = '''
1413            SegDescriptor desc = SrcReg1;
1414
1415            uint64_t target = bits(SrcReg2, 31, 0) << 32;
1416            switch(desc.type) {
1417              case LDT64:
1418              case AvailableTSS64:
1419              case BusyTSS64:
1420                replaceBits(target, 23, 0, desc.baseLow);
1421                replaceBits(target, 31, 24, desc.baseHigh);
1422                break;
1423              case CallGate64:
1424              case IntGate64:
1425              case TrapGate64:
1426                replaceBits(target, 15, 0, bits(desc, 15, 0));
1427                replaceBits(target, 31, 16, bits(desc, 63, 48));
1428                break;
1429              default:
1430                fault = new GenericISA::M5PanicFault(
1431                        "Wrdh used with wrong descriptor type!\\n");
1432            }
1433            DestReg = target;
1434        '''
1435
1436    class Wrtsc(WrRegOp):
1437        code = '''
1438            TscOp = psrc1;
1439        '''
1440
1441    class Rdtsc(RdRegOp):
1442        code = '''
1443            DestReg = TscOp;
1444        '''
1445
1446    class Rdm5reg(RdRegOp):
1447        code = '''
1448            DestReg = M5Reg;
1449        '''
1450
1451    class Wrdl(RegOp):
1452        code = '''
1453            SegDescriptor desc = SrcReg1;
1454            SegSelector selector = SrcReg2;
1455            // This while loop is so we can use break statements in the code
1456            // below to skip the rest of this section without a bunch of
1457            // nesting.
1458            while (true) {
1459                if (selector.si || selector.ti) {
1460                    if (!desc.p) {
1461                        fault = new GenericISA::M5PanicFault(
1462                                "Segment not present.\\n");
1463                        break;
1464                    }
1465                    SegAttr attr = 0;
1466                    attr.dpl = desc.dpl;
1467                    attr.unusable = 0;
1468                    attr.defaultSize = desc.d;
1469                    attr.longMode = desc.l;
1470                    attr.avl = desc.avl;
1471                    attr.granularity = desc.g;
1472                    attr.present = desc.p;
1473                    attr.system = desc.s;
1474                    attr.type = desc.type;
1475                    if (!desc.s) {
1476                        // The expand down bit happens to be set for gates.
1477                        if (desc.type.e) {
1478                            fault = new GenericISA::M5PanicFault(
1479                                    "Gate descriptor encountered.\\n");
1480                            break;
1481                        }
1482                        attr.readable = 1;
1483                        attr.writable = 1;
1484                        attr.expandDown = 0;
1485                    } else {
1486                        if (desc.type.codeOrData) {
1487                            attr.expandDown = 0;
1488                            attr.readable = desc.type.r;
1489                            attr.writable = 0;
1490                        } else {
1491                            attr.expandDown = desc.type.e;
1492                            attr.readable = 1;
1493                            attr.writable = desc.type.w;
1494                        }
1495                    }
1496                    Addr base = desc.baseLow | (desc.baseHigh << 24);
1497                    Addr limit = desc.limitLow | (desc.limitHigh << 16);
1498                    if (desc.g)
1499                        limit = (limit << 12) | mask(12);
1500                    SegBaseDest = base;
1501                    SegLimitDest = limit;
1502                    SegAttrDest = attr;
1503                } else {
1504                    SegBaseDest = SegBaseDest;
1505                    SegLimitDest = SegLimitDest;
1506                    SegAttrDest = SegAttrDest;
1507                }
1508                break;
1509            }
1510        '''
1511}};
1512