Index: source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h =================================================================== --- source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h +++ source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h @@ -41,7 +41,7 @@ class LLVMCDisassembler { public: - LLVMCDisassembler (const char *triple, unsigned flavor, DisassemblerLLVMC &owner); + LLVMCDisassembler (const char *triple, const char *cpu, unsigned flavor, DisassemblerLLVMC &owner); ~LLVMCDisassembler(); Index: source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp =================================================================== --- source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp +++ source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp @@ -415,7 +415,7 @@ -DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, unsigned flavor, DisassemblerLLVMC &owner): +DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, const char *cpu, unsigned flavor, DisassemblerLLVMC &owner): m_is_valid(true) { std::string Error; @@ -431,7 +431,7 @@ std::string features_str; - m_subtarget_info_ap.reset(curr_target->createMCSubtargetInfo(triple, "", + m_subtarget_info_ap.reset(curr_target->createMCSubtargetInfo(triple, cpu, features_str)); std::unique_ptr reg_info(curr_target->createMCRegInfo(triple)); @@ -637,7 +637,45 @@ triple = thumb_arch.GetTriple().getTriple().c_str(); } - m_disasm_ap.reset (new LLVMCDisassembler(triple, flavor, *this)); + const char *cpu = ""; + + switch (arch.GetCore()) + { + case ArchSpec::eCore_mips32: + case ArchSpec::eCore_mips32el: + cpu = "mips32"; break; + case ArchSpec::eCore_mips32r2: + case ArchSpec::eCore_mips32r2el: + cpu = "mips32r2"; break; + case ArchSpec::eCore_mips32r3: + case ArchSpec::eCore_mips32r3el: + cpu = "mips32r3"; break; + case ArchSpec::eCore_mips32r5: + case ArchSpec::eCore_mips32r5el: + cpu = "mips32r5"; break; + case ArchSpec::eCore_mips32r6: + case ArchSpec::eCore_mips32r6el: + cpu = "mips32r6"; break; + case ArchSpec::eCore_mips64: + case ArchSpec::eCore_mips64el: + cpu = "mips64"; break; + case ArchSpec::eCore_mips64r2: + case ArchSpec::eCore_mips64r2el: + cpu = "mips64r2"; break; + case ArchSpec::eCore_mips64r3: + case ArchSpec::eCore_mips64r3el: + cpu = "mips64r3"; break; + case ArchSpec::eCore_mips64r5: + case ArchSpec::eCore_mips64r5el: + cpu = "mips64r5"; break; + case ArchSpec::eCore_mips64r6: + case ArchSpec::eCore_mips64r6el: + cpu = "mips64r6"; break; + default: + cpu = ""; break; + } + + m_disasm_ap.reset (new LLVMCDisassembler(triple, cpu, flavor, *this)); if (!m_disasm_ap->IsValid()) { // We use m_disasm_ap.get() to tell whether we are valid or not, so if this isn't good for some reason, @@ -649,7 +687,7 @@ if (arch.GetTriple().getArch() == llvm::Triple::arm) { std::string thumb_triple(thumb_arch.GetTriple().getTriple()); - m_alternate_disasm_ap.reset(new LLVMCDisassembler(thumb_triple.c_str(), flavor, *this)); + m_alternate_disasm_ap.reset(new LLVMCDisassembler(thumb_triple.c_str(), nullptr, flavor, *this)); if (!m_alternate_disasm_ap->IsValid()) { m_disasm_ap.reset(); Index: source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h =================================================================== --- source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h +++ source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h @@ -266,6 +266,36 @@ Emulate_JR (llvm::MCInst& insn); bool + Emulate_BC1F (llvm::MCInst& insn); + + bool + Emulate_BC1T (llvm::MCInst& insn); + + bool + Emulate_BC1FL (llvm::MCInst& insn); + + bool + Emulate_BC1TL (llvm::MCInst& insn); + + bool + Emulate_BC1EQZ (llvm::MCInst& insn); + + bool + Emulate_BC1NEZ (llvm::MCInst& insn); + + bool + Emulate_BC1ANY2F (llvm::MCInst& insn); + + bool + Emulate_BC1ANY2T (llvm::MCInst& insn); + + bool + Emulate_BC1ANY4F (llvm::MCInst& insn); + + bool + Emulate_BC1ANY4T (llvm::MCInst& insn); + + bool nonvolatile_reg_p (uint64_t regnum); const char * Index: source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp =================================================================== --- source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp +++ source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp @@ -208,9 +208,41 @@ { switch (reg_num) { - case gcc_dwarf_sp_mips64: return "r29"; + case gcc_dwarf_sp_mips64: return "r29"; case gcc_dwarf_r30_mips64: return "r30"; - case gcc_dwarf_ra_mips64: return "r31"; + case gcc_dwarf_ra_mips64: return "r31"; + case gcc_dwarf_f0_mips64: return "f0"; + case gcc_dwarf_f1_mips64: return "f1"; + case gcc_dwarf_f2_mips64: return "f2"; + case gcc_dwarf_f3_mips64: return "f3"; + case gcc_dwarf_f4_mips64: return "f4"; + case gcc_dwarf_f5_mips64: return "f5"; + case gcc_dwarf_f6_mips64: return "f6"; + case gcc_dwarf_f7_mips64: return "f7"; + case gcc_dwarf_f8_mips64: return "f8"; + case gcc_dwarf_f9_mips64: return "f9"; + case gcc_dwarf_f10_mips64: return "f10"; + case gcc_dwarf_f11_mips64: return "f11"; + case gcc_dwarf_f12_mips64: return "f12"; + case gcc_dwarf_f13_mips64: return "f13"; + case gcc_dwarf_f14_mips64: return "f14"; + case gcc_dwarf_f15_mips64: return "f15"; + case gcc_dwarf_f16_mips64: return "f16"; + case gcc_dwarf_f17_mips64: return "f17"; + case gcc_dwarf_f18_mips64: return "f18"; + case gcc_dwarf_f19_mips64: return "f19"; + case gcc_dwarf_f20_mips64: return "f20"; + case gcc_dwarf_f21_mips64: return "f21"; + case gcc_dwarf_f22_mips64: return "f22"; + case gcc_dwarf_f23_mips64: return "f23"; + case gcc_dwarf_f24_mips64: return "f24"; + case gcc_dwarf_f25_mips64: return "f25"; + case gcc_dwarf_f26_mips64: return "f26"; + case gcc_dwarf_f27_mips64: return "f27"; + case gcc_dwarf_f28_mips64: return "f28"; + case gcc_dwarf_f29_mips64: return "f29"; + case gcc_dwarf_f30_mips64: return "f30"; + case gcc_dwarf_f31_mips64: return "f31"; default: break; } @@ -257,7 +289,40 @@ case gcc_dwarf_bad_mips64: return "bad"; case gcc_dwarf_cause_mips64: return "cause"; case gcc_dwarf_pc_mips64: return "pc"; - + case gcc_dwarf_f0_mips64: return "fp_reg[0]"; + case gcc_dwarf_f1_mips64: return "fp_reg[1]"; + case gcc_dwarf_f2_mips64: return "fp_reg[2]"; + case gcc_dwarf_f3_mips64: return "fp_reg[3]"; + case gcc_dwarf_f4_mips64: return "fp_reg[4]"; + case gcc_dwarf_f5_mips64: return "fp_reg[5]"; + case gcc_dwarf_f6_mips64: return "fp_reg[6]"; + case gcc_dwarf_f7_mips64: return "fp_reg[7]"; + case gcc_dwarf_f8_mips64: return "fp_reg[8]"; + case gcc_dwarf_f9_mips64: return "fp_reg[9]"; + case gcc_dwarf_f10_mips64: return "fp_reg[10]"; + case gcc_dwarf_f11_mips64: return "fp_reg[11]"; + case gcc_dwarf_f12_mips64: return "fp_reg[12]"; + case gcc_dwarf_f13_mips64: return "fp_reg[13]"; + case gcc_dwarf_f14_mips64: return "fp_reg[14]"; + case gcc_dwarf_f15_mips64: return "fp_reg[15]"; + case gcc_dwarf_f16_mips64: return "fp_reg[16]"; + case gcc_dwarf_f17_mips64: return "fp_reg[17]"; + case gcc_dwarf_f18_mips64: return "fp_reg[18]"; + case gcc_dwarf_f19_mips64: return "fp_reg[19]"; + case gcc_dwarf_f20_mips64: return "fp_reg[20]"; + case gcc_dwarf_f21_mips64: return "fp_reg[21]"; + case gcc_dwarf_f22_mips64: return "fp_reg[22]"; + case gcc_dwarf_f23_mips64: return "fp_reg[23]"; + case gcc_dwarf_f24_mips64: return "fp_reg[24]"; + case gcc_dwarf_f25_mips64: return "fp_reg[25]"; + case gcc_dwarf_f26_mips64: return "fp_reg[26]"; + case gcc_dwarf_f27_mips64: return "fp_reg[27]"; + case gcc_dwarf_f28_mips64: return "fp_reg[28]"; + case gcc_dwarf_f29_mips64: return "fp_reg[29]"; + case gcc_dwarf_f30_mips64: return "fp_reg[30]"; + case gcc_dwarf_f31_mips64: return "fp_reg[31]"; + case gcc_dwarf_fcsr_mips64: return "fcsr"; + case gcc_dwarf_fir_mips64: return "fir"; } return nullptr; } @@ -284,13 +349,13 @@ ::memset (®_info, 0, sizeof(RegisterInfo)); ::memset (reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds)); - if (reg_num == gcc_dwarf_sr_mips64) + if (reg_num == gcc_dwarf_sr_mips64 || reg_num == gcc_dwarf_fcsr_mips || reg_num == gcc_dwarf_fir_mips) { reg_info.byte_size = 4; reg_info.format = eFormatHex; reg_info.encoding = eEncodingUint; } - else if ((int)reg_num >= gcc_dwarf_zero_mips64 && (int)reg_num <= gcc_dwarf_pc_mips64) + else if ((int)reg_num >= gcc_dwarf_zero_mips64 && (int)reg_num <= gcc_dwarf_f31_mips) { reg_info.byte_size = 8; reg_info.format = eFormatHex; @@ -383,6 +448,15 @@ { "JIC", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset" }, { "JR", &EmulateInstructionMIPS64::Emulate_JR, "JR target" }, { "JR_HB", &EmulateInstructionMIPS64::Emulate_JR, "JR.HB target" }, + { "BC1F", &EmulateInstructionMIPS64::Emulate_BC1F, "BC1F cc, offset" }, + { "BC1T", &EmulateInstructionMIPS64::Emulate_BC1T, "BC1T cc, offset" }, + { "BC1FL", &EmulateInstructionMIPS64::Emulate_BC1FL, "BC1FL cc, offset" }, + { "BC1EQZ", &EmulateInstructionMIPS64::Emulate_BC1EQZ, "BC1EQZ ft, offset" }, + { "BC1NEZ", &EmulateInstructionMIPS64::Emulate_BC1NEZ, "BC1NEZ ft, offset" }, + { "BC1ANY2F", &EmulateInstructionMIPS64::Emulate_BC1ANY2F, "BC1ANY2F cc, offset" }, + { "BC1ANY2T", &EmulateInstructionMIPS64::Emulate_BC1ANY2T, "BC1ANY2T cc, offset" }, + { "BC1ANY4F", &EmulateInstructionMIPS64::Emulate_BC1ANY4F, "BC1ANY4F cc, offset" }, + { "BC1ANY4T", &EmulateInstructionMIPS64::Emulate_BC1ANY4T, "BC1ANY4T cc, offset" }, }; static const size_t k_num_mips_opcodes = llvm::array_lengthof(g_opcodes); @@ -2347,7 +2421,7 @@ * RA = PC + 4 */ rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(0).getImm(); + offset = insn.getOperand(1).getImm(); pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); if (!success) @@ -2383,7 +2457,7 @@ * PC = GPR[rt] + offset */ rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(0).getImm(); + offset = insn.getOperand(1).getImm(); rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success); if (!success) @@ -2423,3 +2497,421 @@ return true; } + +bool +EmulateInstructionMIPS64::Emulate_BC1F (llvm::MCInst& insn) +{ + bool success = false; + uint32_t cc, fcsr; + int64_t target, pc, offset; + + /* + * BC1F cc, offset + * condition <- (FPConditionCode(cc) == 0) + * if condition then + * offset = sign_ext (offset) + * PC = PC + offset + */ + cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); + if (!success) + return false; + + fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success); + if (!success) + return false; + + /* fcsr[23], fcsr[25-31] are vaild condition bits */ + fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01); + + if ((fcsr & (1 << cc)) == 0) + target = pc + offset; + else + target = pc + 4; + + Context context; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS64::Emulate_BC1T (llvm::MCInst& insn) +{ + bool success = false; + uint32_t cc, fcsr; + int64_t target, pc, offset; + + /* + * BC1T cc, offset + * condition <- (FPConditionCode(cc) != 0) + * if condition then + * offset = sign_ext (offset) + * PC = PC + offset + */ + cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); + if (!success) + return false; + + fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success); + if (!success) + return false; + + /* fcsr[23], fcsr[25-31] are vaild condition bits */ + fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01); + + if ((fcsr & (1 << cc)) != 0) + target = pc + offset; + else + target = pc + 4; + + Context context; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS64::Emulate_BC1FL (llvm::MCInst& insn) +{ + bool success = false; + uint32_t cc, fcsr; + int64_t target, pc, offset; + + /* + * BC1F cc, offset + * condition <- (FPConditionCode(cc) == 0) + * if condition then + * offset = sign_ext (offset) + * PC = PC + offset + */ + cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); + if (!success) + return false; + + fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success); + if (!success) + return false; + + /* fcsr[23], fcsr[25-31] are vaild condition bits */ + fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01); + + if ((fcsr & (1 << cc)) == 0) + target = pc + offset; + else + target = pc + 8; /* skip delay slot */ + + Context context; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS64::Emulate_BC1TL (llvm::MCInst& insn) +{ + bool success = false; + uint32_t cc, fcsr; + int64_t target, pc, offset; + + /* + * BC1T cc, offset + * condition <- (FPConditionCode(cc) != 0) + * if condition then + * offset = sign_ext (offset) + * PC = PC + offset + */ + cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); + if (!success) + return false; + + fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success); + if (!success) + return false; + + /* fcsr[23], fcsr[25-31] are vaild condition bits */ + fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01); + + if ((fcsr & (1 << cc)) != 0) + target = pc + offset; + else + target = pc + 8; /* skip delay slot */ + + Context context; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS64::Emulate_BC1EQZ (llvm::MCInst& insn) +{ + bool success = false; + uint32_t ft; + uint64_t ft_val; + int64_t target, pc, offset; + + /* + * BC1EQZ ft, offset + * condition <- (FPR[ft].bit0 == 0) + * if condition then + * offset = sign_ext (offset) + * PC = PC + 4 + offset + */ + ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); + if (!success) + return false; + + ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + ft, 0, &success); + if (!success) + return false; + + if ((ft_val & 1) == 0) + target = pc + 4 + offset; + else + target = pc + 4; + + Context context; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS64::Emulate_BC1NEZ (llvm::MCInst& insn) +{ + bool success = false; + uint32_t ft; + uint64_t ft_val; + int64_t target, pc, offset; + + /* + * BC1NEZ ft, offset + * condition <- (FPR[ft].bit0 != 0) + * if condition then + * offset = sign_ext (offset) + * PC = PC + 4 + offset + */ + ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); + if (!success) + return false; + + ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + ft, 0, &success); + if (!success) + return false; + + if ((ft_val & 1) != 0) + target = pc + 4 + offset; + else + target = pc + 4; + + Context context; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS64::Emulate_BC1ANY2F (llvm::MCInst& insn) +{ + bool success = false; + uint32_t cc, fcsr; + int64_t target, pc, offset; + + /* + * BC1ANY2F cc, offset + * condition <- (FPConditionCode(cc) == 0 + * || FPConditionCode(cc+1) == 0) + * if condition then + * offset = sign_ext (offset) + * PC = PC + offset + */ + cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); + if (!success) + return false; + + fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success); + if (!success) + return false; + + /* fcsr[23], fcsr[25-31] are vaild condition bits */ + fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01); + + /* if any one bit is 0 */ + if (((fcsr >> cc) & 3) != 3) + target = pc + offset; + else + target = pc + 4; + + Context context; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS64::Emulate_BC1ANY2T (llvm::MCInst& insn) +{ + bool success = false; + uint32_t cc, fcsr; + int64_t target, pc, offset; + + /* + * BC1ANY2T cc, offset + * condition <- (FPConditionCode(cc) == 1 + * || FPConditionCode(cc+1) == 1) + * if condition then + * offset = sign_ext (offset) + * PC = PC + offset + */ + cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); + if (!success) + return false; + + fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success); + if (!success) + return false; + + /* fcsr[23], fcsr[25-31] are vaild condition bits */ + fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01); + + /* if any one bit is 1 */ + if (((fcsr >> cc) & 3) != 0) + target = pc + offset; + else + target = pc + 4; + + Context context; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS64::Emulate_BC1ANY4F (llvm::MCInst& insn) +{ + bool success = false; + uint32_t cc, fcsr; + int64_t target, pc, offset; + + /* + * BC1ANY4F cc, offset + * condition <- (FPConditionCode(cc) == 0 + * || FPConditionCode(cc+1) == 0) + * || FPConditionCode(cc+2) == 0) + * || FPConditionCode(cc+3) == 0) + * if condition then + * offset = sign_ext (offset) + * PC = PC + offset + */ + cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); + if (!success) + return false; + + fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success); + if (!success) + return false; + + /* fcsr[23], fcsr[25-31] are vaild condition bits */ + fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01); + + /* if any one bit is 0 */ + if (((fcsr >> cc) & 0xf) != 0xf) + target = pc + offset; + else + target = pc + 4; + + Context context; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS64::Emulate_BC1ANY4T (llvm::MCInst& insn) +{ + bool success = false; + uint32_t cc, fcsr; + int64_t target, pc, offset; + + /* + * BC1ANY4T cc, offset + * condition <- (FPConditionCode(cc) == 1 + * || FPConditionCode(cc+1) == 1) + * || FPConditionCode(cc+2) == 1) + * || FPConditionCode(cc+3) == 1) + * if condition then + * offset = sign_ext (offset) + * PC = PC + offset + */ + cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); + if (!success) + return false; + + fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success); + if (!success) + return false; + + /* fcsr[23], fcsr[25-31] are vaild condition bits */ + fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01); + + /* if any one bit is 1 */ + if (((fcsr >> cc) & 0xf) != 0) + target = pc + offset; + else + target = pc + 4; + + Context context; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) + return false; + + return true; +}