branch.isa

来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· ISA 代码 · 共 265 行

ISA
265
字号
// -*- mode:c++ -*-//Copyright (c) 2003, 2004, 2005//The Regents of The University of Michigan//All Rights Reserved//This code is part of the M5 simulator.//Permission is granted to use, copy, create derivative works and//redistribute this software and such derivative works for any purpose,//so long as the copyright notice above, this grant of permission, and//the disclaimer below appear in all copies made; and so long as the//name of The University of Michigan is not used in any advertising or//publicity pertaining to the use or distribution of this software//without specific, written prior authorization.//THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE//UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND WITHOUT//WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER EXPRESS OR//IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF//MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE REGENTS OF//THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE FOR ANY DAMAGES,//INCLUDING DIRECT, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL//DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT OF OR IN CONNECTION//WITH THE USE OF THE SOFTWARE, EVEN IF IT HAS BEEN OR IS HEREAFTER//ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.//Authors: Steven K. Reinhardt//////////////////////////////////////////////////////////////////////// Control transfer instructions//output header {{    /**     * Base class for instructions whose disassembly is not purely a     * function of the machine instruction (i.e., it depends on the     * PC).  This class overrides the disassemble() method to check     * the PC and symbol table values before re-using a cached     * disassembly string.  This is necessary for branches and jumps,     * where the disassembly string includes the target address (which     * may depend on the PC and/or symbol table).     */    class PCDependentDisassembly : public AlphaStaticInst    {      protected:        /// Cached program counter from last disassembly        mutable Addr cachedPC;        /// Cached symbol table pointer from last disassembly        mutable const SymbolTable *cachedSymtab;        /// Constructor        PCDependentDisassembly(const char *mnem, ExtMachInst _machInst,                               OpClass __opClass)            : AlphaStaticInst(mnem, _machInst, __opClass),              cachedPC(0), cachedSymtab(0)        {        }        const std::string &        disassemble(Addr pc, const SymbolTable *symtab) const;    };    /**     * Base class for branches (PC-relative control transfers),     * conditional or unconditional.     */    class Branch : public PCDependentDisassembly    {      protected:        /// Displacement to target address (signed).        int32_t disp;        /// Constructor.        Branch(const char *mnem, ExtMachInst _machInst, OpClass __opClass)            : PCDependentDisassembly(mnem, _machInst, __opClass),              disp(BRDISP << 2)        {        }        Addr branchTarget(Addr branchPC) const;        std::string        generateDisassembly(Addr pc, const SymbolTable *symtab) const;    };    /**     * Base class for jumps (register-indirect control transfers).  In     * the Alpha ISA, these are always unconditional.     */    class Jump : public PCDependentDisassembly    {      protected:        /// Displacement to target address (signed).        int32_t disp;      public:        /// Constructor        Jump(const char *mnem, ExtMachInst _machInst, OpClass __opClass)            : PCDependentDisassembly(mnem, _machInst, __opClass),              disp(BRDISP)        {        }        Addr branchTarget(ThreadContext *tc) const;        std::string        generateDisassembly(Addr pc, const SymbolTable *symtab) const;    };}};output decoder {{    Addr    Branch::branchTarget(Addr branchPC) const    {        return branchPC + 4 + disp;    }    Addr    Jump::branchTarget(ThreadContext *tc) const    {        Addr NPC = tc->readPC() + 4;        uint64_t Rb = tc->readIntReg(_srcRegIdx[0]);        return (Rb & ~3) | (NPC & 1);    }    const std::string &    PCDependentDisassembly::disassemble(Addr pc,                                        const SymbolTable *symtab) const    {        if (!cachedDisassembly ||            pc != cachedPC || symtab != cachedSymtab)        {            if (cachedDisassembly)                delete cachedDisassembly;            cachedDisassembly =                new std::string(generateDisassembly(pc, symtab));            cachedPC = pc;            cachedSymtab = symtab;        }        return *cachedDisassembly;    }    std::string    Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const    {        std::stringstream ss;        ccprintf(ss, "%-10s ", mnemonic);        // There's only one register arg (RA), but it could be        // either a source (the condition for conditional        // branches) or a destination (the link reg for        // unconditional branches)        if (_numSrcRegs > 0) {            printReg(ss, _srcRegIdx[0]);            ss << ",";        }        else if (_numDestRegs > 0) {            printReg(ss, _destRegIdx[0]);            ss << ",";        }#ifdef SS_COMPATIBLE_DISASSEMBLY        if (_numSrcRegs == 0 && _numDestRegs == 0) {            printReg(ss, 31);            ss << ",";        }#endif        Addr target = pc + 4 + disp;        std::string str;        if (symtab && symtab->findSymbol(target, str))            ss << str;        else            ccprintf(ss, "0x%x", target);        return ss.str();    }    std::string    Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const    {        std::stringstream ss;        ccprintf(ss, "%-10s ", mnemonic);#ifdef SS_COMPATIBLE_DISASSEMBLY        if (_numDestRegs == 0) {            printReg(ss, 31);            ss << ",";        }#endif        if (_numDestRegs > 0) {            printReg(ss, _destRegIdx[0]);            ss << ",";        }        ccprintf(ss, "(r%d)", RB);        return ss.str();    }}};def template JumpOrBranchDecode {{    return (RA == 31)        ? (StaticInst *)new %(class_name)s(machInst)        : (StaticInst *)new %(class_name)sAndLink(machInst);}};def format CondBranch(code) {{    code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\n';    iop = InstObjParams(name, Name, 'Branch', code,                        ('IsDirectControl', 'IsCondControl'))    header_output = BasicDeclare.subst(iop)    decoder_output = BasicConstructor.subst(iop)    decode_block = BasicDecode.subst(iop)    exec_output = BasicExecute.subst(iop)}};let {{def UncondCtrlBase(name, Name, base_class, npc_expr, flags):    # Declare basic control transfer w/o link (i.e. link reg is R31)    nolink_code = 'NPC = %s;\n' % npc_expr    nolink_iop = InstObjParams(name, Name, base_class, nolink_code, flags)    header_output = BasicDeclare.subst(nolink_iop)    decoder_output = BasicConstructor.subst(nolink_iop)    exec_output = BasicExecute.subst(nolink_iop)    # Generate declaration of '*AndLink' version, append to decls    link_code = 'Ra = NPC & ~3;\n' + nolink_code    link_iop = InstObjParams(name, Name + 'AndLink', base_class,                             link_code, flags)    header_output += BasicDeclare.subst(link_iop)    decoder_output += BasicConstructor.subst(link_iop)    exec_output += BasicExecute.subst(link_iop)    # need to use link_iop for the decode template since it is expecting    # the shorter version of class_name (w/o "AndLink")    return (header_output, decoder_output,            JumpOrBranchDecode.subst(nolink_iop), exec_output)}};def format UncondBranch(*flags) {{    flags += ('IsUncondControl', 'IsDirectControl')    (header_output, decoder_output, decode_block, exec_output) = \        UncondCtrlBase(name, Name, 'Branch', 'NPC + disp', flags)}};def format Jump(*flags) {{    flags += ('IsUncondControl', 'IsIndirectControl')    (header_output, decoder_output, decode_block, exec_output) = \        UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (NPC & 1)', flags)}};

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?