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 { "ADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu, "ADDIU rt,rs,immediate" }, 487 { "SD", &EmulateInstructionMIPS64::Emulate_SD, "SD rt,offset(rs)" }, 488 { "LD", &EmulateInstructionMIPS64::Emulate_LD, "LD rt,offset(base)" }, 489 490 491 492 493 //---------------------------------------------------------------------- 494 // Load/Store instructions 495 //---------------------------------------------------------------------- 496 /* Following list of emulated instructions are required by implementation of hardware watchpoint 497 for MIPS in lldb. As we just need the address accessed by instructions, we have generalised 498 all these instructions in 2 functions depending on their addressing modes */ 499 500 { "LB", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LB rt, offset(base)" }, 501 { "LBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LBE rt, offset(base)" }, 502 { "LBU", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LBU rt, offset(base)" }, 503 { "LBUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LBUE rt, offset(base)" }, 504 { "LDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LDC1 ft, offset(base)" }, 505 { "LDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LDL rt, offset(base)" }, 506 { "LDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LDR rt, offset(base)" }, 507 { "LLD", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LLD rt, offset(base)" }, 508 { "LDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LDC2 rt, offset(base)" }, 509 { "LDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "LDXC1 fd, index (base)" }, 510 { "LH", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LH rt, offset(base)" }, 511 { "LHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LHE rt, offset(base)" }, 512 { "LHU", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LHU rt, offset(base)" }, 513 { "LHUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LHUE rt, offset(base)" }, 514 { "LL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LL rt, offset(base)" }, 515 { "LLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LLE rt, offset(base)" }, 516 { "LUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "LUXC1 fd, index (base)" }, 517 { "LW", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LW rt, offset(rs)" }, 518 { "LWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWC1 ft, offset(base)" }, 519 { "LWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWC2 rt, offset(base)" }, 520 { "LWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWE rt, offset(base)" }, 521 { "LWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWL rt, offset(base)" }, 522 { "LWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWLE rt, offset(base)" }, 523 { "LWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWR rt, offset(base)" }, 524 { "LWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWRE rt, offset(base)" }, 525 { "LWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "LWXC1 fd, index (base)" }, 526 527 { "SB", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SB rt, offset(base)" }, 528 { "SBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SBE rt, offset(base)" }, 529 { "SC", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SC rt, offset(base)" }, 530 { "SCE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SCE rt, offset(base)" }, 531 { "SCD", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SCD rt, offset(base)" }, 532 { "SDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SDL rt, offset(base)" }, 533 { "SDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SDR rt, offset(base)" }, 534 { "SDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SDC1 ft, offset(base)" }, 535 { "SDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SDC2 rt, offset(base)" }, 536 { "SDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "SDXC1 fs, index (base)" }, 537 { "SH", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SH rt, offset(base)" }, 538 { "SHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SHE rt, offset(base)" }, 539 { "SUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "SUXC1 fs, index (base)" }, 540 { "SW", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SW rt, offset(rs)" }, 541 { "SWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWC1 ft, offset(base)" }, 542 { "SWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWC2 rt, offset(base)" }, 543 { "SWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWE rt, offset(base)" }, 544 { "SWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWL rt, offset(base)" }, 545 { "SWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWLE rt, offset(base)" }, 546 { "SWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWR rt, offset(base)" }, 547 { "SWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWRE rt, offset(base)" }, 548 { "SWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "SWXC1 fs, index (base)" }, 549 550 //---------------------------------------------------------------------- 551 // Branch instructions 552 //---------------------------------------------------------------------- 553 { "BEQ", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQ rs,rt,offset" }, 554 { "BNE", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNE rs,rt,offset" }, 555 { "BEQL", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQL rs,rt,offset" }, 556 { "BNEL", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNEL rs,rt,offset" }, 557 { "BGEZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, "BGEZALL rt,offset" }, 558 { "BAL", &EmulateInstructionMIPS64::Emulate_BAL, "BAL offset" }, 559 { "BGEZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, "BGEZAL rs,offset" }, 560 { "BALC", &EmulateInstructionMIPS64::Emulate_BALC, "BALC offset" }, 561 { "BC", &EmulateInstructionMIPS64::Emulate_BC, "BC offset" }, 562 { "BGEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZ rs,offset" }, 563 { "BLEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BLEZALC rs,offset" }, 564 { "BGEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BGEZALC rs,offset" }, 565 { "BLTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BLTZALC rs,offset" }, 566 { "BGTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BGTZALC rs,offset" }, 567 { "BEQZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BEQZALC rs,offset" }, 568 { "BNEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BNEZALC rs,offset" }, 569 { "BEQC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BEQC rs,rt,offset" }, 570 { "BNEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BNEC rs,rt,offset" }, 571 { "BLTC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BLTC rs,rt,offset" }, 572 { "BGEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BGEC rs,rt,offset" }, 573 { "BLTUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BLTUC rs,rt,offset" }, 574 { "BGEUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BGEUC rs,rt,offset" }, 575 { "BLTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BLTZC rt,offset" }, 576 { "BLEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BLEZC rt,offset" }, 577 { "BGEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BGEZC rt,offset" }, 578 { "BGTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BGTZC rt,offset" }, 579 { "BEQZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BEQZC rt,offset" }, 580 { "BNEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BNEZC rt,offset" }, 581 { "BGEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZL rt,offset" }, 582 { "BGTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZ rt,offset" }, 583 { "BGTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZL rt,offset" }, 584 { "BLEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZ rt,offset" }, 585 { "BLEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZL rt,offset" }, 586 { "BLTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZ rt,offset" }, 587 { "BLTZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, "BLTZAL rt,offset" }, 588 { "BLTZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, "BLTZALL rt,offset" }, 589 { "BLTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZL rt,offset" }, 590 { "BOVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BOVC rs,rt,offset" }, 591 { "BNVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BNVC rs,rt,offset" }, 592 { "J", &EmulateInstructionMIPS64::Emulate_J, "J target" }, 593 { "JAL", &EmulateInstructionMIPS64::Emulate_JAL, "JAL target" }, 594 { "JALX", &EmulateInstructionMIPS64::Emulate_JAL, "JALX target" }, 595 { "JALR", &EmulateInstructionMIPS64::Emulate_JALR, "JALR target" }, 596 { "JALR_HB", &EmulateInstructionMIPS64::Emulate_JALR, "JALR.HB target" }, 597 { "JIALC", &EmulateInstructionMIPS64::Emulate_JIALC, "JIALC rt,offset" }, 598 { "JIC", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset" }, 599 { "JR", &EmulateInstructionMIPS64::Emulate_JR, "JR target" }, 600 { "JR_HB", &EmulateInstructionMIPS64::Emulate_JR, "JR.HB target" }, 601 { "BC1F", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1F cc, offset" }, 602 { "BC1T", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1T cc, offset" }, 603 { "BC1FL", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1FL cc, offset" }, 604 { "BC1TL", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1TL cc, offset" }, 605 { "BC1EQZ", &EmulateInstructionMIPS64::Emulate_BC1EQZ, "BC1EQZ ft, offset" }, 606 { "BC1NEZ", &EmulateInstructionMIPS64::Emulate_BC1NEZ, "BC1NEZ ft, offset" }, 607 { "BC1ANY2F", &EmulateInstructionMIPS64::Emulate_3D_branch, "BC1ANY2F cc, offset" }, 608 { "BC1ANY2T", &EmulateInstructionMIPS64::Emulate_3D_branch, "BC1ANY2T cc, offset" }, 609 { "BC1ANY4F", &EmulateInstructionMIPS64::Emulate_3D_branch, "BC1ANY4F cc, offset" }, 610 { "BC1ANY4T", &EmulateInstructionMIPS64::Emulate_3D_branch, "BC1ANY4T cc, offset" }, 611 { "BNZ_B", &EmulateInstructionMIPS64::Emulate_BNZB, "BNZ.b wt,s16" }, 612 { "BNZ_H", &EmulateInstructionMIPS64::Emulate_BNZH, "BNZ.h wt,s16" }, 613 { "BNZ_W", &EmulateInstructionMIPS64::Emulate_BNZW, "BNZ.w wt,s16" }, 614 { "BNZ_D", &EmulateInstructionMIPS64::Emulate_BNZD, "BNZ.d wt,s16" }, 615 { "BZ_B", &EmulateInstructionMIPS64::Emulate_BZB, "BZ.b wt,s16" }, 616 { "BZ_H", &EmulateInstructionMIPS64::Emulate_BZH, "BZ.h wt,s16" }, 617 { "BZ_W", &EmulateInstructionMIPS64::Emulate_BZW, "BZ.w wt,s16" }, 618 { "BZ_D", &EmulateInstructionMIPS64::Emulate_BZD, "BZ.d wt,s16" }, 619 { "BNZ_V", &EmulateInstructionMIPS64::Emulate_BNZV, "BNZ.V wt,s16" }, 620 { "BZ_V", &EmulateInstructionMIPS64::Emulate_BZV, "BZ.V wt,s16" }, 621 }; 622 623 static const size_t k_num_mips_opcodes = llvm::array_lengthof(g_opcodes); 624 625 for (size_t i = 0; i < k_num_mips_opcodes; ++i) 626 { 627 if (! strcasecmp (g_opcodes[i].op_name, op_name)) 628 return &g_opcodes[i]; 629 } 630 631 return NULL; 632 } 633 634 bool 635 EmulateInstructionMIPS64::ReadInstruction () 636 { 637 bool success = false; 638 m_addr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success); 639 if (success) 640 { 641 Context read_inst_context; 642 read_inst_context.type = eContextReadOpcode; 643 read_inst_context.SetNoArgs (); 644 m_opcode.SetOpcode32 (ReadMemoryUnsigned (read_inst_context, m_addr, 4, 0, &success), GetByteOrder()); 645 } 646 if (!success) 647 m_addr = LLDB_INVALID_ADDRESS; 648 return success; 649 } 650 651 bool 652 EmulateInstructionMIPS64::EvaluateInstruction (uint32_t evaluate_options) 653 { 654 bool success = false; 655 llvm::MCInst mc_insn; 656 uint64_t insn_size; 657 DataExtractor data; 658 659 /* Keep the complexity of the decode logic with the llvm::MCDisassembler class. */ 660 if (m_opcode.GetData (data)) 661 { 662 llvm::MCDisassembler::DecodeStatus decode_status; 663 llvm::ArrayRef<uint8_t> raw_insn (data.GetDataStart(), data.GetByteSize()); 664 decode_status = m_disasm->getInstruction (mc_insn, insn_size, raw_insn, m_addr, llvm::nulls(), llvm::nulls()); 665 if (decode_status != llvm::MCDisassembler::Success) 666 return false; 667 } 668 669 /* 670 * mc_insn.getOpcode() returns decoded opcode. However to make use 671 * of llvm::Mips::<insn> we would need "MipsGenInstrInfo.inc". 672 */ 673 const char *op_name = m_insn_info->getName (mc_insn.getOpcode ()); 674 675 if (op_name == NULL) 676 return false; 677 678 /* 679 * Decoding has been done already. Just get the call-back function 680 * and emulate the instruction. 681 */ 682 MipsOpcode *opcode_data = GetOpcodeForInstruction (op_name); 683 684 if (opcode_data == NULL) 685 return false; 686 687 uint64_t old_pc = 0, new_pc = 0; 688 const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC; 689 690 if (auto_advance_pc) 691 { 692 old_pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 693 if (!success) 694 return false; 695 } 696 697 /* emulate instruction */ 698 success = (this->*opcode_data->callback) (mc_insn); 699 if (!success) 700 return false; 701 702 if (auto_advance_pc) 703 { 704 new_pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 705 if (!success) 706 return false; 707 708 /* If we haven't changed the PC, change it here */ 709 if (old_pc == new_pc) 710 { 711 new_pc += 4; 712 Context context; 713 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, new_pc)) 714 return false; 715 } 716 } 717 718 return true; 719 } 720 721 bool 722 EmulateInstructionMIPS64::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan) 723 { 724 unwind_plan.Clear(); 725 unwind_plan.SetRegisterKind (eRegisterKindDWARF); 726 727 UnwindPlan::RowSP row(new UnwindPlan::Row); 728 const bool can_replace = false; 729 730 // Our previous Call Frame Address is the stack pointer 731 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp_mips64, 0); 732 733 // Our previous PC is in the RA 734 row->SetRegisterLocationToRegister(dwarf_pc_mips64, dwarf_ra_mips64, can_replace); 735 736 unwind_plan.AppendRow (row); 737 738 // All other registers are the same. 739 unwind_plan.SetSourceName ("EmulateInstructionMIPS64"); 740 unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); 741 unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes); 742 unwind_plan.SetReturnAddressRegister (dwarf_ra_mips64); 743 744 return true; 745 } 746 747 bool 748 EmulateInstructionMIPS64::nonvolatile_reg_p (uint64_t regnum) 749 { 750 switch (regnum) 751 { 752 case dwarf_r16_mips64: 753 case dwarf_r17_mips64: 754 case dwarf_r18_mips64: 755 case dwarf_r19_mips64: 756 case dwarf_r20_mips64: 757 case dwarf_r21_mips64: 758 case dwarf_r22_mips64: 759 case dwarf_r23_mips64: 760 case dwarf_gp_mips64: 761 case dwarf_sp_mips64: 762 case dwarf_r30_mips64: 763 case dwarf_ra_mips64: 764 return true; 765 default: 766 return false; 767 } 768 return false; 769 } 770 771 bool 772 EmulateInstructionMIPS64::Emulate_DADDiu (llvm::MCInst& insn) 773 { 774 bool success = false; 775 const uint32_t imm16 = insn.getOperand(2).getImm(); 776 uint64_t imm = SignedBits(imm16, 15, 0); 777 uint64_t result; 778 uint32_t src, dst; 779 780 dst = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 781 src = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); 782 783 /* Check if this is daddiu sp,<src>,imm16 */ 784 if (dst == dwarf_sp_mips64) 785 { 786 /* read <src> register */ 787 uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success); 788 if (!success) 789 return false; 790 791 result = src_opd_val + imm; 792 793 Context context; 794 RegisterInfo reg_info_sp; 795 if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips64, reg_info_sp)) 796 context.SetRegisterPlusOffset (reg_info_sp, imm); 797 798 /* We are allocating bytes on stack */ 799 context.type = eContextAdjustStackPointer; 800 801 WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips64, result); 802 } 803 804 return true; 805 } 806 807 bool 808 EmulateInstructionMIPS64::Emulate_SD (llvm::MCInst& insn) 809 { 810 uint64_t address; 811 RegisterInfo reg_info_base; 812 RegisterInfo reg_info_src; 813 bool success = false; 814 uint32_t imm16 = insn.getOperand(2).getImm(); 815 uint64_t imm = SignedBits(imm16, 15, 0); 816 uint32_t src, base; 817 Context bad_vaddr_context; 818 819 src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 820 base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); 821 822 if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips64 + base, reg_info_base) 823 || !GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips64 + src, reg_info_src)) 824 return false; 825 826 /* read SP */ 827 address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + base, 0, &success); 828 if (!success) 829 return false; 830 831 /* destination address */ 832 address = address + imm; 833 834 /* We look for sp based non-volatile register stores */ 835 if (base == dwarf_sp_mips64 && nonvolatile_reg_p (src)) 836 { 837 Context context; 838 RegisterValue data_src; 839 context.type = eContextPushRegisterOnStack; 840 context.SetRegisterToRegisterPlusOffset (reg_info_src, reg_info_base, 0); 841 842 uint8_t buffer [RegisterValue::kMaxRegisterByteSize]; 843 Error error; 844 845 if (!ReadRegister (®_info_base, data_src)) 846 return false; 847 848 if (data_src.GetAsMemoryData (®_info_src, buffer, reg_info_src.byte_size, eByteOrderLittle, error) == 0) 849 return false; 850 851 if (!WriteMemory (context, address, buffer, reg_info_src.byte_size)) 852 return false; 853 } 854 855 /* Set the bad_vaddr register with base address used in the instruction */ 856 bad_vaddr_context.type = eContextInvalid; 857 WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64, address); 858 859 return true; 860 } 861 862 bool 863 EmulateInstructionMIPS64::Emulate_LD (llvm::MCInst& insn) 864 { 865 bool success =false; 866 uint32_t src, base; 867 int64_t imm, address; 868 Context bad_vaddr_context; 869 870 src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 871 base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); 872 imm = insn.getOperand(2).getImm(); 873 874 RegisterInfo reg_info_base; 875 if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips64 + base, reg_info_base)) 876 return false; 877 878 /* read base register */ 879 address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + base, 0, &success); 880 if (!success) 881 return false; 882 883 /* destination address */ 884 address = address + imm; 885 886 /* Set the bad_vaddr register with base address used in the instruction */ 887 bad_vaddr_context.type = eContextInvalid; 888 WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64, address); 889 890 891 if (base == dwarf_sp_mips64 && nonvolatile_reg_p (src)) 892 { 893 RegisterValue data_src; 894 RegisterInfo reg_info_src; 895 896 if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips64 + src, reg_info_src)) 897 return false; 898 899 Context context; 900 context.type = eContextRegisterLoad; 901 902 if (!WriteRegister (context, ®_info_src, data_src)) 903 return false; 904 905 return true; 906 } 907 908 return false; 909 } 910 911 912 /* 913 Emulate below MIPS branch instructions. 914 BEQ, BNE : Branch on condition 915 BEQL, BNEL : Branch likely 916 */ 917 bool 918 EmulateInstructionMIPS64::Emulate_BXX_3ops (llvm::MCInst& insn) 919 { 920 bool success = false; 921 uint32_t rs, rt; 922 int64_t offset, pc, rs_val, rt_val, target = 0; 923 const char *op_name = m_insn_info->getName (insn.getOpcode ()); 924 925 rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 926 rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); 927 offset = insn.getOperand(2).getImm(); 928 929 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 930 if (!success) 931 return false; 932 933 rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success); 934 if (!success) 935 return false; 936 937 rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success); 938 if (!success) 939 return false; 940 941 if (!strcasecmp (op_name, "BEQ") || 942 !strcasecmp (op_name, "BEQL")) 943 { 944 if (rs_val == rt_val) 945 target = pc + offset; 946 else 947 target = pc + 8; 948 } 949 else if (!strcasecmp (op_name, "BNE") || 950 !strcasecmp (op_name, "BNEL")) 951 { 952 if (rs_val != rt_val) 953 target = pc + offset; 954 else 955 target = pc + 8; 956 } 957 958 Context context; 959 context.type = eContextRelativeBranchImmediate; 960 context.SetImmediate (offset); 961 962 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 963 return false; 964 965 return true; 966 } 967 968 /* 969 Emulate below MIPS Non-Compact conditional branch and link instructions. 970 BLTZAL, BGEZAL : 971 BLTZALL, BGEZALL : Branch likely 972 */ 973 bool 974 EmulateInstructionMIPS64::Emulate_Bcond_Link (llvm::MCInst& insn) 975 { 976 bool success = false; 977 uint32_t rs; 978 int64_t offset, pc, target = 0; 979 int64_t rs_val; 980 const char *op_name = m_insn_info->getName (insn.getOpcode ()); 981 982 rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 983 offset = insn.getOperand(1).getImm(); 984 985 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 986 if (!success) 987 return false; 988 989 rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success); 990 if (!success) 991 return false; 992 993 if (!strcasecmp (op_name, "BLTZAL") || 994 !strcasecmp (op_name, "BLTZALL")) 995 { 996 if (rs_val < 0) 997 target = pc + offset; 998 else 999 target = pc + 8; 1000 } 1001 else if (!strcasecmp (op_name, "BGEZAL") || 1002 !strcasecmp (op_name, "BGEZALL")) 1003 { 1004 if (rs_val >= 0) 1005 target = pc + offset; 1006 else 1007 target = pc + 8; 1008 } 1009 1010 Context context; 1011 1012 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1013 return false; 1014 1015 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 8)) 1016 return false; 1017 1018 return true; 1019 } 1020 1021 bool 1022 EmulateInstructionMIPS64::Emulate_BAL (llvm::MCInst& insn) 1023 { 1024 bool success = false; 1025 int64_t offset, pc, target; 1026 1027 /* 1028 * BAL offset 1029 * offset = sign_ext (offset << 2) 1030 * RA = PC + 8 1031 * PC = PC + offset 1032 */ 1033 offset = insn.getOperand(0).getImm(); 1034 1035 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1036 if (!success) 1037 return false; 1038 1039 target = pc + offset; 1040 1041 Context context; 1042 1043 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1044 return false; 1045 1046 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 8)) 1047 return false; 1048 1049 return true; 1050 } 1051 1052 bool 1053 EmulateInstructionMIPS64::Emulate_BALC (llvm::MCInst& insn) 1054 { 1055 bool success = false; 1056 int64_t offset, pc, target; 1057 1058 /* 1059 * BALC offset 1060 * offset = sign_ext (offset << 2) 1061 * RA = PC + 4 1062 * PC = PC + 4 + offset 1063 */ 1064 offset = insn.getOperand(0).getImm(); 1065 1066 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1067 if (!success) 1068 return false; 1069 1070 target = pc + offset; 1071 1072 Context context; 1073 1074 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1075 return false; 1076 1077 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4)) 1078 return false; 1079 1080 return true; 1081 } 1082 1083 /* 1084 Emulate below MIPS conditional branch and link instructions. 1085 BLEZALC, BGEZALC, BLTZALC, BGTZALC, BEQZALC, BNEZALC : Compact branches 1086 */ 1087 bool 1088 EmulateInstructionMIPS64::Emulate_Bcond_Link_C (llvm::MCInst& insn) 1089 { 1090 bool success = false; 1091 uint32_t rs; 1092 int64_t offset, pc, rs_val, target = 0; 1093 const char *op_name = m_insn_info->getName (insn.getOpcode ()); 1094 1095 rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 1096 offset = insn.getOperand(1).getImm(); 1097 1098 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1099 if (!success) 1100 return false; 1101 1102 rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success); 1103 if (!success) 1104 return false; 1105 1106 if (!strcasecmp (op_name, "BLEZALC")) 1107 { 1108 if (rs_val <= 0) 1109 target = pc + offset; 1110 else 1111 target = pc + 4; 1112 } 1113 else if (!strcasecmp (op_name, "BGEZALC")) 1114 { 1115 if (rs_val >= 0) 1116 target = pc + offset; 1117 else 1118 target = pc + 4; 1119 } 1120 else if (!strcasecmp (op_name, "BLTZALC")) 1121 { 1122 if (rs_val < 0) 1123 target = pc + offset; 1124 else 1125 target = pc + 4; 1126 } 1127 else if (!strcasecmp (op_name, "BGTZALC")) 1128 { 1129 if (rs_val > 0) 1130 target = pc + offset; 1131 else 1132 target = pc + 4; 1133 } 1134 else if (!strcasecmp (op_name, "BEQZALC")) 1135 { 1136 if (rs_val == 0) 1137 target = pc + offset; 1138 else 1139 target = pc + 4; 1140 } 1141 else if (!strcasecmp (op_name, "BNEZALC")) 1142 { 1143 if (rs_val != 0) 1144 target = pc + offset; 1145 else 1146 target = pc + 4; 1147 } 1148 1149 Context context; 1150 1151 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1152 return false; 1153 1154 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4)) 1155 return false; 1156 1157 return true; 1158 } 1159 1160 /* 1161 Emulate below MIPS branch instructions. 1162 BLTZL, BGEZL, BGTZL, BLEZL : Branch likely 1163 BLTZ, BGEZ, BGTZ, BLEZ : Non-compact branches 1164 */ 1165 bool 1166 EmulateInstructionMIPS64::Emulate_BXX_2ops (llvm::MCInst& insn) 1167 { 1168 bool success = false; 1169 uint32_t rs; 1170 int64_t offset, pc, rs_val, target = 0; 1171 const char *op_name = m_insn_info->getName (insn.getOpcode ()); 1172 1173 rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 1174 offset = insn.getOperand(1).getImm(); 1175 1176 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1177 if (!success) 1178 return false; 1179 1180 rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success); 1181 if (!success) 1182 return false; 1183 1184 if (!strcasecmp (op_name, "BLTZL") || 1185 !strcasecmp (op_name, "BLTZ")) 1186 { 1187 if (rs_val < 0) 1188 target = pc + offset; 1189 else 1190 target = pc + 8; 1191 } 1192 else if (!strcasecmp (op_name, "BGEZL") || 1193 !strcasecmp (op_name, "BGEZ")) 1194 { 1195 if (rs_val >= 0) 1196 target = pc + offset; 1197 else 1198 target = pc + 8; 1199 } 1200 else if (!strcasecmp (op_name, "BGTZL") || 1201 !strcasecmp (op_name, "BGTZ")) 1202 { 1203 if (rs_val > 0) 1204 target = pc + offset; 1205 else 1206 target = pc + 8; 1207 } 1208 else if (!strcasecmp (op_name, "BLEZL") || 1209 !strcasecmp (op_name, "BLEZ")) 1210 { 1211 if (rs_val <= 0) 1212 target = pc + offset; 1213 else 1214 target = pc + 8; 1215 } 1216 1217 Context context; 1218 context.type = eContextRelativeBranchImmediate; 1219 context.SetImmediate (offset); 1220 1221 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1222 return false; 1223 1224 return true; 1225 } 1226 1227 bool 1228 EmulateInstructionMIPS64::Emulate_BC (llvm::MCInst& insn) 1229 { 1230 bool success = false; 1231 int64_t offset, pc, target; 1232 1233 /* 1234 * BC offset 1235 * offset = sign_ext (offset << 2) 1236 * PC = PC + 4 + offset 1237 */ 1238 offset = insn.getOperand(0).getImm(); 1239 1240 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1241 if (!success) 1242 return false; 1243 1244 target = pc + offset; 1245 1246 Context context; 1247 1248 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1249 return false; 1250 1251 return true; 1252 } 1253 1254 static int 1255 IsAdd64bitOverflow (int64_t a, int64_t b) 1256 { 1257 int64_t r = (uint64_t) a + (uint64_t) b; 1258 return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0); 1259 } 1260 1261 /* 1262 Emulate below MIPS branch instructions. 1263 BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch instructions with no delay slot 1264 */ 1265 bool 1266 EmulateInstructionMIPS64::Emulate_BXX_3ops_C (llvm::MCInst& insn) 1267 { 1268 bool success = false; 1269 uint32_t rs, rt; 1270 int64_t offset, pc, rs_val, rt_val, target = 0; 1271 const char *op_name = m_insn_info->getName (insn.getOpcode ()); 1272 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize(); 1273 1274 rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 1275 rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); 1276 offset = insn.getOperand(2).getImm(); 1277 1278 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1279 if (!success) 1280 return false; 1281 1282 rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success); 1283 if (!success) 1284 return false; 1285 1286 rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success); 1287 if (!success) 1288 return false; 1289 1290 if (!strcasecmp (op_name, "BEQC")) 1291 { 1292 if (rs_val == rt_val) 1293 target = pc + offset; 1294 else 1295 target = pc + 4; 1296 } 1297 else if (!strcasecmp (op_name, "BNEC")) 1298 { 1299 if (rs_val != rt_val) 1300 target = pc + offset; 1301 else 1302 target = pc + 4; 1303 } 1304 else if (!strcasecmp (op_name, "BLTC")) 1305 { 1306 if (rs_val < rt_val) 1307 target = pc + offset; 1308 else 1309 target = pc + 4; 1310 } 1311 else if (!strcasecmp (op_name, "BGEC")) 1312 { 1313 if (rs_val >= rt_val) 1314 target = pc + offset; 1315 else 1316 target = pc + 4; 1317 } 1318 else if (!strcasecmp (op_name, "BLTUC")) 1319 { 1320 if (rs_val < rt_val) 1321 target = pc + offset; 1322 else 1323 target = pc + 4; 1324 } 1325 else if (!strcasecmp (op_name, "BGEUC")) 1326 { 1327 if ((uint32_t)rs_val >= (uint32_t)rt_val) 1328 target = pc + offset; 1329 else 1330 target = pc + 4; 1331 } 1332 else if (!strcasecmp (op_name, "BOVC")) 1333 { 1334 if (IsAdd64bitOverflow (rs_val, rt_val)) 1335 target = pc + offset; 1336 else 1337 target = pc + 4; 1338 } 1339 else if (!strcasecmp (op_name, "BNVC")) 1340 { 1341 if (!IsAdd64bitOverflow (rs_val, rt_val)) 1342 target = pc + offset; 1343 else 1344 target = pc + 4; 1345 } 1346 1347 Context context; 1348 context.type = eContextRelativeBranchImmediate; 1349 context.SetImmediate (current_inst_size + offset); 1350 1351 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1352 return false; 1353 1354 return true; 1355 } 1356 1357 /* 1358 Emulate below MIPS branch instructions. 1359 BLTZC, BLEZC, BGEZC, BGTZC, BEQZC, BNEZC : Compact Branches 1360 */ 1361 bool 1362 EmulateInstructionMIPS64::Emulate_BXX_2ops_C (llvm::MCInst& insn) 1363 { 1364 bool success = false; 1365 uint32_t rs; 1366 int64_t offset, pc, target = 0; 1367 int64_t rs_val; 1368 const char *op_name = m_insn_info->getName (insn.getOpcode ()); 1369 uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize(); 1370 1371 rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 1372 offset = insn.getOperand(1).getImm(); 1373 1374 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1375 if (!success) 1376 return false; 1377 1378 rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success); 1379 if (!success) 1380 return false; 1381 1382 if (!strcasecmp (op_name, "BLTZC")) 1383 { 1384 if (rs_val < 0) 1385 target = pc + offset; 1386 else 1387 target = pc + 4; 1388 } 1389 else if (!strcasecmp (op_name, "BLEZC")) 1390 { 1391 if (rs_val <= 0) 1392 target = pc + offset; 1393 else 1394 target = pc + 4; 1395 } 1396 else if (!strcasecmp (op_name, "BGEZC")) 1397 { 1398 if (rs_val >= 0) 1399 target = pc + offset; 1400 else 1401 target = pc + 4; 1402 } 1403 else if (!strcasecmp (op_name, "BGTZC")) 1404 { 1405 if (rs_val > 0) 1406 target = pc + offset; 1407 else 1408 target = pc + 4; 1409 } 1410 else if (!strcasecmp (op_name, "BEQZC")) 1411 { 1412 if (rs_val == 0) 1413 target = pc + offset; 1414 else 1415 target = pc + 4; 1416 } 1417 else if (!strcasecmp (op_name, "BNEZC")) 1418 { 1419 if (rs_val != 0) 1420 target = pc + offset; 1421 else 1422 target = pc + 4; 1423 } 1424 1425 Context context; 1426 context.type = eContextRelativeBranchImmediate; 1427 context.SetImmediate (current_inst_size + offset); 1428 1429 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1430 return false; 1431 1432 return true; 1433 } 1434 1435 bool 1436 EmulateInstructionMIPS64::Emulate_J (llvm::MCInst& insn) 1437 { 1438 bool success = false; 1439 uint64_t offset, pc; 1440 1441 /* 1442 * J offset 1443 * offset = sign_ext (offset << 2) 1444 * PC = PC[63-28] | offset 1445 */ 1446 offset = insn.getOperand(0).getImm(); 1447 1448 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1449 if (!success) 1450 return false; 1451 1452 /* This is a PC-region branch and not PC-relative */ 1453 pc = (pc & 0xFFFFFFFFF0000000ULL) | offset; 1454 1455 Context context; 1456 1457 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, pc)) 1458 return false; 1459 1460 return true; 1461 } 1462 1463 bool 1464 EmulateInstructionMIPS64::Emulate_JAL (llvm::MCInst& insn) 1465 { 1466 bool success = false; 1467 uint64_t offset, target, pc; 1468 1469 /* 1470 * JAL offset 1471 * offset = sign_ext (offset << 2) 1472 * PC = PC[63-28] | offset 1473 */ 1474 offset = insn.getOperand(0).getImm(); 1475 1476 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1477 if (!success) 1478 return false; 1479 1480 /* This is a PC-region branch and not PC-relative */ 1481 target = (pc & 0xFFFFFFFFF0000000ULL) | offset; 1482 1483 Context context; 1484 1485 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1486 return false; 1487 1488 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 8)) 1489 return false; 1490 1491 return true; 1492 } 1493 1494 bool 1495 EmulateInstructionMIPS64::Emulate_JALR (llvm::MCInst& insn) 1496 { 1497 bool success = false; 1498 uint32_t rs, rt; 1499 uint64_t pc, rs_val; 1500 1501 /* 1502 * JALR rt, rs 1503 * GPR[rt] = PC + 8 1504 * PC = GPR[rs] 1505 */ 1506 rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 1507 rs = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); 1508 1509 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1510 if (!success) 1511 return false; 1512 1513 rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success); 1514 if (!success) 1515 return false; 1516 1517 Context context; 1518 1519 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, rs_val)) 1520 return false; 1521 1522 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips64 + rt, pc + 8)) 1523 return false; 1524 1525 return true; 1526 } 1527 1528 bool 1529 EmulateInstructionMIPS64::Emulate_JIALC (llvm::MCInst& insn) 1530 { 1531 bool success = false; 1532 uint32_t rt; 1533 int64_t target, offset, pc, rt_val; 1534 1535 /* 1536 * JIALC rt, offset 1537 * offset = sign_ext (offset) 1538 * PC = GPR[rt] + offset 1539 * RA = PC + 4 1540 */ 1541 rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 1542 offset = insn.getOperand(1).getImm(); 1543 1544 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1545 if (!success) 1546 return false; 1547 1548 rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success); 1549 if (!success) 1550 return false; 1551 1552 target = rt_val + offset; 1553 1554 Context context; 1555 1556 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1557 return false; 1558 1559 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4)) 1560 return false; 1561 1562 return true; 1563 } 1564 1565 bool 1566 EmulateInstructionMIPS64::Emulate_JIC (llvm::MCInst& insn) 1567 { 1568 bool success = false; 1569 uint32_t rt; 1570 int64_t target, offset, rt_val; 1571 1572 /* 1573 * JIC rt, offset 1574 * offset = sign_ext (offset) 1575 * PC = GPR[rt] + offset 1576 */ 1577 rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 1578 offset = insn.getOperand(1).getImm(); 1579 1580 rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success); 1581 if (!success) 1582 return false; 1583 1584 target = rt_val + offset; 1585 1586 Context context; 1587 1588 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1589 return false; 1590 1591 return true; 1592 } 1593 1594 bool 1595 EmulateInstructionMIPS64::Emulate_JR (llvm::MCInst& insn) 1596 { 1597 bool success = false; 1598 uint32_t rs; 1599 uint64_t rs_val; 1600 1601 /* 1602 * JR rs 1603 * PC = GPR[rs] 1604 */ 1605 rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 1606 1607 rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success); 1608 if (!success) 1609 return false; 1610 1611 Context context; 1612 1613 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, rs_val)) 1614 return false; 1615 1616 return true; 1617 } 1618 1619 /* 1620 Emulate Branch on FP True/False 1621 BC1F, BC1FL : Branch on FP False (L stands for branch likely) 1622 BC1T, BC1TL : Branch on FP True (L stands for branch likely) 1623 */ 1624 bool 1625 EmulateInstructionMIPS64::Emulate_FP_branch (llvm::MCInst& insn) 1626 { 1627 bool success = false; 1628 uint32_t cc, fcsr; 1629 int64_t pc, offset, target = 0; 1630 const char *op_name = m_insn_info->getName (insn.getOpcode ()); 1631 1632 /* 1633 * BC1F cc, offset 1634 * condition <- (FPConditionCode(cc) == 0) 1635 * if condition then 1636 * offset = sign_ext (offset) 1637 * PC = PC + offset 1638 */ 1639 cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 1640 offset = insn.getOperand(1).getImm(); 1641 1642 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1643 if (!success) 1644 return false; 1645 1646 fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success); 1647 if (!success) 1648 return false; 1649 1650 /* fcsr[23], fcsr[25-31] are vaild condition bits */ 1651 fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01); 1652 1653 if (!strcasecmp (op_name, "BC1F") || 1654 !strcasecmp (op_name, "BC1FL")) 1655 { 1656 if ((fcsr & (1 << cc)) == 0) 1657 target = pc + offset; 1658 else 1659 target = pc + 8; 1660 } 1661 else if (!strcasecmp (op_name, "BC1T") || 1662 !strcasecmp (op_name, "BC1TL")) 1663 { 1664 if ((fcsr & (1 << cc)) != 0) 1665 target = pc + offset; 1666 else 1667 target = pc + 8; 1668 } 1669 1670 Context context; 1671 1672 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1673 return false; 1674 1675 return true; 1676 } 1677 1678 bool 1679 EmulateInstructionMIPS64::Emulate_BC1EQZ (llvm::MCInst& insn) 1680 { 1681 bool success = false; 1682 uint32_t ft; 1683 uint64_t ft_val; 1684 int64_t target, pc, offset; 1685 1686 /* 1687 * BC1EQZ ft, offset 1688 * condition <- (FPR[ft].bit0 == 0) 1689 * if condition then 1690 * offset = sign_ext (offset) 1691 * PC = PC + 4 + offset 1692 */ 1693 ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 1694 offset = insn.getOperand(1).getImm(); 1695 1696 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1697 if (!success) 1698 return false; 1699 1700 ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0, &success); 1701 if (!success) 1702 return false; 1703 1704 if ((ft_val & 1) == 0) 1705 target = pc + 4 + offset; 1706 else 1707 target = pc + 8; 1708 1709 Context context; 1710 1711 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1712 return false; 1713 1714 return true; 1715 } 1716 1717 bool 1718 EmulateInstructionMIPS64::Emulate_BC1NEZ (llvm::MCInst& insn) 1719 { 1720 bool success = false; 1721 uint32_t ft; 1722 uint64_t ft_val; 1723 int64_t target, pc, offset; 1724 1725 /* 1726 * BC1NEZ ft, offset 1727 * condition <- (FPR[ft].bit0 != 0) 1728 * if condition then 1729 * offset = sign_ext (offset) 1730 * PC = PC + 4 + offset 1731 */ 1732 ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 1733 offset = insn.getOperand(1).getImm(); 1734 1735 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1736 if (!success) 1737 return false; 1738 1739 ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0, &success); 1740 if (!success) 1741 return false; 1742 1743 if ((ft_val & 1) != 0) 1744 target = pc + 4 + offset; 1745 else 1746 target = pc + 8; 1747 1748 Context context; 1749 1750 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1751 return false; 1752 1753 return true; 1754 } 1755 1756 /* 1757 Emulate MIPS-3D Branch instructions 1758 BC1ANY2F, BC1ANY2T : Branch on Any of Two Floating Point Condition Codes False/True 1759 BC1ANY4F, BC1ANY4T : Branch on Any of Four Floating Point Condition Codes False/True 1760 */ 1761 bool 1762 EmulateInstructionMIPS64::Emulate_3D_branch (llvm::MCInst& insn) 1763 { 1764 bool success = false; 1765 uint32_t cc, fcsr; 1766 int64_t pc, offset, target = 0; 1767 const char *op_name = m_insn_info->getName (insn.getOpcode ()); 1768 1769 cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 1770 offset = insn.getOperand(1).getImm(); 1771 1772 pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1773 if (!success) 1774 return false; 1775 1776 fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success); 1777 if (!success) 1778 return false; 1779 1780 /* fcsr[23], fcsr[25-31] are vaild condition bits */ 1781 fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01); 1782 1783 if (!strcasecmp (op_name, "BC1ANY2F")) 1784 { 1785 /* if any one bit is 0 */ 1786 if (((fcsr >> cc) & 3) != 3) 1787 target = pc + offset; 1788 else 1789 target = pc + 8; 1790 } 1791 else if (!strcasecmp (op_name, "BC1ANY2T")) 1792 { 1793 /* if any one bit is 1 */ 1794 if (((fcsr >> cc) & 3) != 0) 1795 target = pc + offset; 1796 else 1797 target = pc + 8; 1798 } 1799 else if (!strcasecmp (op_name, "BC1ANY4F")) 1800 { 1801 /* if any one bit is 0 */ 1802 if (((fcsr >> cc) & 0xf) != 0xf) 1803 target = pc + offset; 1804 else 1805 target = pc + 8; 1806 } 1807 else if (!strcasecmp (op_name, "BC1ANY4T")) 1808 { 1809 /* if any one bit is 1 */ 1810 if (((fcsr >> cc) & 0xf) != 0) 1811 target = pc + offset; 1812 else 1813 target = pc + 8; 1814 } 1815 1816 Context context; 1817 1818 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1819 return false; 1820 1821 return true; 1822 } 1823 1824 bool 1825 EmulateInstructionMIPS64::Emulate_BNZB (llvm::MCInst& insn) 1826 { 1827 return Emulate_MSA_Branch_DF(insn, 1, true); 1828 } 1829 1830 bool 1831 EmulateInstructionMIPS64::Emulate_BNZH (llvm::MCInst& insn) 1832 { 1833 return Emulate_MSA_Branch_DF(insn, 2, true); 1834 } 1835 1836 bool 1837 EmulateInstructionMIPS64::Emulate_BNZW (llvm::MCInst& insn) 1838 { 1839 return Emulate_MSA_Branch_DF(insn, 4, true); 1840 } 1841 1842 bool 1843 EmulateInstructionMIPS64::Emulate_BNZD (llvm::MCInst& insn) 1844 { 1845 return Emulate_MSA_Branch_DF(insn, 8, true); 1846 } 1847 1848 bool 1849 EmulateInstructionMIPS64::Emulate_BZB (llvm::MCInst& insn) 1850 { 1851 return Emulate_MSA_Branch_DF(insn, 1, false); 1852 } 1853 1854 bool 1855 EmulateInstructionMIPS64::Emulate_BZH (llvm::MCInst& insn) 1856 { 1857 return Emulate_MSA_Branch_DF(insn, 2, false); 1858 } 1859 1860 bool 1861 EmulateInstructionMIPS64::Emulate_BZW (llvm::MCInst& insn) 1862 { 1863 return Emulate_MSA_Branch_DF(insn, 4, false); 1864 } 1865 1866 bool 1867 EmulateInstructionMIPS64::Emulate_BZD (llvm::MCInst& insn) 1868 { 1869 return Emulate_MSA_Branch_DF(insn, 8, false); 1870 } 1871 1872 bool 1873 EmulateInstructionMIPS64::Emulate_MSA_Branch_DF (llvm::MCInst& insn, int element_byte_size, bool bnz) 1874 { 1875 bool success = false, branch_hit = true; 1876 int64_t target = 0; 1877 RegisterValue reg_value; 1878 const uint8_t *ptr = NULL; 1879 1880 uint32_t wt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 1881 int64_t offset = insn.getOperand(1).getImm(); 1882 1883 int64_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1884 if (!success) 1885 return false; 1886 1887 if (ReadRegister (eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value)) 1888 ptr = (const uint8_t *)reg_value.GetBytes(); 1889 else 1890 return false; 1891 1892 for(int i = 0; i < 16 / element_byte_size; i++) 1893 { 1894 switch(element_byte_size) 1895 { 1896 case 1: 1897 if((*ptr == 0 && bnz) || (*ptr != 0 && !bnz) ) 1898 branch_hit = false; 1899 break; 1900 case 2: 1901 if ((*(const uint16_t *)ptr == 0 && bnz) || (*(const uint16_t *)ptr != 0 && !bnz)) 1902 branch_hit = false; 1903 break; 1904 case 4: 1905 if ((*(const uint32_t *)ptr == 0 && bnz) || (*(const uint32_t *)ptr != 0 && !bnz)) 1906 branch_hit = false; 1907 break; 1908 case 8: 1909 if ((*(const uint64_t *)ptr == 0 && bnz) || (*(const uint64_t *)ptr != 0 && !bnz)) 1910 branch_hit = false; 1911 break; 1912 } 1913 if(!branch_hit) 1914 break; 1915 ptr = ptr + element_byte_size; 1916 } 1917 1918 if(branch_hit) 1919 target = pc + offset; 1920 else 1921 target = pc + 8; 1922 1923 Context context; 1924 context.type = eContextRelativeBranchImmediate; 1925 1926 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1927 return false; 1928 1929 return true; 1930 } 1931 1932 bool 1933 EmulateInstructionMIPS64::Emulate_BNZV (llvm::MCInst& insn) 1934 { 1935 return Emulate_MSA_Branch_V (insn, true); 1936 } 1937 1938 bool 1939 EmulateInstructionMIPS64::Emulate_BZV (llvm::MCInst& insn) 1940 { 1941 return Emulate_MSA_Branch_V (insn, false); 1942 } 1943 1944 bool 1945 EmulateInstructionMIPS64::Emulate_MSA_Branch_V (llvm::MCInst& insn, bool bnz) 1946 { 1947 bool success = false; 1948 int64_t target = 0; 1949 llvm::APInt wr_val = llvm::APInt::getNullValue(128); 1950 llvm::APInt fail_value = llvm::APInt::getMaxValue(128); 1951 llvm::APInt zero_value = llvm::APInt::getNullValue(128); 1952 RegisterValue reg_value; 1953 1954 uint32_t wt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); 1955 int64_t offset = insn.getOperand(1).getImm(); 1956 1957 int64_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); 1958 if (!success) 1959 return false; 1960 1961 if (ReadRegister (eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value)) 1962 wr_val = reg_value.GetAsUInt128(fail_value); 1963 else 1964 return false; 1965 1966 if((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) || (!llvm::APInt::isSameValue(zero_value, wr_val) && bnz)) 1967 target = pc + offset; 1968 else 1969 target = pc + 8; 1970 1971 Context context; 1972 context.type = eContextRelativeBranchImmediate; 1973 1974 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) 1975 return false; 1976 1977 return true; 1978 } 1979 1980 bool 1981 EmulateInstructionMIPS64::Emulate_LDST_Imm (llvm::MCInst& insn) 1982 { 1983 bool success = false; 1984 uint32_t base; 1985 int64_t imm, address; 1986 Context bad_vaddr_context; 1987 1988 uint32_t num_operands = insn.getNumOperands(); 1989 base = m_reg_info->getEncodingValue (insn.getOperand(num_operands-2).getReg()); 1990 imm = insn.getOperand(num_operands-1).getImm(); 1991 1992 RegisterInfo reg_info_base; 1993 if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base)) 1994 return false; 1995 1996 /* read base register */ 1997 address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); 1998 if (!success) 1999 return false; 2000 2001 /* destination address */ 2002 address = address + imm; 2003 2004 /* Set the bad_vaddr register with base address used in the instruction */ 2005 bad_vaddr_context.type = eContextInvalid; 2006 WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address); 2007 2008 return true; 2009 } 2010 2011 bool 2012 EmulateInstructionMIPS64::Emulate_LDST_Reg (llvm::MCInst& insn) 2013 { 2014 bool success = false; 2015 uint32_t base, index; 2016 int64_t address, index_address; 2017 Context bad_vaddr_context; 2018 2019 uint32_t num_operands = insn.getNumOperands(); 2020 base = m_reg_info->getEncodingValue (insn.getOperand(num_operands-2).getReg()); 2021 index = m_reg_info->getEncodingValue (insn.getOperand(num_operands-1).getReg()); 2022 2023 RegisterInfo reg_info_base, reg_info_index; 2024 if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base)) 2025 return false; 2026 2027 if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + index, reg_info_index)) 2028 return false; 2029 2030 /* read base register */ 2031 address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); 2032 if (!success) 2033 return false; 2034 2035 /* read index register */ 2036 index_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + index, 0, &success); 2037 if (!success) 2038 return false; 2039 2040 /* destination address */ 2041 address = address + index_address; 2042 2043 /* Set the bad_vaddr register with base address used in the instruction */ 2044 bad_vaddr_context.type = eContextInvalid; 2045 WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address); 2046 2047 return true; 2048 } 2049