branch.isa revision 3951
12100SN/A// -*- mode:c++ -*-
22083SN/A
32754Sksewell@umich.edu// Copyright (c) 2006 The Regents of The University of Michigan
42706Sksewell@umich.edu// All rights reserved.
52706Sksewell@umich.edu//
62706Sksewell@umich.edu// Redistribution and use in source and binary forms, with or without
72706Sksewell@umich.edu// modification, are permitted provided that the following conditions are
82706Sksewell@umich.edu// met: redistributions of source code must retain the above copyright
92706Sksewell@umich.edu// notice, this list of conditions and the following disclaimer;
102706Sksewell@umich.edu// redistributions in binary form must reproduce the above copyright
112706Sksewell@umich.edu// notice, this list of conditions and the following disclaimer in the
122706Sksewell@umich.edu// documentation and/or other materials provided with the distribution;
132706Sksewell@umich.edu// neither the name of the copyright holders nor the names of its
142706Sksewell@umich.edu// contributors may be used to endorse or promote products derived from
152706Sksewell@umich.edu// this software without specific prior written permission.
162706Sksewell@umich.edu//
172706Sksewell@umich.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
182706Sksewell@umich.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
192706Sksewell@umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
202706Sksewell@umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
212706Sksewell@umich.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
222706Sksewell@umich.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
232706Sksewell@umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
242706Sksewell@umich.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
252706Sksewell@umich.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
262706Sksewell@umich.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
272706Sksewell@umich.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
282706Sksewell@umich.edu//
292706Sksewell@umich.edu// Authors: Korey Sewell
302706Sksewell@umich.edu
312089SN/A////////////////////////////////////////////////////////////////////
322022SN/A//
332089SN/A// Control transfer instructions
342022SN/A//
352022SN/A
362022SN/Aoutput header {{
372083SN/A
382239SN/A#include <iostream>
392239SN/A
402083SN/A    /**
412083SN/A     * Base class for instructions whose disassembly is not purely a
422083SN/A     * function of the machine instruction (i.e., it depends on the
432083SN/A     * PC).  This class overrides the disassemble() method to check
442083SN/A     * the PC and symbol table values before re-using a cached
452083SN/A     * disassembly string.  This is necessary for branches and jumps,
462083SN/A     * where the disassembly string includes the target address (which
472083SN/A     * may depend on the PC and/or symbol table).
482083SN/A     */
492089SN/A    class PCDependentDisassembly : public MipsStaticInst
502083SN/A    {
512083SN/A      protected:
522083SN/A        /// Cached program counter from last disassembly
532083SN/A        mutable Addr cachedPC;
542089SN/A
552083SN/A        /// Cached symbol table pointer from last disassembly
562083SN/A        mutable const SymbolTable *cachedSymtab;
572083SN/A
582083SN/A        /// Constructor
592083SN/A        PCDependentDisassembly(const char *mnem, MachInst _machInst,
602083SN/A                               OpClass __opClass)
612089SN/A            : MipsStaticInst(mnem, _machInst, __opClass),
622083SN/A              cachedPC(0), cachedSymtab(0)
632022SN/A        {
642083SN/A        }
652022SN/A
662083SN/A        const std::string &
672083SN/A        disassemble(Addr pc, const SymbolTable *symtab) const;
682083SN/A    };
692022SN/A
702083SN/A    /**
712083SN/A     * Base class for branches (PC-relative control transfers),
722083SN/A     * conditional or unconditional.
732083SN/A     */
742083SN/A    class Branch : public PCDependentDisassembly
752083SN/A    {
762083SN/A      protected:
772089SN/A        /// target address (signed) Displacement .
782104SN/A        int32_t disp;
792083SN/A
802083SN/A        /// Constructor.
812083SN/A        Branch(const char *mnem, MachInst _machInst, OpClass __opClass)
822083SN/A            : PCDependentDisassembly(mnem, _machInst, __opClass),
832104SN/A              disp(OFFSET << 2)
842089SN/A        {
852239SN/A            //If Bit 17 is 1 then Sign Extend
862239SN/A            if ( (disp & 0x00020000) > 0  ) {
872239SN/A                disp |= 0xFFFE0000;
882239SN/A            }
892089SN/A        }
902089SN/A
912089SN/A        Addr branchTarget(Addr branchPC) const;
922089SN/A
932089SN/A        std::string
942089SN/A        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
952089SN/A    };
962089SN/A
972089SN/A    /**
982083SN/A     * Base class for jumps (register-indirect control transfers).  In
992089SN/A     * the Mips ISA, these are always unconditional.
1002083SN/A     */
1012083SN/A    class Jump : public PCDependentDisassembly
1022083SN/A    {
1032083SN/A      protected:
1042083SN/A
1052083SN/A        /// Displacement to target address (signed).
1062083SN/A        int32_t disp;
1072083SN/A
1082239SN/A        uint32_t target;
1092239SN/A
1102083SN/A      public:
1112083SN/A        /// Constructor
1122083SN/A        Jump(const char *mnem, MachInst _machInst, OpClass __opClass)
1132083SN/A            : PCDependentDisassembly(mnem, _machInst, __opClass),
1142239SN/A              disp(JMPTARG << 2)
1152083SN/A        {
1162083SN/A        }
1172083SN/A
1182687Sksewell@umich.edu        Addr branchTarget(ThreadContext *tc) const;
1192083SN/A
1202083SN/A        std::string
1212083SN/A        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
1222083SN/A    };
1232022SN/A}};
1242022SN/A
1252022SN/Aoutput decoder {{
1262083SN/A    Addr
1272083SN/A    Branch::branchTarget(Addr branchPC) const
1282083SN/A    {
1292083SN/A        return branchPC + 4 + disp;
1302083SN/A    }
1312083SN/A
1322083SN/A    Addr
1332687Sksewell@umich.edu    Jump::branchTarget(ThreadContext *tc) const
1342083SN/A    {
1352687Sksewell@umich.edu        Addr NPC = tc->readPC() + 4;
1362687Sksewell@umich.edu        uint64_t Rb = tc->readIntReg(_srcRegIdx[0]);
1372083SN/A        return (Rb & ~3) | (NPC & 1);
1382083SN/A    }
1392083SN/A
1402083SN/A    const std::string &
1412083SN/A    PCDependentDisassembly::disassemble(Addr pc,
1422083SN/A                                        const SymbolTable *symtab) const
1432083SN/A    {
1442083SN/A        if (!cachedDisassembly ||
1452083SN/A            pc != cachedPC || symtab != cachedSymtab)
1462022SN/A        {
1472083SN/A            if (cachedDisassembly)
1482083SN/A                delete cachedDisassembly;
1492083SN/A
1502083SN/A            cachedDisassembly =
1512083SN/A                new std::string(generateDisassembly(pc, symtab));
1522083SN/A            cachedPC = pc;
1532083SN/A            cachedSymtab = symtab;
1542022SN/A        }
1552083SN/A
1562083SN/A        return *cachedDisassembly;
1572083SN/A    }
1582083SN/A
1592083SN/A    std::string
1602083SN/A    Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const
1612083SN/A    {
1622083SN/A        std::stringstream ss;
1632083SN/A
1642083SN/A        ccprintf(ss, "%-10s ", mnemonic);
1652083SN/A
1662083SN/A        // There's only one register arg (RA), but it could be
1672083SN/A        // either a source (the condition for conditional
1682083SN/A        // branches) or a destination (the link reg for
1692083SN/A        // unconditional branches)
1702239SN/A        if (_numSrcRegs == 1) {
1712083SN/A            printReg(ss, _srcRegIdx[0]);
1722686Sksewell@umich.edu            ss << ", ";
1732239SN/A        } else if(_numSrcRegs == 2) {
1742239SN/A            printReg(ss, _srcRegIdx[0]);
1752686Sksewell@umich.edu            ss << ", ";
1762239SN/A            printReg(ss, _srcRegIdx[1]);
1772686Sksewell@umich.edu            ss << ", ";
1782103SN/A        }
1792103SN/A
1802103SN/A        Addr target = pc + 4 + disp;
1812103SN/A
1822103SN/A        std::string str;
1832103SN/A        if (symtab && symtab->findSymbol(target, str))
1842103SN/A            ss << str;
1852103SN/A        else
1862103SN/A            ccprintf(ss, "0x%x", target);
1872103SN/A
1882103SN/A        return ss.str();
1892103SN/A    }
1902103SN/A
1912103SN/A    std::string
1922083SN/A    Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const
1932083SN/A    {
1942083SN/A        std::stringstream ss;
1952083SN/A
1962083SN/A        ccprintf(ss, "%-10s ", mnemonic);
1972083SN/A
1982239SN/A        if ( mnemonic == "jal" ) {
1992239SN/A            Addr npc = pc + 4;
2002239SN/A            ccprintf(ss,"0x%x",(npc & 0xF0000000) | disp);
2012239SN/A        } else if (_numSrcRegs == 0) {
2022239SN/A            std::string str;
2032239SN/A            if (symtab && symtab->findSymbol(disp, str))
2042239SN/A                ss << str;
2052239SN/A            else
2062239SN/A                ccprintf(ss, "0x%x", disp);
2072239SN/A        } else if (_numSrcRegs == 1) {
2082239SN/A             printReg(ss, _srcRegIdx[0]);
2092239SN/A        } else if(_numSrcRegs == 2) {
2102239SN/A            printReg(ss, _srcRegIdx[0]);
2112686Sksewell@umich.edu            ss << ", ";
2122239SN/A            printReg(ss, _srcRegIdx[1]);
2132083SN/A        }
2142083SN/A
2152083SN/A        return ss.str();
2162083SN/A    }
2172022SN/A}};
2182022SN/A
2192686Sksewell@umich.edudef format Branch(code,*opt_flags) {{
2202686Sksewell@umich.edu    not_taken_code = '  NNPC = NNPC;\n'
2212686Sksewell@umich.edu    not_taken_code += '} \n'
2222686Sksewell@umich.edu
2232686Sksewell@umich.edu    #Build Instruction Flags
2242686Sksewell@umich.edu    #Use Link & Likely Flags to Add Link/Condition Code
2252686Sksewell@umich.edu    inst_flags = ('IsDirectControl', )
2262686Sksewell@umich.edu    for x in opt_flags:
2272686Sksewell@umich.edu        if x == 'Link':
2282686Sksewell@umich.edu            code += 'R31 = NNPC;\n'
2292686Sksewell@umich.edu        elif x == 'Likely':
2302686Sksewell@umich.edu            not_taken_code = '  NPC = NNPC;\n'
2312686Sksewell@umich.edu            not_taken_code += '  NNPC = NNPC + 4;\n'
2322686Sksewell@umich.edu            not_taken_code += '} \n'
2332686Sksewell@umich.edu            inst_flags = ('IsCondDelaySlot', )
2342686Sksewell@umich.edu        else:
2352686Sksewell@umich.edu            inst_flags += (x, )
2362686Sksewell@umich.edu
2372935Sksewell@umich.edu    #Take into account uncond. branch instruction
2382686Sksewell@umich.edu    if 'cond == 1' in code:
2392935Sksewell@umich.edu         inst_flags += ('IsUnCondControl', )
2402935Sksewell@umich.edu    else:
2412686Sksewell@umich.edu         inst_flags += ('IsCondControl', )
2422101SN/A
2432123SN/A    #Condition code
2442123SN/A    code = 'bool cond;\n' + code
2452123SN/A    code += 'if (cond) {\n'
2462123SN/A    code += '  NNPC = NPC + disp;\n'
2472239SN/A    code += '} else {\n'
2482686Sksewell@umich.edu    code += not_taken_code
2492101SN/A
2503951Sgblack@eecs.umich.edu    iop = InstObjParams(name, Name, 'Branch', code, inst_flags)
2512047SN/A    header_output = BasicDeclare.subst(iop)
2522047SN/A    decoder_output = BasicConstructor.subst(iop)
2532047SN/A    decode_block = BasicDecode.subst(iop)
2542047SN/A    exec_output = BasicExecute.subst(iop)
2552022SN/A}};
2562047SN/A
2572686Sksewell@umich.edudef format Jump(code, *opt_flags) {{
2582686Sksewell@umich.edu    #Build Instruction Flags
2592686Sksewell@umich.edu    #Use Link Flag to Add Link Code
2602686Sksewell@umich.edu    inst_flags = ('IsIndirectControl', 'IsUncondControl')
2612686Sksewell@umich.edu    for x in opt_flags:
2622686Sksewell@umich.edu        if x == 'Link':
2632686Sksewell@umich.edu            code = 'R31 = NNPC;\n' + code
2642686Sksewell@umich.edu        elif x == 'ClearHazards':
2652686Sksewell@umich.edu            code += '/* Code Needed to Clear Execute & Inst Hazards */\n'
2662686Sksewell@umich.edu        else:
2672686Sksewell@umich.edu            inst_flags += (x, )
2682104SN/A
2693951Sgblack@eecs.umich.edu    iop = InstObjParams(name, Name, 'Jump', code, inst_flags)
2702089SN/A    header_output = BasicDeclare.subst(iop)
2712089SN/A    decoder_output = BasicConstructor.subst(iop)
2722089SN/A    decode_block = BasicDecode.subst(iop)
2732089SN/A    exec_output = BasicExecute.subst(iop)
2742089SN/A}};
2752083SN/A
2762239SN/A
2772123SN/A
2782123SN/A
279