1// -*- mode:c++ -*- 2 3// Copyright (c) 2007 MIPS Technologies, Inc. 4// All rights reserved. 5// 6// Redistribution and use in source and binary forms, with or without 7// modification, are permitted provided that the following conditions are 8// met: redistributions of source code must retain the above copyright 9// notice, this list of conditions and the following disclaimer; 10// redistributions in binary form must reproduce the above copyright 11// notice, this list of conditions and the following disclaimer in the 12// documentation and/or other materials provided with the distribution; 13// neither the name of the copyright holders nor the names of its 14// contributors may be used to endorse or promote products derived from 15// this software without specific prior written permission. 16// 17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28// 29// Authors: Korey Sewell 30 31//////////////////////////////////////////////////////////////////// 32// 33// Control transfer instructions 34// 35 36output header {{ 37 38#include <iostream> 39 using namespace std; 40 41 /** 42 * Base class for instructions whose disassembly is not purely a 43 * function of the machine instruction (i.e., it depends on the 44 * PC). This class overrides the disassemble() method to check 45 * the PC and symbol table values before re-using a cached 46 * disassembly string. This is necessary for branches and jumps, 47 * where the disassembly string includes the target address (which 48 * may depend on the PC and/or symbol table). 49 */ 50 class PCDependentDisassembly : public MipsStaticInst 51 { 52 protected: 53 /// Cached program counter from last disassembly 54 mutable Addr cachedPC; 55 56 /// Cached symbol table pointer from last disassembly 57 mutable const SymbolTable *cachedSymtab; 58 59 /// Constructor 60 PCDependentDisassembly(const char *mnem, MachInst _machInst, 61 OpClass __opClass) 62 : MipsStaticInst(mnem, _machInst, __opClass), 63 cachedPC(0), cachedSymtab(0) 64 { 65 } 66 67 const std::string & 68 disassemble(Addr pc, const SymbolTable *symtab) const; 69 }; 70 71 /** 72 * Base class for branches (PC-relative control transfers), 73 * conditional or unconditional. 74 */ 75 class Branch : public PCDependentDisassembly 76 { 77 protected: 78 /// target address (signed) Displacement . 79 int32_t disp; 80 81 /// Constructor. 82 Branch(const char *mnem, MachInst _machInst, OpClass __opClass) 83 : PCDependentDisassembly(mnem, _machInst, __opClass), 84 disp(OFFSET << 2) 85 { 86 //If Bit 17 is 1 then Sign Extend 87 if ( (disp & 0x00020000) > 0 ) { 88 disp |= 0xFFFE0000; 89 } 90 } 91 92 MipsISA::PCState branchTarget(const MipsISA::PCState &branchPC) const; 93
| 1// -*- mode:c++ -*- 2 3// Copyright (c) 2007 MIPS Technologies, Inc. 4// All rights reserved. 5// 6// Redistribution and use in source and binary forms, with or without 7// modification, are permitted provided that the following conditions are 8// met: redistributions of source code must retain the above copyright 9// notice, this list of conditions and the following disclaimer; 10// redistributions in binary form must reproduce the above copyright 11// notice, this list of conditions and the following disclaimer in the 12// documentation and/or other materials provided with the distribution; 13// neither the name of the copyright holders nor the names of its 14// contributors may be used to endorse or promote products derived from 15// this software without specific prior written permission. 16// 17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28// 29// Authors: Korey Sewell 30 31//////////////////////////////////////////////////////////////////// 32// 33// Control transfer instructions 34// 35 36output header {{ 37 38#include <iostream> 39 using namespace std; 40 41 /** 42 * Base class for instructions whose disassembly is not purely a 43 * function of the machine instruction (i.e., it depends on the 44 * PC). This class overrides the disassemble() method to check 45 * the PC and symbol table values before re-using a cached 46 * disassembly string. This is necessary for branches and jumps, 47 * where the disassembly string includes the target address (which 48 * may depend on the PC and/or symbol table). 49 */ 50 class PCDependentDisassembly : public MipsStaticInst 51 { 52 protected: 53 /// Cached program counter from last disassembly 54 mutable Addr cachedPC; 55 56 /// Cached symbol table pointer from last disassembly 57 mutable const SymbolTable *cachedSymtab; 58 59 /// Constructor 60 PCDependentDisassembly(const char *mnem, MachInst _machInst, 61 OpClass __opClass) 62 : MipsStaticInst(mnem, _machInst, __opClass), 63 cachedPC(0), cachedSymtab(0) 64 { 65 } 66 67 const std::string & 68 disassemble(Addr pc, const SymbolTable *symtab) const; 69 }; 70 71 /** 72 * Base class for branches (PC-relative control transfers), 73 * conditional or unconditional. 74 */ 75 class Branch : public PCDependentDisassembly 76 { 77 protected: 78 /// target address (signed) Displacement . 79 int32_t disp; 80 81 /// Constructor. 82 Branch(const char *mnem, MachInst _machInst, OpClass __opClass) 83 : PCDependentDisassembly(mnem, _machInst, __opClass), 84 disp(OFFSET << 2) 85 { 86 //If Bit 17 is 1 then Sign Extend 87 if ( (disp & 0x00020000) > 0 ) { 88 disp |= 0xFFFE0000; 89 } 90 } 91 92 MipsISA::PCState branchTarget(const MipsISA::PCState &branchPC) const; 93
|
121 std::string 122 generateDisassembly(Addr pc, const SymbolTable *symtab) const; 123 }; 124}}; 125 126output decoder {{ 127 MipsISA::PCState 128 Branch::branchTarget(const MipsISA::PCState &branchPC) const 129 { 130 MipsISA::PCState target = branchPC; 131 target.advance(); 132 target.npc(branchPC.pc() + sizeof(MachInst) + disp); 133 target.nnpc(target.npc() + sizeof(MachInst)); 134 return target; 135 } 136 137 MipsISA::PCState 138 Jump::branchTarget(ThreadContext *tc) const 139 { 140 MipsISA::PCState target = tc->pcState(); 141 Addr pc = target.pc(); 142 target.advance(); 143 target.npc((pc & 0xF0000000) | disp); 144 target.nnpc(target.npc() + sizeof(MachInst)); 145 return target; 146 } 147 148 const std::string & 149 PCDependentDisassembly::disassemble(Addr pc, 150 const SymbolTable *symtab) const 151 { 152 if (!cachedDisassembly || 153 pc != cachedPC || symtab != cachedSymtab) 154 { 155 if (cachedDisassembly) 156 delete cachedDisassembly; 157 158 cachedDisassembly = 159 new std::string(generateDisassembly(pc, symtab)); 160 cachedPC = pc; 161 cachedSymtab = symtab; 162 } 163 164 return *cachedDisassembly; 165 } 166 167 std::string 168 Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const 169 { 170 std::stringstream ss; 171 172 ccprintf(ss, "%-10s ", mnemonic); 173 174 // There's only one register arg (RA), but it could be 175 // either a source (the condition for conditional 176 // branches) or a destination (the link reg for 177 // unconditional branches) 178 if (_numSrcRegs == 1) { 179 printReg(ss, _srcRegIdx[0]); 180 ss << ", "; 181 } else if(_numSrcRegs == 2) { 182 printReg(ss, _srcRegIdx[0]); 183 ss << ", "; 184 printReg(ss, _srcRegIdx[1]); 185 ss << ", "; 186 } 187 188 Addr target = pc + 4 + disp; 189 190 std::string str; 191 if (symtab && symtab->findSymbol(target, str)) 192 ss << str; 193 else 194 ccprintf(ss, "0x%x", target); 195 196 return ss.str(); 197 } 198 199 std::string 200 Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const 201 { 202 std::stringstream ss; 203 204 ccprintf(ss, "%-10s ", mnemonic); 205 206 if ( strcmp(mnemonic,"jal") == 0 ) { 207 Addr npc = pc + 4; 208 ccprintf(ss,"0x%x",(npc & 0xF0000000) | disp); 209 } else if (_numSrcRegs == 0) { 210 std::string str; 211 if (symtab && symtab->findSymbol(disp, str)) 212 ss << str; 213 else 214 ccprintf(ss, "0x%x", disp); 215 } else if (_numSrcRegs == 1) { 216 printReg(ss, _srcRegIdx[0]); 217 } else if(_numSrcRegs == 2) { 218 printReg(ss, _srcRegIdx[0]); 219 ss << ", "; 220 printReg(ss, _srcRegIdx[1]); 221 } 222 223 return ss.str(); 224 } 225}}; 226 227def format Branch(code, *opt_flags) {{ 228 not_taken_code = 'NNPC = NNPC; NPC = NPC;' 229 230 #Build Instruction Flags 231 #Use Link & Likely Flags to Add Link/Condition Code 232 inst_flags = ('IsDirectControl', ) 233 for x in opt_flags: 234 if x == 'Link': 235 code += 'R31 = NNPC;\n' 236 elif x == 'Likely': 237 not_taken_code = 'NNPC = NPC; NPC = PC;' 238 inst_flags += ('IsCondDelaySlot', ) 239 else: 240 inst_flags += (x, ) 241 242 #Take into account uncond. branch instruction 243 if 'cond = 1' in code: 244 inst_flags += ('IsUncondControl', ) 245 else: 246 inst_flags += ('IsCondControl', ) 247 248 #Condition code 249 code = ''' 250 bool cond; 251 %(code)s 252 if (cond) { 253 NNPC = NPC + disp; 254 } else { 255 %(not_taken_code)s 256 } 257 ''' % { "code" : code, "not_taken_code" : not_taken_code } 258 259 iop = InstObjParams(name, Name, 'Branch', code, inst_flags) 260 header_output = BasicDeclare.subst(iop) 261 decoder_output = BasicConstructor.subst(iop) 262 decode_block = BasicDecode.subst(iop) 263 exec_output = BasicExecute.subst(iop) 264}}; 265 266def format DspBranch(code, *opt_flags) {{ 267 not_taken_code = 'NNPC = NNPC; NPC = NPC;' 268 269 #Build Instruction Flags 270 #Use Link & Likely Flags to Add Link/Condition Code 271 inst_flags = ('IsDirectControl', ) 272 for x in opt_flags: 273 if x == 'Link': 274 code += 'R32 = NNPC;' 275 elif x == 'Likely': 276 not_taken_code = 'NNPC = NPC, NPC = PC;' 277 inst_flags += ('IsCondDelaySlot', ) 278 else: 279 inst_flags += (x, ) 280 281 #Take into account uncond. branch instruction 282 if 'cond = 1' in code: 283 inst_flags += ('IsUncondControl', ) 284 else: 285 inst_flags += ('IsCondControl', ) 286 287 #Condition code 288 code = ''' 289 bool cond; 290 uint32_t dspctl = DSPControl; 291 %(code)s 292 if (cond) { 293 NNPC = NPC + disp; 294 } else { 295 %(not_taken_code)s 296 } 297 ''' % { "code" : code, "not_taken_code" : not_taken_code } 298 299 iop = InstObjParams(name, Name, 'Branch', code, inst_flags) 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, *opt_flags) {{ 307 #Build Instruction Flags 308 #Use Link Flag to Add Link Code 309 inst_flags = ('IsIndirectControl', 'IsUncondControl') 310 for x in opt_flags: 311 if x == 'Link': 312 code = ''' 313 R31 = NNPC; 314 ''' + code 315 elif x == 'ClearHazards': 316 code += '/* Code Needed to Clear Execute & Inst Hazards */\n' 317 else: 318 inst_flags += (x, ) 319 320 iop = InstObjParams(name, Name, 'Jump', code, inst_flags) 321 header_output = BasicDeclare.subst(iop) 322 decoder_output = BasicConstructor.subst(iop) 323 decode_block = BasicDecode.subst(iop) 324 exec_output = BasicExecute.subst(iop) 325}}; 326 327 328 329
| 127 std::string 128 generateDisassembly(Addr pc, const SymbolTable *symtab) const; 129 }; 130}}; 131 132output decoder {{ 133 MipsISA::PCState 134 Branch::branchTarget(const MipsISA::PCState &branchPC) const 135 { 136 MipsISA::PCState target = branchPC; 137 target.advance(); 138 target.npc(branchPC.pc() + sizeof(MachInst) + disp); 139 target.nnpc(target.npc() + sizeof(MachInst)); 140 return target; 141 } 142 143 MipsISA::PCState 144 Jump::branchTarget(ThreadContext *tc) const 145 { 146 MipsISA::PCState target = tc->pcState(); 147 Addr pc = target.pc(); 148 target.advance(); 149 target.npc((pc & 0xF0000000) | disp); 150 target.nnpc(target.npc() + sizeof(MachInst)); 151 return target; 152 } 153 154 const std::string & 155 PCDependentDisassembly::disassemble(Addr pc, 156 const SymbolTable *symtab) const 157 { 158 if (!cachedDisassembly || 159 pc != cachedPC || symtab != cachedSymtab) 160 { 161 if (cachedDisassembly) 162 delete cachedDisassembly; 163 164 cachedDisassembly = 165 new std::string(generateDisassembly(pc, symtab)); 166 cachedPC = pc; 167 cachedSymtab = symtab; 168 } 169 170 return *cachedDisassembly; 171 } 172 173 std::string 174 Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const 175 { 176 std::stringstream ss; 177 178 ccprintf(ss, "%-10s ", mnemonic); 179 180 // There's only one register arg (RA), but it could be 181 // either a source (the condition for conditional 182 // branches) or a destination (the link reg for 183 // unconditional branches) 184 if (_numSrcRegs == 1) { 185 printReg(ss, _srcRegIdx[0]); 186 ss << ", "; 187 } else if(_numSrcRegs == 2) { 188 printReg(ss, _srcRegIdx[0]); 189 ss << ", "; 190 printReg(ss, _srcRegIdx[1]); 191 ss << ", "; 192 } 193 194 Addr target = pc + 4 + disp; 195 196 std::string str; 197 if (symtab && symtab->findSymbol(target, str)) 198 ss << str; 199 else 200 ccprintf(ss, "0x%x", target); 201 202 return ss.str(); 203 } 204 205 std::string 206 Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const 207 { 208 std::stringstream ss; 209 210 ccprintf(ss, "%-10s ", mnemonic); 211 212 if ( strcmp(mnemonic,"jal") == 0 ) { 213 Addr npc = pc + 4; 214 ccprintf(ss,"0x%x",(npc & 0xF0000000) | disp); 215 } else if (_numSrcRegs == 0) { 216 std::string str; 217 if (symtab && symtab->findSymbol(disp, str)) 218 ss << str; 219 else 220 ccprintf(ss, "0x%x", disp); 221 } else if (_numSrcRegs == 1) { 222 printReg(ss, _srcRegIdx[0]); 223 } else if(_numSrcRegs == 2) { 224 printReg(ss, _srcRegIdx[0]); 225 ss << ", "; 226 printReg(ss, _srcRegIdx[1]); 227 } 228 229 return ss.str(); 230 } 231}}; 232 233def format Branch(code, *opt_flags) {{ 234 not_taken_code = 'NNPC = NNPC; NPC = NPC;' 235 236 #Build Instruction Flags 237 #Use Link & Likely Flags to Add Link/Condition Code 238 inst_flags = ('IsDirectControl', ) 239 for x in opt_flags: 240 if x == 'Link': 241 code += 'R31 = NNPC;\n' 242 elif x == 'Likely': 243 not_taken_code = 'NNPC = NPC; NPC = PC;' 244 inst_flags += ('IsCondDelaySlot', ) 245 else: 246 inst_flags += (x, ) 247 248 #Take into account uncond. branch instruction 249 if 'cond = 1' in code: 250 inst_flags += ('IsUncondControl', ) 251 else: 252 inst_flags += ('IsCondControl', ) 253 254 #Condition code 255 code = ''' 256 bool cond; 257 %(code)s 258 if (cond) { 259 NNPC = NPC + disp; 260 } else { 261 %(not_taken_code)s 262 } 263 ''' % { "code" : code, "not_taken_code" : not_taken_code } 264 265 iop = InstObjParams(name, Name, 'Branch', code, inst_flags) 266 header_output = BasicDeclare.subst(iop) 267 decoder_output = BasicConstructor.subst(iop) 268 decode_block = BasicDecode.subst(iop) 269 exec_output = BasicExecute.subst(iop) 270}}; 271 272def format DspBranch(code, *opt_flags) {{ 273 not_taken_code = 'NNPC = NNPC; NPC = NPC;' 274 275 #Build Instruction Flags 276 #Use Link & Likely Flags to Add Link/Condition Code 277 inst_flags = ('IsDirectControl', ) 278 for x in opt_flags: 279 if x == 'Link': 280 code += 'R32 = NNPC;' 281 elif x == 'Likely': 282 not_taken_code = 'NNPC = NPC, NPC = PC;' 283 inst_flags += ('IsCondDelaySlot', ) 284 else: 285 inst_flags += (x, ) 286 287 #Take into account uncond. branch instruction 288 if 'cond = 1' in code: 289 inst_flags += ('IsUncondControl', ) 290 else: 291 inst_flags += ('IsCondControl', ) 292 293 #Condition code 294 code = ''' 295 bool cond; 296 uint32_t dspctl = DSPControl; 297 %(code)s 298 if (cond) { 299 NNPC = NPC + disp; 300 } else { 301 %(not_taken_code)s 302 } 303 ''' % { "code" : code, "not_taken_code" : not_taken_code } 304 305 iop = InstObjParams(name, Name, 'Branch', code, inst_flags) 306 header_output = BasicDeclare.subst(iop) 307 decoder_output = BasicConstructor.subst(iop) 308 decode_block = BasicDecode.subst(iop) 309 exec_output = BasicExecute.subst(iop) 310}}; 311 312def format Jump(code, *opt_flags) {{ 313 #Build Instruction Flags 314 #Use Link Flag to Add Link Code 315 inst_flags = ('IsIndirectControl', 'IsUncondControl') 316 for x in opt_flags: 317 if x == 'Link': 318 code = ''' 319 R31 = NNPC; 320 ''' + code 321 elif x == 'ClearHazards': 322 code += '/* Code Needed to Clear Execute & Inst Hazards */\n' 323 else: 324 inst_flags += (x, ) 325 326 iop = InstObjParams(name, Name, 'Jump', code, inst_flags) 327 header_output = BasicDeclare.subst(iop) 328 decoder_output = BasicConstructor.subst(iop) 329 decode_block = BasicDecode.subst(iop) 330 exec_output = BasicExecute.subst(iop) 331}}; 332 333 334 335
|