branch.isa revision 7794
12068SN/A// -*- mode:c++ -*-
22068SN/A
32068SN/A// Copyright (c) 2003-2005 The Regents of The University of Michigan
42068SN/A// All rights reserved.
52068SN/A//
62068SN/A// Redistribution and use in source and binary forms, with or without
72068SN/A// modification, are permitted provided that the following conditions are
82068SN/A// met: redistributions of source code must retain the above copyright
92068SN/A// notice, this list of conditions and the following disclaimer;
102068SN/A// redistributions in binary form must reproduce the above copyright
112068SN/A// notice, this list of conditions and the following disclaimer in the
122068SN/A// documentation and/or other materials provided with the distribution;
132068SN/A// neither the name of the copyright holders nor the names of its
142068SN/A// contributors may be used to endorse or promote products derived from
152068SN/A// this software without specific prior written permission.
162068SN/A//
172068SN/A// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
182068SN/A// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
192068SN/A// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
202068SN/A// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
212068SN/A// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
222068SN/A// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
232068SN/A// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
242068SN/A// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
252068SN/A// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
262068SN/A// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
272068SN/A// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
282665Ssaidi@eecs.umich.edu//
292665Ssaidi@eecs.umich.edu// Authors: Steve Reinhardt
302068SN/A
312649Ssaidi@eecs.umich.edu////////////////////////////////////////////////////////////////////
322649Ssaidi@eecs.umich.edu//
332649Ssaidi@eecs.umich.edu// Control transfer instructions
342649Ssaidi@eecs.umich.edu//
352649Ssaidi@eecs.umich.edu
362068SN/Aoutput header {{
372068SN/A
382068SN/A    /**
392068SN/A     * Base class for instructions whose disassembly is not purely a
402068SN/A     * function of the machine instruction (i.e., it depends on the
412068SN/A     * PC).  This class overrides the disassemble() method to check
422068SN/A     * the PC and symbol table values before re-using a cached
432068SN/A     * disassembly string.  This is necessary for branches and jumps,
442068SN/A     * where the disassembly string includes the target address (which
452068SN/A     * may depend on the PC and/or symbol table).
462068SN/A     */
472068SN/A    class PCDependentDisassembly : public AlphaStaticInst
482068SN/A    {
492068SN/A      protected:
502068SN/A        /// Cached program counter from last disassembly
512068SN/A        mutable Addr cachedPC;
522068SN/A        /// Cached symbol table pointer from last disassembly
532068SN/A        mutable const SymbolTable *cachedSymtab;
542068SN/A
552068SN/A        /// Constructor
562227SN/A        PCDependentDisassembly(const char *mnem, ExtMachInst _machInst,
572068SN/A                               OpClass __opClass)
582068SN/A            : AlphaStaticInst(mnem, _machInst, __opClass),
592068SN/A              cachedPC(0), cachedSymtab(0)
602068SN/A        {
612068SN/A        }
622068SN/A
632068SN/A        const std::string &
642068SN/A        disassemble(Addr pc, const SymbolTable *symtab) const;
652068SN/A    };
662068SN/A
672068SN/A    /**
682068SN/A     * Base class for branches (PC-relative control transfers),
692068SN/A     * conditional or unconditional.
702068SN/A     */
712068SN/A    class Branch : public PCDependentDisassembly
722068SN/A    {
732068SN/A      protected:
742068SN/A        /// Displacement to target address (signed).
752068SN/A        int32_t disp;
762068SN/A
772068SN/A        /// Constructor.
782227SN/A        Branch(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
792068SN/A            : PCDependentDisassembly(mnem, _machInst, __opClass),
802068SN/A              disp(BRDISP << 2)
812068SN/A        {
822068SN/A        }
832068SN/A
847720Sgblack@eecs.umich.edu        AlphaISA::PCState branchTarget(const AlphaISA::PCState &branchPC) const;
852068SN/A
862068SN/A        std::string
872068SN/A        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
882068SN/A    };
892068SN/A
902068SN/A    /**
912068SN/A     * Base class for jumps (register-indirect control transfers).  In
922068SN/A     * the Alpha ISA, these are always unconditional.
932068SN/A     */
942068SN/A    class Jump : public PCDependentDisassembly
952068SN/A    {
962068SN/A      protected:
972068SN/A
982068SN/A        /// Displacement to target address (signed).
992068SN/A        int32_t disp;
1002068SN/A
1012068SN/A      public:
1022068SN/A        /// Constructor
1032227SN/A        Jump(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
1042068SN/A            : PCDependentDisassembly(mnem, _machInst, __opClass),
1052068SN/A              disp(BRDISP)
1062068SN/A        {
1072068SN/A        }
1082068SN/A
1097720Sgblack@eecs.umich.edu        AlphaISA::PCState branchTarget(ThreadContext *tc) const;
1102068SN/A
1112068SN/A        std::string
1122068SN/A        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
1132068SN/A    };
1142068SN/A}};
1152068SN/A
1162068SN/Aoutput decoder {{
1177720Sgblack@eecs.umich.edu    AlphaISA::PCState
1187720Sgblack@eecs.umich.edu    Branch::branchTarget(const AlphaISA::PCState &branchPC) const
1192068SN/A    {
1207720Sgblack@eecs.umich.edu        return branchPC.pc() + 4 + disp;
1212068SN/A    }
1222068SN/A
1237720Sgblack@eecs.umich.edu    AlphaISA::PCState
1242680Sktlim@umich.edu    Jump::branchTarget(ThreadContext *tc) const
1252068SN/A    {
1267720Sgblack@eecs.umich.edu        PCState pc = tc->pcState();
1272680Sktlim@umich.edu        uint64_t Rb = tc->readIntReg(_srcRegIdx[0]);
1287720Sgblack@eecs.umich.edu        pc.set((Rb & ~3) | (pc.pc() & 1));
1297720Sgblack@eecs.umich.edu        return pc;
1302068SN/A    }
1312068SN/A
1322068SN/A    const std::string &
1332068SN/A    PCDependentDisassembly::disassemble(Addr pc,
1342068SN/A                                        const SymbolTable *symtab) const
1352068SN/A    {
1362068SN/A        if (!cachedDisassembly ||
1372068SN/A            pc != cachedPC || symtab != cachedSymtab)
1382068SN/A        {
1392068SN/A            if (cachedDisassembly)
1402068SN/A                delete cachedDisassembly;
1412068SN/A
1422068SN/A            cachedDisassembly =
1432068SN/A                new std::string(generateDisassembly(pc, symtab));
1442068SN/A            cachedPC = pc;
1452068SN/A            cachedSymtab = symtab;
1462068SN/A        }
1472068SN/A
1482068SN/A        return *cachedDisassembly;
1492068SN/A    }
1502068SN/A
1512068SN/A    std::string
1522068SN/A    Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const
1532068SN/A    {
1542068SN/A        std::stringstream ss;
1552068SN/A
1562068SN/A        ccprintf(ss, "%-10s ", mnemonic);
1572068SN/A
1582068SN/A        // There's only one register arg (RA), but it could be
1592068SN/A        // either a source (the condition for conditional
1602068SN/A        // branches) or a destination (the link reg for
1612068SN/A        // unconditional branches)
1622068SN/A        if (_numSrcRegs > 0) {
1632068SN/A            printReg(ss, _srcRegIdx[0]);
1642068SN/A            ss << ",";
1652068SN/A        }
1662068SN/A        else if (_numDestRegs > 0) {
1672068SN/A            printReg(ss, _destRegIdx[0]);
1682068SN/A            ss << ",";
1692068SN/A        }
1702068SN/A
1712068SN/A#ifdef SS_COMPATIBLE_DISASSEMBLY
1722068SN/A        if (_numSrcRegs == 0 && _numDestRegs == 0) {
1732068SN/A            printReg(ss, 31);
1742068SN/A            ss << ",";
1752068SN/A        }
1762068SN/A#endif
1772068SN/A
1782068SN/A        Addr target = pc + 4 + disp;
1792068SN/A
1802068SN/A        std::string str;
1812068SN/A        if (symtab && symtab->findSymbol(target, str))
1822068SN/A            ss << str;
1832068SN/A        else
1842068SN/A            ccprintf(ss, "0x%x", target);
1852068SN/A
1862068SN/A        return ss.str();
1872068SN/A    }
1882068SN/A
1892068SN/A    std::string
1902068SN/A    Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const
1912068SN/A    {
1922068SN/A        std::stringstream ss;
1932068SN/A
1942068SN/A        ccprintf(ss, "%-10s ", mnemonic);
1952068SN/A
1962068SN/A#ifdef SS_COMPATIBLE_DISASSEMBLY
1972068SN/A        if (_numDestRegs == 0) {
1982068SN/A            printReg(ss, 31);
1992068SN/A            ss << ",";
2002068SN/A        }
2012068SN/A#endif
2022068SN/A
2032068SN/A        if (_numDestRegs > 0) {
2042068SN/A            printReg(ss, _destRegIdx[0]);
2052068SN/A            ss << ",";
2062068SN/A        }
2072068SN/A
2082068SN/A        ccprintf(ss, "(r%d)", RB);
2092068SN/A
2102068SN/A        return ss.str();
2112068SN/A    }
2122068SN/A}};
2132068SN/A
2142068SN/Adef template JumpOrBranchDecode {{
2152068SN/A    return (RA == 31)
2162107SN/A        ? (StaticInst *)new %(class_name)s(machInst)
2172107SN/A        : (StaticInst *)new %(class_name)sAndLink(machInst);
2182068SN/A}};
2192068SN/A
2202068SN/Adef format CondBranch(code) {{
2217720Sgblack@eecs.umich.edu    code = '''
2227720Sgblack@eecs.umich.edu        bool cond;
2237720Sgblack@eecs.umich.edu        %(code)s;
2247720Sgblack@eecs.umich.edu        if (cond)
2257794Sgblack@eecs.umich.edu            NPC = NPC + disp;
2267794Sgblack@eecs.umich.edu        else
2277794Sgblack@eecs.umich.edu            NPC = NPC;
2287720Sgblack@eecs.umich.edu    ''' % { "code" : code }
2293953Sstever@eecs.umich.edu    iop = InstObjParams(name, Name, 'Branch', code,
2302068SN/A                        ('IsDirectControl', 'IsCondControl'))
2312068SN/A    header_output = BasicDeclare.subst(iop)
2322068SN/A    decoder_output = BasicConstructor.subst(iop)
2332068SN/A    decode_block = BasicDecode.subst(iop)
2342068SN/A    exec_output = BasicExecute.subst(iop)
2352068SN/A}};
2362068SN/A
2372068SN/Alet {{
2382068SN/Adef UncondCtrlBase(name, Name, base_class, npc_expr, flags):
2392068SN/A    # Declare basic control transfer w/o link (i.e. link reg is R31)
2407794Sgblack@eecs.umich.edu    nolink_code = 'NPC = %s;\n' % npc_expr
2417720Sgblack@eecs.umich.edu    nolink_iop = InstObjParams(name, Name, base_class,
2427794Sgblack@eecs.umich.edu                               nolink_code, flags)
2432068SN/A    header_output = BasicDeclare.subst(nolink_iop)
2442068SN/A    decoder_output = BasicConstructor.subst(nolink_iop)
2452068SN/A    exec_output = BasicExecute.subst(nolink_iop)
2462068SN/A
2472068SN/A    # Generate declaration of '*AndLink' version, append to decls
2487794Sgblack@eecs.umich.edu    link_code = 'Ra = NPC & ~3;\n' + nolink_code
2492068SN/A    link_iop = InstObjParams(name, Name + 'AndLink', base_class,
2507794Sgblack@eecs.umich.edu                             link_code, flags)
2512068SN/A    header_output += BasicDeclare.subst(link_iop)
2522068SN/A    decoder_output += BasicConstructor.subst(link_iop)
2532068SN/A    exec_output += BasicExecute.subst(link_iop)
2542068SN/A
2552068SN/A    # need to use link_iop for the decode template since it is expecting
2562068SN/A    # the shorter version of class_name (w/o "AndLink")
2572068SN/A
2582068SN/A    return (header_output, decoder_output,
2592068SN/A            JumpOrBranchDecode.subst(nolink_iop), exec_output)
2602068SN/A}};
2612068SN/A
2622068SN/Adef format UncondBranch(*flags) {{
2632068SN/A    flags += ('IsUncondControl', 'IsDirectControl')
2642068SN/A    (header_output, decoder_output, decode_block, exec_output) = \
2657794Sgblack@eecs.umich.edu        UncondCtrlBase(name, Name, 'Branch', 'NPC + disp', flags)
2662068SN/A}};
2672068SN/A
2682068SN/Adef format Jump(*flags) {{
2692068SN/A    flags += ('IsUncondControl', 'IsIndirectControl')
2702068SN/A    (header_output, decoder_output, decode_block, exec_output) = \
2717794Sgblack@eecs.umich.edu        UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (NPC & 1)', flags)
2722068SN/A}};
2732068SN/A
2742068SN/A
275