1 //===-- EmulateInstructionMIPS64.cpp -------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "EmulateInstructionMIPS64.h" 11 12 #include <stdlib.h> 13 14 #include "llvm-c/Disassembler.h" 15 #include "llvm/Support/TargetSelect.h" 16 #include "llvm/Support/TargetRegistry.h" 17 #include "llvm/MC/MCAsmInfo.h" 18 #include "llvm/MC/MCInst.h" 19 #include "llvm/MC/MCInstrInfo.h" 20 #include "llvm/MC/MCDisassembler/MCDisassembler.h" 21 #include "llvm/MC/MCRegisterInfo.h" 22 #include "llvm/MC/MCSubtargetInfo.h" 23 #include "llvm/MC/MCContext.h" 24 #include "lldb/Core/Address.h" 25 #include "lldb/Core/Opcode.h" 26 #include "lldb/Core/ArchSpec.h" 27 #include "lldb/Core/ConstString.h" 28 #include "lldb/Core/PluginManager.h" 29 #include "lldb/Core/DataExtractor.h" 30 #include "lldb/Core/Stream.h" 31 #include "lldb/Symbol/UnwindPlan.h" 32 33 #include "llvm/ADT/STLExtras.h" 34 35 #include "Plugins/Process/Utility/InstructionUtils.h" 36 #include "Plugins/Process/Utility/RegisterContext_mips.h" 37 38 using namespace lldb; 39 using namespace lldb_private; 40 41 #define UInt(x) ((uint64_t)x) 42 #define integer int64_t 43 44 45 //---------------------------------------------------------------------- 46 // 47 // EmulateInstructionMIPS64 implementation 48 // 49 //---------------------------------------------------------------------- 50 51 #ifdef __mips__ 52 extern "C" { 53 void LLVMInitializeMipsTargetInfo (); 54 void LLVMInitializeMipsTarget (); 55 void LLVMInitializeMipsAsmPrinter (); 56 void LLVMInitializeMipsTargetMC (); 57 void LLVMInitializeMipsDisassembler (); 58 } 59 #endif 60 61 EmulateInstructionMIPS64::EmulateInstructionMIPS64 (const lldb_private::ArchSpec &arch) : 62 EmulateInstruction (arch) 63 { 64 /* Create instance of llvm::MCDisassembler */ 65 std::string Error; 66 llvm::Triple triple = arch.GetTriple(); 67 const llvm::Target *target = llvm::TargetRegistry::lookupTarget (triple.getTriple(), Error); 68 69 /* 70 * If we fail to get the target then we haven't registered it. The SystemInitializerCommon 71 * does not initialize targets, MCs and disassemblers. However we need the MCDisassembler 72 * to decode the instructions so that the decoding complexity stays with LLVM. 73 * Initialize the MIPS targets and disassemblers. 74 */ 75 #ifdef __mips__ 76 if (!target) 77 { 78 LLVMInitializeMipsTargetInfo (); 79 LLVMInitializeMipsTarget (); 80 LLVMInitializeMipsAsmPrinter (); 81 LLVMInitializeMipsTargetMC (); 82 LLVMInitializeMipsDisassembler (); 83 target = llvm::TargetRegistry::lookupTarget (triple.getTriple(), Error); 84 } 85 #endif 86 87 assert (target); 88 89 llvm::StringRef cpu; 90 91 switch (arch.GetCore()) 92 { 93 case ArchSpec::eCore_mips32: 94 case ArchSpec::eCore_mips32el: 95 cpu = "mips32"; break; 96 case ArchSpec::eCore_mips32r2: 97 case ArchSpec::eCore_mips32r2el: 98 cpu = "mips32r2"; break; 99 case ArchSpec::eCore_mips32r3: 100 case ArchSpec::eCore_mips32r3el: 101 cpu = "mips32r3"; break; 102 case ArchSpec::eCore_mips32r5: 103 case ArchSpec::eCore_mips32r5el: 104 cpu = "mips32r5"; break; 105 case ArchSpec::eCore_mips32r6: 106 case ArchSpec::eCore_mips32r6el: 107 cpu = "mips32r6"; break; 108 case ArchSpec::eCore_mips64: 109 case ArchSpec::eCore_mips64el: 110 cpu = "mips64"; break; 111 case ArchSpec::eCore_mips64r2: 112 case ArchSpec::eCore_mips64r2el: 113 cpu = "mips64r2"; break; 114 case ArchSpec::eCore_mips64r3: 115 case ArchSpec::eCore_mips64r3el: 116 cpu = "mips64r3"; break; 117 case ArchSpec::eCore_mips64r5: 118 case ArchSpec::eCore_mips64r5el: 119 cpu = "mips64r5"; break; 120 case ArchSpec::eCore_mips64r6: 121 case ArchSpec::eCore_mips64r6el: 122 cpu = "mips64r6"; break; 123 default: 124 cpu = "generic"; break; 125 } 126 127 std::string features = ""; 128 uint32_t arch_flags = arch.GetFlags (); 129 if (arch_flags & ArchSpec::eMIPSAse_msa) 130 features += "+msa,"; 131 if (arch_flags & ArchSpec::eMIPSAse_dsp) 132 features += "+dsp,"; 133 if (arch_flags & ArchSpec::eMIPSAse_dspr2) 134 features += "+dspr2,"; 135 if (arch_flags & ArchSpec::eMIPSAse_mips16) 136 features += "+mips16,"; 137 if (arch_flags & ArchSpec::eMIPSAse_micromips) 138 features += "+micromips,"; 139 140 m_reg_info.reset (target->createMCRegInfo (triple.getTriple())); 141 assert (m_reg_info.get()); 142 143 m_insn_info.reset (target->createMCInstrInfo()); 144 assert (m_insn_info.get()); 145 146 m_asm_info.reset (target->createMCAsmInfo (*m_reg_info, triple.getTriple())); 147 m_subtype_info.reset (target->createMCSubtargetInfo (triple.getTriple(), cpu, features)); 148 assert (m_asm_info.get() && m_subtype_info.get()); 149 150 m_context.reset (new llvm::MCContext (m_asm_info.get(), m_reg_info.get(), nullptr)); 151 assert (m_context.get()); 152 153 m_disasm.reset (target->createMCDisassembler (*m_subtype_info, *m_context)); 154 assert (m_disasm.get()); 155 } 156 157 void 158 EmulateInstructionMIPS64::Initialize () 159 { 160 PluginManager::RegisterPlugin (GetPluginNameStatic (), 161 GetPluginDescriptionStatic (), 162 CreateInstance); 163 } 164 165 void 166 EmulateInstructionMIPS64::Terminate () 167 { 168 PluginManager::UnregisterPlugin (CreateInstance); 169 } 170 171 ConstString 172 EmulateInstructionMIPS64::GetPluginNameStatic () 173 { 174 ConstString g_plugin_name ("lldb.emulate-instruction.mips64"); 175 return g_plugin_name; 176 } 177 178 lldb_private::ConstString 179 EmulateInstructionMIPS64::GetPluginName() 180 { 181 static ConstString g_plugin_name ("EmulateInstructionMIPS64"); 182 return g_plugin_name; 183 } 184 185 const char * 186 EmulateInstructionMIPS64::GetPluginDescriptionStatic () 187 { 188 return "Emulate instructions for the MIPS64 architecture."; 189 } 190 191 EmulateInstruction * 192 EmulateInstructionMIPS64::CreateInstance (const ArchSpec &arch, InstructionType inst_type) 193 { 194 if (EmulateInstructionMIPS64::SupportsEmulatingInstructionsOfTypeStatic(inst_type)) 195 { 196 if (arch.GetTriple().getArch() == llvm::Triple::mips64 197 || arch.GetTriple().getArch() == llvm::Triple::mips64el) 198 { 199 std::auto_ptr<EmulateInstructionMIPS64> emulate_insn_ap (new EmulateInstructionMIPS64 (arch)); 200 if (emulate_insn_ap.get()) 201 return emulate_insn_ap.release(); 202 } 203 } 204 205 return NULL; 206 } 207 208 bool 209 EmulateInstructionMIPS64::SetTargetTriple (const ArchSpec &arch) 210 { 211 if (arch.GetTriple().getArch () == llvm::Triple::mips64 212 || arch.GetTriple().getArch () == llvm::Triple::mips64el) 213 return true; 214 return false; 215 } 216 217 const char * 218 EmulateInstructionMIPS64::GetRegisterName (unsigned reg_num, bool alternate_name) 219 { 220 if (alternate_name) 221 { 222 switch (reg_num) 223 { 224 case dwarf_sp_mips64: return "r29"; 225 case dwarf_r30_mips64: return "r30"; 226 case dwarf_ra_mips64: return "r31"; 227 case dwarf_f0_mips64: return "f0"; 228 case dwarf_f1_mips64: return "f1"; 229 case dwarf_f2_mips64: return "f2"; 230 case dwarf_f3_mips64: return "f3"; 231 case dwarf_f4_mips64: return "f4"; 232 case dwarf_f5_mips64: return "f5"; 233 case dwarf_f6_mips64: return "f6"; 234 case dwarf_f7_mips64: return "f7"; 235 case dwarf_f8_mips64: return "f8"; 236 case dwarf_f9_mips64: return "f9"; 237 case dwarf_f10_mips64: return "f10"; 238 case dwarf_f11_mips64: return "f11"; 239 case dwarf_f12_mips64: return "f12"; 240 case dwarf_f13_mips64: return "f13"; 241 case dwarf_f14_mips64: return "f14"; 242 case dwarf_f15_mips64: return "f15"; 243 case dwarf_f16_mips64: return "f16"; 244 case dwarf_f17_mips64: return "f17"; 245 case dwarf_f18_mips64: return "f18"; 246 case dwarf_f19_mips64: return "f19"; 247 case dwarf_f20_mips64: return "f20"; 248 case dwarf_f21_mips64: return "f21"; 249 case dwarf_f22_mips64: return "f22"; 250 case dwarf_f23_mips64: return "f23"; 251 case dwarf_f24_mips64: return "f24"; 252 case dwarf_f25_mips64: return "f25"; 253 case dwarf_f26_mips64: return "f26"; 254 case dwarf_f27_mips64: return "f27"; 255 case dwarf_f28_mips64: return "f28"; 256 case dwarf_f29_mips64: return "f29"; 257 case dwarf_f30_mips64: return "f30"; 258 case dwarf_f31_mips64: return "f31"; 259 case dwarf_w0_mips64: return "w0"; 260 case dwarf_w1_mips64: return "w1"; 261 case dwarf_w2_mips64: return "w2"; 262 case dwarf_w3_mips64: return "w3"; 263 case dwarf_w4_mips64: return "w4"; 264 case dwarf_w5_mips64: return "w5"; 265 case dwarf_w6_mips64: return "w6"; 266 case dwarf_w7_mips64: return "w7"; 267 case dwarf_w8_mips64: return "w8"; 268 case dwarf_w9_mips64: return "w9"; 269 case dwarf_w10_mips64: return "w10"; 270 case dwarf_w11_mips64: return "w11"; 271 case dwarf_w12_mips64: return "w12"; 272 case dwarf_w13_mips64: return "w13"; 273 case dwarf_w14_mips64: return "w14"; 274 case dwarf_w15_mips64: return "w15"; 275 case dwarf_w16_mips64: return "w16"; 276 case dwarf_w17_mips64: return "w17"; 277 case dwarf_w18_mips64: return "w18"; 278 case dwarf_w19_mips64: return "w19"; 279 case dwarf_w20_mips64: return "w20"; 280 case dwarf_w21_mips64: return "w21"; 281 case dwarf_w22_mips64: return "w22"; 282 case dwarf_w23_mips64: return "w23"; 283 case dwarf_w24_mips64: return "w24"; 284 case dwarf_w25_mips64: return "w25"; 285 case dwarf_w26_mips64: return "w26"; 286 case dwarf_w27_mips64: return "w27"; 287 case dwarf_w28_mips64: return "w28"; 288 case dwarf_w29_mips64: return "w29"; 289 case dwarf_w30_mips64: return "w30"; 290 case dwarf_w31_mips64: return "w31"; 291 case dwarf_mir_mips64: return "mir"; 292 case dwarf_mcsr_mips64: return "mcsr"; 293 case dwarf_config5_mips64: return "config5"; 294 default: 295 break; 296 } 297 return nullptr; 298 } 299 300 switch (reg_num) 301 { 302 case dwarf_zero_mips64: return "r0"; 303 case dwarf_r1_mips64: return "r1"; 304 case dwarf_r2_mips64: return "r2"; 305 case dwarf_r3_mips64: return "r3"; 306 case dwarf_r4_mips64: return "r4"; 307 case dwarf_r5_mips64: return "r5"; 308 case dwarf_r6_mips64: return "r6"; 309 case dwarf_r7_mips64: return "r7"; 310 case dwarf_r8_mips64: return "r8"; 311 case dwarf_r9_mips64: return "r9"; 312 case dwarf_r10_mips64: return "r10"; 313 case dwarf_r11_mips64: return "r11"; 314 case dwarf_r12_mips64: return "r12"; 315 case dwarf_r13_mips64: return "r13"; 316 case dwarf_r14_mips64: return "r14"; 317 case dwarf_r15_mips64: return "r15"; 318 case dwarf_r16_mips64: return "r16"; 319 case dwarf_r17_mips64: return "r17"; 320 case dwarf_r18_mips64: return "r18"; 321 case dwarf_r19_mips64: return "r19"; 322 case dwarf_r20_mips64: return "r20"; 323 case dwarf_r21_mips64: return "r21"; 324 case dwarf_r22_mips64: return "r22"; 325 case dwarf_r23_mips64: return "r23"; 326 case dwarf_r24_mips64: return "r24"; 327 case dwarf_r25_mips64: return "r25"; 328 case dwarf_r26_mips64: return "r26"; 329 case dwarf_r27_mips64: return "r27"; 330 case dwarf_gp_mips64: return "gp"; 331 case dwarf_sp_mips64: return "sp"; 332 case dwarf_r30_mips64: return "fp"; 333 case dwarf_ra_mips64: return "ra"; 334 case dwarf_sr_mips64: return "sr"; 335 case dwarf_lo_mips64: return "lo"; 336 case dwarf_hi_mips64: return "hi"; 337 case dwarf_bad_mips64: return "bad"; 338 case dwarf_cause_mips64: return "cause"; 339 case dwarf_pc_mips64: return "pc"; 340 case dwarf_f0_mips64: return "f0"; 341 case dwarf_f1_mips64: return "f1"; 342 case dwarf_f2_mips64: return "f2"; 343 case dwarf_f3_mips64: return "f3"; 344 case dwarf_f4_mips64: return "f4"; 345 case dwarf_f5_mips64: return "f5"; 346 case dwarf_f6_mips64: return "f6"; 347 case dwarf_f7_mips64: return "f7"; 348 case dwarf_f8_mips64: return "f8"; 349 case dwarf_f9_mips64: return "f9"; 350 case dwarf_f10_mips64: return "f10"; 351 case dwarf_f11_mips64: return "f11"; 352 case dwarf_f12_mips64: return "f12"; 353 case dwarf_f13_mips64: return "f13"; 354 case dwarf_f14_mips64: return "f14"; 355 case dwarf_f15_mips64: return "f15"; 356 case dwarf_f16_mips64: return "f16"; 357 case dwarf_f17_mips64: return "f17"; 358 case dwarf_f18_mips64: return "f18"; 359 case dwarf_f19_mips64: return "f19"; 360 case dwarf_f20_mips64: return "f20"; 361 case dwarf_f21_mips64: return "f21"; 362 case dwarf_f22_mips64: return "f22"; 363 case dwarf_f23_mips64: return "f23"; 364 case dwarf_f24_mips64: return "f24"; 365 case dwarf_f25_mips64: return "f25"; 366 case dwarf_f26_mips64: return "f26"; 367 case dwarf_f27_mips64: return "f27"; 368 case dwarf_f28_mips64: return "f28"; 369 case dwarf_f29_mips64: return "f29"; 370 case dwarf_f30_mips64: return "f30"; 371 case dwarf_f31_mips64: return "f31"; 372 case dwarf_fcsr_mips64: return "fcsr"; 373 case dwarf_fir_mips64: return "fir"; 374 case dwarf_w0_mips64: return "w0"; 375 case dwarf_w1_mips64: return "w1"; 376 case dwarf_w2_mips64: return "w2"; 377 case dwarf_w3_mips64: return "w3"; 378 case dwarf_w4_mips64: return "w4"; 379 case dwarf_w5_mips64: return "w5"; 380 case dwarf_w6_mips64: return "w6"; 381 case dwarf_w7_mips64: return "w7"; 382 case dwarf_w8_mips64: return "w8"; 383 case dwarf_w9_mips64: return "w9"; 384 case dwarf_w10_mips64: return "w10"; 385 case dwarf_w11_mips64: return "w11"; 386 case dwarf_w12_mips64: return "w12"; 387 case dwarf_w13_mips64: return "w13"; 388 case dwarf_w14_mips64: return "w14"; 389 case dwarf_w15_mips64: return "w15"; 390 case dwarf_w16_mips64: return "w16"; 391 case dwarf_w17_mips64: return "w17"; 392 case dwarf_w18_mips64: return "w18"; 393 case dwarf_w19_mips64: return "w19"; 394 case dwarf_w20_mips64: return "w20"; 395 case dwarf_w21_mips64: return "w21"; 396 case dwarf_w22_mips64: return "w22"; 397 case dwarf_w23_mips64: return "w23"; 398 case dwarf_w24_mips64: return "w24"; 399 case dwarf_w25_mips64: return "w25"; 400 case dwarf_w26_mips64: return "w26"; 401 case dwarf_w27_mips64: return "w27"; 402 case dwarf_w28_mips64: return "w28"; 403 case dwarf_w29_mips64: return "w29"; 404 case dwarf_w30_mips64: return "w30"; 405 case dwarf_w31_mips64: return "w31"; 406 case dwarf_mcsr_mips64: return "mcsr"; 407 case dwarf_mir_mips64: return "mir"; 408 case dwarf_config5_mips64: return "config5"; 409 } 410 return nullptr; 411 } 412 413 bool 414 EmulateInstructionMIPS64::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_num, RegisterInfo ®_info) 415 { 416 if (reg_kind == eRegisterKindGeneric) 417 { 418 switch (reg_num) 419 { 420 case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = dwarf_pc_mips64; break; 421 case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_sp_mips64; break; 422 case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_r30_mips64; break; 423 case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = dwarf_ra_mips64; break; 424 case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = dwarf_sr_mips64; break; 425 default: 426 return false; 427 } 428 } 429 430 if (reg_kind == eRegisterKindDWARF) 431 { 432 ::memset (®_info, 0, sizeof(RegisterInfo)); 433 ::memset (reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds)); 434 435 if (reg_num == dwarf_sr_mips64 || reg_num == dwarf_fcsr_mips64 || reg_num == dwarf_fir_mips64 || reg_num == dwarf_mcsr_mips64 || reg_num == dwarf_mir_mips64 || reg_num == dwarf_config5_mips64) 436 { 437 reg_info.byte_size = 4; 438 reg_info.format = eFormatHex; 439 reg_info.encoding = eEncodingUint; 440 } 441 else if ((int)reg_num >= dwarf_zero_mips64 && (int)reg_num <= dwarf_f31_mips64) 442 { 443 reg_info.byte_size = 8; 444 reg_info.format = eFormatHex; 445 reg_info.encoding = eEncodingUint; 446 } 447 else if ((int)reg_num >= dwarf_w0_mips64 && (int)reg_num <= dwarf_w31_mips64) 448 { 449 reg_info.byte_size = 16; 450 reg_info.format = eFormatVectorOfUInt8; 451 reg_info.encoding = eEncodingVector; 452 } 453 else 454 { 455 return false; 456 } 457 458 reg_info.name = GetRegisterName (reg_num, false); 459 reg_info.alt_name = GetRegisterName (reg_num, true); 460 reg_info.kinds[eRegisterKindDWARF] = reg_num; 461 462 switch (reg_num) 463 { 464 case dwarf_r30_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; break; 465 case dwarf_ra_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; break; 466 case dwarf_sp_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; break; 467 case dwarf_pc_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; break; 468 case dwarf_sr_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; break; 469 default: break; 470 } 471 return true; 472 } 473 return false; 474 } 475 476 EmulateInstructionMIPS64::MipsOpcode* 477 EmulateInstructionMIPS64::GetOpcodeForInstruction (const char *op_name) 478 { 479 static EmulateInstructionMIPS64::MipsOpcode 480 g_opcodes[] = 481 { 482 //---------------------------------------------------------------------- 483 // Prologue/Epilogue instructions 484 //---------------------------------------------------------------------- 485 { "DADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu, "DADDIU rt,rs,immediate" }, 486 { "SD", &EmulateInstructionMIPS64::Emulate_SD, "SD rt,offset(rs)" }, 487 { "LD", &EmulateInstructionMIPS64::Emulate_LD, "LD rt,offset(base)" }, 488 489 490 491 492 //---------------------------------------------------------------------- 493 // Load/Store instructions 494 //---------------------------------------------------------------------- 495 /* Following list of emulated instructions are required by implementation of hardware watchpoint 496 for MIPS in lldb. As we just need the address accessed by instructions, we have generalised 497 all these instructions in 2 functions depending on their addressing modes */ 498 499 { "LB", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LB rt, offset(base)" }, 500 { "LBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LBE rt, offset(base)" }, 501 { "LBU", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LBU rt, offset(base)" }, 502 { "LBUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LBUE rt, offset(base)" }, 503 { "LDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LDC1 ft, offset(base)" }, 504 { "LDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LDL rt, offset(base)" }, 505 { "LDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LDR rt, offset(base)" }, 506 { "LLD", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LLD rt, offset(base)" }, 507 { "LDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LDC2 rt, offset(base)" }, 508 { "LDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "LDXC1 fd, index (base)" }, 509 { "LH", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LH rt, offset(base)" }, 510 { "LHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LHE rt, offset(base)" }, 511 { "LHU", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LHU rt, offset(base)" }, 512 { "LHUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LHUE rt, offset(base)" }, 513 { "LL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LL rt, offset(base)" }, 514 { "LLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LLE rt, offset(base)" }, 515 { "LUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "LUXC1 fd, index (base)" }, 516 { "LW", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LW rt, offset(rs)" }, 517 { "LWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWC1 ft, offset(base)" }, 518 { "LWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWC2 rt, offset(base)" }, 519 { "LWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWE rt, offset(base)" }, 520 { "LWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWL rt, offset(base)" }, 521 { "LWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWLE rt, offset(base)" }, 522 { "LWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWR rt, offset(base)" }, 523 { "LWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWRE rt, offset(base)" }, 524 { "LWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "LWXC1 fd, index (base)" }, 525 526 { "SB", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SB rt, offset(base)" }, 527 { "SBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SBE rt, offset(base)" }, 528 { "SC", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SC rt, offset(base)" }, 529 { "SCE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SCE rt, offset(base)" }, 530 { "SCD", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SCD rt, offset(base)" }, 531 { "SDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SDL rt, offset(base)" }, 532 { "SDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SDR rt, offset(base)" }, 533 { "SDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SDC1 ft, offset(base)" }, 534 { "SDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SDC2 rt, offset(base)" }, 535 { "SDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "SDXC1 fs, index (base)" }, 536 { "SH", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SH rt, offset(base)" }, 537 { "SHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SHE rt, offset(base)" }, 538 { "SUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "SUXC1 fs, index (base)" }, 539 { "SW", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SW rt, offset(rs)" }, 540 { "SWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWC1 ft, offset(base)" }, 541 { "SWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWC2 rt, offset(base)" }, 542 { "SWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWE rt, offset(base)" }, 543 { "SWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWL rt, offset(base)" }, 544 { "SWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWLE rt, offset(base)" }, 545 { "SWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWR rt, offset(base)" }, 546 { "SWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWRE rt, offset(base)" }, 547 { "SWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "SWXC1 fs, index (base)" }, 548 549 //---------------------------------------------------------------------- 550 // Branch instructions 551 //---------------------------------------------------------------------- 552 { "BEQ", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQ rs,rt,offset" }, 553 { "BNE", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNE rs,rt,offset" }, 554 { "BEQL", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQL rs,rt,offset" }, 555 { "BNEL", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNEL rs,rt,offset" }, 556 { "BGEZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, "BGEZALL rt,offset" }, 557 { "BAL", &EmulateInstructionMIPS64::Emulate_BAL, "BAL offset" }, 558 { "BGEZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, "BGEZAL rs,offset" }, 559 { "BALC", &EmulateInstructionMIPS64::Emulate_BALC, "BALC offset" }, 560 { "BC", &EmulateInstructionMIPS64::Emulate_BC, "BC offset" }, 561 { "BGEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZ rs,offset" }, 562 { "BLEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BLEZALC rs,offset" }, 563 { "BGEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BGEZALC rs,offset" }, 564 { "BLTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BLTZALC rs,offset" }, 565 { "BGTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BGTZALC rs,offset" }, 566 { "BEQZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BEQZALC rs,offset" }, 567 { "BNEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BNEZALC rs,offset" }, 568 { "BEQC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BEQC rs,rt,offset" }, 569 { "BNEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BNEC rs,rt,offset" }, 570 { "BLTC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BLTC rs,rt,offset" }, 571 { "BGEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BGEC rs,rt,offset" }, 572 { "BLTUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BLTUC rs,rt,offset" }, 573 { "BGEUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BGEUC rs,rt,offset" }, 574 { "BLTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BLTZC rt,offset" }, 575 { "BLEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BLEZC rt,offset" }, 576 { "BGEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BGEZC rt,offset" }, 577 { "BGTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BGTZC rt,offset" }, 578 { "BEQZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BEQZC rt,offset" }, 579 { "BNEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BNEZC rt,offset" }, 580 { "BGEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZL rt,offset" }, 581 { "BGTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZ rt,offset" }, 582 { "BGTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZL rt,offset" }, 583 { "BLEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZ rt,offset" }, 584 { "BLEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZL rt,offset" }, 585 { "BLTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZ rt,offset" }, 586 { "BLTZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, "BLTZAL rt,offset" }, 587 { "BLTZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, "BLTZALL rt,offset" }, 588 { "BLTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZL rt,offset" }, 589 { "BOVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BOVC rs,rt,offset" }, 590 { "BNVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BNVC rs,rt,offset" }, 591 { "J", &EmulateInstructionMIPS64::Emulate_J, "J target" }, 592 { "JAL", &EmulateInstructionMIPS64::Emulate_JAL, "JAL target" }, 593 { "JALX", &EmulateInstructionMIPS64::Emulate_JAL, "JALX target" }, 594 { "JALR", &EmulateInstructionMIPS64::Emulate_JALR, "JALR target" }, 595 { "JALR_HB", &EmulateInstructionMIPS64::Emulate_JALR, "JALR.HB target" }, 596 { "JIALC", &EmulateInstructionMIPS64::Emulate_JIALC, "JIALC rt,offset" }, 597 { "JIC", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset" }, 598 { "JR", &EmulateInstructionMIPS64::Emulate_JR, "JR target" }, 599 { "JR_HB", &EmulateInstructionMIPS64::Emulate_JR, "JR.HB target" }, 600 { "BC1F", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1F cc, offset" }, 601 { "BC1T", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1T cc, offset" }, 602 { "BC1FL", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1FL cc, offset" }, 603 { "BC1TL", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1TL cc, offset" }, 604 { "BC1EQZ", &EmulateInstructionMIPS64::Emulate_BC1EQZ, "BC1EQZ ft, offset" }, 605 { "BC1NEZ", &EmulateInstructionMIPS64::Emulate_BC1NEZ, "BC1NEZ ft, offset" }, 606 { "BC1ANY2F", &EmulateInstructionMIPS64::Emulate_3D_branch, "BC1ANY2F cc, offset" }, 607 { "BC1ANY2T", &EmulateInstructionMIPS64::Emulate_3D_branch, "BC1ANY2T cc, offset" }, 608 { "BC1ANY4F", &EmulateInstructionMIPS64::Emulate_3D_branch, "BC1ANY4F cc, offset" }, 609 { "BC1ANY4T", &EmulateInstructionMIPS64::Emulate_3D_branch, "BC1ANY4T cc, offset" }, 610 { "BNZ_B", &EmulateInstructionMIPS64::Emulate_BNZB, "BNZ.b wt,s16" }, 611 { "BNZ_H", &EmulateInstructionMIPS64::Emulate_BNZH, "BNZ.h wt,s16" }, 612 { "BNZ_W", &EmulateInstructionMIPS64::Emulate_BNZW, "BNZ.w wt,s16" }, 613 { "BNZ_D", &EmulateInstructionMIPS64::Emulate_BNZD, "BNZ.d wt,s16" }, 614 { "BZ_B", &EmulateInstructionMIPS64::Emulate_BZB, "BZ.b wt,s16" }, 615 { "BZ_H", &EmulateInstructionMIPS64::Emulate_BZH, "BZ.h wt,s16" }, 616 { "BZ_W", &EmulateInstructionMIPS64::Emulate_BZW, "BZ.w wt,s16" }, 617 { "BZ_D", &EmulateInstructionMIPS64::Emulate_BZD, "BZ.d wt,s16" }, 618 { "BNZ_V", &EmulateInstructionMIPS64::Emulate_BNZV, "BNZ.V wt,s16" }, 619 { "BZ_V", &EmulateInstructionMIPS64::Emulate_BZV, "BZ.V wt,s16" }, 620 }; 621 622 static const size_t k_num_mips_opcodes = llvm::array_lengthof(g_opcodes); 623 624 for (size_t i = 0; i < k_num_mips_opcodes; ++i) 625 { 626 if (! strcasecmp (g_opcodes[i].op_name, op_name)) 627 return &g_opcodes[i]; 628 } 629 630 return NULL; 631 } 632 633 bool 634 EmulateInstructionMIPS64::ReadInstruction () 635 { 636 bool success = false; 637 m_addr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success); 638 if (success) 639 { 640 Context read_inst_context; 641 read_inst_context.type = eContextReadOpcode; 642 read_inst_context.SetNoArgs (); 643 m_opcode.SetOpcode32 (ReadMemoryUnsigned (read_inst_context, m_addr, 4, 0, &success), GetByteOrder()); 644 } 645 if (!success) 646 m_addr = LLDB_INVALID_ADDRESS; 647 return success; 648 } 649 650 bool 651 EmulateInstructionMIPS64::EvaluateInstruction (uint32_t evaluate_options) 652 { 653 bool success = false; 654 llvm::MCInst mc_insn; 655 uint64_t insn_size; 656 DataExtractor data; 657 658 /* Keep the complexity of the decode logic with the llvm::MCDisassembler class. */ 659 if (m_opcode.GetData (data)) 660 { 661 llvm::MCDisassembler::DecodeStatus decode_status; 662 llvm::ArrayRef<uint8_t> raw_insn (data.GetDataStart(), data.GetByteSize()); 663 decode_status = m_disasm->getInstruction (mc_insn, insn_size, raw_insn, m_addr, llvm::nulls(), llvm::nulls()); 664 if (decode_status != llvm::MCDisassembler::Success) 665 return false; 666 } 667 668 /* 669 * mc_insn.getOpcode() returns decoded opcode. However to make use 670 * of llvm::Mips::<insn> we would need "MipsGenInstrInfo.inc". 671 */ 672 const char *op_name = m_insn_info->getName (mc_insn.getOpcode ()); 673 674 if (op_name == NULL) 675 return false; 676 677 /* 678 * Decoding has been done already. Just get the call-back function 679 * and emulate the instruction. 680 */ 681 MipsOpcode *opcode_data = GetOpcodeForInstruction (op_name); 682 683 if (opcode_data == NULL) 684 return false; 685 686 uint64_t old_pc = 0, new_pc = 0; 687 const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC; 688 689 if (auto_advance_pc) 690 { 691 old_pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 692 if (!success) 693 return false; 694 } 695 696 /* emulate instruction */ 697 success = (this->*opcode_data->callback) (mc_insn); 698 if (!success) 699 return false; 700 701 if (auto_advance_pc) 702 { 703 new_pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 704 if (!success) 705 return false; 706 707 /* If we haven't changed the PC, change it here */ 708 if (old_pc == new_pc) 709 { 710 new_pc += 4; 711 Context context; 712 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, new_pc)) 713 return false; 714 } 715 } 716 717 return true; 718 } 719 720 bool 721 EmulateInstructionMIPS64::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan) 722 { 723 unwind_plan.Clear(); 724 unwind_plan.SetRegisterKind (eRegisterKindDWARF); 725 726 UnwindPlan::RowSP row(new UnwindPlan::Row); 727 const bool can_replace = false; 728 729 // Our previous Call Frame Address is the stack pointer 730 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp_mips64, 0); 731 732 // Our previous PC is in the RA 733 row->SetRegisterLocationToRegister(dwarf_pc_mips64, dwarf_ra_mips64, can_replace); 734 735 unwind_plan.AppendRow (row); 736 737 // All other registers are the same. 738 unwind_plan.SetSourceName ("EmulateInstructionMIPS64"); 739 unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); 740 unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes); 741 unwind_plan.SetReturnAddressRegister (dwarf_ra_mips64); 742 743 return true; 744 } 745 746 bool 747 EmulateInstructionMIPS64::nonvolatile_reg_p (uint64_t regnum) 748 { 749 switch (regnum) 750 { 751 case dwarf_r16_mips64: 752 case dwarf_r17_mips64: 753 case dwarf_r18_mips64: 754 case dwarf_r19_mips64: 755 case dwarf_r20_mips64: 756 case dwarf_r21_mips64: 757 case dwarf_r22_mips64: 758 case dwarf_r23_mips64: 759 case dwarf_gp_mips64: 760 case dwarf_sp_mips64: 761 case dwarf_r30_mips64: 762 case dwarf_ra_mips64: 763 return true; 764 default: 765 return false; 766 } 767 return false; 768 } 769 770 bool 771 EmulateInstructionMIPS64::Emulate_DADDiu (llvm::MCInst& insn) 772 { 773 bool success = false; 774 const uint32_t imm16 = insn.getOperand(2).getImm(); 775 uint64_t imm = SignedBits(imm16, 15, 0); 776 uint64_t result; 777 uint32_t src, dst; 778 779 dst = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 780 src = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); 781 782 /* Check if this is daddiu sp,<src>,imm16 */ 783 if (dst == dwarf_sp_mips64) 784 { 785 /* read <src> register */ 786 uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success); 787 if (!success) 788 return false; 789 790 result = src_opd_val + imm; 791 792 Context context; 793 RegisterInfo reg_info_sp; 794 if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips64, reg_info_sp)) 795 context.SetRegisterPlusOffset (reg_info_sp, imm); 796 797 /* We are allocating bytes on stack */ 798 context.type = eContextAdjustStackPointer; 799 800 WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips64, result); 801 } 802 803 return true; 804 } 805 806 bool 807 EmulateInstructionMIPS64::Emulate_SD (llvm::MCInst& insn) 808 { 809 uint64_t address; 810 RegisterInfo reg_info_base; 811 RegisterInfo reg_info_src; 812 bool success = false; 813 uint32_t imm16 = insn.getOperand(2).getImm(); 814 uint64_t imm = SignedBits(imm16, 15, 0); 815 uint32_t src, base; 816 Context bad_vaddr_context; 817 818 src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 819 base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); 820 821 if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips64 + base, reg_info_base) 822 || !GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips64 + src, reg_info_src)) 823 return false; 824 825 /* read SP */ 826 address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + base, 0, &success); 827 if (!success) 828 return false; 829 830 /* destination address */ 831 address = address + imm; 832 833 /* We look for sp based non-volatile register stores */ 834 if (base == dwarf_sp_mips64 && nonvolatile_reg_p (src)) 835 { 836 Context context; 837 RegisterValue data_src; 838 context.type = eContextPushRegisterOnStack; 839 context.SetRegisterToRegisterPlusOffset (reg_info_src, reg_info_base, 0); 840 841 uint8_t buffer [RegisterValue::kMaxRegisterByteSize]; 842 Error error; 843 844 if (!ReadRegister (®_info_base, data_src)) 845 return false; 846 847 if (data_src.GetAsMemoryData (®_info_src, buffer, reg_info_src.byte_size, eByteOrderLittle, error) == 0) 848 return false; 849 850 if (!WriteMemory (context, address, buffer, reg_info_src.byte_size)) 851 return false; 852 } 853 854 /* Set the bad_vaddr register with base address used in the instruction */ 855 bad_vaddr_context.type = eContextInvalid; 856 WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64, address); 857 858 return true; 859 } 860 861 bool 862 EmulateInstructionMIPS64::Emulate_LD (llvm::MCInst& insn) 863 { 864 bool success =false; 865 uint32_t src, base; 866 int64_t imm, address; 867 Context bad_vaddr_context; 868 869 src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 870 base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); 871 imm = insn.getOperand(2).getImm(); 872 873 RegisterInfo reg_info_base; 874 if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips64 + base, reg_info_base)) 875 return false; 876 877 /* read base register */ 878 address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + base, 0, &success); 879 if (!success) 880 return false; 881 882 /* destination address */ 883 address = address + imm; 884 885 /* Set the bad_vaddr register with base address used in the instruction */ 886 bad_vaddr_context.type = eContextInvalid; 887 WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64, address); 888 889 890 if (base == dwarf_sp_mips64 && nonvolatile_reg_p (src)) 891 { 892 RegisterValue data_src; 893 RegisterInfo reg_info_src; 894 895 if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips64 + src, reg_info_src)) 896 return false; 897 898 Context context; 899 context.type = eContextRegisterLoad; 900 901 if (!WriteRegister (context, ®_info_src, data_src)) 902 return false; 903 904 return true; 905 } 906 907 return false; 908 } 909 910 911 /* 912 Emulate below MIPS branch instructions. 913 BEQ, BNE : Branch on condition 914 BEQL, BNEL : Branch likely 915 */ 916 bool 917 EmulateInstructionMIPS64::Emulate_BXX_3ops (llvm::MCInst& insn) 918 { 919 bool success = false; 920 uint32_t rs, rt; 921 int64_t offset, pc, rs_val, rt_val, target = 0; 922 const char *op_name = m_insn_info->getName (insn.getOpcode ()); 923 924 rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 925 rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); 926 offset = insn.getOperand(2).getImm(); 927 928 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 929 if (!success) 930 return false; 931 932 rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success); 933 if (!success) 934 return false; 935 936 rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success); 937 if (!success) 938 return false; 939 940 if (!strcasecmp (op_name, "BEQ") || 941 !strcasecmp (op_name, "BEQL")) 942 { 943 if (rs_val == rt_val) 944 target = pc + offset; 945 else 946 target = pc + 8; 947 } 948 else if (!strcasecmp (op_name, "BNE") || 949 !strcasecmp (op_name, "BNEL")) 950 { 951 if (rs_val != rt_val) 952 target = pc + offset; 953 else 954 target = pc + 8; 955 } 956 957 Context context; 958 context.type = eContextRelativeBranchImmediate; 959 context.SetImmediate (offset); 960 961 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 962 return false; 963 964 return true; 965 } 966 967 /* 968 Emulate below MIPS Non-Compact conditional branch and link instructions. 969 BLTZAL, BGEZAL : 970 BLTZALL, BGEZALL : Branch likely 971 */ 972 bool 973 EmulateInstructionMIPS64::Emulate_Bcond_Link (llvm::MCInst& insn) 974 { 975 bool success = false; 976 uint32_t rs; 977 int64_t offset, pc, target = 0; 978 int64_t rs_val; 979 const char *op_name = m_insn_info->getName (insn.getOpcode ()); 980 981 rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 982 offset = insn.getOperand(1).getImm(); 983 984 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 985 if (!success) 986 return false; 987 988 rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success); 989 if (!success) 990 return false; 991 992 if (!strcasecmp (op_name, "BLTZAL") || 993 !strcasecmp (op_name, "BLTZALL")) 994 { 995 if (rs_val < 0) 996 target = pc + offset; 997 else 998 target = pc + 8; 999 } 1000 else if (!strcasecmp (op_name, "BGEZAL") || 1001 !strcasecmp (op_name, "BGEZALL")) 1002 { 1003 if (rs_val >= 0) 1004 target = pc + offset; 1005 else 1006 target = pc + 8; 1007 } 1008 1009 Context context; 1010 1011 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1012 return false; 1013 1014 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 8)) 1015 return false; 1016 1017 return true; 1018 } 1019 1020 bool 1021 EmulateInstructionMIPS64::Emulate_BAL (llvm::MCInst& insn) 1022 { 1023 bool success = false; 1024 int64_t offset, pc, target; 1025 1026 /* 1027 * BAL offset 1028 * offset = sign_ext (offset << 2) 1029 * RA = PC + 8 1030 * PC = PC + offset 1031 */ 1032 offset = insn.getOperand(0).getImm(); 1033 1034 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1035 if (!success) 1036 return false; 1037 1038 target = pc + offset; 1039 1040 Context context; 1041 1042 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1043 return false; 1044 1045 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 8)) 1046 return false; 1047 1048 return true; 1049 } 1050 1051 bool 1052 EmulateInstructionMIPS64::Emulate_BALC (llvm::MCInst& insn) 1053 { 1054 bool success = false; 1055 int64_t offset, pc, target; 1056 1057 /* 1058 * BALC offset 1059 * offset = sign_ext (offset << 2) 1060 * RA = PC + 4 1061 * PC = PC + 4 + offset 1062 */ 1063 offset = insn.getOperand(0).getImm(); 1064 1065 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1066 if (!success) 1067 return false; 1068 1069 target = pc + 4 + offset; 1070 1071 Context context; 1072 1073 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1074 return false; 1075 1076 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4)) 1077 return false; 1078 1079 return true; 1080 } 1081 1082 /* 1083 Emulate below MIPS conditional branch and link instructions. 1084 BLEZALC, BGEZALC, BLTZALC, BGTZALC, BEQZALC, BNEZALC : Compact branches 1085 */ 1086 bool 1087 EmulateInstructionMIPS64::Emulate_Bcond_Link_C (llvm::MCInst& insn) 1088 { 1089 bool success = false; 1090 uint32_t rs; 1091 int64_t offset, pc, rs_val, target = 0; 1092 const char *op_name = m_insn_info->getName (insn.getOpcode ()); 1093 1094 rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 1095 offset = insn.getOperand(1).getImm(); 1096 1097 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1098 if (!success) 1099 return false; 1100 1101 rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success); 1102 if (!success) 1103 return false; 1104 1105 if (!strcasecmp (op_name, "BLEZALC")) 1106 { 1107 if (rs_val <= 0) 1108 target = pc + offset; 1109 else 1110 target = pc + 4; 1111 } 1112 else if (!strcasecmp (op_name, "BGEZALC")) 1113 { 1114 if (rs_val >= 0) 1115 target = pc + offset; 1116 else 1117 target = pc + 4; 1118 } 1119 else if (!strcasecmp (op_name, "BLTZALC")) 1120 { 1121 if (rs_val < 0) 1122 target = pc + offset; 1123 else 1124 target = pc + 4; 1125 } 1126 else if (!strcasecmp (op_name, "BGTZALC")) 1127 { 1128 if (rs_val > 0) 1129 target = pc + offset; 1130 else 1131 target = pc + 4; 1132 } 1133 else if (!strcasecmp (op_name, "BEQZALC")) 1134 { 1135 if (rs_val == 0) 1136 target = pc + offset; 1137 else 1138 target = pc + 4; 1139 } 1140 else if (!strcasecmp (op_name, "BNEZALC")) 1141 { 1142 if (rs_val != 0) 1143 target = pc + offset; 1144 else 1145 target = pc + 4; 1146 } 1147 1148 Context context; 1149 1150 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1151 return false; 1152 1153 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4)) 1154 return false; 1155 1156 return true; 1157 } 1158 1159 /* 1160 Emulate below MIPS branch instructions. 1161 BLTZL, BGEZL, BGTZL, BLEZL : Branch likely 1162 BLTZ, BGEZ, BGTZ, BLEZ : Non-compact branches 1163 */ 1164 bool 1165 EmulateInstructionMIPS64::Emulate_BXX_2ops (llvm::MCInst& insn) 1166 { 1167 bool success = false; 1168 uint32_t rs; 1169 int64_t offset, pc, rs_val, target = 0; 1170 const char *op_name = m_insn_info->getName (insn.getOpcode ()); 1171 1172 rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 1173 offset = insn.getOperand(1).getImm(); 1174 1175 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1176 if (!success) 1177 return false; 1178 1179 rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success); 1180 if (!success) 1181 return false; 1182 1183 if (!strcasecmp (op_name, "BLTZL") || 1184 !strcasecmp (op_name, "BLTZ")) 1185 { 1186 if (rs_val < 0) 1187 target = pc + offset; 1188 else 1189 target = pc + 8; 1190 } 1191 else if (!strcasecmp (op_name, "BGEZL") || 1192 !strcasecmp (op_name, "BGEZ")) 1193 { 1194 if (rs_val >= 0) 1195 target = pc + offset; 1196 else 1197 target = pc + 8; 1198 } 1199 else if (!strcasecmp (op_name, "BGTZL") || 1200 !strcasecmp (op_name, "BGTZ")) 1201 { 1202 if (rs_val > 0) 1203 target = pc + offset; 1204 else 1205 target = pc + 8; 1206 } 1207 else if (!strcasecmp (op_name, "BLEZL") || 1208 !strcasecmp (op_name, "BLEZ")) 1209 { 1210 if (rs_val <= 0) 1211 target = pc + offset; 1212 else 1213 target = pc + 8; 1214 } 1215 1216 Context context; 1217 context.type = eContextRelativeBranchImmediate; 1218 context.SetImmediate (offset); 1219 1220 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1221 return false; 1222 1223 return true; 1224 } 1225 1226 bool 1227 EmulateInstructionMIPS64::Emulate_BC (llvm::MCInst& insn) 1228 { 1229 bool success = false; 1230 int64_t offset, pc, target; 1231 1232 /* 1233 * BC offset 1234 * offset = sign_ext (offset << 2) 1235 * PC = PC + 4 + offset 1236 */ 1237 offset = insn.getOperand(0).getImm(); 1238 1239 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1240 if (!success) 1241 return false; 1242 1243 target = pc + 4 + offset; 1244 1245 Context context; 1246 1247 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1248 return false; 1249 1250 return true; 1251 } 1252 1253 static int 1254 IsAdd64bitOverflow (int64_t a, int64_t b) 1255 { 1256 int64_t r = (uint64_t) a + (uint64_t) b; 1257 return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0); 1258 } 1259 1260 /* 1261 Emulate below MIPS branch instructions. 1262 BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch instructions with no delay slot 1263 */ 1264 bool 1265 EmulateInstructionMIPS64::Emulate_BXX_3ops_C (llvm::MCInst& insn) 1266 { 1267 bool success = false; 1268 uint32_t rs, rt; 1269 int64_t offset, pc, rs_val, rt_val, target = 0; 1270 const char *op_name = m_insn_info->getName (insn.getOpcode ()); 1271 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize(); 1272 1273 rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 1274 rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); 1275 offset = insn.getOperand(2).getImm(); 1276 1277 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1278 if (!success) 1279 return false; 1280 1281 rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success); 1282 if (!success) 1283 return false; 1284 1285 rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success); 1286 if (!success) 1287 return false; 1288 1289 if (!strcasecmp (op_name, "BEQC")) 1290 { 1291 if (rs_val == rt_val) 1292 target = pc + 4 + offset; 1293 else 1294 target = pc + 4; 1295 } 1296 else if (!strcasecmp (op_name, "BNEC")) 1297 { 1298 if (rs_val != rt_val) 1299 target = pc + 4 + offset; 1300 else 1301 target = pc + 4; 1302 } 1303 else if (!strcasecmp (op_name, "BLTC")) 1304 { 1305 if (rs_val < rt_val) 1306 target = pc + 4 + offset; 1307 else 1308 target = pc + 4; 1309 } 1310 else if (!strcasecmp (op_name, "BGEC")) 1311 { 1312 if (rs_val >= rt_val) 1313 target = pc + 4 + offset; 1314 else 1315 target = pc + 4; 1316 } 1317 else if (!strcasecmp (op_name, "BLTUC")) 1318 { 1319 if (rs_val < rt_val) 1320 target = pc + 4 + offset; 1321 else 1322 target = pc + 4; 1323 } 1324 else if (!strcasecmp (op_name, "BGEUC")) 1325 { 1326 if ((uint32_t)rs_val >= (uint32_t)rt_val) 1327 target = pc + 4 + offset; 1328 else 1329 target = pc + 4; 1330 } 1331 else if (!strcasecmp (op_name, "BOVC")) 1332 { 1333 if (IsAdd64bitOverflow (rs_val, rt_val)) 1334 target = pc + 4 + offset; 1335 else 1336 target = pc + 4; 1337 } 1338 else if (!strcasecmp (op_name, "BNVC")) 1339 { 1340 if (!IsAdd64bitOverflow (rs_val, rt_val)) 1341 target = pc + 4 + offset; 1342 else 1343 target = pc + 4; 1344 } 1345 1346 Context context; 1347 context.type = eContextRelativeBranchImmediate; 1348 context.SetImmediate (current_inst_size + offset); 1349 1350 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1351 return false; 1352 1353 return true; 1354 } 1355 1356 /* 1357 Emulate below MIPS branch instructions. 1358 BLTZC, BLEZC, BGEZC, BGTZC, BEQZC, BNEZC : Compact Branches 1359 */ 1360 bool 1361 EmulateInstructionMIPS64::Emulate_BXX_2ops_C (llvm::MCInst& insn) 1362 { 1363 bool success = false; 1364 uint32_t rs; 1365 int64_t offset, pc, target = 0; 1366 int64_t rs_val; 1367 const char *op_name = m_insn_info->getName (insn.getOpcode ()); 1368 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize(); 1369 1370 rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 1371 offset = insn.getOperand(1).getImm(); 1372 1373 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1374 if (!success) 1375 return false; 1376 1377 rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success); 1378 if (!success) 1379 return false; 1380 1381 if (!strcasecmp (op_name, "BLTZC")) 1382 { 1383 if (rs_val < 0) 1384 target = pc + 4 + offset; 1385 else 1386 target = pc + 4; 1387 } 1388 else if (!strcasecmp (op_name, "BLEZC")) 1389 { 1390 if (rs_val <= 0) 1391 target = pc + 4 + offset; 1392 else 1393 target = pc + 4; 1394 } 1395 else if (!strcasecmp (op_name, "BGEZC")) 1396 { 1397 if (rs_val >= 0) 1398 target = pc + 4 + offset; 1399 else 1400 target = pc + 4; 1401 } 1402 else if (!strcasecmp (op_name, "BGTZC")) 1403 { 1404 if (rs_val > 0) 1405 target = pc + 4 + offset; 1406 else 1407 target = pc + 4; 1408 } 1409 else if (!strcasecmp (op_name, "BEQZC")) 1410 { 1411 if (rs_val == 0) 1412 target = pc + 4 + offset; 1413 else 1414 target = pc + 4; 1415 } 1416 else if (!strcasecmp (op_name, "BNEZC")) 1417 { 1418 if (rs_val != 0) 1419 target = pc + 4 + offset; 1420 else 1421 target = pc + 4; 1422 } 1423 1424 Context context; 1425 context.type = eContextRelativeBranchImmediate; 1426 context.SetImmediate (current_inst_size + offset); 1427 1428 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1429 return false; 1430 1431 return true; 1432 } 1433 1434 bool 1435 EmulateInstructionMIPS64::Emulate_J (llvm::MCInst& insn) 1436 { 1437 bool success = false; 1438 uint64_t offset, pc; 1439 1440 /* 1441 * J offset 1442 * offset = sign_ext (offset << 2) 1443 * PC = PC[63-28] | offset 1444 */ 1445 offset = insn.getOperand(0).getImm(); 1446 1447 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1448 if (!success) 1449 return false; 1450 1451 /* This is a PC-region branch and not PC-relative */ 1452 pc = (pc & 0xFFFFFFFFF0000000ULL) | offset; 1453 1454 Context context; 1455 1456 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, pc)) 1457 return false; 1458 1459 return true; 1460 } 1461 1462 bool 1463 EmulateInstructionMIPS64::Emulate_JAL (llvm::MCInst& insn) 1464 { 1465 bool success = false; 1466 uint64_t offset, target, pc; 1467 1468 /* 1469 * JAL offset 1470 * offset = sign_ext (offset << 2) 1471 * PC = PC[63-28] | offset 1472 */ 1473 offset = insn.getOperand(0).getImm(); 1474 1475 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1476 if (!success) 1477 return false; 1478 1479 /* This is a PC-region branch and not PC-relative */ 1480 target = (pc & 0xFFFFFFFFF0000000ULL) | offset; 1481 1482 Context context; 1483 1484 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1485 return false; 1486 1487 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 8)) 1488 return false; 1489 1490 return true; 1491 } 1492 1493 bool 1494 EmulateInstructionMIPS64::Emulate_JALR (llvm::MCInst& insn) 1495 { 1496 bool success = false; 1497 uint32_t rs, rt; 1498 uint64_t pc, rs_val; 1499 1500 /* 1501 * JALR rt, rs 1502 * GPR[rt] = PC + 8 1503 * PC = GPR[rs] 1504 */ 1505 rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 1506 rs = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); 1507 1508 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1509 if (!success) 1510 return false; 1511 1512 rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success); 1513 if (!success) 1514 return false; 1515 1516 Context context; 1517 1518 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, rs_val)) 1519 return false; 1520 1521 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips64 + rt, pc + 8)) 1522 return false; 1523 1524 return true; 1525 } 1526 1527 bool 1528 EmulateInstructionMIPS64::Emulate_JIALC (llvm::MCInst& insn) 1529 { 1530 bool success = false; 1531 uint32_t rt; 1532 int64_t target, offset, pc, rt_val; 1533 1534 /* 1535 * JIALC rt, offset 1536 * offset = sign_ext (offset) 1537 * PC = GPR[rt] + offset 1538 * RA = PC + 4 1539 */ 1540 rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 1541 offset = insn.getOperand(1).getImm(); 1542 1543 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1544 if (!success) 1545 return false; 1546 1547 rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success); 1548 if (!success) 1549 return false; 1550 1551 target = rt_val + offset; 1552 1553 Context context; 1554 1555 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1556 return false; 1557 1558 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4)) 1559 return false; 1560 1561 return true; 1562 } 1563 1564 bool 1565 EmulateInstructionMIPS64::Emulate_JIC (llvm::MCInst& insn) 1566 { 1567 bool success = false; 1568 uint32_t rt; 1569 int64_t target, offset, rt_val; 1570 1571 /* 1572 * JIC rt, offset 1573 * offset = sign_ext (offset) 1574 * PC = GPR[rt] + offset 1575 */ 1576 rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 1577 offset = insn.getOperand(1).getImm(); 1578 1579 rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success); 1580 if (!success) 1581 return false; 1582 1583 target = rt_val + offset; 1584 1585 Context context; 1586 1587 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1588 return false; 1589 1590 return true; 1591 } 1592 1593 bool 1594 EmulateInstructionMIPS64::Emulate_JR (llvm::MCInst& insn) 1595 { 1596 bool success = false; 1597 uint32_t rs; 1598 uint64_t rs_val; 1599 1600 /* 1601 * JR rs 1602 * PC = GPR[rs] 1603 */ 1604 rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 1605 1606 rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success); 1607 if (!success) 1608 return false; 1609 1610 Context context; 1611 1612 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, rs_val)) 1613 return false; 1614 1615 return true; 1616 } 1617 1618 /* 1619 Emulate Branch on FP True/False 1620 BC1F, BC1FL : Branch on FP False (L stands for branch likely) 1621 BC1T, BC1TL : Branch on FP True (L stands for branch likely) 1622 */ 1623 bool 1624 EmulateInstructionMIPS64::Emulate_FP_branch (llvm::MCInst& insn) 1625 { 1626 bool success = false; 1627 uint32_t cc, fcsr; 1628 int64_t pc, offset, target = 0; 1629 const char *op_name = m_insn_info->getName (insn.getOpcode ()); 1630 1631 /* 1632 * BC1F cc, offset 1633 * condition <- (FPConditionCode(cc) == 0) 1634 * if condition then 1635 * offset = sign_ext (offset) 1636 * PC = PC + offset 1637 */ 1638 cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 1639 offset = insn.getOperand(1).getImm(); 1640 1641 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1642 if (!success) 1643 return false; 1644 1645 fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success); 1646 if (!success) 1647 return false; 1648 1649 /* fcsr[23], fcsr[25-31] are vaild condition bits */ 1650 fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01); 1651 1652 if (!strcasecmp (op_name, "BC1F") || 1653 !strcasecmp (op_name, "BC1FL")) 1654 { 1655 if ((fcsr & (1 << cc)) == 0) 1656 target = pc + offset; 1657 else 1658 target = pc + 8; 1659 } 1660 else if (!strcasecmp (op_name, "BC1T") || 1661 !strcasecmp (op_name, "BC1TL")) 1662 { 1663 if ((fcsr & (1 << cc)) != 0) 1664 target = pc + offset; 1665 else 1666 target = pc + 8; 1667 } 1668 1669 Context context; 1670 1671 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1672 return false; 1673 1674 return true; 1675 } 1676 1677 bool 1678 EmulateInstructionMIPS64::Emulate_BC1EQZ (llvm::MCInst& insn) 1679 { 1680 bool success = false; 1681 uint32_t ft; 1682 uint64_t ft_val; 1683 int64_t target, pc, offset; 1684 1685 /* 1686 * BC1EQZ ft, offset 1687 * condition <- (FPR[ft].bit0 == 0) 1688 * if condition then 1689 * offset = sign_ext (offset) 1690 * PC = PC + 4 + offset 1691 */ 1692 ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 1693 offset = insn.getOperand(1).getImm(); 1694 1695 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1696 if (!success) 1697 return false; 1698 1699 ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0, &success); 1700 if (!success) 1701 return false; 1702 1703 if ((ft_val & 1) == 0) 1704 target = pc + 4 + offset; 1705 else 1706 target = pc + 8; 1707 1708 Context context; 1709 1710 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1711 return false; 1712 1713 return true; 1714 } 1715 1716 bool 1717 EmulateInstructionMIPS64::Emulate_BC1NEZ (llvm::MCInst& insn) 1718 { 1719 bool success = false; 1720 uint32_t ft; 1721 uint64_t ft_val; 1722 int64_t target, pc, offset; 1723 1724 /* 1725 * BC1NEZ ft, offset 1726 * condition <- (FPR[ft].bit0 != 0) 1727 * if condition then 1728 * offset = sign_ext (offset) 1729 * PC = PC + 4 + offset 1730 */ 1731 ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 1732 offset = insn.getOperand(1).getImm(); 1733 1734 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1735 if (!success) 1736 return false; 1737 1738 ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0, &success); 1739 if (!success) 1740 return false; 1741 1742 if ((ft_val & 1) != 0) 1743 target = pc + 4 + offset; 1744 else 1745 target = pc + 8; 1746 1747 Context context; 1748 1749 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1750 return false; 1751 1752 return true; 1753 } 1754 1755 /* 1756 Emulate MIPS-3D Branch instructions 1757 BC1ANY2F, BC1ANY2T : Branch on Any of Two Floating Point Condition Codes False/True 1758 BC1ANY4F, BC1ANY4T : Branch on Any of Four Floating Point Condition Codes False/True 1759 */ 1760 bool 1761 EmulateInstructionMIPS64::Emulate_3D_branch (llvm::MCInst& insn) 1762 { 1763 bool success = false; 1764 uint32_t cc, fcsr; 1765 int64_t pc, offset, target = 0; 1766 const char *op_name = m_insn_info->getName (insn.getOpcode ()); 1767 1768 cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 1769 offset = insn.getOperand(1).getImm(); 1770 1771 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1772 if (!success) 1773 return false; 1774 1775 fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success); 1776 if (!success) 1777 return false; 1778 1779 /* fcsr[23], fcsr[25-31] are vaild condition bits */ 1780 fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01); 1781 1782 if (!strcasecmp (op_name, "BC1ANY2F")) 1783 { 1784 /* if any one bit is 0 */ 1785 if (((fcsr >> cc) & 3) != 3) 1786 target = pc + offset; 1787 else 1788 target = pc + 8; 1789 } 1790 else if (!strcasecmp (op_name, "BC1ANY2T")) 1791 { 1792 /* if any one bit is 1 */ 1793 if (((fcsr >> cc) & 3) != 0) 1794 target = pc + offset; 1795 else 1796 target = pc + 8; 1797 } 1798 else if (!strcasecmp (op_name, "BC1ANY4F")) 1799 { 1800 /* if any one bit is 0 */ 1801 if (((fcsr >> cc) & 0xf) != 0xf) 1802 target = pc + offset; 1803 else 1804 target = pc + 8; 1805 } 1806 else if (!strcasecmp (op_name, "BC1ANY4T")) 1807 { 1808 /* if any one bit is 1 */ 1809 if (((fcsr >> cc) & 0xf) != 0) 1810 target = pc + offset; 1811 else 1812 target = pc + 8; 1813 } 1814 1815 Context context; 1816 1817 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1818 return false; 1819 1820 return true; 1821 } 1822 1823 bool 1824 EmulateInstructionMIPS64::Emulate_BNZB (llvm::MCInst& insn) 1825 { 1826 return Emulate_MSA_Branch_DF(insn, 1, true); 1827 } 1828 1829 bool 1830 EmulateInstructionMIPS64::Emulate_BNZH (llvm::MCInst& insn) 1831 { 1832 return Emulate_MSA_Branch_DF(insn, 2, true); 1833 } 1834 1835 bool 1836 EmulateInstructionMIPS64::Emulate_BNZW (llvm::MCInst& insn) 1837 { 1838 return Emulate_MSA_Branch_DF(insn, 4, true); 1839 } 1840 1841 bool 1842 EmulateInstructionMIPS64::Emulate_BNZD (llvm::MCInst& insn) 1843 { 1844 return Emulate_MSA_Branch_DF(insn, 8, true); 1845 } 1846 1847 bool 1848 EmulateInstructionMIPS64::Emulate_BZB (llvm::MCInst& insn) 1849 { 1850 return Emulate_MSA_Branch_DF(insn, 1, false); 1851 } 1852 1853 bool 1854 EmulateInstructionMIPS64::Emulate_BZH (llvm::MCInst& insn) 1855 { 1856 return Emulate_MSA_Branch_DF(insn, 2, false); 1857 } 1858 1859 bool 1860 EmulateInstructionMIPS64::Emulate_BZW (llvm::MCInst& insn) 1861 { 1862 return Emulate_MSA_Branch_DF(insn, 4, false); 1863 } 1864 1865 bool 1866 EmulateInstructionMIPS64::Emulate_BZD (llvm::MCInst& insn) 1867 { 1868 return Emulate_MSA_Branch_DF(insn, 8, false); 1869 } 1870 1871 bool 1872 EmulateInstructionMIPS64::Emulate_MSA_Branch_DF (llvm::MCInst& insn, int element_byte_size, bool bnz) 1873 { 1874 bool success = false, branch_hit = true; 1875 int64_t target = 0; 1876 RegisterValue reg_value; 1877 uint8_t * ptr = NULL; 1878 1879 uint32_t wt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 1880 int64_t offset = insn.getOperand(1).getImm(); 1881 1882 int64_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1883 if (!success) 1884 return false; 1885 1886 if (ReadRegister (eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value)) 1887 ptr = (uint8_t *)reg_value.GetBytes(); 1888 else 1889 return false; 1890 1891 for(int i = 0; i < 16 / element_byte_size; i++) 1892 { 1893 switch(element_byte_size) 1894 { 1895 case 1: 1896 if((*ptr == 0 && bnz) || (*ptr != 0 && !bnz) ) 1897 branch_hit = false; 1898 break; 1899 case 2: 1900 if((*(uint16_t *)ptr == 0 && bnz) || (*(uint16_t *)ptr != 0 && !bnz)) 1901 branch_hit = false; 1902 break; 1903 case 4: 1904 if((*(uint32_t *)ptr == 0 && bnz) || (*(uint32_t *)ptr != 0 && !bnz)) 1905 branch_hit = false; 1906 break; 1907 case 8: 1908 if((*(uint64_t *)ptr == 0 && bnz) || (*(uint64_t *)ptr != 0 && !bnz)) 1909 branch_hit = false; 1910 break; 1911 } 1912 if(!branch_hit) 1913 break; 1914 ptr = ptr + element_byte_size; 1915 } 1916 1917 if(branch_hit) 1918 target = pc + offset; 1919 else 1920 target = pc + 8; 1921 1922 Context context; 1923 context.type = eContextRelativeBranchImmediate; 1924 1925 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1926 return false; 1927 1928 return true; 1929 } 1930 1931 bool 1932 EmulateInstructionMIPS64::Emulate_BNZV (llvm::MCInst& insn) 1933 { 1934 return Emulate_MSA_Branch_V (insn, true); 1935 } 1936 1937 bool 1938 EmulateInstructionMIPS64::Emulate_BZV (llvm::MCInst& insn) 1939 { 1940 return Emulate_MSA_Branch_V (insn, false); 1941 } 1942 1943 bool 1944 EmulateInstructionMIPS64::Emulate_MSA_Branch_V (llvm::MCInst& insn, bool bnz) 1945 { 1946 bool success = false; 1947 int64_t target = 0; 1948 llvm::APInt wr_val = llvm::APInt::getNullValue(128); 1949 llvm::APInt fail_value = llvm::APInt::getMaxValue(128); 1950 llvm::APInt zero_value = llvm::APInt::getNullValue(128); 1951 RegisterValue reg_value; 1952 1953 uint32_t wt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 1954 int64_t offset = insn.getOperand(1).getImm(); 1955 1956 int64_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1957 if (!success) 1958 return false; 1959 1960 if (ReadRegister (eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value)) 1961 wr_val = reg_value.GetAsUInt128(fail_value); 1962 else 1963 return false; 1964 1965 if((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) || (!llvm::APInt::isSameValue(zero_value, wr_val) && bnz)) 1966 target = pc + offset; 1967 else 1968 target = pc + 8; 1969 1970 Context context; 1971 context.type = eContextRelativeBranchImmediate; 1972 1973 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1974 return false; 1975 1976 return true; 1977 } 1978 1979 bool 1980 EmulateInstructionMIPS64::Emulate_LDST_Imm (llvm::MCInst& insn) 1981 { 1982 bool success = false; 1983 uint32_t base; 1984 int64_t imm, address; 1985 Context bad_vaddr_context; 1986 1987 uint32_t num_operands = insn.getNumOperands(); 1988 base = m_reg_info->getEncodingValue (insn.getOperand(num_operands-2).getReg()); 1989 imm = insn.getOperand(num_operands-1).getImm(); 1990 1991 RegisterInfo reg_info_base; 1992 if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base)) 1993 return false; 1994 1995 /* read base register */ 1996 address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); 1997 if (!success) 1998 return false; 1999 2000 /* destination address */ 2001 address = address + imm; 2002 2003 /* Set the bad_vaddr register with base address used in the instruction */ 2004 bad_vaddr_context.type = eContextInvalid; 2005 WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address); 2006 2007 return true; 2008 } 2009 2010 bool 2011 EmulateInstructionMIPS64::Emulate_LDST_Reg (llvm::MCInst& insn) 2012 { 2013 bool success = false; 2014 uint32_t base, index; 2015 int64_t address, index_address; 2016 Context bad_vaddr_context; 2017 2018 uint32_t num_operands = insn.getNumOperands(); 2019 base = m_reg_info->getEncodingValue (insn.getOperand(num_operands-2).getReg()); 2020 index = m_reg_info->getEncodingValue (insn.getOperand(num_operands-1).getReg()); 2021 2022 RegisterInfo reg_info_base, reg_info_index; 2023 if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base)) 2024 return false; 2025 2026 if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + index, reg_info_index)) 2027 return false; 2028 2029 /* read base register */ 2030 address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); 2031 if (!success) 2032 return false; 2033 2034 /* read index register */ 2035 index_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + index, 0, &success); 2036 if (!success) 2037 return false; 2038 2039 /* destination address */ 2040 address = address + index_address; 2041 2042 /* Set the bad_vaddr register with base address used in the instruction */ 2043 bad_vaddr_context.type = eContextInvalid; 2044 WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address); 2045 2046 return true; 2047 } 2048