macroop.isa revision 12236:126ac9da6050
15323Sgblack@eecs.umich.edu// -*- mode:c++ -*-
22934Sktlim@umich.edu
32934Sktlim@umich.edu// Copyright (c) 2007 The Hewlett-Packard Development Company
42934Sktlim@umich.edu// All rights reserved.
52934Sktlim@umich.edu//
62934Sktlim@umich.edu// The license below extends only to copyright in the software and shall
72934Sktlim@umich.edu// not be construed as granting a license to any other intellectual
82934Sktlim@umich.edu// property including but not limited to intellectual property relating
92934Sktlim@umich.edu// to a hardware implementation of the functionality of the software
102934Sktlim@umich.edu// licensed hereunder.  You may use the software subject to the license
112934Sktlim@umich.edu// terms below provided that you ensure that this notice is replicated
122934Sktlim@umich.edu// unmodified and in its entirety in all distributions of the software,
132934Sktlim@umich.edu// modified or unmodified, in source code or in binary form.
142934Sktlim@umich.edu//
152934Sktlim@umich.edu// Redistribution and use in source and binary forms, with or without
162934Sktlim@umich.edu// modification, are permitted provided that the following conditions are
172934Sktlim@umich.edu// met: redistributions of source code must retain the above copyright
182934Sktlim@umich.edu// notice, this list of conditions and the following disclaimer;
192934Sktlim@umich.edu// redistributions in binary form must reproduce the above copyright
202934Sktlim@umich.edu// notice, this list of conditions and the following disclaimer in the
212934Sktlim@umich.edu// documentation and/or other materials provided with the distribution;
222934Sktlim@umich.edu// neither the name of the copyright holders nor the names of its
232934Sktlim@umich.edu// contributors may be used to endorse or promote products derived from
242934Sktlim@umich.edu// this software without specific prior written permission.
252934Sktlim@umich.edu//
262934Sktlim@umich.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
272934Sktlim@umich.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
282934Sktlim@umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
292934Sktlim@umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
302969Sktlim@umich.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
312934Sktlim@umich.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
322995Ssaidi@eecs.umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
332934Sktlim@umich.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
342934Sktlim@umich.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
352934Sktlim@umich.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
362934Sktlim@umich.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
372934Sktlim@umich.edu//
382934Sktlim@umich.edu// Authors: Gabe Black
392934Sktlim@umich.edu
402934Sktlim@umich.edu//////////////////////////////////////////////////////////////////////////////
414520Ssaidi@eecs.umich.edu//
424520Ssaidi@eecs.umich.edu//  Architecture independent
434982Ssaidi@eecs.umich.edu//
444520Ssaidi@eecs.umich.edu
454520Ssaidi@eecs.umich.edu// Execute method for macroops.
462934Sktlim@umich.edudef template MacroExecPanic {{
472934Sktlim@umich.edu        Fault execute(ExecContext *, Trace::InstRecord *) const
483005Sstever@eecs.umich.edu        {
493005Sstever@eecs.umich.edu            panic("Tried to execute macroop directly!");
503304Sstever@eecs.umich.edu            return NoFault;
512995Ssaidi@eecs.umich.edu        }
522934Sktlim@umich.edu}};
532934Sktlim@umich.edu
544965Ssaidi@eecs.umich.eduoutput header {{
555266Sksewell@umich.edu
562934Sktlim@umich.edu        // Base class for combinationally generated macroops
572934Sktlim@umich.edu        class Macroop : public X86ISA::MacroopBase
582934Sktlim@umich.edu        {
592934Sktlim@umich.edu          public:
602934Sktlim@umich.edu            Macroop(const char *mnem, ExtMachInst _machInst,
612995Ssaidi@eecs.umich.edu                    uint32_t _numMicroops, X86ISA::EmulEnv _env)
622934Sktlim@umich.edu                        : MacroopBase(mnem, _machInst, _numMicroops, _env)
632934Sktlim@umich.edu            {}
642934Sktlim@umich.edu
652934Sktlim@umich.edu            Fault
662934Sktlim@umich.edu            execute(ExecContext *, Trace::InstRecord *) const
672995Ssaidi@eecs.umich.edu            {
682934Sktlim@umich.edu                panic("Tried to execute macroop directly!");
692934Sktlim@umich.edu            }
702953Sktlim@umich.edu        };
715478Snate@binkert.org}};
722934Sktlim@umich.edu
733449Shsul@eecs.umich.edu//////////////////////////////////////////////////////////////////////////////
742934Sktlim@umich.edu//
752934Sktlim@umich.edu//  X86 specific
762934Sktlim@umich.edu//
772934Sktlim@umich.edu//////////////////////////////////////////////////////////////////////////////
782934Sktlim@umich.edu
793584Ssaidi@eecs.umich.edu// Basic instruction class declaration template.
804486Sbinkertn@umich.edudef template MacroDeclare {{
814486Sbinkertn@umich.edu        namespace X86Macroop
824486Sbinkertn@umich.edu        {
834486Sbinkertn@umich.edu            /**
844486Sbinkertn@umich.edu             * Static instruction class for "%(mnemonic)s".
854486Sbinkertn@umich.edu             */
864486Sbinkertn@umich.edu            class %(class_name)s : public %(base_class)s
873584Ssaidi@eecs.umich.edu            {
883584Ssaidi@eecs.umich.edu              private:
893584Ssaidi@eecs.umich.edu                %(declareLabels)s
903584Ssaidi@eecs.umich.edu              public:
913584Ssaidi@eecs.umich.edu                // Constructor.
923743Sgblack@eecs.umich.edu                %(class_name)s(ExtMachInst machInst, X86ISA::EmulEnv _env);
933584Ssaidi@eecs.umich.edu
944972Ssaidi@eecs.umich.edu                std::string
953743Sgblack@eecs.umich.edu                generateDisassembly(Addr pc, const SymbolTable *symtab) const;
964104Ssaidi@eecs.umich.edu            };
973743Sgblack@eecs.umich.edu        }
983823Ssaidi@eecs.umich.edu}};
993814Ssaidi@eecs.umich.edu
1003743Sgblack@eecs.umich.edudef template MacroDisassembly {{
1013743Sgblack@eecs.umich.edu    std::string
1023584Ssaidi@eecs.umich.edu    X86Macroop::%(class_name)s::generateDisassembly(Addr pc,
1033814Ssaidi@eecs.umich.edu            const SymbolTable *symtab) const
1043584Ssaidi@eecs.umich.edu    {
1053745Sgblack@eecs.umich.edu        std::stringstream out;
1063745Sgblack@eecs.umich.edu        out << mnemonic << "\t";
1073745Sgblack@eecs.umich.edu
1083584Ssaidi@eecs.umich.edu        int regSize = %(regSize)s;
1093898Ssaidi@eecs.umich.edu        %(disassembly)s
1103898Ssaidi@eecs.umich.edu        // Shut up gcc.
1113898Ssaidi@eecs.umich.edu        regSize = regSize;
1124103Ssaidi@eecs.umich.edu        return out.str();
1134103Ssaidi@eecs.umich.edu    }
1144103Ssaidi@eecs.umich.edu}};
1153745Sgblack@eecs.umich.edu
1163745Sgblack@eecs.umich.edu// Basic instruction class constructor template.
1173745Sgblack@eecs.umich.edudef template MacroConstructor {{
1183584Ssaidi@eecs.umich.edu        X86Macroop::%(class_name)s::%(class_name)s(
1193584Ssaidi@eecs.umich.edu                ExtMachInst machInst, EmulEnv _env)
1203584Ssaidi@eecs.umich.edu            : %(base_class)s("%(mnemonic)s", machInst, %(num_microops)s, _env)
1215222Sksewell@umich.edu        {
1225222Sksewell@umich.edu            %(adjust_env)s;
1235222Sksewell@umich.edu            %(adjust_imm)s;
1245222Sksewell@umich.edu            %(adjust_disp)s;
1255222Sksewell@umich.edu            %(init_env)s;
1265222Sksewell@umich.edu            %(constructor)s;
1275222Sksewell@umich.edu            const char *macrocodeBlock = "%(class_name)s";
1285222Sksewell@umich.edu            //alloc_microops is the code that sets up the microops
1295222Sksewell@umich.edu            //array in the parent class.
1305222Sksewell@umich.edu            %(alloc_microops)s;
1315222Sksewell@umich.edu        }
1325222Sksewell@umich.edu}};
1335222Sksewell@umich.edu
1345222Sksewell@umich.edulet {{
1355222Sksewell@umich.edu    from micro_asm import Combinational_Macroop, Rom_Macroop
1365222Sksewell@umich.edu    class X86Macroop(Combinational_Macroop):
1375222Sksewell@umich.edu        def add_microop(self, mnemonic, microop):
1385222Sksewell@umich.edu            microop.mnemonic = mnemonic
1395222Sksewell@umich.edu            microop.micropc = len(self.microops)
1405222Sksewell@umich.edu            self.microops.append(microop)
1415222Sksewell@umich.edu        def setAdjustEnv(self, val):
1425222Sksewell@umich.edu            self.adjust_env = val
1435222Sksewell@umich.edu        def adjustImm(self, val):
1445222Sksewell@umich.edu            self.adjust_imm += val
1455222Sksewell@umich.edu        def adjustDisp(self, val):
1465222Sksewell@umich.edu            self.adjust_disp += val
1475222Sksewell@umich.edu        def serializing(self):
1485222Sksewell@umich.edu            self.serializing = True
1495222Sksewell@umich.edu
1505222Sksewell@umich.edu        def function_call(self):
1515478Snate@binkert.org            self.function_call = True
1525222Sksewell@umich.edu        def function_return(self):
1535222Sksewell@umich.edu            self.function_return = True
1545222Sksewell@umich.edu
1555222Sksewell@umich.edu        def __init__(self, name):
1565222Sksewell@umich.edu            super(X86Macroop, self).__init__(name)
1575222Sksewell@umich.edu            self.directives = {
1585323Sgblack@eecs.umich.edu                "adjust_env" : self.setAdjustEnv,
1595357Sgblack@eecs.umich.edu                "adjust_imm" : self.adjustImm,
1605323Sgblack@eecs.umich.edu                "adjust_disp" : self.adjustDisp,
1615323Sgblack@eecs.umich.edu                "serializing" : self.serializing,
1625613Sgblack@eecs.umich.edu                "function_call" : self.function_call,
1635613Sgblack@eecs.umich.edu                "function_return" : self.function_return
1645613Sgblack@eecs.umich.edu            }
1655613Sgblack@eecs.umich.edu            self.declared = False
1665133Sgblack@eecs.umich.edu            self.adjust_env = ""
1675133Sgblack@eecs.umich.edu            self.init_env = ""
1685133Sgblack@eecs.umich.edu            self.adjust_imm = '''
1695133Sgblack@eecs.umich.edu                uint64_t adjustedImm = IMMEDIATE;
1705133Sgblack@eecs.umich.edu                //This is to pacify gcc in case the immediate isn't used.
1715133Sgblack@eecs.umich.edu                adjustedImm = adjustedImm;
1725323Sgblack@eecs.umich.edu            '''
1735450Sgblack@eecs.umich.edu            self.adjust_disp = '''
1745133Sgblack@eecs.umich.edu                uint64_t adjustedDisp = DISPLACEMENT;
1755133Sgblack@eecs.umich.edu                //This is to pacify gcc in case the displacement isn't used.
1765613Sgblack@eecs.umich.edu                adjustedDisp = adjustedDisp;
1775613Sgblack@eecs.umich.edu            '''
1785613Sgblack@eecs.umich.edu            self.serializing = False
1795613Sgblack@eecs.umich.edu            self.function_call = False
1805613Sgblack@eecs.umich.edu            self.function_return = False
1815613Sgblack@eecs.umich.edu
1825613Sgblack@eecs.umich.edu        def getAllocator(self, env):
1835638Sgblack@eecs.umich.edu            return "new X86Macroop::%s(machInst, %s)" % \
1845613Sgblack@eecs.umich.edu                    (self.name, env.getAllocator())
1855613Sgblack@eecs.umich.edu        def getMnemonic(self):
1865613Sgblack@eecs.umich.edu            mnemonic = self.name.lower()
1875613Sgblack@eecs.umich.edu            mnemonic = re.match(r'[^_]*', mnemonic).group(0)
1885615Sgblack@eecs.umich.edu            return mnemonic
1895615Sgblack@eecs.umich.edu        def getDeclaration(self):
1905615Sgblack@eecs.umich.edu            #FIXME This first parameter should be the mnemonic. I need to
1915615Sgblack@eecs.umich.edu            #write some code which pulls that out
1925641Sgblack@eecs.umich.edu            declareLabels = ""
1935641Sgblack@eecs.umich.edu            for (label, microop) in self.labels.items():
1945641Sgblack@eecs.umich.edu                declareLabels += "const static uint64_t label_%s = %d;\n" \
1955641Sgblack@eecs.umich.edu                                  % (label, microop.micropc)
1965641Sgblack@eecs.umich.edu            iop = InstObjParams(self.getMnemonic(), self.name, "Macroop",
1975641Sgblack@eecs.umich.edu                    {"code" : "",
1985641Sgblack@eecs.umich.edu                     "declareLabels" : declareLabels
1995641Sgblack@eecs.umich.edu                    })
2005613Sgblack@eecs.umich.edu            return MacroDeclare.subst(iop);
2015613Sgblack@eecs.umich.edu        def getDefinition(self, env):
2025613Sgblack@eecs.umich.edu            #FIXME This first parameter should be the mnemonic. I need to
2035613Sgblack@eecs.umich.edu            #write some code which pulls that out
2045613Sgblack@eecs.umich.edu            numMicroops = len(self.microops)
2055613Sgblack@eecs.umich.edu            allocMicroops = ''
2065613Sgblack@eecs.umich.edu            micropc = 0
2075450Sgblack@eecs.umich.edu            for op in self.microops:
2085450Sgblack@eecs.umich.edu                flags = ["IsMicroop"]
2095450Sgblack@eecs.umich.edu                if micropc == numMicroops - 1:
2105450Sgblack@eecs.umich.edu                    flags.append("IsLastMicroop")
2115450Sgblack@eecs.umich.edu
2125450Sgblack@eecs.umich.edu                    if self.serializing:
2135450Sgblack@eecs.umich.edu                        flags.append("IsSerializing")
2145450Sgblack@eecs.umich.edu                        flags.append("IsSerializeAfter")
2155450Sgblack@eecs.umich.edu
2165450Sgblack@eecs.umich.edu                    if self.function_call:
2175450Sgblack@eecs.umich.edu                        flags.append("IsCall")
2185450Sgblack@eecs.umich.edu                    if self.function_return:
2195450Sgblack@eecs.umich.edu                        flags.append("IsReturn")
2205450Sgblack@eecs.umich.edu                else:
2215450Sgblack@eecs.umich.edu                    flags.append("IsDelayedCommit")
2225450Sgblack@eecs.umich.edu                if micropc == 0:
2235330Sgblack@eecs.umich.edu                    flags.append("IsFirstMicroop")
2245416Sgblack@eecs.umich.edu                allocMicroops += \
2255330Sgblack@eecs.umich.edu                    "microops[%d] = %s;\n" % \
2265133Sgblack@eecs.umich.edu                    (micropc, op.getAllocator(flags))
2275133Sgblack@eecs.umich.edu                micropc += 1
2283584Ssaidi@eecs.umich.edu            if env.useStackSize:
2293025Ssaidi@eecs.umich.edu                useStackSize = "true"
2302934Sktlim@umich.edu            else:
2312995Ssaidi@eecs.umich.edu                useStackSize = "false"
2322995Ssaidi@eecs.umich.edu            if env.memoryInst:
2334981Ssaidi@eecs.umich.edu                memoryInst = "true"
2344981Ssaidi@eecs.umich.edu            else:
2354981Ssaidi@eecs.umich.edu                memoryInst = "false"
2364981Ssaidi@eecs.umich.edu            regSize = '''(%s || (env.base == INTREG_RSP && %s) ?
2373025Ssaidi@eecs.umich.edu                         env.stackSize :
2383025Ssaidi@eecs.umich.edu                         env.dataSize)''' % (useStackSize, memoryInst)
2393025Ssaidi@eecs.umich.edu            iop = InstObjParams(self.getMnemonic(), self.name, "Macroop",
2402934Sktlim@umich.edu                                {"code" : "", "num_microops" : numMicroops,
2412934Sktlim@umich.edu                                 "alloc_microops" : allocMicroops,
2425253Sksewell@umich.edu                                 "adjust_env" : self.adjust_env,
2435263Sksewell@umich.edu                                 "adjust_imm" : self.adjust_imm,
2445253Sksewell@umich.edu                                 "adjust_disp" : self.adjust_disp,
2455253Sksewell@umich.edu                                 "disassembly" : env.disassembly,
2465253Sksewell@umich.edu                                 "regSize" : regSize,
2475253Sksewell@umich.edu                                 "init_env" : self.initEnv})
2485253Sksewell@umich.edu            return MacroConstructor.subst(iop) + \
2495253Sksewell@umich.edu                   MacroDisassembly.subst(iop);
2505253Sksewell@umich.edu}};
2515253Sksewell@umich.edu
2525253Sksewell@umich.edulet {{
2535253Sksewell@umich.edu    class EmulEnv(object):
2545253Sksewell@umich.edu        def __init__(self):
2555253Sksewell@umich.edu            self.reg = "0"
2565253Sksewell@umich.edu            self.regUsed = False
2575253Sksewell@umich.edu            self.regm = "0"
2585253Sksewell@umich.edu            self.regmUsed = False
2595253Sksewell@umich.edu            self.seg = "SEGMENT_REG_DS"
2605253Sksewell@umich.edu            self.size = None
2615253Sksewell@umich.edu            self.addressSize = "ADDRSIZE"
2625253Sksewell@umich.edu            self.dataSize = "OPSIZE"
2635253Sksewell@umich.edu            self.stackSize = "STACKSIZE"
2645253Sksewell@umich.edu            self.doModRM = False
2655253Sksewell@umich.edu            self.disassembly = ""
2665253Sksewell@umich.edu            self.firstArgument = True
2675253Sksewell@umich.edu            self.useStackSize = False
2685253Sksewell@umich.edu            self.memoryInst = False
2695253Sksewell@umich.edu
2705253Sksewell@umich.edu        def addToDisassembly(self, code):
2715253Sksewell@umich.edu            if not self.firstArgument:
2725253Sksewell@umich.edu                self.disassembly += "out << \", \";\n"
2735253Sksewell@umich.edu            self.firstArgument = False
2745253Sksewell@umich.edu            self.disassembly += code
2755253Sksewell@umich.edu
2765253Sksewell@umich.edu        def getAllocator(self):
2775253Sksewell@umich.edu            if self.size == 'b':
2785253Sksewell@umich.edu                self.dataSize = 1
2795253Sksewell@umich.edu            elif self.size == 'd':
2805253Sksewell@umich.edu                self.dataSize = 4
2815253Sksewell@umich.edu            #This is for "double plus" which is normally a double word unless
2825253Sksewell@umich.edu            #the REX W bit is set, in which case it's a quad word. It's used
2835253Sksewell@umich.edu            #for some SSE instructions.
2845253Sksewell@umich.edu            elif self.size == 'dp':
2855253Sksewell@umich.edu                self.dataSize = "(REX_W ? 8 : 4)"
2865253Sksewell@umich.edu            elif self.size == 'q':
2875253Sksewell@umich.edu                self.dataSize = 8
2885253Sksewell@umich.edu            elif self.size == 'v':
2895253Sksewell@umich.edu                self.dataSize = "OPSIZE"
2905253Sksewell@umich.edu            elif self.size == 'w':
2915253Sksewell@umich.edu                self.dataSize = 2
2925253Sksewell@umich.edu            elif self.size == 'z':
2935253Sksewell@umich.edu                self.dataSize = "((OPSIZE == 8) ? 4 : OPSIZE)"
2945253Sksewell@umich.edu            elif self.size:
2955253Sksewell@umich.edu                raise Exception, "Unrecognized size type %s!" % self.size
2965253Sksewell@umich.edu            return '''EmulEnv(%(reg)s,
2975253Sksewell@umich.edu                              %(regm)s,
2985253Sksewell@umich.edu                              %(dataSize)s,
2995253Sksewell@umich.edu                              %(addressSize)s,
3005253Sksewell@umich.edu                              %(stackSize)s)''' % \
3015253Sksewell@umich.edu                self.__dict__
3025253Sksewell@umich.edu
3035253Sksewell@umich.edu        def addReg(self, reg):
3045253Sksewell@umich.edu            if not self.regUsed:
3055253Sksewell@umich.edu                self.reg = reg
3065253Sksewell@umich.edu                self.regUsed = True
3075253Sksewell@umich.edu            elif not self.regmUsed:
3085253Sksewell@umich.edu                self.regm = reg
3095253Sksewell@umich.edu                self.regmUsed = True
3105253Sksewell@umich.edu            else:
3115253Sksewell@umich.edu                raise Exception, "EmulEnv is out of register specialization spots."
312        def setSize(self, size):
313            if not self.size:
314                self.size = size
315            else:
316                if self.size != size:
317                    raise Exception, "Conflicting register sizes %s and %s!" %\
318                        (self.size, size)
319}};
320
321let {{
322    doModRMString = "env.doModRM(machInst);\n"
323    noModRMString = "env.setSeg(machInst);\n"
324    def genMacroop(Name, env):
325        blocks = OutputBlocks()
326        if not macroopDict.has_key(Name):
327            raise Exception, "Unrecognized instruction: %s" % Name
328        macroop = macroopDict[Name]
329        if not macroop.declared:
330            if env.doModRM:
331                macroop.initEnv = doModRMString
332            else:
333                macroop.initEnv = noModRMString
334            blocks.header_output = macroop.getDeclaration()
335            blocks.decoder_output = macroop.getDefinition(env)
336            macroop.declared = True
337        blocks.decode_block = "return %s;\n" % macroop.getAllocator(env)
338        return blocks
339}};
340