macroop.isa revision 10184:bbfa3152bdea
12SN/A// -*- mode:c++ -*-
21762SN/A
32SN/A// Copyright (c) 2007 The Hewlett-Packard Development Company
42SN/A// All rights reserved.
52SN/A//
62SN/A// The license below extends only to copyright in the software and shall
72SN/A// not be construed as granting a license to any other intellectual
82SN/A// property including but not limited to intellectual property relating
92SN/A// to a hardware implementation of the functionality of the software
102SN/A// licensed hereunder.  You may use the software subject to the license
112SN/A// terms below provided that you ensure that this notice is replicated
122SN/A// unmodified and in its entirety in all distributions of the software,
132SN/A// modified or unmodified, in source code or in binary form.
142SN/A//
152SN/A// Redistribution and use in source and binary forms, with or without
162SN/A// modification, are permitted provided that the following conditions are
172SN/A// met: redistributions of source code must retain the above copyright
182SN/A// notice, this list of conditions and the following disclaimer;
192SN/A// redistributions in binary form must reproduce the above copyright
202SN/A// notice, this list of conditions and the following disclaimer in the
212SN/A// documentation and/or other materials provided with the distribution;
222SN/A// neither the name of the copyright holders nor the names of its
232SN/A// contributors may be used to endorse or promote products derived from
242SN/A// this software without specific prior written permission.
252SN/A//
262SN/A// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
272665Ssaidi@eecs.umich.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
282665Ssaidi@eecs.umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
292665Ssaidi@eecs.umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
302SN/A// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
312SN/A// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
324997Sgblack@eecs.umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
331110SN/A// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
344997Sgblack@eecs.umich.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
358229Snate@binkert.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
368229Snate@binkert.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
372680Sktlim@umich.edu//
388229Snate@binkert.org// Authors: Gabe Black
392800Ssaidi@eecs.umich.edu
408780Sgblack@eecs.umich.edu//////////////////////////////////////////////////////////////////////////////
412SN/A//
425569Snate@binkert.org//  Architecture independent
432167SN/A//
442203SN/A
452203SN/A// Execute method for macroops.
462222SN/Adef template MacroExecPanic {{
472166SN/A        Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const
482203SN/A        {
492203SN/A            panic("Tried to execute macroop directly!");
502222SN/A            return NoFault;
512166SN/A        }
522147SN/A}};
532147SN/A
542222SN/Aoutput header {{
552147SN/A
562147SN/A        // Base class for combinationally generated macroops
572147SN/A        class Macroop : public X86ISA::MacroopBase
582222SN/A        {
592147SN/A          public:
602147SN/A            Macroop(const char *mnem, ExtMachInst _machInst,
612147SN/A                    uint32_t _numMicroops, X86ISA::EmulEnv _env)
622222SN/A                        : MacroopBase(mnem, _machInst, _numMicroops, _env)
632147SN/A            {}
642147SN/A            %(MacroExecPanic)s
652147SN/A        };
662222SN/A}};
672147SN/A
682147SN/A//////////////////////////////////////////////////////////////////////////////
692147SN/A//
702222SN/A//  X86 specific
712147SN/A//
728405Sksewell@umich.edu//////////////////////////////////////////////////////////////////////////////
732147SN/A
742222SN/A// Basic instruction class declaration template.
752147SN/Adef template MacroDeclare {{
768405Sksewell@umich.edu        namespace X86Macroop
772147SN/A        {
782222SN/A            /**
792147SN/A             * Static instruction class for "%(mnemonic)s".
802289SN/A             */
812289SN/A            class %(class_name)s : public %(base_class)s
822289SN/A            {
832289SN/A              private:
842147SN/A                %(declareLabels)s
852147SN/A              public:
862222SN/A                // Constructor.
872147SN/A                %(class_name)s(ExtMachInst machInst, X86ISA::EmulEnv _env);
882147SN/A
892147SN/A                std::string
902222SN/A                generateDisassembly(Addr pc, const SymbolTable *symtab) const;
912147SN/A            };
922147SN/A        }
932147SN/A}};
942222SN/A
952147SN/Adef template MacroDisassembly {{
962147SN/A    std::string
972147SN/A    X86Macroop::%(class_name)s::generateDisassembly(Addr pc,
982222SN/A            const SymbolTable *symtab) const
992147SN/A    {
1002147SN/A        std::stringstream out;
1012147SN/A        out << mnemonic << "\t";
1022222SN/A
1032147SN/A        int regSize = %(regSize)s;
1042147SN/A        %(disassembly)s
1052147SN/A        // Shut up gcc.
1062222SN/A        regSize = regSize;
1072147SN/A        return out.str();
1085569Snate@binkert.org    }
1097678Sgblack@eecs.umich.edu}};
1102174SN/A
1112680Sktlim@umich.edu// Basic instruction class constructor template.
1128780Sgblack@eecs.umich.edudef template MacroConstructor {{
1138780Sgblack@eecs.umich.edu        X86Macroop::%(class_name)s::%(class_name)s(
1142222SN/A                ExtMachInst machInst, EmulEnv _env)
1152174SN/A            : %(base_class)s("%(mnemonic)s", machInst, %(num_microops)s, _env)
1167720Sgblack@eecs.umich.edu        {
1177720Sgblack@eecs.umich.edu            %(adjust_env)s;
1182196SN/A            %(adjust_imm)s;
1197720Sgblack@eecs.umich.edu            %(adjust_disp)s;
1207720Sgblack@eecs.umich.edu            %(init_env)s;
1212196SN/A            %(constructor)s;
1222201SN/A            const char *macrocodeBlock = "%(class_name)s";
1232196SN/A            //alloc_microops is the code that sets up the microops
1245568Snate@binkert.org            //array in the parent class.
1255568Snate@binkert.org            %(alloc_microops)s;
1262196SN/A        }
1272196SN/A}};
1287720Sgblack@eecs.umich.edu
1297720Sgblack@eecs.umich.edulet {{
1302174SN/A    from micro_asm import Combinational_Macroop, Rom_Macroop
1312174SN/A    class X86Macroop(Combinational_Macroop):
1325569Snate@binkert.org        def add_microop(self, mnemonic, microop):
1337678Sgblack@eecs.umich.edu            microop.mnemonic = mnemonic
1342201SN/A            microop.micropc = len(self.microops)
1352680Sktlim@umich.edu            self.microops.append(microop)
1368780Sgblack@eecs.umich.edu        def setAdjustEnv(self, val):
1378780Sgblack@eecs.umich.edu            self.adjust_env = val
1382201SN/A        def adjustImm(self, val):
1392201SN/A            self.adjust_imm += val
1402201SN/A        def adjustDisp(self, val):
1415569Snate@binkert.org            self.adjust_disp += val
1427678Sgblack@eecs.umich.edu        def serializing(self):
1432289SN/A            self.serializing = True
1448780Sgblack@eecs.umich.edu
1458780Sgblack@eecs.umich.edu        def function_call(self):
1468780Sgblack@eecs.umich.edu            self.function_call = True
1478780Sgblack@eecs.umich.edu        def function_return(self):
1488780Sgblack@eecs.umich.edu            self.function_return = True
1498780Sgblack@eecs.umich.edu
1508780Sgblack@eecs.umich.edu        def __init__(self, name):
1518780Sgblack@eecs.umich.edu            super(X86Macroop, self).__init__(name)
1528780Sgblack@eecs.umich.edu            self.directives = {
1538780Sgblack@eecs.umich.edu                "adjust_env" : self.setAdjustEnv,
1542289SN/A                "adjust_imm" : self.adjustImm,
1558780Sgblack@eecs.umich.edu                "adjust_disp" : self.adjustDisp,
1568780Sgblack@eecs.umich.edu                "serializing" : self.serializing,
1578780Sgblack@eecs.umich.edu                "function_call" : self.function_call,
1588780Sgblack@eecs.umich.edu                "function_return" : self.function_return
1598780Sgblack@eecs.umich.edu            }
1608780Sgblack@eecs.umich.edu            self.declared = False
1612289SN/A            self.adjust_env = ""
1628780Sgblack@eecs.umich.edu            self.init_env = ""
1638780Sgblack@eecs.umich.edu            self.adjust_imm = '''
1648780Sgblack@eecs.umich.edu                uint64_t adjustedImm = IMMEDIATE;
1658780Sgblack@eecs.umich.edu                //This is to pacify gcc in case the immediate isn't used.
1662289SN/A                adjustedImm = adjustedImm;
1672289SN/A            '''
1682680Sktlim@umich.edu            self.adjust_disp = '''
1692289SN/A                uint64_t adjustedDisp = DISPLACEMENT;
1702289SN/A                //This is to pacify gcc in case the displacement isn't used.
1715569Snate@binkert.org                adjustedDisp = adjustedDisp;
1727678Sgblack@eecs.umich.edu            '''
1732289SN/A            self.serializing = False
1748780Sgblack@eecs.umich.edu            self.function_call = False
1758780Sgblack@eecs.umich.edu            self.function_return = False
1768780Sgblack@eecs.umich.edu
1778780Sgblack@eecs.umich.edu        def getAllocator(self, env):
1788780Sgblack@eecs.umich.edu            return "new X86Macroop::%s(machInst, %s)" % \
1798780Sgblack@eecs.umich.edu                    (self.name, env.getAllocator())
1802289SN/A        def getMnemonic(self):
1812289SN/A            mnemonic = self.name.lower()
1822680Sktlim@umich.edu            mnemonic = re.match(r'[^_]*', mnemonic).group(0)
1832289SN/A            return mnemonic
1842289SN/A        def getDeclaration(self):
1855569Snate@binkert.org            #FIXME This first parameter should be the mnemonic. I need to
1867678Sgblack@eecs.umich.edu            #write some code which pulls that out
1874997Sgblack@eecs.umich.edu            declareLabels = ""
1888780Sgblack@eecs.umich.edu            for (label, microop) in self.labels.items():
1898780Sgblack@eecs.umich.edu                declareLabels += "const static uint64_t label_%s = %d;\n" \
1904997Sgblack@eecs.umich.edu                                  % (label, microop.micropc)
1918780Sgblack@eecs.umich.edu            iop = InstObjParams(self.getMnemonic(), self.name, "Macroop",
1928780Sgblack@eecs.umich.edu                    {"code" : "",
1938780Sgblack@eecs.umich.edu                     "declareLabels" : declareLabels
1948780Sgblack@eecs.umich.edu                    })
1958780Sgblack@eecs.umich.edu            return MacroDeclare.subst(iop);
1968780Sgblack@eecs.umich.edu        def getDefinition(self, env):
1978780Sgblack@eecs.umich.edu            #FIXME This first parameter should be the mnemonic. I need to
1988780Sgblack@eecs.umich.edu            #write some code which pulls that out
1998780Sgblack@eecs.umich.edu            numMicroops = len(self.microops)
2004997Sgblack@eecs.umich.edu            allocMicroops = ''
2014997Sgblack@eecs.umich.edu            micropc = 0
2024997Sgblack@eecs.umich.edu            for op in self.microops:
2035569Snate@binkert.org                flags = ["IsMicroop"]
2047678Sgblack@eecs.umich.edu                if micropc == numMicroops - 1:
2054997Sgblack@eecs.umich.edu                    flags.append("IsLastMicroop")
2068780Sgblack@eecs.umich.edu
2078780Sgblack@eecs.umich.edu                    if self.serializing:
2084997Sgblack@eecs.umich.edu                        flags.append("IsSerializing")
2098780Sgblack@eecs.umich.edu                        flags.append("IsSerializeAfter")
2108780Sgblack@eecs.umich.edu
2118780Sgblack@eecs.umich.edu                    if self.function_call:
2128780Sgblack@eecs.umich.edu                        flags.append("IsCall")
2138780Sgblack@eecs.umich.edu                    if self.function_return:
2148780Sgblack@eecs.umich.edu                        flags.append("IsReturn")
2158780Sgblack@eecs.umich.edu                else:
2168780Sgblack@eecs.umich.edu                    flags.append("IsDelayedCommit")
2178780Sgblack@eecs.umich.edu                if micropc == 0:
2188780Sgblack@eecs.umich.edu                    flags.append("IsFirstMicroop")
2198780Sgblack@eecs.umich.edu                allocMicroops += \
2208780Sgblack@eecs.umich.edu                    "microops[%d] = %s;\n" % \
2214997Sgblack@eecs.umich.edu                    (micropc, op.getAllocator(flags))
2224997Sgblack@eecs.umich.edu                micropc += 1
2234997Sgblack@eecs.umich.edu            if env.useStackSize:
2242167SN/A                useStackSize = "true"
2252167SN/A            else:
226                useStackSize = "false"
227            if env.memoryInst:
228                memoryInst = "true"
229            else:
230                memoryInst = "false"
231            regSize = '''(%s || (env.base == INTREG_RSP && %s) ?
232                         env.stackSize :
233                         env.dataSize)''' % (useStackSize, memoryInst)
234            iop = InstObjParams(self.getMnemonic(), self.name, "Macroop",
235                                {"code" : "", "num_microops" : numMicroops,
236                                 "alloc_microops" : allocMicroops,
237                                 "adjust_env" : self.adjust_env,
238                                 "adjust_imm" : self.adjust_imm,
239                                 "adjust_disp" : self.adjust_disp,
240                                 "disassembly" : env.disassembly,
241                                 "regSize" : regSize,
242                                 "init_env" : self.initEnv})
243            return MacroConstructor.subst(iop) + \
244                   MacroDisassembly.subst(iop);
245}};
246
247let {{
248    class EmulEnv(object):
249        def __init__(self):
250            self.reg = "0"
251            self.regUsed = False
252            self.regm = "0"
253            self.regmUsed = False
254            self.seg = "SEGMENT_REG_DS"
255            self.size = None
256            self.addressSize = "ADDRSIZE"
257            self.dataSize = "OPSIZE"
258            self.stackSize = "STACKSIZE"
259            self.doModRM = False
260            self.disassembly = ""
261            self.firstArgument = True
262            self.useStackSize = False
263            self.memoryInst = False
264
265        def addToDisassembly(self, code):
266            if not self.firstArgument:
267                self.disassembly += "out << \", \";\n"
268            self.firstArgument = False
269            self.disassembly += code
270
271        def getAllocator(self):
272            if self.size == 'b':
273                self.dataSize = 1
274            elif self.size == 'd':
275                self.dataSize = 4
276            #This is for "double plus" which is normally a double word unless
277            #the REX W bit is set, in which case it's a quad word. It's used
278            #for some SSE instructions.
279            elif self.size == 'dp':
280                self.dataSize = "(REX_W ? 8 : 4)"
281            elif self.size == 'q':
282                self.dataSize = 8
283            elif self.size == 'v':
284                self.dataSize = "OPSIZE"
285            elif self.size == 'w':
286                self.dataSize = 2
287            elif self.size == 'z':
288                self.dataSize = "((OPSIZE == 8) ? 4 : OPSIZE)"
289            elif self.size:
290                raise Exception, "Unrecognized size type %s!" % self.size
291            return '''EmulEnv(%(reg)s,
292                              %(regm)s,
293                              %(dataSize)s,
294                              %(addressSize)s,
295                              %(stackSize)s)''' % \
296                self.__dict__
297
298        def addReg(self, reg):
299            if not self.regUsed:
300                self.reg = reg
301                self.regUsed = True
302            elif not self.regmUsed:
303                self.regm = reg
304                self.regmUsed = True
305            else:
306                raise Exception, "EmulEnv is out of register specialization spots."
307        def setSize(self, size):
308            if not self.size:
309                self.size = size
310            else:
311                if self.size != size:
312                    raise Exception, "Conflicting register sizes %s and %s!" %\
313                        (self.size, size)
314}};
315
316let {{
317    doModRMString = "env.doModRM(machInst);\n"
318    noModRMString = "env.setSeg(machInst);\n"
319    def genMacroop(Name, env):
320        blocks = OutputBlocks()
321        if not macroopDict.has_key(Name):
322            raise Exception, "Unrecognized instruction: %s" % Name
323        macroop = macroopDict[Name]
324        if not macroop.declared:
325            if env.doModRM:
326                macroop.initEnv = doModRMString
327            else:
328                macroop.initEnv = noModRMString
329            blocks.header_output = macroop.getDeclaration()
330            blocks.decoder_output = macroop.getDefinition(env)
331            macroop.declared = True
332        blocks.decode_block = "return %s;\n" % macroop.getAllocator(env)
333        return blocks
334}};
335