Index: source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h =================================================================== --- source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h +++ source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h @@ -302,6 +302,36 @@ Emulate_BC1ANY4T (llvm::MCInst& insn); bool + Emulate_BNZB (llvm::MCInst& insn); + + bool + Emulate_BNZH (llvm::MCInst& insn); + + bool + Emulate_BNZW (llvm::MCInst& insn); + + bool + Emulate_BNZD (llvm::MCInst& insn); + + bool + Emulate_BZB (llvm::MCInst& insn); + + bool + Emulate_BZH (llvm::MCInst& insn); + + bool + Emulate_BZW (llvm::MCInst& insn); + + bool + Emulate_BZD (llvm::MCInst& insn); + + bool + Emulate_BNZV (llvm::MCInst& insn); + + bool + Emulate_BZV (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 @@ -256,6 +256,38 @@ case gcc_dwarf_f29_mips64: return "f29"; case gcc_dwarf_f30_mips64: return "f30"; case gcc_dwarf_f31_mips64: return "f31"; + case gcc_dwarf_w0_mips64: return "w0"; + case gcc_dwarf_w1_mips64: return "w1"; + case gcc_dwarf_w2_mips64: return "w2"; + case gcc_dwarf_w3_mips64: return "w3"; + case gcc_dwarf_w4_mips64: return "w4"; + case gcc_dwarf_w5_mips64: return "w5"; + case gcc_dwarf_w6_mips64: return "w6"; + case gcc_dwarf_w7_mips64: return "w7"; + case gcc_dwarf_w8_mips64: return "w8"; + case gcc_dwarf_w9_mips64: return "w9"; + case gcc_dwarf_w10_mips64: return "w10"; + case gcc_dwarf_w11_mips64: return "w11"; + case gcc_dwarf_w12_mips64: return "w12"; + case gcc_dwarf_w13_mips64: return "w13"; + case gcc_dwarf_w14_mips64: return "w14"; + case gcc_dwarf_w15_mips64: return "w15"; + case gcc_dwarf_w16_mips64: return "w16"; + case gcc_dwarf_w17_mips64: return "w17"; + case gcc_dwarf_w18_mips64: return "w18"; + case gcc_dwarf_w19_mips64: return "w19"; + case gcc_dwarf_w20_mips64: return "w20"; + case gcc_dwarf_w21_mips64: return "w21"; + case gcc_dwarf_w22_mips64: return "w22"; + case gcc_dwarf_w23_mips64: return "w23"; + case gcc_dwarf_w24_mips64: return "w24"; + case gcc_dwarf_w25_mips64: return "w25"; + case gcc_dwarf_w26_mips64: return "w26"; + case gcc_dwarf_w27_mips64: return "w27"; + case gcc_dwarf_w28_mips64: return "w28"; + case gcc_dwarf_w29_mips64: return "w29"; + case gcc_dwarf_w30_mips64: return "w30"; + case gcc_dwarf_w31_mips64: return "w31"; default: break; } @@ -336,6 +368,41 @@ case gcc_dwarf_f31_mips64: return "f31"; case gcc_dwarf_fcsr_mips64: return "fcsr"; case gcc_dwarf_fir_mips64: return "fir"; + case gcc_dwarf_w0_mips64: return "w0"; + case gcc_dwarf_w1_mips64: return "w1"; + case gcc_dwarf_w2_mips64: return "w2"; + case gcc_dwarf_w3_mips64: return "w3"; + case gcc_dwarf_w4_mips64: return "w4"; + case gcc_dwarf_w5_mips64: return "w5"; + case gcc_dwarf_w6_mips64: return "w6"; + case gcc_dwarf_w7_mips64: return "w7"; + case gcc_dwarf_w8_mips64: return "w8"; + case gcc_dwarf_w9_mips64: return "w9"; + case gcc_dwarf_w10_mips64: return "w10"; + case gcc_dwarf_w11_mips64: return "w11"; + case gcc_dwarf_w12_mips64: return "w12"; + case gcc_dwarf_w13_mips64: return "w13"; + case gcc_dwarf_w14_mips64: return "w14"; + case gcc_dwarf_w15_mips64: return "w15"; + case gcc_dwarf_w16_mips64: return "w16"; + case gcc_dwarf_w17_mips64: return "w17"; + case gcc_dwarf_w18_mips64: return "w18"; + case gcc_dwarf_w19_mips64: return "w19"; + case gcc_dwarf_w20_mips64: return "w20"; + case gcc_dwarf_w21_mips64: return "w21"; + case gcc_dwarf_w22_mips64: return "w22"; + case gcc_dwarf_w23_mips64: return "w23"; + case gcc_dwarf_w24_mips64: return "w24"; + case gcc_dwarf_w25_mips64: return "w25"; + case gcc_dwarf_w26_mips64: return "w26"; + case gcc_dwarf_w27_mips64: return "w27"; + case gcc_dwarf_w28_mips64: return "w28"; + case gcc_dwarf_w29_mips64: return "w29"; + case gcc_dwarf_w30_mips64: return "w30"; + case gcc_dwarf_w31_mips64: return "w31"; + case gcc_dwarf_mcsr_mips64: return "mcsr"; + case gcc_dwarf_mir_mips64: return "mir"; + case gcc_dwarf_config5_mips64: return "config5"; } return nullptr; } @@ -374,6 +441,12 @@ reg_info.format = eFormatHex; reg_info.encoding = eEncodingUint; } + else if ((int)reg_num >= gcc_dwarf_w0_mips64 && (int)reg_num <= gcc_dwarf_w31_mips64) + { + reg_info.byte_size = 16; + reg_info.format = eFormatVectorOfUInt8; + reg_info.encoding = eEncodingVector; + } else { return false; @@ -474,6 +547,16 @@ { "BC1ANY2T", &EmulateInstructionMIPS64::Emulate_BC1ANY2T, "BC1ANY2T cc, offset" }, { "BC1ANY4F", &EmulateInstructionMIPS64::Emulate_BC1ANY4F, "BC1ANY4F cc, offset" }, { "BC1ANY4T", &EmulateInstructionMIPS64::Emulate_BC1ANY4T, "BC1ANY4T cc, offset" }, + { "BNZ_B", &EmulateInstructionMIPS64::Emulate_BNZB, "BNZ.b wt,s16" }, + { "BNZ_H", &EmulateInstructionMIPS64::Emulate_BNZH, "BNZ.h wt,s16" }, + { "BNZ_W", &EmulateInstructionMIPS64::Emulate_BNZW, "BNZ.w wt,s16" }, + { "BNZ_D", &EmulateInstructionMIPS64::Emulate_BNZD, "BNZ.d wt,s16" }, + { "BZ_B", &EmulateInstructionMIPS64::Emulate_BZB, "BZ.b wt,s16" }, + { "BZ_H", &EmulateInstructionMIPS64::Emulate_BZH, "BZ.h wt,s16" }, + { "BZ_W", &EmulateInstructionMIPS64::Emulate_BZW, "BZ.w wt,s16" }, + { "BZ_D", &EmulateInstructionMIPS64::Emulate_BZD, "BZ.d wt,s16" }, + { "BNZ_V", &EmulateInstructionMIPS64::Emulate_BNZV, "BNZ.V wt,s16" }, + { "BZ_V", &EmulateInstructionMIPS64::Emulate_BZV, "BZ.V wt,s16" }, }; static const size_t k_num_mips_opcodes = llvm::array_lengthof(g_opcodes); @@ -2996,3 +3079,437 @@ return true; } + +bool +EmulateInstructionMIPS64::Emulate_BNZB (llvm::MCInst& insn) +{ + bool success = false, branch_hit = true; + uint32_t wt; + int64_t offset, pc, target; + RegisterValue reg_value; + uint8_t * ptr = NULL; + + wt = 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; + + if (ReadRegister (eRegisterKindDWARF, gcc_dwarf_w0_mips64 + wt, reg_value)) + ptr = (uint8_t *)reg_value.GetBytes(); + else + return false; + + for(int i = 1 ; i < 16; i++) + { + if(*ptr == 0) + { + branch_hit = false; + break; + } + ptr = ptr + 1; + } + + if(branch_hit) + target = pc + offset; + else + target = pc + 4; + + Context context; + context.type = eContextInvalid; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS64::Emulate_BNZH (llvm::MCInst& insn) +{ + bool success = false, branch_hit = true; + uint32_t wt; + int64_t offset, pc, target; + RegisterValue reg_value; + uint16_t * ptr = NULL; + + wt = 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; + + if (ReadRegister (eRegisterKindDWARF, gcc_dwarf_w0_mips64 + wt, reg_value)) + ptr = (uint16_t *)reg_value.GetBytes(); + else + return false; + + for(int i = 1 ; i < 8; i++) + { + if(*ptr == 0) + { + branch_hit = false; + break; + } + ptr = ptr + 1; + } + + if(branch_hit) + target = pc + offset; + else + target = pc + 4; + + Context context; + context.type = eContextInvalid; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS64::Emulate_BNZW (llvm::MCInst& insn) +{ + bool success = false, branch_hit = true; + uint32_t wt; + int64_t offset, pc, target; + RegisterValue reg_value; + uint32_t * ptr = NULL; + + wt = 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; + + if (ReadRegister (eRegisterKindDWARF, gcc_dwarf_w0_mips64 + wt, reg_value)) + ptr = (uint32_t *)reg_value.GetBytes(); + else + return false; + + for(int i = 1 ; i < 4; i++) + { + if(*ptr == 0) + { + branch_hit = false; + break; + } + ptr = ptr + 1; + } + + if(branch_hit) + target = pc + offset; + else + target = pc + 4; + + Context context; + context.type = eContextInvalid; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS64::Emulate_BNZD (llvm::MCInst& insn) +{ + bool success = false, branch_hit = true; + uint32_t wt; + int64_t offset, pc, target; + RegisterValue reg_value; + uint64_t * ptr = NULL; + + wt = 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; + + if (ReadRegister (eRegisterKindDWARF, gcc_dwarf_w0_mips64 + wt, reg_value)) + ptr = (uint64_t *)reg_value.GetBytes(); + else + return false; + + for(int i = 1; i < 2; i++) + { + if(*ptr == 0) + { + branch_hit = false; + break; + } + ptr = ptr + 1; + } + + if(branch_hit) + target = pc + offset; + else + target = pc + 4; + + Context context; + context.type = eContextInvalid; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS64::Emulate_BZB (llvm::MCInst& insn) +{ + bool success = false, branch_hit = true; + uint32_t wt; + int64_t offset, pc, target; + RegisterValue reg_value; + uint8_t * ptr = NULL; + + wt = 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; + + if (ReadRegister (eRegisterKindDWARF, gcc_dwarf_w0_mips64 + wt, reg_value)) + ptr = (uint8_t *)reg_value.GetBytes(); + else + return false; + + for(int i = 1 ; i < 16 ; i++) + { + if(*ptr != 0) + { + branch_hit = false; + break; + } + ptr = ptr + 1; + } + + if(branch_hit) + target = pc + offset; + else + target = pc + 4; + + Context context; + context.type = eContextInvalid; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS64::Emulate_BZH (llvm::MCInst& insn) +{ + bool success = false, branch_hit = true; + uint32_t wt; + int64_t offset, pc, target; + RegisterValue reg_value; + uint16_t * ptr = NULL; + + wt = 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; + + if (ReadRegister (eRegisterKindDWARF, gcc_dwarf_w0_mips64 + wt, reg_value)) + ptr = (uint16_t *)reg_value.GetBytes(); + else + return false; + + for(int i = 1 ; i < 8; i++) + { + if(*ptr != 0) + { + branch_hit = false; + break; + } + ptr = ptr + 1; + } + + if(branch_hit) + target = pc + offset; + else + target = pc + 4; + + Context context; + context.type = eContextInvalid; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS64::Emulate_BZW (llvm::MCInst& insn) +{ + bool success = false, branch_hit = true; + uint32_t wt; + int64_t offset, pc, target; + RegisterValue reg_value; + uint32_t * ptr = NULL; + + wt = 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; + + if (ReadRegister (eRegisterKindDWARF, gcc_dwarf_w0_mips64 + wt, reg_value)) + ptr = (uint32_t *)reg_value.GetBytes(); + else + return false; + + for(int i = 1 ; i < 4; i++) + { + if(*ptr != 0) + { + branch_hit = false; + break; + } + ptr = ptr + 1; + } + + if(branch_hit) + target = pc + offset; + else + target = pc + 4; + + Context context; + context.type = eContextInvalid; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS64::Emulate_BZD (llvm::MCInst& insn) +{ + bool success = false, branch_hit = true; + uint32_t wt; + int64_t offset, pc, target; + RegisterValue reg_value; + uint64_t * ptr = NULL; + + wt = 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; + + if (ReadRegister (eRegisterKindDWARF, gcc_dwarf_w0_mips64 + wt, reg_value)) + ptr = (uint64_t *)reg_value.GetBytes(); + else + return false; + + for(int i = 1 ; i < 2; i++) + { + if(*ptr != 0) + { + branch_hit = false; + break; + } + ptr = ptr + 1; + } + + if(branch_hit) + target = pc + offset; + else + target = pc + 4; + + Context context; + context.type = eContextInvalid; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS64::Emulate_BNZV (llvm::MCInst& insn) +{ + bool success = false; + uint32_t wt; + int64_t offset, pc, target; + llvm::APInt wr_val; + llvm::APInt fail_value = llvm::APInt::getMaxValue(128); + llvm::APInt zero_value = llvm::APInt::getNullValue(128); + RegisterValue reg_value; + + wt = 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; + + if (ReadRegister (eRegisterKindDWARF, gcc_dwarf_w0_mips64 + wt, reg_value)) + wr_val = reg_value.GetAsUInt128(fail_value); + else + return false; + + if(!llvm::APInt::isSameValue(zero_value, wr_val)) + target = pc + offset; + else + target = pc + 4; + + Context context; + context.type = eContextInvalid; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) + return false; + + return true; +} + +bool +EmulateInstructionMIPS64::Emulate_BZV (llvm::MCInst& insn) +{ + bool success = false; + uint32_t wt; + int64_t offset, pc, target; + llvm::APInt wr_val; + llvm::APInt fail_value = llvm::APInt::getMaxValue(128); + llvm::APInt zero_value = llvm::APInt::getNullValue(128); + RegisterValue reg_value; + + wt = 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; + + if (ReadRegister (eRegisterKindDWARF, gcc_dwarf_w0_mips64 + wt, reg_value)) + wr_val = reg_value.GetAsUInt128(fail_value); + else + return false; + + if(llvm::APInt::isSameValue(zero_value, wr_val)) + target = pc + offset; + else + target = pc + 4; + + Context context; + context.type = eContextInvalid; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) + return false; + + return true; +}