macroop.isa revision 12584:2af98e1fb894
15633Sgblack@eecs.umich.edu// -*- mode:c++ -*-
25633Sgblack@eecs.umich.edu
35633Sgblack@eecs.umich.edu// Copyright (c) 2007 The Hewlett-Packard Development Company
45633Sgblack@eecs.umich.edu// All rights reserved.
55633Sgblack@eecs.umich.edu//
65633Sgblack@eecs.umich.edu// The license below extends only to copyright in the software and shall
75633Sgblack@eecs.umich.edu// not be construed as granting a license to any other intellectual
85633Sgblack@eecs.umich.edu// property including but not limited to intellectual property relating
95633Sgblack@eecs.umich.edu// to a hardware implementation of the functionality of the software
105633Sgblack@eecs.umich.edu// licensed hereunder.  You may use the software subject to the license
115633Sgblack@eecs.umich.edu// terms below provided that you ensure that this notice is replicated
125633Sgblack@eecs.umich.edu// unmodified and in its entirety in all distributions of the software,
135633Sgblack@eecs.umich.edu// modified or unmodified, in source code or in binary form.
145633Sgblack@eecs.umich.edu//
155633Sgblack@eecs.umich.edu// Redistribution and use in source and binary forms, with or without
165633Sgblack@eecs.umich.edu// modification, are permitted provided that the following conditions are
175633Sgblack@eecs.umich.edu// met: redistributions of source code must retain the above copyright
185633Sgblack@eecs.umich.edu// notice, this list of conditions and the following disclaimer;
195633Sgblack@eecs.umich.edu// redistributions in binary form must reproduce the above copyright
205633Sgblack@eecs.umich.edu// notice, this list of conditions and the following disclaimer in the
215633Sgblack@eecs.umich.edu// documentation and/or other materials provided with the distribution;
225633Sgblack@eecs.umich.edu// neither the name of the copyright holders nor the names of its
235633Sgblack@eecs.umich.edu// contributors may be used to endorse or promote products derived from
245633Sgblack@eecs.umich.edu// this software without specific prior written permission.
255633Sgblack@eecs.umich.edu//
265633Sgblack@eecs.umich.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
275633Sgblack@eecs.umich.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
285633Sgblack@eecs.umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
295633Sgblack@eecs.umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
305633Sgblack@eecs.umich.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
315633Sgblack@eecs.umich.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
325633Sgblack@eecs.umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
335633Sgblack@eecs.umich.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
346216Snate@binkert.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
355651Sgblack@eecs.umich.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
365633Sgblack@eecs.umich.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
375651Sgblack@eecs.umich.edu//
386045Sgblack@eecs.umich.edu// Authors: Gabe Black
395651Sgblack@eecs.umich.edu
405651Sgblack@eecs.umich.edu//////////////////////////////////////////////////////////////////////////////
415633Sgblack@eecs.umich.edu//
425827Sgblack@eecs.umich.edu//  Architecture independent
435827Sgblack@eecs.umich.edu//
445827Sgblack@eecs.umich.edu
455633Sgblack@eecs.umich.edu// Execute method for macroops.
466138Sgblack@eecs.umich.edudef template MacroExecPanic {{
476138Sgblack@eecs.umich.edu        Fault execute(ExecContext *, Trace::InstRecord *) const
485633Sgblack@eecs.umich.edu        {
495633Sgblack@eecs.umich.edu            panic("Tried to execute macroop directly!");
506138Sgblack@eecs.umich.edu            return NoFault;
516138Sgblack@eecs.umich.edu        }
525633Sgblack@eecs.umich.edu}};
535633Sgblack@eecs.umich.edu
545651Sgblack@eecs.umich.eduoutput header {{
555651Sgblack@eecs.umich.edu
565651Sgblack@eecs.umich.edu        // Base class for combinationally generated macroops
575651Sgblack@eecs.umich.edu        class Macroop : public X86ISA::MacroopBase
585651Sgblack@eecs.umich.edu        {
595651Sgblack@eecs.umich.edu          public:
605651Sgblack@eecs.umich.edu            Macroop(const char *mnem, ExtMachInst _machInst,
615651Sgblack@eecs.umich.edu                    uint32_t _numMicroops, X86ISA::EmulEnv _env)
625651Sgblack@eecs.umich.edu                        : MacroopBase(mnem, _machInst, _numMicroops, _env)
635651Sgblack@eecs.umich.edu            {}
645651Sgblack@eecs.umich.edu
655651Sgblack@eecs.umich.edu            Fault
665651Sgblack@eecs.umich.edu            execute(ExecContext *, Trace::InstRecord *) const
675651Sgblack@eecs.umich.edu            {
685651Sgblack@eecs.umich.edu                panic("Tried to execute macroop directly!");
695651Sgblack@eecs.umich.edu            }
705651Sgblack@eecs.umich.edu        };
715651Sgblack@eecs.umich.edu}};
725651Sgblack@eecs.umich.edu
735651Sgblack@eecs.umich.edu//////////////////////////////////////////////////////////////////////////////
745651Sgblack@eecs.umich.edu//
755651Sgblack@eecs.umich.edu//  X86 specific
765651Sgblack@eecs.umich.edu//
775651Sgblack@eecs.umich.edu//////////////////////////////////////////////////////////////////////////////
786064Sgblack@eecs.umich.edu
796064Sgblack@eecs.umich.edu// Basic instruction class declaration template.
806064Sgblack@eecs.umich.edudef template MacroDeclare {{
816064Sgblack@eecs.umich.edu        namespace X86Macroop
826064Sgblack@eecs.umich.edu        {
836045Sgblack@eecs.umich.edu            /**
846045Sgblack@eecs.umich.edu             * Static instruction class for "%(mnemonic)s".
856138Sgblack@eecs.umich.edu             */
866138Sgblack@eecs.umich.edu            class %(class_name)s : public %(base_class)s
876045Sgblack@eecs.umich.edu            {
885651Sgblack@eecs.umich.edu              private:
895651Sgblack@eecs.umich.edu                %(declareLabels)s
905651Sgblack@eecs.umich.edu              public:
915651Sgblack@eecs.umich.edu                // Constructor.
925651Sgblack@eecs.umich.edu                %(class_name)s(ExtMachInst machInst, X86ISA::EmulEnv _env);
935651Sgblack@eecs.umich.edu
945651Sgblack@eecs.umich.edu                std::string
955651Sgblack@eecs.umich.edu                generateDisassembly(Addr pc, const SymbolTable *symtab) const;
965651Sgblack@eecs.umich.edu            };
975651Sgblack@eecs.umich.edu        }
985651Sgblack@eecs.umich.edu}};
995633Sgblack@eecs.umich.edu
1005651Sgblack@eecs.umich.edudef template MacroDisassembly {{
1015651Sgblack@eecs.umich.edu    std::string
1025651Sgblack@eecs.umich.edu    X86Macroop::%(class_name)s::generateDisassembly(Addr pc,
1035651Sgblack@eecs.umich.edu            const SymbolTable *symtab) const
1045651Sgblack@eecs.umich.edu    {
1055651Sgblack@eecs.umich.edu        std::stringstream out;
1065651Sgblack@eecs.umich.edu        out << mnemonic << "\t";
1075651Sgblack@eecs.umich.edu
1085651Sgblack@eecs.umich.edu        int regSize = %(regSize)s;
1095651Sgblack@eecs.umich.edu        %(disassembly)s
1105633Sgblack@eecs.umich.edu        // Shut up gcc.
1115633Sgblack@eecs.umich.edu        regSize = regSize;
1125651Sgblack@eecs.umich.edu        return out.str();
1135633Sgblack@eecs.umich.edu    }
1145651Sgblack@eecs.umich.edu}};
1155651Sgblack@eecs.umich.edu
1165651Sgblack@eecs.umich.edu// Basic instruction class constructor template.
1175651Sgblack@eecs.umich.edudef template MacroConstructor {{
1185651Sgblack@eecs.umich.edu        X86Macroop::%(class_name)s::%(class_name)s(
1195827Sgblack@eecs.umich.edu                ExtMachInst machInst, EmulEnv _env)
1205827Sgblack@eecs.umich.edu            : %(base_class)s("%(mnemonic)s", machInst, %(num_microops)s, _env)
1215827Sgblack@eecs.umich.edu        {
1225827Sgblack@eecs.umich.edu            %(adjust_env)s;
1235827Sgblack@eecs.umich.edu            %(adjust_imm)s;
1245827Sgblack@eecs.umich.edu            %(adjust_disp)s;
1255827Sgblack@eecs.umich.edu            %(init_env)s;
1265827Sgblack@eecs.umich.edu            %(constructor)s;
1275827Sgblack@eecs.umich.edu            const char *macrocodeBlock = "%(class_name)s";
1285827Sgblack@eecs.umich.edu            //alloc_microops is the code that sets up the microops
1295827Sgblack@eecs.umich.edu            //array in the parent class.
1305827Sgblack@eecs.umich.edu            %(alloc_microops)s;
1315651Sgblack@eecs.umich.edu        }
1325651Sgblack@eecs.umich.edu}};
1335651Sgblack@eecs.umich.edu
1345651Sgblack@eecs.umich.edulet {{
1355651Sgblack@eecs.umich.edu    from micro_asm import Combinational_Macroop, Rom_Macroop
1365651Sgblack@eecs.umich.edu    class X86Macroop(Combinational_Macroop):
1375651Sgblack@eecs.umich.edu        def add_microop(self, mnemonic, microop):
1386064Sgblack@eecs.umich.edu            microop.mnemonic = mnemonic
1396064Sgblack@eecs.umich.edu            microop.micropc = len(self.microops)
1406064Sgblack@eecs.umich.edu            self.microops.append(microop)
1416064Sgblack@eecs.umich.edu        def setAdjustEnv(self, val):
1426064Sgblack@eecs.umich.edu            self.adjust_env = val
1436064Sgblack@eecs.umich.edu        def adjustImm(self, val):
1446064Sgblack@eecs.umich.edu            self.adjust_imm += val
1456064Sgblack@eecs.umich.edu        def adjustDisp(self, val):
1465651Sgblack@eecs.umich.edu            self.adjust_disp += val
1475651Sgblack@eecs.umich.edu        def serializeBefore(self):
1485651Sgblack@eecs.umich.edu            self.serialize_before = True
1495651Sgblack@eecs.umich.edu        def serializeAfter(self):
1505651Sgblack@eecs.umich.edu            self.serialize_after = True
1515633Sgblack@eecs.umich.edu
1525633Sgblack@eecs.umich.edu        def function_call(self):
1535827Sgblack@eecs.umich.edu            self.function_call = True
1545633Sgblack@eecs.umich.edu        def function_return(self):
1555827Sgblack@eecs.umich.edu            self.function_return = True
1565633Sgblack@eecs.umich.edu
1575827Sgblack@eecs.umich.edu        def __init__(self, name):
1585633Sgblack@eecs.umich.edu            super(X86Macroop, self).__init__(name)
1595827Sgblack@eecs.umich.edu            self.directives = {
1605657Sgblack@eecs.umich.edu                "adjust_env" : self.setAdjustEnv,
1615633Sgblack@eecs.umich.edu                "adjust_imm" : self.adjustImm,
1625633Sgblack@eecs.umich.edu                "adjust_disp" : self.adjustDisp,
1635633Sgblack@eecs.umich.edu                "serialize_before" : self.serializeBefore,
1645633Sgblack@eecs.umich.edu                "serialize_after" : self.serializeAfter,
1655633Sgblack@eecs.umich.edu                "function_call" : self.function_call,
1665633Sgblack@eecs.umich.edu                "function_return" : self.function_return
1675827Sgblack@eecs.umich.edu            }
1685827Sgblack@eecs.umich.edu            self.declared = False
1695633Sgblack@eecs.umich.edu            self.adjust_env = ""
1705633Sgblack@eecs.umich.edu            self.init_env = ""
1715633Sgblack@eecs.umich.edu            self.adjust_imm = '''
1725827Sgblack@eecs.umich.edu                uint64_t adjustedImm = IMMEDIATE;
1735827Sgblack@eecs.umich.edu                //This is to pacify gcc in case the immediate isn't used.
1745827Sgblack@eecs.umich.edu                adjustedImm = adjustedImm;
1755827Sgblack@eecs.umich.edu            '''
1765827Sgblack@eecs.umich.edu            self.adjust_disp = '''
1775827Sgblack@eecs.umich.edu                uint64_t adjustedDisp = DISPLACEMENT;
1785827Sgblack@eecs.umich.edu                //This is to pacify gcc in case the displacement isn't used.
1795827Sgblack@eecs.umich.edu                adjustedDisp = adjustedDisp;
1805827Sgblack@eecs.umich.edu            '''
1815827Sgblack@eecs.umich.edu            self.serialize_before = False
1825827Sgblack@eecs.umich.edu            self.serialize_after = False
1835827Sgblack@eecs.umich.edu            self.function_call = False
1845827Sgblack@eecs.umich.edu            self.function_return = False
1855827Sgblack@eecs.umich.edu
1865827Sgblack@eecs.umich.edu        def getAllocator(self, env):
1875633Sgblack@eecs.umich.edu            return "new X86Macroop::%s(machInst, %s)" % \
1885633Sgblack@eecs.umich.edu                    (self.name, env.getAllocator())
1895827Sgblack@eecs.umich.edu        def getMnemonic(self):
1905633Sgblack@eecs.umich.edu            mnemonic = self.name.lower()
1915827Sgblack@eecs.umich.edu            mnemonic = re.match(r'[^_]*', mnemonic).group(0)
1925827Sgblack@eecs.umich.edu            return mnemonic
1935827Sgblack@eecs.umich.edu        def getDeclaration(self):
1945827Sgblack@eecs.umich.edu            #FIXME This first parameter should be the mnemonic. I need to
1955827Sgblack@eecs.umich.edu            #write some code which pulls that out
1965827Sgblack@eecs.umich.edu            declareLabels = ""
1975827Sgblack@eecs.umich.edu            for (label, microop) in self.labels.items():
1985827Sgblack@eecs.umich.edu                declareLabels += "const static uint64_t label_%s = %d;\n" \
1995827Sgblack@eecs.umich.edu                                  % (label, microop.micropc)
2005827Sgblack@eecs.umich.edu            iop = InstObjParams(self.getMnemonic(), self.name, "Macroop",
2015827Sgblack@eecs.umich.edu                    {"code" : "",
2025827Sgblack@eecs.umich.edu                     "declareLabels" : declareLabels
2035827Sgblack@eecs.umich.edu                    })
2045827Sgblack@eecs.umich.edu            return MacroDeclare.subst(iop);
2055827Sgblack@eecs.umich.edu        def getDefinition(self, env):
2065827Sgblack@eecs.umich.edu            #FIXME This first parameter should be the mnemonic. I need to
2075827Sgblack@eecs.umich.edu            #write some code which pulls that out
2085827Sgblack@eecs.umich.edu            numMicroops = len(self.microops)
2095827Sgblack@eecs.umich.edu            allocMicroops = ''
2105827Sgblack@eecs.umich.edu            micropc = 0
2115827Sgblack@eecs.umich.edu            for op in self.microops:
2125827Sgblack@eecs.umich.edu                flags = ["IsMicroop"]
2135827Sgblack@eecs.umich.edu                if micropc == 0:
2145827Sgblack@eecs.umich.edu                    flags.append("IsFirstMicroop")
2155827Sgblack@eecs.umich.edu
2165827Sgblack@eecs.umich.edu                    if self.serialize_before:
2175827Sgblack@eecs.umich.edu                        flags.append("IsSerializing")
2185827Sgblack@eecs.umich.edu                        flags.append("IsSerializeBefore")
2195827Sgblack@eecs.umich.edu
2205827Sgblack@eecs.umich.edu                if micropc == numMicroops - 1:
2215827Sgblack@eecs.umich.edu                    flags.append("IsLastMicroop")
2225827Sgblack@eecs.umich.edu
2235827Sgblack@eecs.umich.edu                    if self.serialize_after:
2245827Sgblack@eecs.umich.edu                        flags.append("IsSerializing")
2255827Sgblack@eecs.umich.edu                        flags.append("IsSerializeAfter")
2265827Sgblack@eecs.umich.edu
2275827Sgblack@eecs.umich.edu                    if self.function_call:
2285827Sgblack@eecs.umich.edu                        flags.append("IsCall")
2295827Sgblack@eecs.umich.edu                    if self.function_return:
2305827Sgblack@eecs.umich.edu                        flags.append("IsReturn")
2315827Sgblack@eecs.umich.edu                else:
2325827Sgblack@eecs.umich.edu                    flags.append("IsDelayedCommit")
2335827Sgblack@eecs.umich.edu
2345633Sgblack@eecs.umich.edu                allocMicroops += \
2355633Sgblack@eecs.umich.edu                    "microops[%d] = %s;\n" % \
2365633Sgblack@eecs.umich.edu                    (micropc, op.getAllocator(flags))
2377811Ssteve.reinhardt@amd.com                micropc += 1
2385633Sgblack@eecs.umich.edu            if env.useStackSize:
2395633Sgblack@eecs.umich.edu                useStackSize = "true"
240            else:
241                useStackSize = "false"
242            if env.memoryInst:
243                memoryInst = "true"
244            else:
245                memoryInst = "false"
246            regSize = '''(%s || (env.base == INTREG_RSP && %s) ?
247                         env.stackSize :
248                         env.dataSize)''' % (useStackSize, memoryInst)
249            iop = InstObjParams(self.getMnemonic(), self.name, "Macroop",
250                                {"code" : "", "num_microops" : numMicroops,
251                                 "alloc_microops" : allocMicroops,
252                                 "adjust_env" : self.adjust_env,
253                                 "adjust_imm" : self.adjust_imm,
254                                 "adjust_disp" : self.adjust_disp,
255                                 "disassembly" : env.disassembly,
256                                 "regSize" : regSize,
257                                 "init_env" : self.initEnv})
258            return MacroConstructor.subst(iop) + \
259                   MacroDisassembly.subst(iop);
260}};
261
262let {{
263    class EmulEnv(object):
264        def __init__(self):
265            self.reg = "0"
266            self.regUsed = False
267            self.regm = "0"
268            self.regmUsed = False
269            self.seg = "SEGMENT_REG_DS"
270            self.size = None
271            self.addressSize = "ADDRSIZE"
272            self.dataSize = "OPSIZE"
273            self.stackSize = "STACKSIZE"
274            self.doModRM = False
275            self.disassembly = ""
276            self.firstArgument = True
277            self.useStackSize = False
278            self.memoryInst = False
279
280        def addToDisassembly(self, code):
281            if not self.firstArgument:
282                self.disassembly += "out << \", \";\n"
283            self.firstArgument = False
284            self.disassembly += code
285
286        def getAllocator(self):
287            if self.size == 'b':
288                self.dataSize = 1
289            elif self.size == 'd':
290                self.dataSize = 4
291            #This is for "double plus" which is normally a double word unless
292            #the REX W bit is set, in which case it's a quad word. It's used
293            #for some SSE instructions.
294            elif self.size == 'dp':
295                self.dataSize = "(REX_W ? 8 : 4)"
296            elif self.size == 'q':
297                self.dataSize = 8
298            elif self.size == 'v':
299                self.dataSize = "OPSIZE"
300            elif self.size == 'w':
301                self.dataSize = 2
302            elif self.size == 'z':
303                self.dataSize = "((OPSIZE == 8) ? 4 : OPSIZE)"
304            elif self.size:
305                raise Exception, "Unrecognized size type %s!" % self.size
306            return '''EmulEnv(%(reg)s,
307                              %(regm)s,
308                              %(dataSize)s,
309                              %(addressSize)s,
310                              %(stackSize)s)''' % \
311                self.__dict__
312
313        def addReg(self, reg):
314            if not self.regUsed:
315                self.reg = reg
316                self.regUsed = True
317            elif not self.regmUsed:
318                self.regm = reg
319                self.regmUsed = True
320            else:
321                raise Exception, "EmulEnv is out of register specialization spots."
322        def setSize(self, size):
323            if not self.size:
324                self.size = size
325            else:
326                if self.size != size:
327                    raise Exception, "Conflicting register sizes %s and %s!" %\
328                        (self.size, size)
329}};
330
331let {{
332    doModRMString = "env.doModRM(machInst);\n"
333    noModRMString = "env.setSeg(machInst);\n"
334    def genMacroop(Name, env):
335        blocks = OutputBlocks()
336        if not macroopDict.has_key(Name):
337            raise Exception, "Unrecognized instruction: %s" % Name
338        macroop = macroopDict[Name]
339        if not macroop.declared:
340            if env.doModRM:
341                macroop.initEnv = doModRMString
342            else:
343                macroop.initEnv = noModRMString
344            blocks.header_output = macroop.getDeclaration()
345            blocks.decoder_output = macroop.getDefinition(env)
346            macroop.declared = True
347        blocks.decode_block = "return %s;\n" % macroop.getAllocator(env)
348        return blocks
349}};
350