branch.isa revision 5222
12100SN/A// -*- mode:c++ -*-
22083SN/A
35222Sksewell@umich.edu// Copyright .AN) 2007 MIPS Technologies, Inc.  All Rights Reserved
45222Sksewell@umich.edu
55222Sksewell@umich.edu//  This software is part of the M5 simulator.
65222Sksewell@umich.edu
75222Sksewell@umich.edu//  THIS IS A LEGAL AGREEMENT.  BY DOWNLOADING, USING, COPYING, CREATING
85222Sksewell@umich.edu//  DERIVATIVE WORKS, AND/OR DISTRIBUTING THIS SOFTWARE YOU ARE AGREEING
95222Sksewell@umich.edu//  TO THESE TERMS AND CONDITIONS.
105222Sksewell@umich.edu
115222Sksewell@umich.edu//  Permission is granted to use, copy, create derivative works and
125222Sksewell@umich.edu//  distribute this software and such derivative works for any purpose,
135222Sksewell@umich.edu//  so long as (1) the copyright notice above, this grant of permission,
145222Sksewell@umich.edu//  and the disclaimer below appear in all copies and derivative works
155222Sksewell@umich.edu//  made, (2) the copyright notice above is augmented as appropriate to
165222Sksewell@umich.edu//  reflect the addition of any new copyrightable work in a derivative
175222Sksewell@umich.edu//  work (e.g., Copyright .AN) <Publication Year> Copyright Owner), and (3)
185222Sksewell@umich.edu//  the name of MIPS Technologies, Inc. ($B!H(BMIPS$B!I(B) is not used in any
195222Sksewell@umich.edu//  advertising or publicity pertaining to the use or distribution of
205222Sksewell@umich.edu//  this software without specific, written prior authorization.
215222Sksewell@umich.edu
225222Sksewell@umich.edu//  THIS SOFTWARE IS PROVIDED $B!H(BAS IS.$B!I(B  MIPS MAKES NO WARRANTIES AND
235222Sksewell@umich.edu//  DISCLAIMS ALL WARRANTIES, WHETHER EXPRESS, STATUTORY, IMPLIED OR
245222Sksewell@umich.edu//  OTHERWISE, INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
255222Sksewell@umich.edu//  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
265222Sksewell@umich.edu//  NON-INFRINGEMENT OF THIRD PARTY RIGHTS, REGARDING THIS SOFTWARE.
275222Sksewell@umich.edu//  IN NO EVENT SHALL MIPS BE LIABLE FOR ANY DAMAGES, INCLUDING DIRECT,
285222Sksewell@umich.edu//  INDIRECT, INCIDENTAL, CONSEQUENTIAL, SPECIAL, OR PUNITIVE DAMAGES OF
295222Sksewell@umich.edu//  ANY KIND OR NATURE, ARISING OUT OF OR IN CONNECTION WITH THIS AGREEMENT,
305222Sksewell@umich.edu//  THIS SOFTWARE AND/OR THE USE OF THIS SOFTWARE, WHETHER SUCH LIABILITY
315222Sksewell@umich.edu//  IS ASSERTED ON THE BASIS OF CONTRACT, TORT (INCLUDING NEGLIGENCE OR
325222Sksewell@umich.edu//  STRICT LIABILITY), OR OTHERWISE, EVEN IF MIPS HAS BEEN WARNED OF THE
335222Sksewell@umich.edu//  POSSIBILITY OF ANY SUCH LOSS OR DAMAGE IN ADVANCE.
345222Sksewell@umich.edu
355222Sksewell@umich.edu//Authors: Korey L. Sewell
362706Sksewell@umich.edu
372089SN/A////////////////////////////////////////////////////////////////////
382022SN/A//
392089SN/A// Control transfer instructions
402022SN/A//
412022SN/A
422022SN/Aoutput header {{
432083SN/A
442239SN/A#include <iostream>
454661Sksewell@umich.edu    using namespace std;
462239SN/A
472083SN/A    /**
482083SN/A     * Base class for instructions whose disassembly is not purely a
492083SN/A     * function of the machine instruction (i.e., it depends on the
502083SN/A     * PC).  This class overrides the disassemble() method to check
512083SN/A     * the PC and symbol table values before re-using a cached
522083SN/A     * disassembly string.  This is necessary for branches and jumps,
532083SN/A     * where the disassembly string includes the target address (which
542083SN/A     * may depend on the PC and/or symbol table).
552083SN/A     */
562089SN/A    class PCDependentDisassembly : public MipsStaticInst
572083SN/A    {
582083SN/A      protected:
592083SN/A        /// Cached program counter from last disassembly
602083SN/A        mutable Addr cachedPC;
612089SN/A
622083SN/A        /// Cached symbol table pointer from last disassembly
632083SN/A        mutable const SymbolTable *cachedSymtab;
642083SN/A
652083SN/A        /// Constructor
662083SN/A        PCDependentDisassembly(const char *mnem, MachInst _machInst,
672083SN/A                               OpClass __opClass)
682089SN/A            : MipsStaticInst(mnem, _machInst, __opClass),
692083SN/A              cachedPC(0), cachedSymtab(0)
702022SN/A        {
712083SN/A        }
722022SN/A
732083SN/A        const std::string &
742083SN/A        disassemble(Addr pc, const SymbolTable *symtab) const;
752083SN/A    };
762022SN/A
772083SN/A    /**
782083SN/A     * Base class for branches (PC-relative control transfers),
792083SN/A     * conditional or unconditional.
802083SN/A     */
812083SN/A    class Branch : public PCDependentDisassembly
822083SN/A    {
832083SN/A      protected:
842089SN/A        /// target address (signed) Displacement .
852104SN/A        int32_t disp;
862083SN/A
872083SN/A        /// Constructor.
882083SN/A        Branch(const char *mnem, MachInst _machInst, OpClass __opClass)
892083SN/A            : PCDependentDisassembly(mnem, _machInst, __opClass),
902104SN/A              disp(OFFSET << 2)
912089SN/A        {
922239SN/A            //If Bit 17 is 1 then Sign Extend
932239SN/A            if ( (disp & 0x00020000) > 0  ) {
942239SN/A                disp |= 0xFFFE0000;
952239SN/A            }
962089SN/A        }
972089SN/A
982089SN/A        Addr branchTarget(Addr branchPC) const;
992089SN/A
1002089SN/A        std::string
1012089SN/A        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
1022089SN/A    };
1032089SN/A
1042089SN/A    /**
1052083SN/A     * Base class for jumps (register-indirect control transfers).  In
1062089SN/A     * the Mips ISA, these are always unconditional.
1072083SN/A     */
1082083SN/A    class Jump : public PCDependentDisassembly
1092083SN/A    {
1102083SN/A      protected:
1112083SN/A
1122083SN/A        /// Displacement to target address (signed).
1132083SN/A        int32_t disp;
1142083SN/A
1152239SN/A        uint32_t target;
1162239SN/A
1172083SN/A      public:
1182083SN/A        /// Constructor
1192083SN/A        Jump(const char *mnem, MachInst _machInst, OpClass __opClass)
1202083SN/A            : PCDependentDisassembly(mnem, _machInst, __opClass),
1212239SN/A              disp(JMPTARG << 2)
1222083SN/A        {
1232083SN/A        }
1242083SN/A
1252687Sksewell@umich.edu        Addr branchTarget(ThreadContext *tc) const;
1262083SN/A
1272083SN/A        std::string
1282083SN/A        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
1292083SN/A    };
1302022SN/A}};
1312022SN/A
1322022SN/Aoutput decoder {{
1332083SN/A    Addr
1342083SN/A    Branch::branchTarget(Addr branchPC) const
1352083SN/A    {
1362083SN/A        return branchPC + 4 + disp;
1372083SN/A    }
1382083SN/A
1392083SN/A    Addr
1402687Sksewell@umich.edu    Jump::branchTarget(ThreadContext *tc) const
1412083SN/A    {
1425222Sksewell@umich.edu      Addr NPC = tc->readNextPC();
1435222Sksewell@umich.edu      return (NPC & 0xF0000000) | (disp);
1442083SN/A    }
1452083SN/A
1462083SN/A    const std::string &
1472083SN/A    PCDependentDisassembly::disassemble(Addr pc,
1482083SN/A                                        const SymbolTable *symtab) const
1492083SN/A    {
1502083SN/A        if (!cachedDisassembly ||
1512083SN/A            pc != cachedPC || symtab != cachedSymtab)
1522022SN/A        {
1532083SN/A            if (cachedDisassembly)
1542083SN/A                delete cachedDisassembly;
1552083SN/A
1562083SN/A            cachedDisassembly =
1572083SN/A                new std::string(generateDisassembly(pc, symtab));
1582083SN/A            cachedPC = pc;
1592083SN/A            cachedSymtab = symtab;
1602022SN/A        }
1612083SN/A
1622083SN/A        return *cachedDisassembly;
1632083SN/A    }
1642083SN/A
1652083SN/A    std::string
1662083SN/A    Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const
1672083SN/A    {
1682083SN/A        std::stringstream ss;
1692083SN/A
1702083SN/A        ccprintf(ss, "%-10s ", mnemonic);
1712083SN/A
1722083SN/A        // There's only one register arg (RA), but it could be
1732083SN/A        // either a source (the condition for conditional
1742083SN/A        // branches) or a destination (the link reg for
1752083SN/A        // unconditional branches)
1762239SN/A        if (_numSrcRegs == 1) {
1772083SN/A            printReg(ss, _srcRegIdx[0]);
1782686Sksewell@umich.edu            ss << ", ";
1792239SN/A        } else if(_numSrcRegs == 2) {
1802239SN/A            printReg(ss, _srcRegIdx[0]);
1812686Sksewell@umich.edu            ss << ", ";
1822239SN/A            printReg(ss, _srcRegIdx[1]);
1832686Sksewell@umich.edu            ss << ", ";
1842103SN/A        }
1852103SN/A
1862103SN/A        Addr target = pc + 4 + disp;
1872103SN/A
1882103SN/A        std::string str;
1892103SN/A        if (symtab && symtab->findSymbol(target, str))
1902103SN/A            ss << str;
1912103SN/A        else
1922103SN/A            ccprintf(ss, "0x%x", target);
1932103SN/A
1942103SN/A        return ss.str();
1952103SN/A    }
1962103SN/A
1972103SN/A    std::string
1982083SN/A    Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const
1992083SN/A    {
2002083SN/A        std::stringstream ss;
2012083SN/A
2022083SN/A        ccprintf(ss, "%-10s ", mnemonic);
2032083SN/A
2045222Sksewell@umich.edu        if ( mnemonic == "jal" ) {
2052239SN/A            Addr npc = pc + 4;
2062239SN/A            ccprintf(ss,"0x%x",(npc & 0xF0000000) | disp);
2072239SN/A        } else if (_numSrcRegs == 0) {
2082239SN/A            std::string str;
2092239SN/A            if (symtab && symtab->findSymbol(disp, str))
2102239SN/A                ss << str;
2112239SN/A            else
2122239SN/A                ccprintf(ss, "0x%x", disp);
2132239SN/A        } else if (_numSrcRegs == 1) {
2142239SN/A             printReg(ss, _srcRegIdx[0]);
2152239SN/A        } else if(_numSrcRegs == 2) {
2162239SN/A            printReg(ss, _srcRegIdx[0]);
2172686Sksewell@umich.edu            ss << ", ";
2182239SN/A            printReg(ss, _srcRegIdx[1]);
2192083SN/A        }
2202083SN/A
2212083SN/A        return ss.str();
2222083SN/A    }
2232022SN/A}};
2242022SN/A
2254661Sksewell@umich.edudef format Branch(code, *opt_flags) {{
2262686Sksewell@umich.edu    not_taken_code = '  NNPC = NNPC;\n'
2272686Sksewell@umich.edu    not_taken_code += '} \n'
2282686Sksewell@umich.edu
2292686Sksewell@umich.edu    #Build Instruction Flags
2302686Sksewell@umich.edu    #Use Link & Likely Flags to Add Link/Condition Code
2312686Sksewell@umich.edu    inst_flags = ('IsDirectControl', )
2322686Sksewell@umich.edu    for x in opt_flags:
2332686Sksewell@umich.edu        if x == 'Link':
2342686Sksewell@umich.edu            code += 'R31 = NNPC;\n'
2352686Sksewell@umich.edu        elif x == 'Likely':
2362686Sksewell@umich.edu            not_taken_code = '  NPC = NNPC;\n'
2372686Sksewell@umich.edu            not_taken_code += '  NNPC = NNPC + 4;\n'
2382686Sksewell@umich.edu            not_taken_code += '} \n'
2394661Sksewell@umich.edu            inst_flags += ('IsCondDelaySlot', )
2402686Sksewell@umich.edu        else:
2412686Sksewell@umich.edu            inst_flags += (x, )
2422686Sksewell@umich.edu
2432935Sksewell@umich.edu    #Take into account uncond. branch instruction
2444661Sksewell@umich.edu    if 'cond = 1' in code:
2454661Sksewell@umich.edu         inst_flags += ('IsUncondControl', )
2462935Sksewell@umich.edu    else:
2472686Sksewell@umich.edu         inst_flags += ('IsCondControl', )
2482101SN/A
2492123SN/A    #Condition code
2502123SN/A    code = 'bool cond;\n' + code
2512123SN/A    code += 'if (cond) {\n'
2522123SN/A    code += '  NNPC = NPC + disp;\n'
2532239SN/A    code += '} else {\n'
2542686Sksewell@umich.edu    code += not_taken_code
2552101SN/A
2563951Sgblack@eecs.umich.edu    iop = InstObjParams(name, Name, 'Branch', code, inst_flags)
2572047SN/A    header_output = BasicDeclare.subst(iop)
2582047SN/A    decoder_output = BasicConstructor.subst(iop)
2592047SN/A    decode_block = BasicDecode.subst(iop)
2602047SN/A    exec_output = BasicExecute.subst(iop)
2612022SN/A}};
2622047SN/A
2634661Sksewell@umich.edudef format DspBranch(code, *opt_flags) {{
2644661Sksewell@umich.edu    not_taken_code = '  NNPC = NNPC;\n'
2654661Sksewell@umich.edu    not_taken_code += '} \n'
2664661Sksewell@umich.edu
2674661Sksewell@umich.edu    #Build Instruction Flags
2684661Sksewell@umich.edu    #Use Link & Likely Flags to Add Link/Condition Code
2694661Sksewell@umich.edu    inst_flags = ('IsDirectControl', )
2704661Sksewell@umich.edu    for x in opt_flags:
2714661Sksewell@umich.edu        if x == 'Link':
2724661Sksewell@umich.edu            code += 'R31 = NNPC;\n'
2734661Sksewell@umich.edu        elif x == 'Likely':
2744661Sksewell@umich.edu            not_taken_code = '  NPC = NNPC;\n'
2754661Sksewell@umich.edu            not_taken_code += '  NNPC = NNPC + 4;\n'
2764661Sksewell@umich.edu            not_taken_code += '} \n'
2774661Sksewell@umich.edu            inst_flags += ('IsCondDelaySlot', )
2784661Sksewell@umich.edu        else:
2794661Sksewell@umich.edu            inst_flags += (x, )
2804661Sksewell@umich.edu
2814661Sksewell@umich.edu    #Take into account uncond. branch instruction
2824661Sksewell@umich.edu    if 'cond = 1' in code:
2834661Sksewell@umich.edu         inst_flags += ('IsUncondControl', )
2844661Sksewell@umich.edu    else:
2854661Sksewell@umich.edu         inst_flags += ('IsCondControl', )
2864661Sksewell@umich.edu
2874661Sksewell@umich.edu    #Declaration code
2884661Sksewell@umich.edu    decl_code = 'bool cond;\n'
2894661Sksewell@umich.edu    decl_code += 'uint32_t dspctl;\n'
2904661Sksewell@umich.edu
2914661Sksewell@umich.edu    #Fetch code
2924661Sksewell@umich.edu    fetch_code = 'dspctl = DSPControl;\n'
2934661Sksewell@umich.edu
2944661Sksewell@umich.edu    #Condition code
2954661Sksewell@umich.edu    code = decl_code + fetch_code + code
2964661Sksewell@umich.edu    code += 'if (cond) {\n'
2974661Sksewell@umich.edu    code += '  NNPC = NPC + disp;\n'
2984661Sksewell@umich.edu    code += '} else {\n'
2994661Sksewell@umich.edu    code += not_taken_code
3004661Sksewell@umich.edu
3014661Sksewell@umich.edu    iop = InstObjParams(name, Name, 'Branch', code, inst_flags)
3024661Sksewell@umich.edu    header_output = BasicDeclare.subst(iop)
3034661Sksewell@umich.edu    decoder_output = BasicConstructor.subst(iop)
3044661Sksewell@umich.edu    decode_block = BasicDecode.subst(iop)
3054661Sksewell@umich.edu    exec_output = BasicExecute.subst(iop)
3064661Sksewell@umich.edu}};
3074661Sksewell@umich.edu
3082686Sksewell@umich.edudef format Jump(code, *opt_flags) {{
3092686Sksewell@umich.edu    #Build Instruction Flags
3102686Sksewell@umich.edu    #Use Link Flag to Add Link Code
3112686Sksewell@umich.edu    inst_flags = ('IsIndirectControl', 'IsUncondControl')
3122686Sksewell@umich.edu    for x in opt_flags:
3132686Sksewell@umich.edu        if x == 'Link':
3142686Sksewell@umich.edu            code = 'R31 = NNPC;\n' + code
3152686Sksewell@umich.edu        elif x == 'ClearHazards':
3162686Sksewell@umich.edu            code += '/* Code Needed to Clear Execute & Inst Hazards */\n'
3172686Sksewell@umich.edu        else:
3182686Sksewell@umich.edu            inst_flags += (x, )
3192104SN/A
3203951Sgblack@eecs.umich.edu    iop = InstObjParams(name, Name, 'Jump', code, inst_flags)
3212089SN/A    header_output = BasicDeclare.subst(iop)
3222089SN/A    decoder_output = BasicConstructor.subst(iop)
3232089SN/A    decode_block = BasicDecode.subst(iop)
3242089SN/A    exec_output = BasicExecute.subst(iop)
3252089SN/A}};
3262083SN/A
3272239SN/A
3282123SN/A
3292123SN/A
330