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