Index: include/lldb/Host/common/NativeRegisterContext.h =================================================================== --- include/lldb/Host/common/NativeRegisterContext.h +++ include/lldb/Host/common/NativeRegisterContext.h @@ -141,6 +141,9 @@ lldb::addr_t GetPC (lldb::addr_t fail_value = LLDB_INVALID_ADDRESS); + virtual lldb::addr_t + GetPCfromBreakpointLocation (lldb::addr_t fail_value = LLDB_INVALID_ADDRESS); + Error SetPC (lldb::addr_t pc); Index: source/Host/common/NativeRegisterContext.cpp =================================================================== --- source/Host/common/NativeRegisterContext.cpp +++ source/Host/common/NativeRegisterContext.cpp @@ -143,6 +143,12 @@ return retval; } +lldb::addr_t +NativeRegisterContext::GetPCfromBreakpointLocation (lldb::addr_t fail_value) +{ + return GetPC (fail_value); +} + Error NativeRegisterContext::SetPC (lldb::addr_t pc) { Index: source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h =================================================================== --- source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h +++ source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h @@ -131,6 +131,171 @@ Emulate_LW (llvm::MCInst& insn); bool + Emulate_BEQ (llvm::MCInst& insn); + + bool + Emulate_BNE (llvm::MCInst& insn); + + bool + Emulate_BEQL (llvm::MCInst& insn); + + bool + Emulate_BNEL (llvm::MCInst& insn); + + bool + Emulate_BGEZALL (llvm::MCInst& insn); + + bool + Emulate_BAL (llvm::MCInst& insn); + + bool + Emulate_BGEZAL (llvm::MCInst& insn); + + bool + Emulate_BALC (llvm::MCInst& insn); + + bool + Emulate_BC (llvm::MCInst& insn); + + bool + Emulate_BGEZ (llvm::MCInst& insn); + + bool + Emulate_BLEZALC (llvm::MCInst& insn); + + bool + Emulate_BGEZALC (llvm::MCInst& insn); + + bool + Emulate_BLTZALC (llvm::MCInst& insn); + + bool + Emulate_BGTZALC (llvm::MCInst& insn); + + bool + Emulate_BEQZALC (llvm::MCInst& insn); + + bool + Emulate_BNEZALC (llvm::MCInst& insn); + + bool + Emulate_BEQC (llvm::MCInst& insn); + + bool + Emulate_BNEC (llvm::MCInst& insn); + + bool + Emulate_BLTC (llvm::MCInst& insn); + + bool + Emulate_BGEC (llvm::MCInst& insn); + + bool + Emulate_BLTUC (llvm::MCInst& insn); + + bool + Emulate_BGEUC (llvm::MCInst& insn); + + bool + Emulate_BLTZC (llvm::MCInst& insn); + + bool + Emulate_BLEZC (llvm::MCInst& insn); + + bool + Emulate_BGEZC (llvm::MCInst& insn); + + bool + Emulate_BGTZC (llvm::MCInst& insn); + + bool + Emulate_BEQZC (llvm::MCInst& insn); + + bool + Emulate_BNEZC (llvm::MCInst& insn); + + bool + Emulate_BGEZL (llvm::MCInst& insn); + + bool + Emulate_BGTZ (llvm::MCInst& insn); + + bool + Emulate_BGTZL (llvm::MCInst& insn); + + bool + Emulate_BLEZ (llvm::MCInst& insn); + + bool + Emulate_BLEZL (llvm::MCInst& insn); + + bool + Emulate_BLTZ (llvm::MCInst& insn); + + bool + Emulate_BLTZAL (llvm::MCInst& insn); + + bool + Emulate_BLTZALL (llvm::MCInst& insn); + + bool + Emulate_BLTZL (llvm::MCInst& insn); + + bool + Emulate_BOVC (llvm::MCInst& insn); + + bool + Emulate_BNVC (llvm::MCInst& insn); + + bool + Emulate_J (llvm::MCInst& insn); + + bool + Emulate_JAL (llvm::MCInst& insn); + + bool + Emulate_JALR (llvm::MCInst& insn); + + bool + Emulate_JIALC (llvm::MCInst& insn); + + bool + Emulate_JIC (llvm::MCInst& insn); + + bool + 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 (uint32_t regnum); const char * Index: source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp =================================================================== --- source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp +++ source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp @@ -208,9 +208,41 @@ { switch (reg_num) { - case gcc_dwarf_sp_mips64: return "r29"; - case gcc_dwarf_r30_mips64: return "r30"; - case gcc_dwarf_ra_mips64: return "r31"; + case gcc_dwarf_sp_mips: return "r29"; + case gcc_dwarf_r30_mips: return "r30"; + case gcc_dwarf_ra_mips: return "r31"; + case gcc_dwarf_f0_mips: return "f0"; + case gcc_dwarf_f1_mips: return "f1"; + case gcc_dwarf_f2_mips: return "f2"; + case gcc_dwarf_f3_mips: return "f3"; + case gcc_dwarf_f4_mips: return "f4"; + case gcc_dwarf_f5_mips: return "f5"; + case gcc_dwarf_f6_mips: return "f6"; + case gcc_dwarf_f7_mips: return "f7"; + case gcc_dwarf_f8_mips: return "f8"; + case gcc_dwarf_f9_mips: return "f9"; + case gcc_dwarf_f10_mips: return "f10"; + case gcc_dwarf_f11_mips: return "f11"; + case gcc_dwarf_f12_mips: return "f12"; + case gcc_dwarf_f13_mips: return "f13"; + case gcc_dwarf_f14_mips: return "f14"; + case gcc_dwarf_f15_mips: return "f15"; + case gcc_dwarf_f16_mips: return "f16"; + case gcc_dwarf_f17_mips: return "f17"; + case gcc_dwarf_f18_mips: return "f18"; + case gcc_dwarf_f19_mips: return "f19"; + case gcc_dwarf_f20_mips: return "f20"; + case gcc_dwarf_f21_mips: return "f21"; + case gcc_dwarf_f22_mips: return "f22"; + case gcc_dwarf_f23_mips: return "f23"; + case gcc_dwarf_f24_mips: return "f24"; + case gcc_dwarf_f25_mips: return "f25"; + case gcc_dwarf_f26_mips: return "f26"; + case gcc_dwarf_f27_mips: return "f27"; + case gcc_dwarf_f28_mips: return "f28"; + case gcc_dwarf_f29_mips: return "f29"; + case gcc_dwarf_f30_mips: return "f30"; + case gcc_dwarf_f31_mips: return "f31"; default: break; } @@ -219,45 +251,78 @@ switch (reg_num) { - case gcc_dwarf_zero_mips64: return "r0"; - case gcc_dwarf_r1_mips64: return "r1"; - case gcc_dwarf_r2_mips64: return "r2"; - case gcc_dwarf_r3_mips64: return "r3"; - case gcc_dwarf_r4_mips64: return "r4"; - case gcc_dwarf_r5_mips64: return "r5"; - case gcc_dwarf_r6_mips64: return "r6"; - case gcc_dwarf_r7_mips64: return "r7"; - case gcc_dwarf_r8_mips64: return "r8"; - case gcc_dwarf_r9_mips64: return "r9"; - case gcc_dwarf_r10_mips64: return "r10"; - case gcc_dwarf_r11_mips64: return "r11"; - case gcc_dwarf_r12_mips64: return "r12"; - case gcc_dwarf_r13_mips64: return "r13"; - case gcc_dwarf_r14_mips64: return "r14"; - case gcc_dwarf_r15_mips64: return "r15"; - case gcc_dwarf_r16_mips64: return "r16"; - case gcc_dwarf_r17_mips64: return "r17"; - case gcc_dwarf_r18_mips64: return "r18"; - case gcc_dwarf_r19_mips64: return "r19"; - case gcc_dwarf_r20_mips64: return "r20"; - case gcc_dwarf_r21_mips64: return "r21"; - case gcc_dwarf_r22_mips64: return "r22"; - case gcc_dwarf_r23_mips64: return "r23"; - case gcc_dwarf_r24_mips64: return "r24"; - case gcc_dwarf_r25_mips64: return "r25"; - case gcc_dwarf_r26_mips64: return "r26"; - case gcc_dwarf_r27_mips64: return "r27"; - case gcc_dwarf_gp_mips64: return "gp"; - case gcc_dwarf_sp_mips64: return "sp"; - case gcc_dwarf_r30_mips64: return "fp"; - case gcc_dwarf_ra_mips64: return "ra"; - case gcc_dwarf_sr_mips64: return "sr"; - case gcc_dwarf_lo_mips64: return "lo"; - case gcc_dwarf_hi_mips64: return "hi"; - case gcc_dwarf_bad_mips64: return "bad"; - case gcc_dwarf_cause_mips64: return "cause"; - case gcc_dwarf_pc_mips64: return "pc"; - + case gcc_dwarf_zero_mips: return "r0"; + case gcc_dwarf_r1_mips: return "r1"; + case gcc_dwarf_r2_mips: return "r2"; + case gcc_dwarf_r3_mips: return "r3"; + case gcc_dwarf_r4_mips: return "r4"; + case gcc_dwarf_r5_mips: return "r5"; + case gcc_dwarf_r6_mips: return "r6"; + case gcc_dwarf_r7_mips: return "r7"; + case gcc_dwarf_r8_mips: return "r8"; + case gcc_dwarf_r9_mips: return "r9"; + case gcc_dwarf_r10_mips: return "r10"; + case gcc_dwarf_r11_mips: return "r11"; + case gcc_dwarf_r12_mips: return "r12"; + case gcc_dwarf_r13_mips: return "r13"; + case gcc_dwarf_r14_mips: return "r14"; + case gcc_dwarf_r15_mips: return "r15"; + case gcc_dwarf_r16_mips: return "r16"; + case gcc_dwarf_r17_mips: return "r17"; + case gcc_dwarf_r18_mips: return "r18"; + case gcc_dwarf_r19_mips: return "r19"; + case gcc_dwarf_r20_mips: return "r20"; + case gcc_dwarf_r21_mips: return "r21"; + case gcc_dwarf_r22_mips: return "r22"; + case gcc_dwarf_r23_mips: return "r23"; + case gcc_dwarf_r24_mips: return "r24"; + case gcc_dwarf_r25_mips: return "r25"; + case gcc_dwarf_r26_mips: return "r26"; + case gcc_dwarf_r27_mips: return "r27"; + case gcc_dwarf_gp_mips: return "gp"; + case gcc_dwarf_sp_mips: return "sp"; + case gcc_dwarf_r30_mips: return "fp"; + case gcc_dwarf_ra_mips: return "ra"; + case gcc_dwarf_sr_mips: return "sr"; + case gcc_dwarf_lo_mips: return "lo"; + case gcc_dwarf_hi_mips: return "hi"; + case gcc_dwarf_bad_mips: return "bad"; + case gcc_dwarf_cause_mips: return "cause"; + case gcc_dwarf_pc_mips: return "pc"; + case gcc_dwarf_f0_mips: return "fp_reg[0]"; + case gcc_dwarf_f1_mips: return "fp_reg[1]"; + case gcc_dwarf_f2_mips: return "fp_reg[2]"; + case gcc_dwarf_f3_mips: return "fp_reg[3]"; + case gcc_dwarf_f4_mips: return "fp_reg[4]"; + case gcc_dwarf_f5_mips: return "fp_reg[5]"; + case gcc_dwarf_f6_mips: return "fp_reg[6]"; + case gcc_dwarf_f7_mips: return "fp_reg[7]"; + case gcc_dwarf_f8_mips: return "fp_reg[8]"; + case gcc_dwarf_f9_mips: return "fp_reg[9]"; + case gcc_dwarf_f10_mips: return "fp_reg[10]"; + case gcc_dwarf_f11_mips: return "fp_reg[11]"; + case gcc_dwarf_f12_mips: return "fp_reg[12]"; + case gcc_dwarf_f13_mips: return "fp_reg[13]"; + case gcc_dwarf_f14_mips: return "fp_reg[14]"; + case gcc_dwarf_f15_mips: return "fp_reg[15]"; + case gcc_dwarf_f16_mips: return "fp_reg[16]"; + case gcc_dwarf_f17_mips: return "fp_reg[17]"; + case gcc_dwarf_f18_mips: return "fp_reg[18]"; + case gcc_dwarf_f19_mips: return "fp_reg[19]"; + case gcc_dwarf_f20_mips: return "fp_reg[20]"; + case gcc_dwarf_f21_mips: return "fp_reg[21]"; + case gcc_dwarf_f22_mips: return "fp_reg[22]"; + case gcc_dwarf_f23_mips: return "fp_reg[23]"; + case gcc_dwarf_f24_mips: return "fp_reg[24]"; + case gcc_dwarf_f25_mips: return "fp_reg[25]"; + case gcc_dwarf_f26_mips: return "fp_reg[26]"; + case gcc_dwarf_f27_mips: return "fp_reg[27]"; + case gcc_dwarf_f28_mips: return "fp_reg[28]"; + case gcc_dwarf_f29_mips: return "fp_reg[29]"; + case gcc_dwarf_f30_mips: return "fp_reg[30]"; + case gcc_dwarf_f31_mips: return "fp_reg[31]"; + case gcc_dwarf_fcsr_mips: return "fcsr"; + case gcc_dwarf_fir_mips: return "fir"; } return nullptr; } @@ -269,11 +334,11 @@ { switch (reg_num) { - case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_pc_mips64; break; - case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_sp_mips64; break; - case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_r30_mips64; break; - case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_ra_mips64; break; - case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_sr_mips64; break; + case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_pc_mips; break; + case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_sp_mips; break; + case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_r30_mips; break; + case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_ra_mips; break; + case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_sr_mips; break; default: return false; } @@ -284,27 +349,34 @@ ::memset (®_info, 0, sizeof(RegisterInfo)); ::memset (reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds)); - if ((int)reg_num >= gcc_dwarf_zero_mips64 && (int)reg_num <= gcc_dwarf_pc_mips64) + if (reg_num == gcc_dwarf_sr_mips || 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; - reg_info.name = GetRegisterName (reg_num, false); - reg_info.alt_name = GetRegisterName (reg_num, true); - reg_info.kinds[eRegisterKindDWARF] = reg_num; + } + else if ((int)reg_num >= gcc_dwarf_zero_mips && (int)reg_num <= gcc_dwarf_f31_mips) + { + reg_info.byte_size = 8; + reg_info.format = eFormatHex; + reg_info.encoding = eEncodingUint; } else { return false; } + reg_info.name = GetRegisterName (reg_num, false); + reg_info.alt_name = GetRegisterName (reg_num, true); + reg_info.kinds[eRegisterKindDWARF] = reg_num; + switch (reg_num) { - case gcc_dwarf_r30_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; break; - case gcc_dwarf_ra_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; break; - case gcc_dwarf_sp_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; break; - case gcc_dwarf_pc_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; break; - case gcc_dwarf_sr_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; break; + case gcc_dwarf_r30_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; break; + case gcc_dwarf_ra_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; break; + case gcc_dwarf_sp_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; break; + case gcc_dwarf_pc_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; break; + case gcc_dwarf_sr_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; break; default: break; } return true; @@ -324,6 +396,68 @@ { "ADDiu", &EmulateInstructionMIPS::Emulate_ADDiu, "ADDIU rt,rs,immediate" }, { "SW", &EmulateInstructionMIPS::Emulate_SW, "SW rt,offset(rs)" }, { "LW", &EmulateInstructionMIPS::Emulate_LW, "LW rt,offset(base)" }, + + //---------------------------------------------------------------------- + // Branch instructions + //---------------------------------------------------------------------- + { "BEQ", &EmulateInstructionMIPS::Emulate_BEQ, "BEQ rs,rt,offset" }, + { "BNE", &EmulateInstructionMIPS::Emulate_BNE, "BNE rs,rt,offset" }, + { "BEQL", &EmulateInstructionMIPS::Emulate_BEQL, "BEQL rs,rt,offset" }, + { "BNEL", &EmulateInstructionMIPS::Emulate_BNEL, "BNEL rs,rt,offset" }, + { "BGEZALL", &EmulateInstructionMIPS::Emulate_BGEZALL, "BGEZALL rt,offset" }, + { "BAL", &EmulateInstructionMIPS::Emulate_BAL, "BAL offset" }, + { "BGEZAL", &EmulateInstructionMIPS::Emulate_BGEZAL, "BGEZAL rs,offset" }, + { "BALC", &EmulateInstructionMIPS::Emulate_BALC, "BALC offset" }, + { "BC", &EmulateInstructionMIPS::Emulate_BC, "BC offset" }, + { "BGEZ", &EmulateInstructionMIPS::Emulate_BGEZ, "BGEZ rs,offset" }, + { "BLEZALC", &EmulateInstructionMIPS::Emulate_BLEZALC, "BLEZALC rs,offset" }, + { "BGEZALC", &EmulateInstructionMIPS::Emulate_BGEZALC, "BGEZALC rs,offset" }, + { "BLTZALC", &EmulateInstructionMIPS::Emulate_BLTZALC, "BLTZALC rs,offset" }, + { "BGTZALC", &EmulateInstructionMIPS::Emulate_BGTZALC, "BGTZALC rs,offset" }, + { "BEQZALC", &EmulateInstructionMIPS::Emulate_BEQZALC, "BEQZALC rs,offset" }, + { "BNEZALC", &EmulateInstructionMIPS::Emulate_BNEZALC, "BNEZALC rs,offset" }, + { "BEQC", &EmulateInstructionMIPS::Emulate_BEQC, "BEQC rs,rt,offset" }, + { "BNEC", &EmulateInstructionMIPS::Emulate_BNEC, "BNEC rs,rt,offset" }, + { "BLTC", &EmulateInstructionMIPS::Emulate_BLTC, "BLTC rs,rt,offset" }, + { "BGEC", &EmulateInstructionMIPS::Emulate_BGEC, "BGEC rs,rt,offset" }, + { "BLTUC", &EmulateInstructionMIPS::Emulate_BLTUC, "BLTUC rs,rt,offset" }, + { "BGEUC", &EmulateInstructionMIPS::Emulate_BGEUC, "BGEUC rs,rt,offset" }, + { "BLTZC", &EmulateInstructionMIPS::Emulate_BLTZC, "BLTZC rt,offset" }, + { "BLEZC", &EmulateInstructionMIPS::Emulate_BLEZC, "BLEZC rt,offset" }, + { "BGEZC", &EmulateInstructionMIPS::Emulate_BGEZC, "BGEZC rt,offset" }, + { "BGTZC", &EmulateInstructionMIPS::Emulate_BGTZC, "BGTZC rt,offset" }, + { "BEQZC", &EmulateInstructionMIPS::Emulate_BEQZC, "BEQZC rt,offset" }, + { "BNEZC", &EmulateInstructionMIPS::Emulate_BNEZC, "BNEZC rt,offset" }, + { "BGEZL", &EmulateInstructionMIPS::Emulate_BGEZL, "BGEZL rt,offset" }, + { "BGTZ", &EmulateInstructionMIPS::Emulate_BGTZ, "BGTZ rt,offset" }, + { "BGTZL", &EmulateInstructionMIPS::Emulate_BGTZL, "BGTZL rt,offset" }, + { "BLEZ", &EmulateInstructionMIPS::Emulate_BLEZ, "BLEZ rt,offset" }, + { "BLEZL", &EmulateInstructionMIPS::Emulate_BLEZL, "BLEZL rt,offset" }, + { "BLTZ", &EmulateInstructionMIPS::Emulate_BLTZ, "BLTZ rt,offset" }, + { "BLTZAL", &EmulateInstructionMIPS::Emulate_BLTZAL, "BLTZAL rt,offset" }, + { "BLTZALL", &EmulateInstructionMIPS::Emulate_BLTZALL, "BLTZALL rt,offset" }, + { "BLTZL", &EmulateInstructionMIPS::Emulate_BLTZL, "BLTZL rt,offset" }, + { "BOVC", &EmulateInstructionMIPS::Emulate_BOVC, "BOVC rs,rt,offset" }, + { "BNVC", &EmulateInstructionMIPS::Emulate_BNVC, "BNVC rs,rt,offset" }, + { "J", &EmulateInstructionMIPS::Emulate_J, "J target" }, + { "JAL", &EmulateInstructionMIPS::Emulate_JAL, "JAL target" }, + { "JALX", &EmulateInstructionMIPS::Emulate_JAL, "JALX target" }, + { "JALR", &EmulateInstructionMIPS::Emulate_JALR, "JALR target" }, + { "JALR_HB", &EmulateInstructionMIPS::Emulate_JALR, "JALR.HB target" }, + { "JIALC", &EmulateInstructionMIPS::Emulate_JIALC, "JIALC rt,offset" }, + { "JIC", &EmulateInstructionMIPS::Emulate_JIC, "JIC rt,offset" }, + { "JR", &EmulateInstructionMIPS::Emulate_JR, "JR target" }, + { "JR_HB", &EmulateInstructionMIPS::Emulate_JR, "JR.HB target" }, + { "BC1F", &EmulateInstructionMIPS::Emulate_BC1F, "BC1F cc, offset" }, + { "BC1T", &EmulateInstructionMIPS::Emulate_BC1T, "BC1T cc, offset" }, + { "BC1FL", &EmulateInstructionMIPS::Emulate_BC1FL, "BC1FL cc, offset" }, + { "BC1TL", &EmulateInstructionMIPS::Emulate_BC1TL, "BC1TL cc, offset" }, + { "BC1EQZ", &EmulateInstructionMIPS::Emulate_BC1EQZ, "BC1EQZ ft, offset" }, + { "BC1NEZ", &EmulateInstructionMIPS::Emulate_BC1NEZ, "BC1NEZ ft, offset" }, + { "BC1ANY2F", &EmulateInstructionMIPS::Emulate_BC1ANY2F, "BC1ANY2F cc, offset" }, + { "BC1ANY2T", &EmulateInstructionMIPS::Emulate_BC1ANY2T, "BC1ANY2T cc, offset" }, + { "BC1ANY4F", &EmulateInstructionMIPS::Emulate_BC1ANY4F, "BC1ANY4F cc, offset" }, + { "BC1ANY4T", &EmulateInstructionMIPS::Emulate_BC1ANY4T, "BC1ANY4T cc, offset" }, }; static const size_t k_num_mips_opcodes = llvm::array_lengthof(g_opcodes); @@ -395,7 +529,7 @@ if (auto_advance_pc) { - old_pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); + old_pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); if (!success) return false; } @@ -407,7 +541,7 @@ if (auto_advance_pc) { - new_pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); + new_pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); if (!success) return false; @@ -416,7 +550,7 @@ { new_pc += 4; Context context; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, new_pc)) + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, new_pc)) return false; } } @@ -434,10 +568,10 @@ const bool can_replace = false; // Our previous Call Frame Address is the stack pointer - row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_sp_mips64, 0); + row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_sp_mips, 0); // Our previous PC is in the RA - row->SetRegisterLocationToRegister(gcc_dwarf_pc_mips64, gcc_dwarf_ra_mips64, can_replace); + row->SetRegisterLocationToRegister(gcc_dwarf_pc_mips, gcc_dwarf_ra_mips, can_replace); unwind_plan.AppendRow (row); @@ -454,18 +588,18 @@ { switch (regnum) { - case gcc_dwarf_r16_mips64: - case gcc_dwarf_r17_mips64: - case gcc_dwarf_r18_mips64: - case gcc_dwarf_r19_mips64: - case gcc_dwarf_r20_mips64: - case gcc_dwarf_r21_mips64: - case gcc_dwarf_r22_mips64: - case gcc_dwarf_r23_mips64: - case gcc_dwarf_gp_mips64: - case gcc_dwarf_sp_mips64: - case gcc_dwarf_r30_mips64: - case gcc_dwarf_ra_mips64: + case gcc_dwarf_r16_mips: + case gcc_dwarf_r17_mips: + case gcc_dwarf_r18_mips: + case gcc_dwarf_r19_mips: + case gcc_dwarf_r20_mips: + case gcc_dwarf_r21_mips: + case gcc_dwarf_r22_mips: + case gcc_dwarf_r23_mips: + case gcc_dwarf_gp_mips: + case gcc_dwarf_sp_mips: + case gcc_dwarf_r30_mips: + case gcc_dwarf_ra_mips: return true; default: return false; @@ -486,10 +620,10 @@ src = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); /* Check if this is addiu sp,,imm16 */ - if (dst == gcc_dwarf_sp_mips64) + if (dst == gcc_dwarf_sp_mips) { /* read register */ - uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, 0, &success); + uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + src, 0, &success); if (!success) return false; @@ -497,13 +631,13 @@ Context context; RegisterInfo reg_info_sp; - if (GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_sp_mips64, reg_info_sp)) + if (GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_sp_mips, reg_info_sp)) context.SetRegisterPlusOffset (reg_info_sp, imm); /* We are allocating bytes on stack */ context.type = eContextAdjustStackPointer; - WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_sp_mips64, result); + WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_sp_mips, result); } return true; @@ -521,18 +655,18 @@ base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); /* We look for sp based non-volatile register stores */ - if (base == gcc_dwarf_sp_mips64 && nonvolatile_reg_p (src)) + if (base == gcc_dwarf_sp_mips && nonvolatile_reg_p (src)) { uint32_t address; RegisterInfo reg_info_base; RegisterInfo reg_info_src; - if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, reg_info_base) - || !GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, reg_info_src)) + if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips + base, reg_info_base) + || !GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips + src, reg_info_src)) return false; /* read SP */ - address = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, 0, &success); + address = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + base, 0, &success); if (!success) return false; @@ -570,12 +704,12 @@ src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); - if (base == gcc_dwarf_sp_mips64 && nonvolatile_reg_p (src)) + if (base == gcc_dwarf_sp_mips && nonvolatile_reg_p (src)) { RegisterValue data_src; RegisterInfo reg_info_src; - if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, reg_info_src)) + if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips + src, reg_info_src)) return false; Context context; @@ -589,3 +723,2196 @@ return false; } + +bool +EmulateInstructionMIPS::Emulate_BEQ (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs, rt; + int32_t offset, pc, target, rs_val, rt_val; + + /* + * BEQ rs, rt, offset + * condition <- (GPR[rs] = GPR[rt]) + * if condition then + * PC = PC + sign_ext (offset << 2) + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); + offset = insn.getOperand(2).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success); + if (!success) + return false; + + if (rs_val == rt_val) + target = pc + offset; + else + target = pc + 8; + + Context context; + context.type = eContextRelativeBranchImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BNE (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs, rt; + int32_t offset, pc, target, rs_val, rt_val; + + /* + * BNE rs, rt, offset + * condition <- (GPR[rs] != GPR[rt]) + * if condition then + * PC = PC + sign_ext (offset << 2) + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); + offset = insn.getOperand(2).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success); + if (!success) + return false; + + if (rs_val != rt_val) + target = pc + offset; + else + target = pc + 8; + + Context context; + context.type = eContextRelativeBranchImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BEQL (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs, rt; + int32_t offset, pc, target, rs_val, rt_val; + + /* + * BEQL rs, rt, offset + * condition <- (GPR[rs] = GPR[rt]) + * if condition then + * PC = PC + sign_ext (offset << 2) + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); + offset = insn.getOperand(2).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success); + if (!success) + return false; + + if (rs_val == rt_val) + target = pc + offset; + else + target = pc + 8; /* skip delay slot */ + + Context context; + context.type = eContextRelativeBranchImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BNEL (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs, rt; + int32_t offset, pc, target, rs_val, rt_val; + + /* + * BNEL rs, rt, offset + * condition <- (GPR[rs] != GPR[rt]) + * if condition then + * PC = PC + sign_ext (offset << 2) + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); + offset = insn.getOperand(2).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success); + if (!success) + return false; + + if (rs_val != rt_val) + target = pc + offset; + else + target = pc + 8; /* skip delay slot */ + + Context context; + context.type = eContextRelativeBranchImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BGEZL (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs; + int32_t offset, pc, target; + int32_t rs_val; + + /* + * BGEZL rs, offset + * condition <- (GPR[rs] >= 0) + * if condition then + * PC = PC + sign_ext (offset << 2) + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + if (rs_val >= 0) + target = pc + offset; + else + target = pc + 8; /* skip delay slot */ + + Context context; + context.type = eContextRelativeBranchImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BLTZL (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs; + int32_t offset, pc, target; + int32_t rs_val; + + /* + * BLTZL rs, offset + * condition <- (GPR[rs] < 0) + * if condition then + * PC = PC + sign_ext (offset << 2) + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + if (rs_val < 0) + target = pc + offset; + else + target = pc + 8; /* skip delay slot */ + + Context context; + context.type = eContextRelativeBranchImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BGTZL (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs; + int32_t offset, pc, target; + int32_t rs_val; + + /* + * BGTZL rs, offset + * condition <- (GPR[rs] > 0) + * if condition then + * PC = PC + sign_ext (offset << 2) + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + if (rs_val > 0) + target = pc + offset; + else + target = pc + 8; /* skip delay slot */ + + Context context; + context.type = eContextRelativeBranchImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BLEZL (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs; + int32_t offset, pc, target; + int32_t rs_val; + + /* + * BLEZL rs, offset + * condition <- (GPR[rs] <= 0) + * if condition then + * PC = PC + sign_ext (offset << 2) + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + if (rs_val <= 0) + target = pc + offset; + else + target = pc + 8; /* skip delay slot */ + + Context context; + context.type = eContextRelativeBranchImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BGTZ (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs; + int32_t offset, pc, target; + int32_t rs_val; + + /* + * BGTZ rs, offset + * condition <- (GPR[rs] > 0) + * if condition then + * PC = PC + sign_ext (offset << 2) + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + if (rs_val > 0) + target = pc + offset; + else + target = pc + 8; + + Context context; + context.type = eContextRelativeBranchImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BLEZ (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs; + int32_t offset, pc, target; + int32_t rs_val; + + /* + * BLEZ rs, offset + * condition <- (GPR[rs] <= 0) + * if condition then + * PC = PC + sign_ext (offset << 2) + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + if (rs_val <= 0) + target = pc + offset; + else + target = pc + 8; + + Context context; + context.type = eContextRelativeBranchImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BLTZ (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs; + int32_t offset, pc, target; + int32_t rs_val; + + /* + * BLTZ rs, offset + * condition <- (GPR[rs] < 0) + * if condition then + * PC = PC + sign_ext (offset << 2) + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + if (rs_val < 0) + target = pc + offset; + else + target = pc + 8; + + Context context; + context.type = eContextRelativeBranchImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BGEZALL (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs; + int32_t offset, pc, target; + int32_t rs_val; + + /* + * BGEZALL rt, offset + * condition <- (GPR[rs] >= 0) + * if condition then + * PC = PC + sign_ext (offset << 2) + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + if (rs_val >= 0) + target = pc + offset; + else + target = pc + 8; /* skip delay slot */ + + Context context; + context.type = eContextRelativeBranchImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BAL (llvm::MCInst& insn) +{ + bool success = false; + int32_t offset, pc, target; + + /* + * BAL offset + * offset = sign_ext (offset << 2) + * RA = PC + 8 + * PC = PC + offset + */ + offset = insn.getOperand(0).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + target = pc + offset; + + Context context; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BALC (llvm::MCInst& insn) +{ + bool success = false; + int32_t offset, pc, target; + + /* + * BALC offset + * offset = sign_ext (offset << 2) + * RA = PC + 4 + * PC = PC + 4 + offset + */ + offset = insn.getOperand(0).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + target = pc + 4 + offset; + + Context context; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BGEZAL (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs; + int32_t offset, pc, target; + int32_t rs_val; + + /* + * BGEZAL rs,offset + * offset = sign_ext (offset << 2) + * condition <- (GPR[rs] >= 0) + * if condition then + * RA = PC + 8 + * PC = PC + offset + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + Context context; + + if ((int32_t) rs_val >= 0) + target = pc + offset; + else + target = pc + 8; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BLTZAL (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs; + int32_t offset, pc, target; + int32_t rs_val; + + /* + * BLTZAL rs,offset + * offset = sign_ext (offset << 2) + * condition <- (GPR[rs] < 0) + * if condition then + * RA = PC + 8 + * PC = PC + offset + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + Context context; + + if ((int32_t) rs_val < 0) + target = pc + offset; + else + target = pc + 8; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BLTZALL (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs; + int32_t offset, pc, target; + int32_t rs_val; + + /* + * BLTZALL rs,offset + * offset = sign_ext (offset << 2) + * condition <- (GPR[rs] < 0) + * if condition then + * RA = PC + 8 + * PC = PC + offset + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + Context context; + + if (rs_val < 0) + target = pc + offset; + else + target = pc + 8; /* skip delay slot */ + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8)) + return false; + + return true; +} + + +bool +EmulateInstructionMIPS::Emulate_BLEZALC (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs; + int32_t offset, pc, target; + int32_t rs_val; + + /* + * BLEZALC rs,offset + * offset = sign_ext (offset << 2) + * condition <- (GPR[rs] <= 0) + * if condition then + * RA = PC + 4 + * PC = PC + offset + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + Context context; + + if (rs_val <= 0) + target = pc + offset; + else + target = pc + 4; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BGEZALC (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs; + int32_t offset, pc, target; + int32_t rs_val; + + /* + * BGEZALC rs,offset + * offset = sign_ext (offset << 2) + * condition <- (GPR[rs] >= 0) + * if condition then + * RA = PC + 4 + * PC = PC + offset + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + Context context; + + if (rs_val >= 0) + target = pc + offset; + else + target = pc + 4; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BLTZALC (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs; + int32_t offset, pc, target; + int32_t rs_val; + + /* + * BLTZALC rs,offset + * offset = sign_ext (offset << 2) + * condition <- (GPR[rs] < 0) + * if condition then + * RA = PC + 4 + * PC = PC + offset + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + Context context; + + if (rs_val < 0) + target = pc + offset; + else + target = pc + 4; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BGTZALC (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs; + int32_t offset, pc, target; + int32_t rs_val; + + /* + * BGTZALC rs,offset + * offset = sign_ext (offset << 2) + * condition <- (GPR[rs] > 0) + * if condition then + * RA = PC + 4 + * PC = PC + offset + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + Context context; + + if (rs_val > 0) + target = pc + offset; + else + target = pc + 4; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BEQZALC (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs; + int32_t offset, pc, target, rs_val; + + /* + * BEQZALC rs,offset + * offset = sign_ext (offset << 2) + * condition <- (GPR[rs] == 0) + * if condition then + * RA = PC + 4 + * PC = PC + offset + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + Context context; + + if (rs_val == 0) + target = pc + offset; + else + target = pc + 4; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BNEZALC (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs; + int32_t offset, pc, target, rs_val; + + /* + * BNEZALC rs,offset + * offset = sign_ext (offset << 2) + * condition <- (GPR[rs] != 0) + * if condition then + * RA = PC + 4 + * PC = PC + offset + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + Context context; + + if (rs_val != 0) + target = pc + offset; + else + target = pc + 4; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BGEZ (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs; + int32_t offset, pc, target, rs_val; + + /* + * BGEZ rs,offset + * offset = sign_ext (offset << 2) + * condition <- (GPR[rs] >= 0) + * if condition then + * PC = PC + offset + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + Context context; + + if (rs_val >= 0) + target = pc + offset; + else + target = pc + 8; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BC (llvm::MCInst& insn) +{ + bool success = false; + int32_t offset, pc, target; + + /* + * BC offset + * offset = sign_ext (offset << 2) + * PC = PC + 4 + offset + */ + offset = insn.getOperand(0).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + target = pc + 4 + offset; + + Context context; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BEQC (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs, rt; + int32_t offset, pc, target, rs_val, rt_val; + + /* + * BEQC rs, rt, offset + * condition <- (GPR[rs] = GPR[rt]) + * if condition then + * PC = PC + sign_ext (offset << 2) + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); + offset = insn.getOperand(2).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success); + if (!success) + return false; + + if (rs_val == rt_val) + target = pc + 4 + offset; + else + target = pc + 4; + + Context context; + context.type = eContextRelativeBranchImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BNEC (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs, rt; + int32_t offset, pc, target, rs_val, rt_val; + + /* + * BNEC rs, rt, offset + * condition <- (GPR[rs] != GPR[rt]) + * if condition then + * PC = PC + sign_ext (offset << 2) + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); + offset = insn.getOperand(2).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success); + if (!success) + return false; + + if (rs_val != rt_val) + target = pc + 4 + offset; + else + target = pc + 4; + + Context context; + context.type = eContextRelativeBranchImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BLTC (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs, rt; + int32_t offset, pc, target; + int32_t rs_val, rt_val; + + /* + * BLTC rs, rt, offset + * condition <- (GPR[rs] < GPR[rt]) + * if condition then + * PC = PC + sign_ext (offset << 2) + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); + offset = insn.getOperand(2).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success); + if (!success) + return false; + + if (rs_val < rt_val) + target = pc + 4 + offset; + else + target = pc + 4; + + Context context; + context.type = eContextRelativeBranchImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BGEC (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs, rt; + int32_t offset, pc, target; + int32_t rs_val, rt_val; + + /* + * BGEC rs, rt, offset + * condition <- (GPR[rs] > GPR[rt]) + * if condition then + * PC = PC + sign_ext (offset << 2) + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); + offset = insn.getOperand(2).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success); + if (!success) + return false; + + if (rs_val > rt_val) + target = pc + 4 + offset; + else + target = pc + 4; + + Context context; + context.type = eContextRelativeBranchImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BLTUC (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs, rt; + int32_t offset, pc, target; + uint32_t rs_val, rt_val; + + /* + * BLTUC rs, rt, offset + * condition <- (GPR[rs] < GPR[rt]) + * if condition then + * PC = PC + sign_ext (offset << 2) + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); + offset = insn.getOperand(2).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success); + if (!success) + return false; + + if (rs_val < rt_val) + target = pc + 4 + offset; + else + target = pc + 4; + + Context context; + context.type = eContextRelativeBranchImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BGEUC (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs, rt; + int32_t offset, pc, target; + uint32_t rs_val, rt_val; + + /* + * BGEUC rs, rt, offset + * condition <- (GPR[rs] > GPR[rt]) + * if condition then + * PC = PC + sign_ext (offset << 2) + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); + offset = insn.getOperand(2).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success); + if (!success) + return false; + + if (rs_val > rt_val) + target = pc + 4 + offset; + else + target = pc + 4; + + Context context; + context.type = eContextRelativeBranchImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BLTZC (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs; + int32_t offset, pc, target; + int32_t rs_val; + + /* + * BLTZC rs, offset + * condition <- (GPR[rs] < 0) + * if condition then + * PC = PC + sign_ext (offset << 2) + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + if (rs_val < 0) + target = pc + 4 + offset; + else + target = pc + 4; + + Context context; + context.type = eContextRelativeBranchImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BLEZC (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs; + int32_t offset, pc, target; + int32_t rs_val; + + /* + * BLEZC rs, offset + * condition <- (GPR[rs] <= 0) + * if condition then + * PC = PC + sign_ext (offset << 2) + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + if (rs_val <= 0) + target = pc + 4 + offset; + else + target = pc + 4; + + Context context; + context.type = eContextRelativeBranchImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BGEZC (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs; + int32_t offset, pc, target; + int32_t rs_val; + + /* + * BGEZC rs, offset + * condition <- (GPR[rs] >= 0) + * if condition then + * PC = PC + sign_ext (offset << 2) + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + if (rs_val >= 0) + target = pc + 4 + offset; + else + target = pc + 4; + + Context context; + context.type = eContextRelativeBranchImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BGTZC (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs; + int32_t offset, pc, target; + int32_t rs_val; + + /* + * BGTZC rs, offset + * condition <- (GPR[rs] > 0) + * if condition then + * PC = PC + sign_ext (offset << 2) + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + if (rs_val > 0) + target = pc + 4 + offset; + else + target = pc + 4; + + Context context; + context.type = eContextRelativeBranchImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BEQZC (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs; + int32_t offset, pc, target; + uint32_t rs_val; + + /* + * BEQZC rs, offset + * condition <- (GPR[rs] = 0) + * if condition then + * PC = PC + sign_ext (offset << 2) + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + if (rs_val == 0) + target = pc + 4 + offset; + else + target = pc + 4; + + Context context; + context.type = eContextRelativeBranchImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BNEZC (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs; + int32_t offset, pc, target; + uint32_t rs_val; + + /* + * BNEZC rs, offset + * condition <- (GPR[rs] != 0) + * if condition then + * PC = PC + sign_ext (offset << 2) + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + if (rs_val != 0) + target = pc + 4 + offset; + else + target = pc + 4; + + Context context; + context.type = eContextRelativeBranchImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +static int +IsAdd64bitOverflow (int32_t a, int32_t b) +{ + int32_t r = (uint32_t) a + (uint32_t) b; + return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0); +} + +bool +EmulateInstructionMIPS::Emulate_BOVC (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs, rt; + int32_t offset, pc, target; + int32_t rs_val, rt_val; + + /* + * BOVC rs, rt, offset + * condition <- overflow(GPR[rs] + GPR[rt]) + * if condition then + * PC = PC + sign_ext (offset << 2) + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); + offset = insn.getOperand(2).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success); + if (!success) + return false; + + if (IsAdd64bitOverflow (rs_val, rt_val)) + target = pc + offset; + else + target = pc + 4; + + Context context; + context.type = eContextRelativeBranchImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BNVC (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs, rt; + int32_t offset, pc, target; + int32_t rs_val, rt_val; + + /* + * BNVC rs, rt, offset + * condition <- overflow(GPR[rs] + GPR[rt]) + * if condition then + * PC = PC + sign_ext (offset << 2) + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); + offset = insn.getOperand(2).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success); + if (!success) + return false; + + if (! IsAdd64bitOverflow (rs_val, rt_val)) + target = pc + offset; + else + target = pc + 4; + + Context context; + context.type = eContextRelativeBranchImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_J (llvm::MCInst& insn) +{ + bool success = false; + uint32_t offset, pc; + + /* + * J offset + * offset = sign_ext (offset << 2) + * PC = PC[63-28] | offset + */ + offset = insn.getOperand(0).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + /* This is a PC-region branch and not PC-relative */ + pc = (pc & 0xF0000000UL) | offset; + + Context context; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, pc)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_JAL (llvm::MCInst& insn) +{ + bool success = false; + uint32_t offset, target, pc; + + /* + * JAL offset + * offset = sign_ext (offset << 2) + * PC = PC[63-28] | offset + */ + offset = insn.getOperand(0).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + /* This is a PC-region branch and not PC-relative */ + target = (pc & 0xF0000000UL) | offset; + + Context context; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_JALR (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs, rt; + uint32_t pc, rs_val; + + /* + * JALR rt, rs + * GPR[rt] = PC + 8 + * PC = GPR[rs] + */ + rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + rs = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + Context context; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, rs_val)) + return false; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, pc + 8)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_JIALC (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rt; + int32_t target, offset, pc, rt_val; + + /* + * JIALC rt, offset + * offset = sign_ext (offset) + * PC = GPR[rt] + offset + * RA = PC + 4 + */ + rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); + if (!success) + return false; + + rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success); + if (!success) + return false; + + target = rt_val + offset; + + Context context; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_JIC (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rt; + int32_t target, offset, rt_val; + + /* + * JIC rt, offset + * offset = sign_ext (offset) + * PC = GPR[rt] + offset + */ + rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success); + if (!success) + return false; + + target = rt_val + offset; + + Context context; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_JR (llvm::MCInst& insn) +{ + bool success = false; + uint32_t rs; + uint32_t rs_val; + + /* + * JR rs + * PC = GPR[rs] + */ + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + + rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + Context context; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, rs_val)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BC1F (llvm::MCInst& insn) +{ + bool success = false; + uint32_t cc, fcsr; + int32_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_mips, 0, &success); + if (!success) + return false; + + fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 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; + + Context context; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BC1T (llvm::MCInst& insn) +{ + bool success = false; + uint32_t cc, fcsr; + int32_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_mips, 0, &success); + if (!success) + return false; + + fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 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; + + Context context; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BC1FL (llvm::MCInst& insn) +{ + bool success = false; + uint32_t cc, fcsr; + int32_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_mips, 0, &success); + if (!success) + return false; + + fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 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_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BC1TL (llvm::MCInst& insn) +{ + bool success = false; + uint32_t cc, fcsr; + int32_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_mips, 0, &success); + if (!success) + return false; + + fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 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_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BC1EQZ (llvm::MCInst& insn) +{ + bool success = false; + uint32_t ft; + uint32_t ft_val; + int32_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_mips, 0, &success); + if (!success) + return false; + + ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + ft, 0, &success); + if (!success) + return false; + + if ((ft_val & 1) == 0) + target = pc + 4 + offset; + else + target = pc + 8; + + Context context; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BC1NEZ (llvm::MCInst& insn) +{ + bool success = false; + uint32_t ft; + uint32_t ft_val; + int32_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_mips, 0, &success); + if (!success) + return false; + + ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + ft, 0, &success); + if (!success) + return false; + + if ((ft_val & 1) != 0) + target = pc + 4 + offset; + else + target = pc + 8; + + Context context; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BC1ANY2F (llvm::MCInst& insn) +{ + bool success = false; + uint32_t cc, fcsr; + int32_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_mips, 0, &success); + if (!success) + return false; + + fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 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 + 8; + + Context context; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BC1ANY2T (llvm::MCInst& insn) +{ + bool success = false; + uint32_t cc, fcsr; + int32_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_mips, 0, &success); + if (!success) + return false; + + fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 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 + 8; + + Context context; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BC1ANY4F (llvm::MCInst& insn) +{ + bool success = false; + uint32_t cc, fcsr; + int32_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_mips, 0, &success); + if (!success) + return false; + + fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 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 + 8; + + Context context; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_BC1ANY4T (llvm::MCInst& insn) +{ + bool success = false; + uint32_t cc, fcsr; + int32_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_mips, 0, &success); + if (!success) + return false; + + fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 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 + 8; + + Context context; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) + return false; + + return true; +} Index: source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp =================================================================== --- source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp +++ source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp @@ -756,7 +756,7 @@ if (rs_val == rt_val) target = pc + offset; else - target = pc + 4; + target = pc + 8; Context context; context.type = eContextRelativeBranchImmediate; @@ -799,7 +799,7 @@ if (rs_val != rt_val) target = pc + offset; else - target = pc + 4; + target = pc + 8; Context context; context.type = eContextRelativeBranchImmediate; @@ -911,7 +911,7 @@ * PC = PC + sign_ext (offset << 2) */ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(2).getImm(); + offset = insn.getOperand(1).getImm(); pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); if (!success) @@ -950,7 +950,7 @@ * PC = PC + sign_ext (offset << 2) */ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(2).getImm(); + offset = insn.getOperand(1).getImm(); pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); if (!success) @@ -989,7 +989,7 @@ * PC = PC + sign_ext (offset << 2) */ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(2).getImm(); + offset = insn.getOperand(1).getImm(); pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); if (!success) @@ -1028,7 +1028,7 @@ * PC = PC + sign_ext (offset << 2) */ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(2).getImm(); + offset = insn.getOperand(1).getImm(); pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); if (!success) @@ -1067,7 +1067,7 @@ * PC = PC + sign_ext (offset << 2) */ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(2).getImm(); + offset = insn.getOperand(1).getImm(); pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); if (!success) @@ -1080,7 +1080,7 @@ if (rs_val > 0) target = pc + offset; else - target = pc + 4; + target = pc + 8; Context context; context.type = eContextRelativeBranchImmediate; @@ -1106,7 +1106,7 @@ * PC = PC + sign_ext (offset << 2) */ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(2).getImm(); + offset = insn.getOperand(1).getImm(); pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); if (!success) @@ -1119,7 +1119,7 @@ if (rs_val <= 0) target = pc + offset; else - target = pc + 4; + target = pc + 8; Context context; context.type = eContextRelativeBranchImmediate; @@ -1145,7 +1145,7 @@ * PC = PC + sign_ext (offset << 2) */ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(2).getImm(); + offset = insn.getOperand(1).getImm(); pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); if (!success) @@ -1158,7 +1158,7 @@ if (rs_val < 0) target = pc + offset; else - target = pc + 4; + target = pc + 8; Context context; context.type = eContextRelativeBranchImmediate; @@ -1305,7 +1305,7 @@ if ((int64_t) rs_val >= 0) target = pc + offset; else - target = pc + 4; + target = pc + 8; if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) return false; @@ -1348,7 +1348,7 @@ if ((int64_t) rs_val < 0) target = pc + offset; else - target = pc + 4; + target = pc + 8; if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) return false; @@ -1689,7 +1689,7 @@ if (rs_val >= 0) target = pc + offset; else - target = pc + 4; + target = pc + 8; if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) return false; @@ -2530,7 +2530,7 @@ if ((fcsr & (1 << cc)) == 0) target = pc + offset; else - target = pc + 4; + target = pc + 8; Context context; @@ -2571,7 +2571,7 @@ if ((fcsr & (1 << cc)) != 0) target = pc + offset; else - target = pc + 4; + target = pc + 8; Context context; @@ -2692,7 +2692,7 @@ if ((ft_val & 1) == 0) target = pc + 4 + offset; else - target = pc + 4; + target = pc + 8; Context context; @@ -2731,7 +2731,7 @@ if ((ft_val & 1) != 0) target = pc + 4 + offset; else - target = pc + 4; + target = pc + 8; Context context; @@ -2774,7 +2774,7 @@ if (((fcsr >> cc) & 3) != 3) target = pc + offset; else - target = pc + 4; + target = pc + 8; Context context; @@ -2817,7 +2817,7 @@ if (((fcsr >> cc) & 3) != 0) target = pc + offset; else - target = pc + 4; + target = pc + 8; Context context; @@ -2862,7 +2862,7 @@ if (((fcsr >> cc) & 0xf) != 0xf) target = pc + offset; else - target = pc + 4; + target = pc + 8; Context context; @@ -2907,7 +2907,7 @@ if (((fcsr >> cc) & 0xf) != 0) target = pc + offset; else - target = pc + 4; + target = pc + 8; Context context; Index: source/Plugins/Process/Linux/NativeProcessLinux.cpp =================================================================== --- source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -2018,7 +2018,7 @@ { // If a watchpoint was hit, report it uint32_t wp_index; - Error error = thread_sp->GetRegisterContext()->GetWatchpointHitIndex(wp_index, NULL); + Error error = thread_sp->GetRegisterContext()->GetWatchpointHitIndex(wp_index, LLDB_INVALID_ADDRESS); if (error.Fail() && log) log->Printf("NativeProcessLinux::%s() " "received error while checking for watchpoint hits, " @@ -2442,7 +2442,9 @@ } } else if (m_arch.GetMachine() == llvm::Triple::mips64 - || m_arch.GetMachine() == llvm::Triple::mips64el) + || m_arch.GetMachine() == llvm::Triple::mips64el + || m_arch.GetMachine() == llvm::Triple::mips + || m_arch.GetMachine() == llvm::Triple::mipsel) error = SetSoftwareBreakpoint(next_pc, 4); else { @@ -2462,7 +2464,8 @@ NativeProcessLinux::SupportHardwareSingleStepping() const { if (m_arch.GetMachine() == llvm::Triple::arm - || m_arch.GetMachine() == llvm::Triple::mips64 || m_arch.GetMachine() == llvm::Triple::mips64el) + || m_arch.GetMachine() == llvm::Triple::mips64 || m_arch.GetMachine() == llvm::Triple::mips64el + || m_arch.GetMachine() == llvm::Triple::mips || m_arch.GetMachine() == llvm::Triple::mipsel) return false; return true; } @@ -3028,7 +3031,6 @@ // set per architecture. Need ARM, MIPS support here. static const uint8_t g_aarch64_opcode[] = { 0x00, 0x00, 0x20, 0xd4 }; static const uint8_t g_i386_opcode [] = { 0xCC }; - static const uint8_t g_mips64_opcode[] = { 0x00, 0x00, 0x00, 0x0d }; switch (m_arch.GetMachine ()) { @@ -3049,7 +3051,7 @@ case llvm::Triple::mips64el: case llvm::Triple::mips: case llvm::Triple::mipsel: - actual_opcode_size = static_cast (sizeof(g_mips64_opcode)); + actual_opcode_size = 0; return Error (); default: @@ -3553,7 +3555,7 @@ } // First try probing for a breakpoint at a software breakpoint location: PC - breakpoint size. - const lldb::addr_t initial_pc_addr = context_sp->GetPC (); + const lldb::addr_t initial_pc_addr = context_sp->GetPCfromBreakpointLocation (); lldb::addr_t breakpoint_addr = initial_pc_addr; if (breakpoint_size > 0) { Index: source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h =================================================================== --- source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h +++ source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h @@ -33,6 +33,9 @@ uint32_t GetRegisterSetCount () const override; + lldb::addr_t + GetPCfromBreakpointLocation (lldb::addr_t fail_value = LLDB_INVALID_ADDRESS) override; + const RegisterSet * GetRegisterSet (uint32_t set_index) const override; Index: source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp =================================================================== --- source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp +++ source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp @@ -485,6 +485,59 @@ return k_num_register_sets; } +// JAY: TODO: +lldb::addr_t +NativeRegisterContextLinux_mips64::GetPCfromBreakpointLocation (lldb::addr_t fail_value) +{ + Error error; + RegisterValue pc_value; + lldb::addr_t pc = fail_value; + Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); + + if (log) + log->Printf ("NativeRegisterContextLinux_mips64::%s Reading PC from breakpoint location", __FUNCTION__); + + // PC register is at index 34 of the register array + const RegisterInfo *const pc_info_p = GetRegisterInfoAtIndex (34); + + error = ReadRegister (pc_info_p, pc_value); + if (error.Success ()) + { + pc = pc_value.GetAsUInt64 (); + + // CAUSE register is at index 37 of the register array + const RegisterInfo *const cause_info_p = GetRegisterInfoAtIndex (37); + RegisterValue cause_value; + + ReadRegister (cause_info_p, cause_value); + + uint64_t cause = cause_value.GetAsUInt64 (); + + if (log) + log->Printf ("NativeRegisterContextLinux_mips64::%s PC 0x%" PRIx64 " Cause 0x%" PRIx64, __FUNCTION__, pc, cause); + + /* + * The breakpoint might be in a delay slot. In this case PC points + * to the delayed branch instruction rather then the instruction + * in the delay slot. If the CAUSE.BD flag is set then adjust the + * PC based on the size of the branch instruction. + */ + if ((cause & (1 << 31)) != 0) + { + lldb::addr_t branch_delay = 0; + branch_delay = 4; // FIXME - Adjust according to size of branch instruction at PC + pc = pc + branch_delay; + pc_value.SetUInt64 (pc); + WriteRegister (pc_info_p, pc_value); + + if (log) + log->Printf ("NativeRegisterContextLinux_mips64::%s New PC 0x%" PRIx64, __FUNCTION__, pc); + } + } + + return pc; +} + const RegisterSet * NativeRegisterContextLinux_mips64::GetRegisterSet (uint32_t set_index) const {