Minor Sconscript edit ... mips decoder changes ... initialize NNPC and output fault...
[gem5.git] / arch / mips / isa / formats / branch.isa
1 // -*- mode:c++ -*-
2
3 ////////////////////////////////////////////////////////////////////
4 //
5 // Control transfer instructions
6 //
7
8 output 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
121 output 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
254 def 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 iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
269 ('IsDirectControl', 'IsCondControl'))
270
271 header_output = BasicDeclare.subst(iop)
272 decoder_output = BasicConstructor.subst(iop)
273 decode_block = BasicDecode.subst(iop)
274 exec_output = BasicExecute.subst(iop)
275 }};
276
277
278 def format BranchLikely(code,*flags) {{
279 #Add Link Code if Link instruction
280 strlen = len(name)
281 if name[strlen-3:] == 'all':
282 code += 'r31 = NNPC;\n'
283
284 #Condition code
285 code = 'bool cond;\n' + code
286 code += 'if (cond) {'
287 code += 'NNPC = NPC + disp;\n'
288 code += '} \n'
289
290
291 iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
292 ('IsDirectControl', 'IsCondControl','IsCondDelaySlot'))
293
294 header_output = BasicDeclare.subst(iop)
295 decoder_output = BasicConstructor.subst(iop)
296 decode_block = BasicDecode.subst(iop)
297 exec_output = BasicExecute.subst(iop)
298 }};
299
300 def format Jump(code,*flags) {{
301 #Add Link Code if Link instruction
302 strlen = len(name)
303 if strlen > 1 and name[1:] == 'al':
304 code = 'r31 = NNPC;\n' + code
305
306
307 iop = InstObjParams(name, Name, 'Jump', CodeBlock(code),\
308 ('IsIndirectControl', 'IsUncondControl'))
309
310 header_output = BasicDeclare.subst(iop)
311 decoder_output = BasicConstructor.subst(iop)
312 decode_block = BasicDecode.subst(iop)
313 exec_output = BasicExecute.subst(iop)
314 }};
315
316
317
318