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