branch.isa revision 6019
16019Shines@cs.fsu.edu// -*- mode:c++ -*-
26019Shines@cs.fsu.edu
36019Shines@cs.fsu.edu// Copyright (c) 2007-2008 The Florida State University
46019Shines@cs.fsu.edu// All rights reserved.
56019Shines@cs.fsu.edu//
66019Shines@cs.fsu.edu// Redistribution and use in source and binary forms, with or without
76019Shines@cs.fsu.edu// modification, are permitted provided that the following conditions are
86019Shines@cs.fsu.edu// met: redistributions of source code must retain the above copyright
96019Shines@cs.fsu.edu// notice, this list of conditions and the following disclaimer;
106019Shines@cs.fsu.edu// redistributions in binary form must reproduce the above copyright
116019Shines@cs.fsu.edu// notice, this list of conditions and the following disclaimer in the
126019Shines@cs.fsu.edu// documentation and/or other materials provided with the distribution;
136019Shines@cs.fsu.edu// neither the name of the copyright holders nor the names of its
146019Shines@cs.fsu.edu// contributors may be used to endorse or promote products derived from
156019Shines@cs.fsu.edu// this software without specific prior written permission.
166019Shines@cs.fsu.edu//
176019Shines@cs.fsu.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
186019Shines@cs.fsu.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
196019Shines@cs.fsu.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
206019Shines@cs.fsu.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
216019Shines@cs.fsu.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
226019Shines@cs.fsu.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
236019Shines@cs.fsu.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
246019Shines@cs.fsu.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
256019Shines@cs.fsu.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
266019Shines@cs.fsu.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
276019Shines@cs.fsu.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
286019Shines@cs.fsu.edu//
296019Shines@cs.fsu.edu// Authors: Stephen Hines
306019Shines@cs.fsu.edu
316019Shines@cs.fsu.edu////////////////////////////////////////////////////////////////////
326019Shines@cs.fsu.edu//
336019Shines@cs.fsu.edu// Control transfer instructions
346019Shines@cs.fsu.edu//
356019Shines@cs.fsu.edu
366019Shines@cs.fsu.eduoutput header {{
376019Shines@cs.fsu.edu
386019Shines@cs.fsu.edu#include <iostream>
396019Shines@cs.fsu.edu
406019Shines@cs.fsu.edu    /**
416019Shines@cs.fsu.edu     * Base class for instructions whose disassembly is not purely a
426019Shines@cs.fsu.edu     * function of the machine instruction (i.e., it depends on the
436019Shines@cs.fsu.edu     * PC).  This class overrides the disassemble() method to check
446019Shines@cs.fsu.edu     * the PC and symbol table values before re-using a cached
456019Shines@cs.fsu.edu     * disassembly string.  This is necessary for branches and jumps,
466019Shines@cs.fsu.edu     * where the disassembly string includes the target address (which
476019Shines@cs.fsu.edu     * may depend on the PC and/or symbol table).
486019Shines@cs.fsu.edu     */
496019Shines@cs.fsu.edu    class PCDependentDisassembly : public PredOp
506019Shines@cs.fsu.edu    {
516019Shines@cs.fsu.edu      protected:
526019Shines@cs.fsu.edu        /// Cached program counter from last disassembly
536019Shines@cs.fsu.edu        mutable Addr cachedPC;
546019Shines@cs.fsu.edu
556019Shines@cs.fsu.edu        /// Cached symbol table pointer from last disassembly
566019Shines@cs.fsu.edu        mutable const SymbolTable *cachedSymtab;
576019Shines@cs.fsu.edu
586019Shines@cs.fsu.edu        /// Constructor
596019Shines@cs.fsu.edu        PCDependentDisassembly(const char *mnem, MachInst _machInst,
606019Shines@cs.fsu.edu                               OpClass __opClass)
616019Shines@cs.fsu.edu            : PredOp(mnem, _machInst, __opClass),
626019Shines@cs.fsu.edu              cachedPC(0), cachedSymtab(0)
636019Shines@cs.fsu.edu        {
646019Shines@cs.fsu.edu        }
656019Shines@cs.fsu.edu
666019Shines@cs.fsu.edu        const std::string &
676019Shines@cs.fsu.edu        disassemble(Addr pc, const SymbolTable *symtab) const;
686019Shines@cs.fsu.edu    };
696019Shines@cs.fsu.edu
706019Shines@cs.fsu.edu    /**
716019Shines@cs.fsu.edu     * Base class for branches (PC-relative control transfers),
726019Shines@cs.fsu.edu     * conditional or unconditional.
736019Shines@cs.fsu.edu     */
746019Shines@cs.fsu.edu    class Branch : public PCDependentDisassembly
756019Shines@cs.fsu.edu    {
766019Shines@cs.fsu.edu      protected:
776019Shines@cs.fsu.edu        /// target address (signed) Displacement .
786019Shines@cs.fsu.edu        int32_t disp;
796019Shines@cs.fsu.edu
806019Shines@cs.fsu.edu        /// Constructor.
816019Shines@cs.fsu.edu        Branch(const char *mnem, MachInst _machInst, OpClass __opClass)
826019Shines@cs.fsu.edu            : PCDependentDisassembly(mnem, _machInst, __opClass),
836019Shines@cs.fsu.edu              disp(OFFSET << 2)
846019Shines@cs.fsu.edu        {
856019Shines@cs.fsu.edu            //If Bit 26 is 1 then Sign Extend
866019Shines@cs.fsu.edu            if ( (disp & 0x02000000) > 0  ) {
876019Shines@cs.fsu.edu                disp |=  0xFC000000;
886019Shines@cs.fsu.edu            }
896019Shines@cs.fsu.edu        }
906019Shines@cs.fsu.edu
916019Shines@cs.fsu.edu        Addr branchTarget(Addr branchPC) const;
926019Shines@cs.fsu.edu
936019Shines@cs.fsu.edu        std::string
946019Shines@cs.fsu.edu        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
956019Shines@cs.fsu.edu    };
966019Shines@cs.fsu.edu
976019Shines@cs.fsu.edu    /**
986019Shines@cs.fsu.edu     * Base class for branch and exchange instructions on the ARM
996019Shines@cs.fsu.edu     */
1006019Shines@cs.fsu.edu    class BranchExchange : public PredOp
1016019Shines@cs.fsu.edu    {
1026019Shines@cs.fsu.edu      protected:
1036019Shines@cs.fsu.edu        /// Constructor
1046019Shines@cs.fsu.edu        BranchExchange(const char *mnem, MachInst _machInst,
1056019Shines@cs.fsu.edu                               OpClass __opClass)
1066019Shines@cs.fsu.edu            : PredOp(mnem, _machInst, __opClass)
1076019Shines@cs.fsu.edu        {
1086019Shines@cs.fsu.edu        }
1096019Shines@cs.fsu.edu
1106019Shines@cs.fsu.edu        std::string
1116019Shines@cs.fsu.edu        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
1126019Shines@cs.fsu.edu    };
1136019Shines@cs.fsu.edu
1146019Shines@cs.fsu.edu
1156019Shines@cs.fsu.edu    /**
1166019Shines@cs.fsu.edu     * Base class for jumps (register-indirect control transfers).  In
1176019Shines@cs.fsu.edu     * the Arm ISA, these are always unconditional.
1186019Shines@cs.fsu.edu     */
1196019Shines@cs.fsu.edu    class Jump : public PCDependentDisassembly
1206019Shines@cs.fsu.edu    {
1216019Shines@cs.fsu.edu      protected:
1226019Shines@cs.fsu.edu
1236019Shines@cs.fsu.edu        /// Displacement to target address (signed).
1246019Shines@cs.fsu.edu        int32_t disp;
1256019Shines@cs.fsu.edu
1266019Shines@cs.fsu.edu        uint32_t target;
1276019Shines@cs.fsu.edu
1286019Shines@cs.fsu.edu      public:
1296019Shines@cs.fsu.edu        /// Constructor
1306019Shines@cs.fsu.edu        Jump(const char *mnem, MachInst _machInst, OpClass __opClass)
1316019Shines@cs.fsu.edu            : PCDependentDisassembly(mnem, _machInst, __opClass),
1326019Shines@cs.fsu.edu              disp(OFFSET << 2)
1336019Shines@cs.fsu.edu        {
1346019Shines@cs.fsu.edu        }
1356019Shines@cs.fsu.edu
1366019Shines@cs.fsu.edu        Addr branchTarget(ThreadContext *tc) const;
1376019Shines@cs.fsu.edu
1386019Shines@cs.fsu.edu        std::string
1396019Shines@cs.fsu.edu        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
1406019Shines@cs.fsu.edu    };
1416019Shines@cs.fsu.edu}};
1426019Shines@cs.fsu.edu
1436019Shines@cs.fsu.eduoutput decoder {{
1446019Shines@cs.fsu.edu    Addr
1456019Shines@cs.fsu.edu    Branch::branchTarget(Addr branchPC) const
1466019Shines@cs.fsu.edu    {
1476019Shines@cs.fsu.edu        return branchPC + 8 + disp;
1486019Shines@cs.fsu.edu    }
1496019Shines@cs.fsu.edu
1506019Shines@cs.fsu.edu    Addr
1516019Shines@cs.fsu.edu    Jump::branchTarget(ThreadContext *tc) const
1526019Shines@cs.fsu.edu    {
1536019Shines@cs.fsu.edu        Addr NPC = tc->readPC() + 8;
1546019Shines@cs.fsu.edu        uint64_t Rb = tc->readIntReg(_srcRegIdx[0]);
1556019Shines@cs.fsu.edu        return (Rb & ~3) | (NPC & 1);
1566019Shines@cs.fsu.edu    }
1576019Shines@cs.fsu.edu
1586019Shines@cs.fsu.edu    const std::string &
1596019Shines@cs.fsu.edu    PCDependentDisassembly::disassemble(Addr pc,
1606019Shines@cs.fsu.edu                                        const SymbolTable *symtab) const
1616019Shines@cs.fsu.edu    {
1626019Shines@cs.fsu.edu        if (!cachedDisassembly ||
1636019Shines@cs.fsu.edu            pc != cachedPC || symtab != cachedSymtab)
1646019Shines@cs.fsu.edu        {
1656019Shines@cs.fsu.edu            if (cachedDisassembly)
1666019Shines@cs.fsu.edu                delete cachedDisassembly;
1676019Shines@cs.fsu.edu
1686019Shines@cs.fsu.edu            cachedDisassembly =
1696019Shines@cs.fsu.edu                new std::string(generateDisassembly(pc, symtab));
1706019Shines@cs.fsu.edu            cachedPC = pc;
1716019Shines@cs.fsu.edu            cachedSymtab = symtab;
1726019Shines@cs.fsu.edu        }
1736019Shines@cs.fsu.edu
1746019Shines@cs.fsu.edu        return *cachedDisassembly;
1756019Shines@cs.fsu.edu    }
1766019Shines@cs.fsu.edu
1776019Shines@cs.fsu.edu    std::string
1786019Shines@cs.fsu.edu    Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const
1796019Shines@cs.fsu.edu    {
1806019Shines@cs.fsu.edu        std::stringstream ss;
1816019Shines@cs.fsu.edu
1826019Shines@cs.fsu.edu        ccprintf(ss, "%-10s ", mnemonic);
1836019Shines@cs.fsu.edu
1846019Shines@cs.fsu.edu        Addr target = pc + 8 + disp;
1856019Shines@cs.fsu.edu
1866019Shines@cs.fsu.edu        std::string str;
1876019Shines@cs.fsu.edu        if (symtab && symtab->findSymbol(target, str))
1886019Shines@cs.fsu.edu            ss << str;
1896019Shines@cs.fsu.edu        else
1906019Shines@cs.fsu.edu            ccprintf(ss, "0x%x", target);
1916019Shines@cs.fsu.edu
1926019Shines@cs.fsu.edu        return ss.str();
1936019Shines@cs.fsu.edu    }
1946019Shines@cs.fsu.edu
1956019Shines@cs.fsu.edu    std::string
1966019Shines@cs.fsu.edu    BranchExchange::generateDisassembly(Addr pc, const SymbolTable *symtab) const
1976019Shines@cs.fsu.edu    {
1986019Shines@cs.fsu.edu        std::stringstream ss;
1996019Shines@cs.fsu.edu
2006019Shines@cs.fsu.edu        ccprintf(ss, "%-10s ", mnemonic);
2016019Shines@cs.fsu.edu
2026019Shines@cs.fsu.edu        if (_numSrcRegs > 0) {
2036019Shines@cs.fsu.edu            printReg(ss, _srcRegIdx[0]);
2046019Shines@cs.fsu.edu        }
2056019Shines@cs.fsu.edu
2066019Shines@cs.fsu.edu        return ss.str();
2076019Shines@cs.fsu.edu    }
2086019Shines@cs.fsu.edu
2096019Shines@cs.fsu.edu    std::string
2106019Shines@cs.fsu.edu    Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const
2116019Shines@cs.fsu.edu    {
2126019Shines@cs.fsu.edu        std::stringstream ss;
2136019Shines@cs.fsu.edu
2146019Shines@cs.fsu.edu        ccprintf(ss, "%-10s ", mnemonic);
2156019Shines@cs.fsu.edu
2166019Shines@cs.fsu.edu        return ss.str();
2176019Shines@cs.fsu.edu    }
2186019Shines@cs.fsu.edu}};
2196019Shines@cs.fsu.edu
2206019Shines@cs.fsu.edudef format Branch(code,*opt_flags) {{
2216019Shines@cs.fsu.edu
2226019Shines@cs.fsu.edu    #Build Instruction Flags
2236019Shines@cs.fsu.edu    #Use Link & Likely Flags to Add Link/Condition Code
2246019Shines@cs.fsu.edu    inst_flags = ('IsDirectControl', )
2256019Shines@cs.fsu.edu    for x in opt_flags:
2266019Shines@cs.fsu.edu        if x == 'Link':
2276019Shines@cs.fsu.edu            code += 'LR = NPC;\n'
2286019Shines@cs.fsu.edu        else:
2296019Shines@cs.fsu.edu            inst_flags += (x, )
2306019Shines@cs.fsu.edu
2316019Shines@cs.fsu.edu    #Take into account uncond. branch instruction
2326019Shines@cs.fsu.edu    if 'cond == 1' in code:
2336019Shines@cs.fsu.edu         inst_flags += ('IsUnCondControl', )
2346019Shines@cs.fsu.edu    else:
2356019Shines@cs.fsu.edu         inst_flags += ('IsCondControl', )
2366019Shines@cs.fsu.edu
2376019Shines@cs.fsu.edu    icode =  'if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) {\n'
2386019Shines@cs.fsu.edu    icode += code
2396019Shines@cs.fsu.edu    icode += '  NPC = NPC + 4 + disp;\n'
2406019Shines@cs.fsu.edu    icode += '} else {\n'
2416019Shines@cs.fsu.edu    icode += '  NPC = NPC;\n'
2426019Shines@cs.fsu.edu    icode += '};\n'
2436019Shines@cs.fsu.edu
2446019Shines@cs.fsu.edu    code = icode
2456019Shines@cs.fsu.edu
2466019Shines@cs.fsu.edu    iop = InstObjParams(name, Name, 'Branch', code, inst_flags)
2476019Shines@cs.fsu.edu    header_output = BasicDeclare.subst(iop)
2486019Shines@cs.fsu.edu    decoder_output = BasicConstructor.subst(iop)
2496019Shines@cs.fsu.edu    decode_block = BasicDecode.subst(iop)
2506019Shines@cs.fsu.edu    exec_output = BasicExecute.subst(iop)
2516019Shines@cs.fsu.edu}};
2526019Shines@cs.fsu.edu
2536019Shines@cs.fsu.edudef format BranchExchange(code,*opt_flags) {{
2546019Shines@cs.fsu.edu    #Build Instruction Flags
2556019Shines@cs.fsu.edu    #Use Link & Likely Flags to Add Link/Condition Code
2566019Shines@cs.fsu.edu    inst_flags = ('IsIndirectControl', )
2576019Shines@cs.fsu.edu    for x in opt_flags:
2586019Shines@cs.fsu.edu        if x == 'Link':
2596019Shines@cs.fsu.edu            code += 'LR = NPC;\n'
2606019Shines@cs.fsu.edu        else:
2616019Shines@cs.fsu.edu            inst_flags += (x, )
2626019Shines@cs.fsu.edu
2636019Shines@cs.fsu.edu    #Take into account uncond. branch instruction
2646019Shines@cs.fsu.edu    if 'cond == 1' in code:
2656019Shines@cs.fsu.edu         inst_flags += ('IsUnCondControl', )
2666019Shines@cs.fsu.edu    else:
2676019Shines@cs.fsu.edu         inst_flags += ('IsCondControl', )
2686019Shines@cs.fsu.edu
2696019Shines@cs.fsu.edu    #Condition code
2706019Shines@cs.fsu.edu
2716019Shines@cs.fsu.edu    icode =  'if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) {\n'
2726019Shines@cs.fsu.edu    icode += code
2736019Shines@cs.fsu.edu    icode += '  NPC = Rm & 0xfffffffe; // Masks off bottom bit\n'
2746019Shines@cs.fsu.edu    icode += '} else {\n'
2756019Shines@cs.fsu.edu    icode += '  NPC = NPC;\n'
2766019Shines@cs.fsu.edu    icode += '};\n'
2776019Shines@cs.fsu.edu
2786019Shines@cs.fsu.edu    code = icode
2796019Shines@cs.fsu.edu
2806019Shines@cs.fsu.edu    iop = InstObjParams(name, Name, 'BranchExchange', code, inst_flags)
2816019Shines@cs.fsu.edu    header_output = BasicDeclare.subst(iop)
2826019Shines@cs.fsu.edu    decoder_output = BasicConstructor.subst(iop)
2836019Shines@cs.fsu.edu    decode_block = BasicDecode.subst(iop)
2846019Shines@cs.fsu.edu    exec_output = BasicExecute.subst(iop)
2856019Shines@cs.fsu.edu}};
2866019Shines@cs.fsu.edu
2876019Shines@cs.fsu.edudef format Jump(code, *opt_flags) {{
2886019Shines@cs.fsu.edu    #Build Instruction Flags
2896019Shines@cs.fsu.edu    #Use Link Flag to Add Link Code
2906019Shines@cs.fsu.edu    inst_flags = ('IsIndirectControl', 'IsUncondControl')
2916019Shines@cs.fsu.edu    for x in opt_flags:
2926019Shines@cs.fsu.edu        if x == 'Link':
2936019Shines@cs.fsu.edu            code = 'LR = NPC;\n' + code
2946019Shines@cs.fsu.edu        elif x == 'ClearHazards':
2956019Shines@cs.fsu.edu            code += '/* Code Needed to Clear Execute & Inst Hazards */\n'
2966019Shines@cs.fsu.edu        else:
2976019Shines@cs.fsu.edu            inst_flags += (x, )
2986019Shines@cs.fsu.edu
2996019Shines@cs.fsu.edu    iop = InstObjParams(name, Name, 'Jump', code, inst_flags)
3006019Shines@cs.fsu.edu    header_output = BasicDeclare.subst(iop)
3016019Shines@cs.fsu.edu    decoder_output = BasicConstructor.subst(iop)
3026019Shines@cs.fsu.edu    decode_block = BasicDecode.subst(iop)
3036019Shines@cs.fsu.edu    exec_output = BasicExecute.subst(iop)
3046019Shines@cs.fsu.edu    #exec_output = PredOpExecute.subst(iop)
3056019Shines@cs.fsu.edu}};
3066019Shines@cs.fsu.edu
3076019Shines@cs.fsu.edu
308