branch.isa revision 2701:38218635db4c
1// -*- mode:c++ -*-
2
3////////////////////////////////////////////////////////////////////
4//
5// Control transfer instructions
6//
7
8output header {{
9
10#include <iostream>
11    using namespace std;
12
13    /**
14     * Base class for instructions whose disassembly is not purely a
15     * function of the machine instruction (i.e., it depends on the
16     * PC).  This class overrides the disassemble() method to check
17     * the PC and symbol table values before re-using a cached
18     * disassembly string.  This is necessary for branches and jumps,
19     * where the disassembly string includes the target address (which
20     * may depend on the PC and/or symbol table).
21     */
22    class PCDependentDisassembly : public MipsStaticInst
23    {
24      protected:
25        /// Cached program counter from last disassembly
26        mutable Addr cachedPC;
27
28        /// Cached symbol table pointer from last disassembly
29        mutable const SymbolTable *cachedSymtab;
30
31        /// Constructor
32        PCDependentDisassembly(const char *mnem, MachInst _machInst,
33                               OpClass __opClass)
34            : MipsStaticInst(mnem, _machInst, __opClass),
35              cachedPC(0), cachedSymtab(0)
36        {
37        }
38
39        const std::string &
40        disassemble(Addr pc, const SymbolTable *symtab) const;
41    };
42
43    /**
44     * Base class for branches (PC-relative control transfers),
45     * conditional or unconditional.
46     */
47    class Branch : public PCDependentDisassembly
48    {
49      protected:
50        /// target address (signed) Displacement .
51        int32_t disp;
52
53        /// Constructor.
54        Branch(const char *mnem, MachInst _machInst, OpClass __opClass)
55            : PCDependentDisassembly(mnem, _machInst, __opClass),
56              disp(OFFSET << 2)
57        {
58            //If Bit 17 is 1 then Sign Extend
59            if ( (disp & 0x00020000) > 0  ) {
60                disp |= 0xFFFE0000;
61            }
62        }
63
64        Addr branchTarget(Addr branchPC) const;
65
66        std::string
67        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
68    };
69
70    /**
71     * Base class for branch likely branches (PC-relative control transfers),
72     */
73    class BranchLikely : public PCDependentDisassembly
74    {
75      protected:
76        /// target address (signed) Displacement .
77        int32_t disp;
78
79        /// Constructor.
80        BranchLikely(const char *mnem, MachInst _machInst, OpClass __opClass)
81            : PCDependentDisassembly(mnem, _machInst, __opClass),
82              disp(OFFSET << 2)
83        {
84
85        }
86
87        Addr branchTarget(Addr branchPC) const;
88
89        std::string
90        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
91    };
92
93    /**
94     * Base class for jumps (register-indirect control transfers).  In
95     * the Mips ISA, these are always unconditional.
96     */
97    class Jump : public PCDependentDisassembly
98    {
99      protected:
100
101        /// Displacement to target address (signed).
102        int32_t disp;
103
104        uint32_t target;
105
106      public:
107        /// Constructor
108        Jump(const char *mnem, MachInst _machInst, OpClass __opClass)
109            : PCDependentDisassembly(mnem, _machInst, __opClass),
110              disp(JMPTARG << 2)
111        {
112        }
113
114        Addr branchTarget(ThreadContext *tc) const;
115
116        std::string
117        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
118    };
119}};
120
121output decoder {{
122    Addr
123    Branch::branchTarget(Addr branchPC) const
124    {
125        return branchPC + 4 + disp;
126    }
127
128    Addr
129    BranchLikely::branchTarget(Addr branchPC) const
130    {
131        return branchPC + 4 + disp;
132    }
133
134    Addr
135    Jump::branchTarget(ThreadContext *tc) const
136    {
137        Addr NPC = tc->readPC() + 4;
138        uint64_t Rb = tc->readIntReg(_srcRegIdx[0]);
139        return (Rb & ~3) | (NPC & 1);
140    }
141
142    const std::string &
143    PCDependentDisassembly::disassemble(Addr pc,
144                                        const SymbolTable *symtab) const
145    {
146        if (!cachedDisassembly ||
147            pc != cachedPC || symtab != cachedSymtab)
148        {
149            if (cachedDisassembly)
150                delete cachedDisassembly;
151
152            cachedDisassembly =
153                new std::string(generateDisassembly(pc, symtab));
154            cachedPC = pc;
155            cachedSymtab = symtab;
156        }
157
158        return *cachedDisassembly;
159    }
160
161    std::string
162    Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const
163    {
164        std::stringstream ss;
165
166        ccprintf(ss, "%-10s ", mnemonic);
167
168        // There's only one register arg (RA), but it could be
169        // either a source (the condition for conditional
170        // branches) or a destination (the link reg for
171        // unconditional branches)
172        if (_numSrcRegs == 1) {
173            printReg(ss, _srcRegIdx[0]);
174            ss << ",";
175        } else if(_numSrcRegs == 2) {
176            printReg(ss, _srcRegIdx[0]);
177            ss << ",";
178            printReg(ss, _srcRegIdx[1]);
179            ss << ",";
180        }
181
182        Addr target = pc + 4 + disp;
183
184        std::string str;
185        if (symtab && symtab->findSymbol(target, str))
186            ss << str;
187        else
188            ccprintf(ss, "0x%x", target);
189
190        string inst_name = mnemonic;
191
192        if (inst_name.substr(inst_name.length()-2,inst_name.length()) == "al"){
193            ccprintf(ss, " (r31=0x%x)",pc+8);
194        }
195
196        return ss.str();
197    }
198
199    std::string
200    BranchLikely::generateDisassembly(Addr pc, const SymbolTable *symtab) const
201    {
202        std::stringstream ss;
203
204        ccprintf(ss, "%-10s ", mnemonic);
205
206        // There's only one register arg (RA), but it could be
207        // either a source (the condition for conditional
208        // branches) or a destination (the link reg for
209        // unconditional branches)
210        if (_numSrcRegs > 0) {
211            printReg(ss, _srcRegIdx[0]);
212            ss << ",";
213        }
214        else if (_numDestRegs > 0) {
215            printReg(ss, _destRegIdx[0]);
216            ss << ",";
217        }
218
219        Addr target = pc + 4 + disp;
220
221        std::string str;
222        if (symtab && symtab->findSymbol(target, str))
223            ss << str;
224        else
225            ccprintf(ss, "0x%x", target);
226
227        return ss.str();
228    }
229
230    std::string
231    Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const
232    {
233        std::stringstream ss;
234
235        ccprintf(ss, "%-10s ", mnemonic);
236
237        if ( mnemonic == "jal" ) {
238            Addr npc = pc + 4;
239            ccprintf(ss,"0x%x",(npc & 0xF0000000) | disp);
240        } else if (_numSrcRegs == 0) {
241            std::string str;
242            if (symtab && symtab->findSymbol(disp, str))
243                ss << str;
244            else
245                ccprintf(ss, "0x%x", disp);
246        } else if (_numSrcRegs == 1) {
247             printReg(ss, _srcRegIdx[0]);
248        } else if(_numSrcRegs == 2) {
249            printReg(ss, _srcRegIdx[0]);
250            ss << ",";
251            printReg(ss, _srcRegIdx[1]);
252        } else {
253            panic(">= 3 Source Registers!!!");
254        }
255
256        return ss.str();
257    }
258}};
259
260def format Branch(code,*flags) {{
261    #Add Link Code if Link instruction
262    strlen = len(name)
263    if name[strlen-2:] == 'al':
264        code += 'R31 = NNPC;\n'
265
266    #Condition code
267    code = 'bool cond;\n' + code
268    code += 'if (cond) {\n'
269    code += '  NNPC = NPC + disp;\n'
270    code += '} else {\n'
271    code += '  NNPC = NNPC;\n'
272    code += '} \n'
273
274    iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
275                        ('IsDirectControl', 'IsCondControl'))
276
277    header_output = BasicDeclare.subst(iop)
278    decoder_output = BasicConstructor.subst(iop)
279    decode_block = BasicDecode.subst(iop)
280    exec_output = BasicExecute.subst(iop)
281}};
282
283
284def format BranchLikely(code,*flags) {{
285    #Add Link Code if Link instruction
286    strlen = len(name)
287    if name[strlen-3:] == 'all':
288        code += 'R31 = NNPC;\n'
289
290    #Condition code
291    code = 'bool cond;\n' + code
292    code += 'if (cond) {'
293    code += 'NNPC = NPC + disp;\n'
294    code += '} \n'
295
296
297    iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
298                        ('IsDirectControl', 'IsCondControl','IsCondDelaySlot'))
299
300    header_output = BasicDeclare.subst(iop)
301    decoder_output = BasicConstructor.subst(iop)
302    decode_block = BasicDecode.subst(iop)
303    exec_output = BasicExecute.subst(iop)
304}};
305
306def format Jump(code,*flags) {{
307    #Add Link Code if Link instruction
308    strlen = len(name)
309    if strlen > 1 and name[1:] == 'al':
310            code = 'R31 = NNPC;\n' + code
311
312
313    iop = InstObjParams(name, Name, 'Jump', CodeBlock(code),\
314                        ('IsIndirectControl', 'IsUncondControl'))
315
316    header_output = BasicDeclare.subst(iop)
317    decoder_output = BasicConstructor.subst(iop)
318    decode_block = BasicDecode.subst(iop)
319    exec_output = BasicExecute.subst(iop)
320}};
321
322
323
324
325