3 ////////////////////////////////////////////////////////////////////
5 // Control transfer instructions
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).
22 class PCDependentDisassembly : public MipsStaticInst
25 /// Cached program counter from last disassembly
26 mutable Addr cachedPC;
28 /// Cached symbol table pointer from last disassembly
29 mutable const SymbolTable *cachedSymtab;
32 PCDependentDisassembly(const char *mnem, MachInst _machInst,
34 : MipsStaticInst(mnem, _machInst, __opClass),
35 cachedPC(0), cachedSymtab(0)
40 disassemble(Addr pc, const SymbolTable *symtab) const;
44 * Base class for branches (PC-relative control transfers),
45 * conditional or unconditional.
47 class Branch : public PCDependentDisassembly
50 /// target address (signed) Displacement .
54 Branch(const char *mnem, MachInst _machInst, OpClass __opClass)
55 : PCDependentDisassembly(mnem, _machInst, __opClass),
58 //If Bit 17 is 1 then Sign Extend
59 if ( (disp & 0x00020000) > 0 ) {
64 Addr branchTarget(Addr branchPC) const;
67 generateDisassembly(Addr pc, const SymbolTable *symtab) const;
71 * Base class for branch likely branches (PC-relative control transfers),
73 class BranchLikely : public PCDependentDisassembly
76 /// target address (signed) Displacement .
80 BranchLikely(const char *mnem, MachInst _machInst, OpClass __opClass)
81 : PCDependentDisassembly(mnem, _machInst, __opClass),
87 Addr branchTarget(Addr branchPC) const;
90 generateDisassembly(Addr pc, const SymbolTable *symtab) const;
94 * Base class for jumps (register-indirect control transfers). In
95 * the Mips ISA, these are always unconditional.
97 class Jump : public PCDependentDisassembly
101 /// Displacement to target address (signed).
108 Jump(const char *mnem, MachInst _machInst, OpClass __opClass)
109 : PCDependentDisassembly(mnem, _machInst, __opClass),
114 Addr branchTarget(ExecContext *xc) const;
117 generateDisassembly(Addr pc, const SymbolTable *symtab) const;
123 Branch::branchTarget(Addr branchPC) const
125 return branchPC + 4 + disp;
129 BranchLikely::branchTarget(Addr branchPC) const
131 return branchPC + 4 + disp;
135 Jump::branchTarget(ExecContext *xc) const
137 Addr NPC = xc->readPC() + 4;
138 uint64_t Rb = xc->readIntReg(_srcRegIdx[0]);
139 return (Rb & ~3) | (NPC & 1);
143 PCDependentDisassembly::disassemble(Addr pc,
144 const SymbolTable *symtab) const
146 if (!cachedDisassembly ||
147 pc != cachedPC || symtab != cachedSymtab)
149 if (cachedDisassembly)
150 delete cachedDisassembly;
153 new std::string(generateDisassembly(pc, symtab));
155 cachedSymtab = symtab;
158 return *cachedDisassembly;
162 Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const
164 std::stringstream ss;
166 ccprintf(ss, "%-10s ", mnemonic);
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]);
175 } else if(_numSrcRegs == 2) {
176 printReg(ss, _srcRegIdx[0]);
178 printReg(ss, _srcRegIdx[1]);
182 Addr target = pc + 8 + disp;
185 if (symtab && symtab->findSymbol(target, str))
188 ccprintf(ss, "0x%x", target);
194 BranchLikely::generateDisassembly(Addr pc, const SymbolTable *symtab) const
196 std::stringstream ss;
198 ccprintf(ss, "%-10s ", mnemonic);
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]);
208 else if (_numDestRegs > 0) {
209 printReg(ss, _destRegIdx[0]);
213 Addr target = pc + 4 + disp;
216 if (symtab && symtab->findSymbol(target, str))
219 ccprintf(ss, "0x%x", target);
225 Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const
227 std::stringstream ss;
229 ccprintf(ss, "%-10s ", mnemonic);
231 if ( mnemonic == "jal" ) {
233 ccprintf(ss,"0x%x",(npc & 0xF0000000) | disp);
234 } else if (_numSrcRegs == 0) {
236 if (symtab && symtab->findSymbol(disp, str))
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]);
245 printReg(ss, _srcRegIdx[1]);
247 panic(">= 3 Source Registers!!!");
254 def format Branch(code,*flags) {{
255 #Add Link Code if Link instruction
257 if name[strlen-2:] == 'al':
258 code += 'r31 = NNPC;\n'
261 code = 'bool cond;\n' + code
262 code += 'if (cond) {\n'
263 code += ' NNPC = NPC + disp;\n'
265 code += ' NNPC = NNPC;\n'
268 iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
269 ('IsDirectControl', 'IsCondControl'))
271 header_output = BasicDeclare.subst(iop)
272 decoder_output = BasicConstructor.subst(iop)
273 decode_block = BasicDecode.subst(iop)
274 exec_output = BasicExecute.subst(iop)
278 def format BranchLikely(code,*flags) {{
279 #Add Link Code if Link instruction
281 if name[strlen-3:] == 'all':
282 code += 'r31 = NNPC;\n'
285 code = 'bool cond;\n' + code
286 code += 'if (cond) {'
287 code += 'NNPC = NPC + disp;\n'
291 iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
292 ('IsDirectControl', 'IsCondControl','IsCondDelaySlot'))
294 header_output = BasicDeclare.subst(iop)
295 decoder_output = BasicConstructor.subst(iop)
296 decode_block = BasicDecode.subst(iop)
297 exec_output = BasicExecute.subst(iop)
300 def format Jump(code,*flags) {{
301 #Add Link Code if Link instruction
303 if strlen > 1 and name[1:] == 'al':
304 code = 'r31 = NNPC;\n' + code
307 iop = InstObjParams(name, Name, 'Jump', CodeBlock(code),\
308 ('IsIndirectControl', 'IsUncondControl'))
310 header_output = BasicDeclare.subst(iop)
311 decoder_output = BasicConstructor.subst(iop)
312 decode_block = BasicDecode.subst(iop)
313 exec_output = BasicExecute.subst(iop)