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