branch.isa revision 2239
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(ExecContext *xc) 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(ExecContext *xc) const
136    {
137        Addr NPC = xc->readPC() + 4;
138        uint64_t Rb = xc->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 + 8 + 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        return ss.str();
191    }
192
193    std::string
194    BranchLikely::generateDisassembly(Addr pc, const SymbolTable *symtab) const
195    {
196        std::stringstream ss;
197
198        ccprintf(ss, "%-10s ", mnemonic);
199
200        // There's only one register arg (RA), but it could be
201        // either a source (the condition for conditional
202        // branches) or a destination (the link reg for
203        // unconditional branches)
204        if (_numSrcRegs > 0) {
205            printReg(ss, _srcRegIdx[0]);
206            ss << ",";
207        }
208        else if (_numDestRegs > 0) {
209            printReg(ss, _destRegIdx[0]);
210            ss << ",";
211        }
212
213        Addr target = pc + 4 + disp;
214
215        std::string str;
216        if (symtab && symtab->findSymbol(target, str))
217            ss << str;
218        else
219            ccprintf(ss, "0x%x", target);
220
221        return ss.str();
222    }
223
224    std::string
225    Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const
226    {
227        std::stringstream ss;
228
229        ccprintf(ss, "%-10s ", mnemonic);
230
231        if ( mnemonic == "jal" ) {
232            Addr npc = pc + 4;
233            ccprintf(ss,"0x%x",(npc & 0xF0000000) | disp);
234        } else if (_numSrcRegs == 0) {
235            std::string str;
236            if (symtab && symtab->findSymbol(disp, str))
237                ss << str;
238            else
239                ccprintf(ss, "0x%x", disp);
240        } else if (_numSrcRegs == 1) {
241             printReg(ss, _srcRegIdx[0]);
242        } else if(_numSrcRegs == 2) {
243            printReg(ss, _srcRegIdx[0]);
244            ss << ",";
245            printReg(ss, _srcRegIdx[1]);
246        } else {
247            panic(">= 3 Source Registers!!!");
248        }
249
250        return ss.str();
251    }
252}};
253
254def format Branch(code,*flags) {{
255    #Add Link Code if Link instruction
256    strlen = len(name)
257    if name[strlen-2:] == 'al':
258        code += 'r31 = NNPC;\n'
259
260    #Condition code
261    code = 'bool cond;\n' + code
262    code += 'if (cond) {\n'
263    code += '  NNPC = NPC + disp;\n'
264    code += '} else {\n'
265    code += '  NNPC = NNPC;\n'
266    code += '} \n'
267
268    code += 'cout << hex << "NPC: " << NPC << " + " << disp << " = " << NNPC << endl;'
269
270    iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
271                        ('IsDirectControl', 'IsCondControl'))
272
273    header_output = BasicDeclare.subst(iop)
274    decoder_output = BasicConstructor.subst(iop)
275    decode_block = BasicDecode.subst(iop)
276    exec_output = BasicExecute.subst(iop)
277}};
278
279
280def format BranchLikely(code,*flags) {{
281    #Add Link Code if Link instruction
282    strlen = len(name)
283    if name[strlen-3:] == 'all':
284        code += 'r31 = NNPC;\n'
285
286    #Condition code
287    code = 'bool cond;\n' + code
288    code += 'if (cond) {'
289    code += 'NNPC = NPC + disp;\n'
290    code += '} \n'
291
292
293    iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
294                        ('IsDirectControl', 'IsCondControl','IsCondDelaySlot'))
295
296    header_output = BasicDeclare.subst(iop)
297    decoder_output = BasicConstructor.subst(iop)
298    decode_block = BasicDecode.subst(iop)
299    exec_output = BasicExecute.subst(iop)
300}};
301
302def format Jump(code,*flags) {{
303    #Add Link Code if Link instruction
304    strlen = len(name)
305    if strlen > 1 and name[1:] == 'al':
306            code = 'r31 = NNPC;\n' + code
307
308    #code += 'if(NNPC == 0x80000638) { NNPC = r31; cout << "SKIPPING JUMP TO SIM_GET_MEM_CONF" << endl;}'
309    #code += 'target = NNPC;'
310
311    iop = InstObjParams(name, Name, 'Jump', CodeBlock(code),\
312                        ('IsIndirectControl', 'IsUncondControl'))
313
314    header_output = BasicDeclare.subst(iop)
315    decoder_output = BasicConstructor.subst(iop)
316    decode_block = BasicDecode.subst(iop)
317    exec_output = BasicExecute.subst(iop)
318}};
319
320
321
322
323