branch.isa revision 2227
16313Sgblack@eecs.umich.edu// -*- mode:c++ -*-
26313Sgblack@eecs.umich.edu
36313Sgblack@eecs.umich.edu// Copyright (c) 2003-2005 The Regents of The University of Michigan
46313Sgblack@eecs.umich.edu// All rights reserved.
56313Sgblack@eecs.umich.edu//
66313Sgblack@eecs.umich.edu// Redistribution and use in source and binary forms, with or without
76313Sgblack@eecs.umich.edu// modification, are permitted provided that the following conditions are
86313Sgblack@eecs.umich.edu// met: redistributions of source code must retain the above copyright
96313Sgblack@eecs.umich.edu// notice, this list of conditions and the following disclaimer;
106313Sgblack@eecs.umich.edu// redistributions in binary form must reproduce the above copyright
116313Sgblack@eecs.umich.edu// notice, this list of conditions and the following disclaimer in the
126313Sgblack@eecs.umich.edu// documentation and/or other materials provided with the distribution;
136313Sgblack@eecs.umich.edu// neither the name of the copyright holders nor the names of its
146313Sgblack@eecs.umich.edu// contributors may be used to endorse or promote products derived from
156313Sgblack@eecs.umich.edu// this software without specific prior written permission.
166313Sgblack@eecs.umich.edu//
176313Sgblack@eecs.umich.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
186313Sgblack@eecs.umich.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
196313Sgblack@eecs.umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
206313Sgblack@eecs.umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
216313Sgblack@eecs.umich.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
226313Sgblack@eecs.umich.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
236313Sgblack@eecs.umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
246313Sgblack@eecs.umich.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
256313Sgblack@eecs.umich.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
266313Sgblack@eecs.umich.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
276313Sgblack@eecs.umich.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
286313Sgblack@eecs.umich.edu
296313Sgblack@eecs.umich.eduoutput header {{
306313Sgblack@eecs.umich.edu
316313Sgblack@eecs.umich.edu    /**
326336Sgblack@eecs.umich.edu     * Base class for instructions whose disassembly is not purely a
336336Sgblack@eecs.umich.edu     * function of the machine instruction (i.e., it depends on the
346313Sgblack@eecs.umich.edu     * PC).  This class overrides the disassemble() method to check
356336Sgblack@eecs.umich.edu     * the PC and symbol table values before re-using a cached
366313Sgblack@eecs.umich.edu     * disassembly string.  This is necessary for branches and jumps,
376313Sgblack@eecs.umich.edu     * where the disassembly string includes the target address (which
386313Sgblack@eecs.umich.edu     * may depend on the PC and/or symbol table).
396313Sgblack@eecs.umich.edu     */
406313Sgblack@eecs.umich.edu    class PCDependentDisassembly : public AlphaStaticInst
416336Sgblack@eecs.umich.edu    {
426336Sgblack@eecs.umich.edu      protected:
436336Sgblack@eecs.umich.edu        /// Cached program counter from last disassembly
446712Snate@binkert.org        mutable Addr cachedPC;
456336Sgblack@eecs.umich.edu        /// Cached symbol table pointer from last disassembly
466336Sgblack@eecs.umich.edu        mutable const SymbolTable *cachedSymtab;
476336Sgblack@eecs.umich.edu
486336Sgblack@eecs.umich.edu        /// Constructor
496336Sgblack@eecs.umich.edu        PCDependentDisassembly(const char *mnem, ExtMachInst _machInst,
506336Sgblack@eecs.umich.edu                               OpClass __opClass)
516336Sgblack@eecs.umich.edu            : AlphaStaticInst(mnem, _machInst, __opClass),
526336Sgblack@eecs.umich.edu              cachedPC(0), cachedSymtab(0)
536336Sgblack@eecs.umich.edu        {
546336Sgblack@eecs.umich.edu        }
556336Sgblack@eecs.umich.edu
566336Sgblack@eecs.umich.edu        const std::string &
576336Sgblack@eecs.umich.edu        disassemble(Addr pc, const SymbolTable *symtab) const;
586336Sgblack@eecs.umich.edu    };
596336Sgblack@eecs.umich.edu
606336Sgblack@eecs.umich.edu    /**
616336Sgblack@eecs.umich.edu     * Base class for branches (PC-relative control transfers),
626336Sgblack@eecs.umich.edu     * conditional or unconditional.
636336Sgblack@eecs.umich.edu     */
646336Sgblack@eecs.umich.edu    class Branch : public PCDependentDisassembly
656336Sgblack@eecs.umich.edu    {
666336Sgblack@eecs.umich.edu      protected:
676336Sgblack@eecs.umich.edu        /// Displacement to target address (signed).
686336Sgblack@eecs.umich.edu        int32_t disp;
696336Sgblack@eecs.umich.edu
706336Sgblack@eecs.umich.edu        /// Constructor.
716336Sgblack@eecs.umich.edu        Branch(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
726336Sgblack@eecs.umich.edu            : PCDependentDisassembly(mnem, _machInst, __opClass),
736336Sgblack@eecs.umich.edu              disp(BRDISP << 2)
746336Sgblack@eecs.umich.edu        {
756336Sgblack@eecs.umich.edu        }
766336Sgblack@eecs.umich.edu
776336Sgblack@eecs.umich.edu        Addr branchTarget(Addr branchPC) const;
786336Sgblack@eecs.umich.edu
796336Sgblack@eecs.umich.edu        std::string
806336Sgblack@eecs.umich.edu        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
816336Sgblack@eecs.umich.edu    };
826336Sgblack@eecs.umich.edu
836336Sgblack@eecs.umich.edu    /**
846336Sgblack@eecs.umich.edu     * Base class for jumps (register-indirect control transfers).  In
856336Sgblack@eecs.umich.edu     * the Alpha ISA, these are always unconditional.
866336Sgblack@eecs.umich.edu     */
876336Sgblack@eecs.umich.edu    class Jump : public PCDependentDisassembly
886336Sgblack@eecs.umich.edu    {
896336Sgblack@eecs.umich.edu      protected:
906336Sgblack@eecs.umich.edu
916336Sgblack@eecs.umich.edu        /// Displacement to target address (signed).
926336Sgblack@eecs.umich.edu        int32_t disp;
936336Sgblack@eecs.umich.edu
946336Sgblack@eecs.umich.edu      public:
956336Sgblack@eecs.umich.edu        /// Constructor
966336Sgblack@eecs.umich.edu        Jump(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
976336Sgblack@eecs.umich.edu            : PCDependentDisassembly(mnem, _machInst, __opClass),
986336Sgblack@eecs.umich.edu              disp(BRDISP)
996336Sgblack@eecs.umich.edu        {
1006313Sgblack@eecs.umich.edu        }
1016313Sgblack@eecs.umich.edu
1026336Sgblack@eecs.umich.edu        Addr branchTarget(ExecContext *xc) const;
1036336Sgblack@eecs.umich.edu
1046336Sgblack@eecs.umich.edu        std::string
1056336Sgblack@eecs.umich.edu        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
1066336Sgblack@eecs.umich.edu    };
1076313Sgblack@eecs.umich.edu}};
1086313Sgblack@eecs.umich.edu
1096313Sgblack@eecs.umich.eduoutput decoder {{
1106313Sgblack@eecs.umich.edu    Addr
1116313Sgblack@eecs.umich.edu    Branch::branchTarget(Addr branchPC) const
1126336Sgblack@eecs.umich.edu    {
1136336Sgblack@eecs.umich.edu        return branchPC + 4 + disp;
1146336Sgblack@eecs.umich.edu    }
1156336Sgblack@eecs.umich.edu
1166336Sgblack@eecs.umich.edu    Addr
1176336Sgblack@eecs.umich.edu    Jump::branchTarget(ExecContext *xc) const
1186336Sgblack@eecs.umich.edu    {
1196336Sgblack@eecs.umich.edu        Addr NPC = xc->readPC() + 4;
1206336Sgblack@eecs.umich.edu        uint64_t Rb = xc->readIntReg(_srcRegIdx[0]);
1216336Sgblack@eecs.umich.edu        return (Rb & ~3) | (NPC & 1);
1226313Sgblack@eecs.umich.edu    }
1236313Sgblack@eecs.umich.edu
1246313Sgblack@eecs.umich.edu    const std::string &
1256336Sgblack@eecs.umich.edu    PCDependentDisassembly::disassemble(Addr pc,
1266313Sgblack@eecs.umich.edu                                        const SymbolTable *symtab) const
1276336Sgblack@eecs.umich.edu    {
1286336Sgblack@eecs.umich.edu        if (!cachedDisassembly ||
1296336Sgblack@eecs.umich.edu            pc != cachedPC || symtab != cachedSymtab)
1306336Sgblack@eecs.umich.edu        {
1316313Sgblack@eecs.umich.edu            if (cachedDisassembly)
1326313Sgblack@eecs.umich.edu                delete cachedDisassembly;
1336313Sgblack@eecs.umich.edu
1346336Sgblack@eecs.umich.edu            cachedDisassembly =
1356313Sgblack@eecs.umich.edu                new std::string(generateDisassembly(pc, symtab));
1366336Sgblack@eecs.umich.edu            cachedPC = pc;
1376336Sgblack@eecs.umich.edu            cachedSymtab = symtab;
1386336Sgblack@eecs.umich.edu        }
1396336Sgblack@eecs.umich.edu
1406336Sgblack@eecs.umich.edu        return *cachedDisassembly;
1416336Sgblack@eecs.umich.edu    }
1426336Sgblack@eecs.umich.edu
1436336Sgblack@eecs.umich.edu    std::string
1446336Sgblack@eecs.umich.edu    Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const
1456313Sgblack@eecs.umich.edu    {
1466313Sgblack@eecs.umich.edu        std::stringstream ss;
1476313Sgblack@eecs.umich.edu
1486336Sgblack@eecs.umich.edu        ccprintf(ss, "%-10s ", mnemonic);
1496313Sgblack@eecs.umich.edu
1506336Sgblack@eecs.umich.edu        // There's only one register arg (RA), but it could be
1516336Sgblack@eecs.umich.edu        // either a source (the condition for conditional
1526336Sgblack@eecs.umich.edu        // branches) or a destination (the link reg for
1536336Sgblack@eecs.umich.edu        // unconditional branches)
1546336Sgblack@eecs.umich.edu        if (_numSrcRegs > 0) {
1556336Sgblack@eecs.umich.edu            printReg(ss, _srcRegIdx[0]);
1566336Sgblack@eecs.umich.edu            ss << ",";
1576336Sgblack@eecs.umich.edu        }
1586336Sgblack@eecs.umich.edu        else if (_numDestRegs > 0) {
1596336Sgblack@eecs.umich.edu            printReg(ss, _destRegIdx[0]);
1606336Sgblack@eecs.umich.edu            ss << ",";
1616336Sgblack@eecs.umich.edu        }
1626336Sgblack@eecs.umich.edu
1636336Sgblack@eecs.umich.edu#ifdef SS_COMPATIBLE_DISASSEMBLY
1646336Sgblack@eecs.umich.edu        if (_numSrcRegs == 0 && _numDestRegs == 0) {
1656336Sgblack@eecs.umich.edu            printReg(ss, 31);
1666336Sgblack@eecs.umich.edu            ss << ",";
1676336Sgblack@eecs.umich.edu        }
1686336Sgblack@eecs.umich.edu#endif
1696336Sgblack@eecs.umich.edu
1706336Sgblack@eecs.umich.edu        Addr target = pc + 4 + disp;
1716336Sgblack@eecs.umich.edu
1726336Sgblack@eecs.umich.edu        std::string str;
1736336Sgblack@eecs.umich.edu        if (symtab && symtab->findSymbol(target, str))
1746336Sgblack@eecs.umich.edu            ss << str;
1756336Sgblack@eecs.umich.edu        else
1766336Sgblack@eecs.umich.edu            ccprintf(ss, "0x%x", target);
1776336Sgblack@eecs.umich.edu
1786336Sgblack@eecs.umich.edu        return ss.str();
1796336Sgblack@eecs.umich.edu    }
1806336Sgblack@eecs.umich.edu
1816336Sgblack@eecs.umich.edu    std::string
1826336Sgblack@eecs.umich.edu    Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const
1836336Sgblack@eecs.umich.edu    {
1846336Sgblack@eecs.umich.edu        std::stringstream ss;
1856336Sgblack@eecs.umich.edu
1866336Sgblack@eecs.umich.edu        ccprintf(ss, "%-10s ", mnemonic);
1876336Sgblack@eecs.umich.edu
1886336Sgblack@eecs.umich.edu#ifdef SS_COMPATIBLE_DISASSEMBLY
1896336Sgblack@eecs.umich.edu        if (_numDestRegs == 0) {
1906336Sgblack@eecs.umich.edu            printReg(ss, 31);
1916336Sgblack@eecs.umich.edu            ss << ",";
1926336Sgblack@eecs.umich.edu        }
1936336Sgblack@eecs.umich.edu#endif
1946336Sgblack@eecs.umich.edu
1956336Sgblack@eecs.umich.edu        if (_numDestRegs > 0) {
1966336Sgblack@eecs.umich.edu            printReg(ss, _destRegIdx[0]);
1976336Sgblack@eecs.umich.edu            ss << ",";
1986336Sgblack@eecs.umich.edu        }
1996336Sgblack@eecs.umich.edu
2006336Sgblack@eecs.umich.edu        ccprintf(ss, "(r%d)", RB);
2016336Sgblack@eecs.umich.edu
2026336Sgblack@eecs.umich.edu        return ss.str();
2036336Sgblack@eecs.umich.edu    }
2046336Sgblack@eecs.umich.edu}};
2056336Sgblack@eecs.umich.edu
2066336Sgblack@eecs.umich.edudef template JumpOrBranchDecode {{
2076336Sgblack@eecs.umich.edu    return (RA == 31)
2086336Sgblack@eecs.umich.edu        ? (StaticInst *)new %(class_name)s(machInst)
2096336Sgblack@eecs.umich.edu        : (StaticInst *)new %(class_name)sAndLink(machInst);
2106336Sgblack@eecs.umich.edu}};
2116336Sgblack@eecs.umich.edu
2126336Sgblack@eecs.umich.edudef format CondBranch(code) {{
2136336Sgblack@eecs.umich.edu    code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\n';
2146336Sgblack@eecs.umich.edu    iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
2156336Sgblack@eecs.umich.edu                        ('IsDirectControl', 'IsCondControl'))
2166336Sgblack@eecs.umich.edu    header_output = BasicDeclare.subst(iop)
2176336Sgblack@eecs.umich.edu    decoder_output = BasicConstructor.subst(iop)
2186336Sgblack@eecs.umich.edu    decode_block = BasicDecode.subst(iop)
2196336Sgblack@eecs.umich.edu    exec_output = BasicExecute.subst(iop)
2206336Sgblack@eecs.umich.edu}};
2216336Sgblack@eecs.umich.edu
2226336Sgblack@eecs.umich.edulet {{
2236336Sgblack@eecs.umich.edudef UncondCtrlBase(name, Name, base_class, npc_expr, flags):
2246336Sgblack@eecs.umich.edu    # Declare basic control transfer w/o link (i.e. link reg is R31)
2256336Sgblack@eecs.umich.edu    nolink_code = 'NPC = %s;\n' % npc_expr
2266336Sgblack@eecs.umich.edu    nolink_iop = InstObjParams(name, Name, base_class,
2276336Sgblack@eecs.umich.edu                               CodeBlock(nolink_code), flags)
2286336Sgblack@eecs.umich.edu    header_output = BasicDeclare.subst(nolink_iop)
2296336Sgblack@eecs.umich.edu    decoder_output = BasicConstructor.subst(nolink_iop)
2306336Sgblack@eecs.umich.edu    exec_output = BasicExecute.subst(nolink_iop)
2316336Sgblack@eecs.umich.edu
2326336Sgblack@eecs.umich.edu    # Generate declaration of '*AndLink' version, append to decls
2336336Sgblack@eecs.umich.edu    link_code = 'Ra = NPC & ~3;\n' + nolink_code
2346336Sgblack@eecs.umich.edu    link_iop = InstObjParams(name, Name + 'AndLink', base_class,
2356336Sgblack@eecs.umich.edu                             CodeBlock(link_code), flags)
2366336Sgblack@eecs.umich.edu    header_output += BasicDeclare.subst(link_iop)
2376336Sgblack@eecs.umich.edu    decoder_output += BasicConstructor.subst(link_iop)
2386336Sgblack@eecs.umich.edu    exec_output += BasicExecute.subst(link_iop)
2396336Sgblack@eecs.umich.edu
2406336Sgblack@eecs.umich.edu    # need to use link_iop for the decode template since it is expecting
2416336Sgblack@eecs.umich.edu    # the shorter version of class_name (w/o "AndLink")
2426336Sgblack@eecs.umich.edu
2436336Sgblack@eecs.umich.edu    return (header_output, decoder_output,
2446336Sgblack@eecs.umich.edu            JumpOrBranchDecode.subst(nolink_iop), exec_output)
2456336Sgblack@eecs.umich.edu}};
2466336Sgblack@eecs.umich.edu
2476336Sgblack@eecs.umich.edudef format UncondBranch(*flags) {{
2486336Sgblack@eecs.umich.edu    flags += ('IsUncondControl', 'IsDirectControl')
2496336Sgblack@eecs.umich.edu    (header_output, decoder_output, decode_block, exec_output) = \
2506336Sgblack@eecs.umich.edu        UncondCtrlBase(name, Name, 'Branch', 'NPC + disp', flags)
2516336Sgblack@eecs.umich.edu}};
2526336Sgblack@eecs.umich.edu
2536336Sgblack@eecs.umich.edudef format Jump(*flags) {{
2546336Sgblack@eecs.umich.edu    flags += ('IsUncondControl', 'IsIndirectControl')
2556336Sgblack@eecs.umich.edu    (header_output, decoder_output, decode_block, exec_output) = \
2566336Sgblack@eecs.umich.edu        UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (NPC & 1)', flags)
2576336Sgblack@eecs.umich.edu}};
2586336Sgblack@eecs.umich.edu
2596336Sgblack@eecs.umich.edu
2606336Sgblack@eecs.umich.edu