branch.isa revision 2101
12089SN/A// -*- mode:c++ -*-
22022SN/A
35268Sksewell@umich.edu////////////////////////////////////////////////////////////////////
45222Sksewell@umich.edu//
55268Sksewell@umich.edu// Control transfer instructions
65268Sksewell@umich.edu//
75268Sksewell@umich.edu
85268Sksewell@umich.eduoutput header {{
95268Sksewell@umich.edu
105268Sksewell@umich.edu    /**
115268Sksewell@umich.edu     * Base class for instructions whose disassembly is not purely a
125268Sksewell@umich.edu     * function of the machine instruction (i.e., it depends on the
135268Sksewell@umich.edu     * PC).  This class overrides the disassemble() method to check
145268Sksewell@umich.edu     * the PC and symbol table values before re-using a cached
155268Sksewell@umich.edu     * disassembly string.  This is necessary for branches and jumps,
165268Sksewell@umich.edu     * where the disassembly string includes the target address (which
175268Sksewell@umich.edu     * may depend on the PC and/or symbol table).
185268Sksewell@umich.edu     */
195268Sksewell@umich.edu    class PCDependentDisassembly : public MipsStaticInst
205268Sksewell@umich.edu    {
215268Sksewell@umich.edu      protected:
225268Sksewell@umich.edu        /// Cached program counter from last disassembly
235268Sksewell@umich.edu        mutable Addr cachedPC;
245268Sksewell@umich.edu
255268Sksewell@umich.edu        /// Cached symbol table pointer from last disassembly
265268Sksewell@umich.edu        mutable const SymbolTable *cachedSymtab;
275268Sksewell@umich.edu
285268Sksewell@umich.edu        /// Constructor
295268Sksewell@umich.edu        PCDependentDisassembly(const char *mnem, MachInst _machInst,
305268Sksewell@umich.edu                               OpClass __opClass)
315268Sksewell@umich.edu            : MipsStaticInst(mnem, _machInst, __opClass),
325268Sksewell@umich.edu              cachedPC(0), cachedSymtab(0)
332706Sksewell@umich.edu        {
342022SN/A        }
352022SN/A
3612234Sgabeblack@google.com        const std::string &
372022SN/A        disassemble(Addr pc, const SymbolTable *symtab) const;
382022SN/A    };
392022SN/A
402022SN/A    /**
412022SN/A     * Base class for branches (PC-relative control transfers),
422022SN/A     * conditional or unconditional.
432022SN/A     */
442022SN/A    class Branch : public PCDependentDisassembly
452022SN/A    {
462686Sksewell@umich.edu      protected:
472022SN/A        /// target address (signed) Displacement .
482022SN/A        int32_t targetOffset;
492022SN/A
502686Sksewell@umich.edu        /// Constructor.
512022SN/A        Branch(const char *mnem, MachInst _machInst, OpClass __opClass)
522022SN/A            : PCDependentDisassembly(mnem, _machInst, __opClass),
532022SN/A              targetOffset(OFFSET << 2)
542022SN/A        {
5510184SCurtis.Dunham@arm.com        }
562022SN/A
572022SN/A        Addr branchTarget(Addr branchPC) const;
582022SN/A
592022SN/A        std::string
602022SN/A        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
612686Sksewell@umich.edu    };
622022SN/A
632022SN/A    /**
6412234Sgabeblack@google.com     * Base class for branch likely branches (PC-relative control transfers),
6512234Sgabeblack@google.com     */
662022SN/A    class BranchLikely : public PCDependentDisassembly
672239SN/A    {
682022SN/A      protected:
692022SN/A        /// target address (signed) Displacement .
702022SN/A        int32_t targetOffset;
712022SN/A
722239SN/A        /// Constructor.
732022SN/A        Branch(const char *mnem, MachInst _machInst, OpClass __opClass)
745222Sksewell@umich.edu            : PCDependentDisassembly(mnem, _machInst, __opClass),
755222Sksewell@umich.edu              targetOffset(OFFSET << 2)
762104SN/A        {
775222Sksewell@umich.edu        }
782022SN/A
792022SN/A        Addr branchTarget(Addr branchPC) const;
802022SN/A
812022SN/A        std::string
822022SN/A        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
832022SN/A    };
842022SN/A
852022SN/A    /**
862022SN/A     * Base class for jumps (register-indirect control transfers).  In
872022SN/A     * the Mips ISA, these are always unconditional.
882022SN/A     */
892022SN/A    class Jump : public PCDependentDisassembly
902022SN/A    {
912022SN/A      protected:
922022SN/A
932935Sksewell@umich.edu        /// Displacement to target address (signed).
942083SN/A        int32_t disp;
953951Sgblack@eecs.umich.edu
962022SN/A      public:
972022SN/A        /// Constructor
982022SN/A        Jump(const char *mnem, MachInst _machInst, OpClass __opClass)
992022SN/A            : PCDependentDisassembly(mnem, _machInst, __opClass),
1002022SN/A              disp(OFFSET)
101        {
102        }
103
104        Addr branchTarget(ExecContext *xc) const;
105
106        std::string
107        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
108    };
109}};
110
111output decoder {{
112    Addr
113    Branch::branchTarget(Addr branchPC) const
114    {
115        return branchPC + 4 + disp;
116    }
117
118    Addr
119    Jump::branchTarget(ExecContext *xc) const
120    {
121        Addr NPC = xc->readPC() + 4;
122        uint64_t Rb = xc->readIntReg(_srcRegIdx[0]);
123        return (Rb & ~3) | (NPC & 1);
124    }
125
126    const std::string &
127    PCDependentDisassembly::disassemble(Addr pc,
128                                        const SymbolTable *symtab) const
129    {
130        if (!cachedDisassembly ||
131            pc != cachedPC || symtab != cachedSymtab)
132        {
133            if (cachedDisassembly)
134                delete cachedDisassembly;
135
136            cachedDisassembly =
137                new std::string(generateDisassembly(pc, symtab));
138            cachedPC = pc;
139            cachedSymtab = symtab;
140        }
141
142        return *cachedDisassembly;
143    }
144
145    std::string
146    Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const
147    {
148        std::stringstream ss;
149
150        ccprintf(ss, "%-10s ", mnemonic);
151
152        // There's only one register arg (RA), but it could be
153        // either a source (the condition for conditional
154        // branches) or a destination (the link reg for
155        // unconditional branches)
156        if (_numSrcRegs > 0) {
157            printReg(ss, _srcRegIdx[0]);
158            ss << ",";
159        }
160        else if (_numDestRegs > 0) {
161            printReg(ss, _destRegIdx[0]);
162            ss << ",";
163        }
164
165#ifdef SS_COMPATIBLE_DISASSEMBLY
166        if (_numSrcRegs == 0 && _numDestRegs == 0) {
167            printReg(ss, 31);
168            ss << ",";
169        }
170#endif
171
172        Addr target = pc + 4 + disp;
173
174        std::string str;
175        if (symtab && symtab->findSymbol(target, str))
176            ss << str;
177        else
178            ccprintf(ss, "0x%x", target);
179
180        return ss.str();
181    }
182
183    std::string
184    Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const
185    {
186        std::stringstream ss;
187
188        ccprintf(ss, "%-10s ", mnemonic);
189
190#ifdef SS_COMPATIBLE_DISASSEMBLY
191        if (_numDestRegs == 0) {
192            printReg(ss, 31);
193            ss << ",";
194        }
195#endif
196
197        if (_numDestRegs > 0) {
198            printReg(ss, _destRegIdx[0]);
199            ss << ",";
200        }
201
202        ccprintf(ss, "(r%d)", RB);
203
204        return ss.str();
205    }
206}};
207
208
209def template JumpOrBranchDecode {{
210    return (RD == 0)
211        ? (StaticInst<MipsISA> *)new %(class_name)s(machInst)
212        : (StaticInst<MipsISA> *)new %(class_name)sAndLink(machInst);
213}};
214
215def format Branch(code,*flags) {{
216    code = 'bool cond;\n' + code + '\n'
217
218    if flags == 'IsLink':
219        code += 'R31 = NPC + 8\n'
220
221    code += '\nif (cond) NPC = NPC + disp;\n';
222
223    iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
224                        ('IsDirectControl', 'IsCondControl'))
225    header_output = BasicDeclare.subst(iop)
226    decoder_output = BasicConstructor.subst(iop)
227    decode_block = BasicDecode.subst(iop)
228    exec_output = BasicExecute.subst(iop)
229}};
230
231def format BranchLikely(code,*flags) {{
232    code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\n';
233
234    if flags == 'IsLink':
235        code += 'R31 = NPC + 8\n'
236
237    iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
238                        ('IsDirectControl', 'IsCondControl','IsCondDelaySlot'))
239    header_output = BasicDeclare.subst(iop)
240    decoder_output = BasicConstructor.subst(iop)
241    decode_block = BasicDecode.subst(iop)
242    exec_output = BasicExecute.subst(iop)
243}};
244
245def format Unconditional(code,*flags) {{
246    iop = InstObjParams(name, Name, 'Jump', CodeBlock(code),
247                        ('IsIndirectControl', 'IsUncondControl'))
248    header_output = BasicDeclare.subst(iop)
249    decoder_output = BasicConstructor.subst(iop)
250    decode_block = BasicDecode.subst(iop)
251    exec_output = BasicExecute.subst(iop)
252}};
253
254
255
256
257