branch.isa revision 12106
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
869552Sandreas.hansson@arm.com        /// Explicitly import the otherwise hidden branchTarget
879552Sandreas.hansson@arm.com        using StaticInst::branchTarget;
889552Sandreas.hansson@arm.com
892068SN/A        std::string
902068SN/A        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
912068SN/A    };
922068SN/A
932068SN/A    /**
942068SN/A     * Base class for jumps (register-indirect control transfers).  In
952068SN/A     * the Alpha ISA, these are always unconditional.
962068SN/A     */
972068SN/A    class Jump : public PCDependentDisassembly
982068SN/A    {
992068SN/A      protected:
1002068SN/A
1012068SN/A        /// Displacement to target address (signed).
1022068SN/A        int32_t disp;
1032068SN/A
1042068SN/A      public:
1052068SN/A        /// Constructor
1062227SN/A        Jump(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
1072068SN/A            : PCDependentDisassembly(mnem, _machInst, __opClass),
1082068SN/A              disp(BRDISP)
1092068SN/A        {
1102068SN/A        }
1112068SN/A
1127720Sgblack@eecs.umich.edu        AlphaISA::PCState branchTarget(ThreadContext *tc) const;
1132068SN/A
1149552Sandreas.hansson@arm.com        /// Explicitly import the otherwise hidden branchTarget
1159552Sandreas.hansson@arm.com        using StaticInst::branchTarget;
1169552Sandreas.hansson@arm.com
1172068SN/A        std::string
1182068SN/A        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
1192068SN/A    };
1202068SN/A}};
1212068SN/A
1222068SN/Aoutput decoder {{
1237720Sgblack@eecs.umich.edu    AlphaISA::PCState
1247720Sgblack@eecs.umich.edu    Branch::branchTarget(const AlphaISA::PCState &branchPC) const
1252068SN/A    {
1267720Sgblack@eecs.umich.edu        return branchPC.pc() + 4 + disp;
1272068SN/A    }
1282068SN/A
1297720Sgblack@eecs.umich.edu    AlphaISA::PCState
1302680Sktlim@umich.edu    Jump::branchTarget(ThreadContext *tc) const
1312068SN/A    {
1327720Sgblack@eecs.umich.edu        PCState pc = tc->pcState();
13312106SRekai.GonzalezAlberquilla@arm.com        uint64_t Rb = tc->readIntReg(_srcRegIdx[0].index());
1347720Sgblack@eecs.umich.edu        pc.set((Rb & ~3) | (pc.pc() & 1));
1357720Sgblack@eecs.umich.edu        return pc;
1362068SN/A    }
1372068SN/A
1382068SN/A    const std::string &
1392068SN/A    PCDependentDisassembly::disassemble(Addr pc,
1402068SN/A                                        const SymbolTable *symtab) const
1412068SN/A    {
1422068SN/A        if (!cachedDisassembly ||
1432068SN/A            pc != cachedPC || symtab != cachedSymtab)
1442068SN/A        {
1452068SN/A            if (cachedDisassembly)
1462068SN/A                delete cachedDisassembly;
1472068SN/A
1482068SN/A            cachedDisassembly =
1492068SN/A                new std::string(generateDisassembly(pc, symtab));
1502068SN/A            cachedPC = pc;
1512068SN/A            cachedSymtab = symtab;
1522068SN/A        }
1532068SN/A
1542068SN/A        return *cachedDisassembly;
1552068SN/A    }
1562068SN/A
1572068SN/A    std::string
1582068SN/A    Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const
1592068SN/A    {
1602068SN/A        std::stringstream ss;
1612068SN/A
1622068SN/A        ccprintf(ss, "%-10s ", mnemonic);
1632068SN/A
1642068SN/A        // There's only one register arg (RA), but it could be
1652068SN/A        // either a source (the condition for conditional
1662068SN/A        // branches) or a destination (the link reg for
1672068SN/A        // unconditional branches)
1682068SN/A        if (_numSrcRegs > 0) {
1692068SN/A            printReg(ss, _srcRegIdx[0]);
1702068SN/A            ss << ",";
1712068SN/A        }
1722068SN/A        else if (_numDestRegs > 0) {
1732068SN/A            printReg(ss, _destRegIdx[0]);
1742068SN/A            ss << ",";
1752068SN/A        }
1762068SN/A
1772068SN/A#ifdef SS_COMPATIBLE_DISASSEMBLY
1782068SN/A        if (_numSrcRegs == 0 && _numDestRegs == 0) {
1792068SN/A            printReg(ss, 31);
1802068SN/A            ss << ",";
1812068SN/A        }
1822068SN/A#endif
1832068SN/A
1842068SN/A        Addr target = pc + 4 + disp;
1852068SN/A
1862068SN/A        std::string str;
1872068SN/A        if (symtab && symtab->findSymbol(target, str))
1882068SN/A            ss << str;
1892068SN/A        else
1902068SN/A            ccprintf(ss, "0x%x", target);
1912068SN/A
1922068SN/A        return ss.str();
1932068SN/A    }
1942068SN/A
1952068SN/A    std::string
1962068SN/A    Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const
1972068SN/A    {
1982068SN/A        std::stringstream ss;
1992068SN/A
2002068SN/A        ccprintf(ss, "%-10s ", mnemonic);
2012068SN/A
2022068SN/A#ifdef SS_COMPATIBLE_DISASSEMBLY
2032068SN/A        if (_numDestRegs == 0) {
2042068SN/A            printReg(ss, 31);
2052068SN/A            ss << ",";
2062068SN/A        }
2072068SN/A#endif
2082068SN/A
2092068SN/A        if (_numDestRegs > 0) {
2102068SN/A            printReg(ss, _destRegIdx[0]);
2112068SN/A            ss << ",";
2122068SN/A        }
2132068SN/A
2142068SN/A        ccprintf(ss, "(r%d)", RB);
2152068SN/A
2162068SN/A        return ss.str();
2172068SN/A    }
2182068SN/A}};
2192068SN/A
2202068SN/Adef template JumpOrBranchDecode {{
2212068SN/A    return (RA == 31)
2222107SN/A        ? (StaticInst *)new %(class_name)s(machInst)
2232107SN/A        : (StaticInst *)new %(class_name)sAndLink(machInst);
2242068SN/A}};
2252068SN/A
2262068SN/Adef format CondBranch(code) {{
2277720Sgblack@eecs.umich.edu    code = '''
2287720Sgblack@eecs.umich.edu        bool cond;
2297720Sgblack@eecs.umich.edu        %(code)s;
2307720Sgblack@eecs.umich.edu        if (cond)
2317794Sgblack@eecs.umich.edu            NPC = NPC + disp;
2327794Sgblack@eecs.umich.edu        else
2337794Sgblack@eecs.umich.edu            NPC = NPC;
2347720Sgblack@eecs.umich.edu    ''' % { "code" : code }
2353953Sstever@eecs.umich.edu    iop = InstObjParams(name, Name, 'Branch', code,
2362068SN/A                        ('IsDirectControl', 'IsCondControl'))
2372068SN/A    header_output = BasicDeclare.subst(iop)
2382068SN/A    decoder_output = BasicConstructor.subst(iop)
2392068SN/A    decode_block = BasicDecode.subst(iop)
2402068SN/A    exec_output = BasicExecute.subst(iop)
2412068SN/A}};
2422068SN/A
2432068SN/Alet {{
2442068SN/Adef UncondCtrlBase(name, Name, base_class, npc_expr, flags):
2452068SN/A    # Declare basic control transfer w/o link (i.e. link reg is R31)
2467794Sgblack@eecs.umich.edu    nolink_code = 'NPC = %s;\n' % npc_expr
2477720Sgblack@eecs.umich.edu    nolink_iop = InstObjParams(name, Name, base_class,
2487794Sgblack@eecs.umich.edu                               nolink_code, flags)
2492068SN/A    header_output = BasicDeclare.subst(nolink_iop)
2502068SN/A    decoder_output = BasicConstructor.subst(nolink_iop)
2512068SN/A    exec_output = BasicExecute.subst(nolink_iop)
2522068SN/A
2532068SN/A    # Generate declaration of '*AndLink' version, append to decls
2547794Sgblack@eecs.umich.edu    link_code = 'Ra = NPC & ~3;\n' + nolink_code
2552068SN/A    link_iop = InstObjParams(name, Name + 'AndLink', base_class,
2567794Sgblack@eecs.umich.edu                             link_code, flags)
2572068SN/A    header_output += BasicDeclare.subst(link_iop)
2582068SN/A    decoder_output += BasicConstructor.subst(link_iop)
2592068SN/A    exec_output += BasicExecute.subst(link_iop)
2602068SN/A
2612068SN/A    # need to use link_iop for the decode template since it is expecting
2622068SN/A    # the shorter version of class_name (w/o "AndLink")
2632068SN/A
2642068SN/A    return (header_output, decoder_output,
2652068SN/A            JumpOrBranchDecode.subst(nolink_iop), exec_output)
2662068SN/A}};
2672068SN/A
2682068SN/Adef format UncondBranch(*flags) {{
2692068SN/A    flags += ('IsUncondControl', 'IsDirectControl')
2702068SN/A    (header_output, decoder_output, decode_block, exec_output) = \
2717794Sgblack@eecs.umich.edu        UncondCtrlBase(name, Name, 'Branch', 'NPC + disp', flags)
2722068SN/A}};
2732068SN/A
2742068SN/Adef format Jump(*flags) {{
2752068SN/A    flags += ('IsUncondControl', 'IsIndirectControl')
2762068SN/A    (header_output, decoder_output, decode_block, exec_output) = \
2777794Sgblack@eecs.umich.edu        UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (NPC & 1)', flags)
2782068SN/A}};
2792068SN/A
2802068SN/A
281