Index: source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h =================================================================== --- source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h +++ source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h @@ -160,121 +160,37 @@ Emulate_LDST_Reg (llvm::MCInst& insn); bool - Emulate_BEQ (llvm::MCInst& insn); + Emulate_BXX_3ops (llvm::MCInst& insn); bool - Emulate_BNE (llvm::MCInst& insn); + Emulate_BXX_3ops_C (llvm::MCInst& insn); bool - Emulate_BEQL (llvm::MCInst& insn); + Emulate_BXX_2ops (llvm::MCInst& insn); bool - Emulate_BNEL (llvm::MCInst& insn); + Emulate_BXX_2ops_C (llvm::MCInst& insn); bool - Emulate_BGEZALL (llvm::MCInst& insn); + Emulate_Bcond_Link_C (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); + Emulate_Bcond_Link (llvm::MCInst& insn); bool - Emulate_BGEZC (llvm::MCInst& insn); + Emulate_FP_branch (llvm::MCInst& insn); bool - Emulate_BGTZC (llvm::MCInst& insn); + Emulate_3D_branch (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); + Emulate_BAL (llvm::MCInst& insn); bool - Emulate_BOVC (llvm::MCInst& insn); + Emulate_BALC (llvm::MCInst& insn); bool - Emulate_BNVC (llvm::MCInst& insn); + Emulate_BC (llvm::MCInst& insn); bool Emulate_J (llvm::MCInst& insn); @@ -295,36 +211,12 @@ 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 Emulate_BNZB (llvm::MCInst& insn); bool Index: source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp =================================================================== --- source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp +++ source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp @@ -591,45 +591,45 @@ //---------------------------------------------------------------------- // 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" }, + { "BEQ", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BEQ rs,rt,offset" }, + { "BNE", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BNE rs,rt,offset" }, + { "BEQL", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BEQL rs,rt,offset" }, + { "BNEL", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BNEL rs,rt,offset" }, + { "BGEZALL", &EmulateInstructionMIPS::Emulate_Bcond_Link, "BGEZALL rt,offset" }, { "BAL", &EmulateInstructionMIPS::Emulate_BAL, "BAL offset" }, - { "BGEZAL", &EmulateInstructionMIPS::Emulate_BGEZAL, "BGEZAL rs,offset" }, + { "BGEZAL", &EmulateInstructionMIPS::Emulate_Bcond_Link, "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" }, + { "BGEZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGEZ rs,offset" }, + { "BLEZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,"BLEZALC rs,offset" }, + { "BGEZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,"BGEZALC rs,offset" }, + { "BLTZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,"BLTZALC rs,offset" }, + { "BGTZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,"BGTZALC rs,offset" }, + { "BEQZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,"BEQZALC rs,offset" }, + { "BNEZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,"BNEZALC rs,offset" }, + { "BEQC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, "BEQC rs,rt,offset" }, + { "BNEC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, "BNEC rs,rt,offset" }, + { "BLTC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, "BLTC rs,rt,offset" }, + { "BGEC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, "BGEC rs,rt,offset" }, + { "BLTUC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, "BLTUC rs,rt,offset" }, + { "BGEUC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, "BGEUC rs,rt,offset" }, + { "BLTZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BLTZC rt,offset" }, + { "BLEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BLEZC rt,offset" }, + { "BGEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BGEZC rt,offset" }, + { "BGTZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BGTZC rt,offset" }, + { "BEQZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BEQZC rt,offset" }, + { "BNEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BNEZC rt,offset" }, + { "BGEZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGEZL rt,offset" }, + { "BGTZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGTZ rt,offset" }, + { "BGTZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGTZL rt,offset" }, + { "BLEZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLEZ rt,offset" }, + { "BLEZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLEZL rt,offset" }, + { "BLTZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLTZ rt,offset" }, + { "BLTZAL", &EmulateInstructionMIPS::Emulate_Bcond_Link, "BLTZAL rt,offset" }, + { "BLTZALL", &EmulateInstructionMIPS::Emulate_Bcond_Link, "BLTZALL rt,offset" }, + { "BLTZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLTZL rt,offset" }, + { "BOVC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, "BOVC rs,rt,offset" }, + { "BNVC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, "BNVC rs,rt,offset" }, { "J", &EmulateInstructionMIPS::Emulate_J, "J target" }, { "JAL", &EmulateInstructionMIPS::Emulate_JAL, "JAL target" }, { "JALX", &EmulateInstructionMIPS::Emulate_JAL, "JALX target" }, @@ -639,16 +639,16 @@ { "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" }, + { "BC1F", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1F cc, offset" }, + { "BC1T", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1T cc, offset" }, + { "BC1FL", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1FL cc, offset" }, + { "BC1TL", &EmulateInstructionMIPS::Emulate_FP_branch, "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" }, + { "BC1ANY2F", &EmulateInstructionMIPS::Emulate_3D_branch, "BC1ANY2F cc, offset" }, + { "BC1ANY2T", &EmulateInstructionMIPS::Emulate_3D_branch, "BC1ANY2T cc, offset" }, + { "BC1ANY4F", &EmulateInstructionMIPS::Emulate_3D_branch, "BC1ANY4F cc, offset" }, + { "BC1ANY4T", &EmulateInstructionMIPS::Emulate_3D_branch, "BC1ANY4T cc, offset" }, { "BNZ_B", &EmulateInstructionMIPS::Emulate_BNZB, "BNZ.b wt,s16" }, { "BNZ_H", &EmulateInstructionMIPS::Emulate_BNZH, "BNZ.h wt,s16" }, { "BNZ_W", &EmulateInstructionMIPS::Emulate_BNZW, "BNZ.w wt,s16" }, @@ -1387,19 +1387,26 @@ 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); +} + +/* + Emulate below MIPS branch instructions. + BEQ, BNE : Branch on condition + BEQL, BNEL : Branch likely +*/ bool -EmulateInstructionMIPS::Emulate_BEQ (llvm::MCInst& insn) +EmulateInstructionMIPS::Emulate_BXX_3ops (llvm::MCInst& insn) { bool success = false; uint32_t rs, rt; int32_t offset, pc, target, rs_val, rt_val; + const char *op_name = m_insn_info->getName (insn.getOpcode ()); - /* - * 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(); @@ -1416,1551 +1423,49 @@ 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, dwarf_pc_mips, target)) - return false; - - return true; -} - -bool -EmulateInstructionMIPS::Emulate_B16_MM (llvm::MCInst& insn) -{ - bool success = false; - int32_t offset, pc, target; - uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize(); - - offset = insn.getOperand(0).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - // unconditional branch - target = pc + offset; - - Context context; - context.type = eContextRelativeBranchImmediate; - context.SetImmediate (current_inst_size + offset); - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) - return false; - - return true; -} - -/* - BEQZC, BNEZC are 32 bit compact instructions without a delay slot. - BEQZ16, BNEZ16 are 16 bit instructions with delay slot. - BGEZALS, BLTZALS are 16 bit instructions with short (2-byte) delay slot. -*/ -bool -EmulateInstructionMIPS::Emulate_Branch_MM (llvm::MCInst& insn) -{ - bool success = false; - int32_t target = 0; - uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize(); - const char *op_name = m_insn_info->getName (insn.getOpcode ()); - bool update_ra = false; - uint32_t ra_offset = 0; - - /* - * BEQZ16 rs, offset - * condition <- (GPR[rs] = 0) - * if condition then - * PC = PC + sign_ext (offset || 0) - * - * BNEZ16 rs, offset - * condition <- (GPR[rs] != 0) - * if condition then - * PC = PC + sign_ext (offset || 0) - * - * BEQZC rs, offset (compact instruction: No delay slot) - * condition <- (GPR[rs] == 0) - * if condition then - * PC = PC + 4 + sign_ext (offset || 0) - */ - - uint32_t rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - int32_t offset = insn.getOperand(1).getImm(); - - int32_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - int32_t rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); - if (!success) - return false; - - if (!strcasecmp (op_name, "BEQZ16_MM")) - { - if (rs_val == 0) - target = pc + offset; - else - target = pc + current_inst_size + m_next_inst_size; // Skip delay slot instruction. - } - else if (!strcasecmp (op_name, "BNEZ16_MM")) - { - if (rs_val != 0) - target = pc + offset; - else - target = pc + current_inst_size + m_next_inst_size; // Skip delay slot instruction. - } - else if (!strcasecmp (op_name, "BEQZC_MM")) - { - if (rs_val == 0) - target = pc + 4 + offset; - else - target = pc + 4; // 32 bit instruction and does not have delay slot instruction. - } - else if (!strcasecmp (op_name, "BNEZC_MM")) - { - if (rs_val != 0) - target = pc + 4 + offset; - else - target = pc + 4; // 32 bit instruction and does not have delay slot instruction. - } - else if (!strcasecmp (op_name, "BGEZALS_MM")) - { - if (rs_val >= 0) - target = pc + offset; - else - target = pc + 6; // 32 bit instruction with short (2-byte) delay slot - - update_ra = true; - ra_offset = 6; - } - else if (!strcasecmp (op_name, "BLTZALS_MM")) + if (!strcasecmp (op_name, "BEQ") || + !strcasecmp (op_name, "BEQL")) { - if (rs_val >= 0) + if (rs_val == rt_val) target = pc + offset; else - target = pc + 6; // 32 bit instruction with short (2-byte) delay slot - - update_ra = true; - ra_offset = 6; - } - - Context context; - context.type = eContextRelativeBranchImmediate; - context.SetImmediate (current_inst_size + offset); - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) - return false; - - if (update_ra) - { - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + ra_offset)) - return false; - } - return true; -} - -/* Emulate micromips jump instructions. - JALR16,JALRS16 -*/ -bool -EmulateInstructionMIPS::Emulate_JALRx16_MM (llvm::MCInst& insn) -{ - bool success = false; - uint32_t ra_offset = 0; - const char *op_name = m_insn_info->getName (insn.getOpcode ()); - - uint32_t rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - - uint32_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - uint32_t rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); - if (!success) - return false; - - if (!strcasecmp (op_name, "JALR16_MM")) - ra_offset = 6; // 2-byte instruction with 4-byte delay slot. - else if (!strcasecmp (op_name, "JALRS16_MM")) - ra_offset = 4; // 2-byte instruction with 2-byte delay slot. - - Context context; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, rs_val)) - return false; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + ra_offset)) - return false; - - return true; -} - -/* Emulate JALS and JALX instructions. - JALS 32 bit instruction with short (2-byte) delay slot. - JALX 32 bit instruction with 4-byte delay slot. -*/ -bool -EmulateInstructionMIPS::Emulate_JALx (llvm::MCInst& insn) -{ - bool success = false; - uint32_t offset=0, target=0, pc=0, ra_offset=0; - const char *op_name = m_insn_info->getName (insn.getOpcode ()); - - /* - * JALS target - * RA = PC + 6 - * offset = sign_ext (offset << 1) - * PC = PC[31-27] | offset - * JALX target - * RA = PC + 8 - * offset = sign_ext (offset << 2) - * PC = PC[31-28] | offset - */ - offset = insn.getOperand(0).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - // These are PC-region branches and not PC-relative. - if (!strcasecmp (op_name, "JALS_MM")) - { - // target address is in the “current” 128 MB-aligned region - target = (pc & 0xF8000000UL) | offset; - ra_offset = 6; + target = pc + 8; + } + else if (!strcasecmp (op_name, "BNE") || + !strcasecmp (op_name, "BNEL")) + { + if (rs_val != rt_val) + target = pc + offset; + else + target = pc + 8; } - else if (!strcasecmp (op_name, "JALX_MM")) - { - // target address is in the “current” 256 MB-aligned region - target = (pc & 0xF0000000UL) | offset; - ra_offset = 8; - } - - Context context; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) - return false; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + ra_offset)) - return false; - - return true; -} - -bool -EmulateInstructionMIPS::Emulate_JALRS (llvm::MCInst& insn) -{ - bool success = false; - uint32_t rs=0, rt=0; - int32_t pc=0, rs_val=0; - - /* - JALRS rt, rs - GPR[rt] <- PC + 6 - PC <- GPR[rs] - */ - - rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - rs = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); - - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); - if (!success) - return false; - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - Context context; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, rs_val)) - return false; - - // This is 4-byte instruction with 2-byte delay slot. - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips + rt, pc + 6)) - 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); - if (!success) - return false; - - rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, 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, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); - if (!success) - return false; - - rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, 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, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); - if (!success) - return false; - - rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, 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, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, 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, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, 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, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, 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, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, 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, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, 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, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, 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, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, 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, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, 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, dwarf_pc_mips, target)) - return false; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - target = pc + offset; - - Context context; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) - return false; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - target = pc + 4 + offset; - - Context context; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) - return false; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, 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, dwarf_pc_mips, target)) - return false; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, 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, dwarf_pc_mips, target)) - return false; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, 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, dwarf_pc_mips, target)) - return false; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, 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, dwarf_pc_mips, target)) - return false; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, 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, dwarf_pc_mips, target)) - return false; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, 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, dwarf_pc_mips, target)) - return false; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, 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, dwarf_pc_mips, target)) - return false; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, 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, dwarf_pc_mips, target)) - return false; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, 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, dwarf_pc_mips, target)) - return false; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, 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, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - target = pc + 4 + offset; - - Context context; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); - if (!success) - return false; - - rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, 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, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); - if (!success) - return false; - - rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, 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, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); - if (!success) - return false; - - rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, 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, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); - if (!success) - return false; - - rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, 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, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); - if (!success) - return false; - - rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, 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, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); - if (!success) - return false; - - rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, 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, 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, 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; + context.SetImmediate (offset); if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) - return false; - + return false; + return true; } +/* + Emulate below MIPS branch instructions. + BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch instructions with no delay slot +*/ bool -EmulateInstructionMIPS::Emulate_BLEZC (llvm::MCInst& insn) +EmulateInstructionMIPS::Emulate_BXX_3ops_C (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) - */ + uint32_t rs, rt; + int32_t offset, pc, target, rs_val, rt_val; + const char *op_name = m_insn_info->getName (insn.getOpcode ()); + uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize(); + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(1).getImm(); + rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); + offset = insn.getOperand(2).getImm(); pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); if (!success) @@ -2970,34 +1475,90 @@ if (!success) return false; - if (rs_val <= 0) - target = pc + 4 + offset; - else - target = pc + 4; + rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success); + if (!success) + return false; + + if (!strcasecmp (op_name, "BEQC")) + { + if (rs_val == rt_val) + target = pc + 4 + offset; + else + target = pc + 4; + } + else if (!strcasecmp (op_name, "BNEC")) + { + if (rs_val != rt_val) + target = pc + 4 + offset; + else + target = pc + 4; + } + else if (!strcasecmp (op_name, "BLTC")) + { + if (rs_val < rt_val) + target = pc + 4 + offset; + else + target = pc + 4; + } + else if (!strcasecmp (op_name, "BGEC")) + { + if (rs_val >= rt_val) + target = pc + 4 + offset; + else + target = pc + 4; + } + else if (!strcasecmp (op_name, "BLTUC")) + { + if (rs_val < rt_val) + target = pc + 4 + offset; + else + target = pc + 4; + } + else if (!strcasecmp (op_name, "BGEUC")) + { + if ((uint32_t)rs_val >= (uint32_t)rt_val) + target = pc + 4 + offset; + else + target = pc + 4; + } + else if (!strcasecmp (op_name, "BOVC")) + { + if (IsAdd64bitOverflow (rs_val, rt_val)) + target = pc + 4 + offset; + else + target = pc + 4; + } + else if (!strcasecmp (op_name, "BNVC")) + { + if (!IsAdd64bitOverflow (rs_val, rt_val)) + target = pc + 4 + offset; + else + target = pc + 4; + } Context context; context.type = eContextRelativeBranchImmediate; + context.SetImmediate (current_inst_size + offset); if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) - return false; - + return false; + return true; } +/* + Emulate below MIPS conditional branch and link instructions. + BLEZALC, BGEZALC, BLTZALC, BGTZALC, BEQZALC, BNEZALC : Compact branches +*/ bool -EmulateInstructionMIPS::Emulate_BGEZC (llvm::MCInst& insn) +EmulateInstructionMIPS::Emulate_Bcond_Link_C (llvm::MCInst& insn) { bool success = false; uint32_t rs; int32_t offset, pc, target; int32_t rs_val; + const char *op_name = m_insn_info->getName (insn.getOpcode ()); - /* - * 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(); @@ -3009,34 +1570,74 @@ if (!success) return false; - if (rs_val >= 0) - target = pc + 4 + offset; - else - target = pc + 4; + if (!strcasecmp (op_name, "BLEZALC")) + { + if (rs_val <= 0) + target = pc + offset; + else + target = pc + 4; + } + else if (!strcasecmp (op_name, "BGEZALC")) + { + if (rs_val >= 0) + target = pc + offset; + else + target = pc + 4; + } + else if (!strcasecmp (op_name, "BLTZALC")) + { + if (rs_val < 0) + target = pc + offset; + else + target = pc + 4; + } + else if (!strcasecmp (op_name, "BGTZALC")) + { + if (rs_val > 0) + target = pc + offset; + else + target = pc + 4; + } + else if (!strcasecmp (op_name, "BEQZALC")) + { + if (rs_val == 0) + target = pc + offset; + else + target = pc + 4; + } + else if (!strcasecmp (op_name, "BNEZALC")) + { + if (rs_val != 0) + target = pc + offset; + else + target = pc + 4; + } Context context; - context.type = eContextRelativeBranchImmediate; - + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) return false; + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 4)) + return false; + return true; } +/* + Emulate below MIPS Non-Compact conditional branch and link instructions. + BLTZAL, BGEZAL : + BLTZALL, BGEZALL : Branch likely +*/ bool -EmulateInstructionMIPS::Emulate_BGTZC (llvm::MCInst& insn) +EmulateInstructionMIPS::Emulate_Bcond_Link (llvm::MCInst& insn) { bool success = false; uint32_t rs; int32_t offset, pc, target; int32_t rs_val; + const char *op_name = m_insn_info->getName (insn.getOpcode ()); - /* - * 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(); @@ -3048,34 +1649,48 @@ if (!success) return false; - if (rs_val > 0) - target = pc + 4 + offset; - else - target = pc + 4; + if (!strcasecmp (op_name, "BLTZAL") || + !strcasecmp (op_name, "BLTZALL")) + { + if ((int32_t) rs_val < 0) + target = pc + offset; + else + target = pc + 8; + } + else if (!strcasecmp (op_name, "BGEZAL") || + !strcasecmp (op_name, "BGEZALL")) + { + if ((int32_t) rs_val >= 0) + target = pc + offset; + else + target = pc + 8; + } Context context; - context.type = eContextRelativeBranchImmediate; if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) return false; + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 8)) + return false; + return true; } +/* + Emulate below MIPS branch instructions. + BLTZL, BGEZL, BGTZL, BLEZL : Branch likely + BLTZ, BGEZ, BGTZ, BLEZ : Non-compact branches +*/ bool -EmulateInstructionMIPS::Emulate_BEQZC (llvm::MCInst& insn) +EmulateInstructionMIPS::Emulate_BXX_2ops (llvm::MCInst& insn) { bool success = false; uint32_t rs; int32_t offset, pc, target; - uint32_t rs_val; + int32_t rs_val; + const char *op_name = m_insn_info->getName (insn.getOpcode ()); - /* - * 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(); @@ -3083,17 +1698,46 @@ if (!success) return false; - rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); if (!success) return false; - if (rs_val == 0) - target = pc + 4 + offset; - else - target = pc + 4; + if (!strcasecmp (op_name, "BLTZL") || + !strcasecmp (op_name, "BLTZ")) + { + if (rs_val < 0) + target = pc + offset; + else + target = pc + 8; + } + else if (!strcasecmp (op_name, "BGEZL") || + !strcasecmp (op_name, "BGEZ")) + { + if (rs_val >= 0) + target = pc + offset; + else + target = pc + 8; + } + else if (!strcasecmp (op_name, "BGTZL") || + !strcasecmp (op_name, "BGTZ")) + { + if (rs_val > 0) + target = pc + offset; + else + target = pc + 8; + } + else if (!strcasecmp (op_name, "BLEZL") || + !strcasecmp (op_name, "BLEZ")) + { + if (rs_val <= 0) + target = pc + offset; + else + target = pc + 8; + } Context context; context.type = eContextRelativeBranchImmediate; + context.SetImmediate (offset); if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) return false; @@ -3101,20 +1745,20 @@ return true; } +/* + Emulate below MIPS branch instructions. + BLTZC, BLEZC, BGEZC, BGTZC, BEQZC, BNEZC : Compact Branches +*/ bool -EmulateInstructionMIPS::Emulate_BNEZC (llvm::MCInst& insn) +EmulateInstructionMIPS::Emulate_BXX_2ops_C (llvm::MCInst& insn) { bool success = false; uint32_t rs; int32_t offset, pc, target; - uint32_t rs_val; + int32_t rs_val; + const char *op_name = m_insn_info->getName (insn.getOpcode ()); + uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize(); - /* - * 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(); @@ -3122,17 +1766,56 @@ if (!success) return false; - rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); if (!success) return false; - if (rs_val != 0) - target = pc + 4 + offset; - else - target = pc + 4; + if (!strcasecmp (op_name, "BLTZC")) + { + if (rs_val < 0) + target = pc + 4 + offset; + else + target = pc + 4; + } + else if (!strcasecmp (op_name, "BLEZC")) + { + if (rs_val <= 0) + target = pc + 4 + offset; + else + target = pc + 4; + } + else if (!strcasecmp (op_name, "BGEZC")) + { + if (rs_val >= 0) + target = pc + 4 + offset; + else + target = pc + 4; + } + else if (!strcasecmp (op_name, "BGTZC")) + { + if (rs_val > 0) + target = pc + 4 + offset; + else + target = pc + 4; + } + else if (!strcasecmp (op_name, "BEQZC")) + { + if (rs_val == 0) + target = pc + 4 + offset; + else + target = pc + 4; + } + else if (!strcasecmp (op_name, "BNEZC")) + { + if (rs_val != 0) + target = pc + 4 + offset; + else + target = pc + 4; + } Context context; context.type = eContextRelativeBranchImmediate; + context.SetImmediate (current_inst_size + offset); if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) return false; @@ -3140,50 +1823,25 @@ 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) +EmulateInstructionMIPS::Emulate_B16_MM (llvm::MCInst& insn) { bool success = false; - uint32_t rs, rt; int32_t offset, pc, target; - int32_t rs_val, rt_val; + uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize(); - /* - * 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(); + offset = insn.getOperand(0).getImm(); pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); if (!success) return false; - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); - if (!success) - return false; - - rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success); - if (!success) - return false; - - if (IsAdd64bitOverflow (rs_val, rt_val)) - target = pc + offset; - else - target = pc + 4; + // unconditional branch + target = pc + offset; Context context; context.type = eContextRelativeBranchImmediate; + context.SetImmediate (current_inst_size + offset); if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) return false; @@ -3191,88 +1849,169 @@ return true; } +/* + BEQZC, BNEZC are 32 bit compact instructions without a delay slot. + BEQZ16, BNEZ16 are 16 bit instructions with delay slot. + BGEZALS, BLTZALS are 16 bit instructions with short (2-byte) delay slot. +*/ bool -EmulateInstructionMIPS::Emulate_BNVC (llvm::MCInst& insn) +EmulateInstructionMIPS::Emulate_Branch_MM (llvm::MCInst& insn) { bool success = false; - uint32_t rs, rt; - int32_t offset, pc, target; - int32_t rs_val, rt_val; + int32_t target = 0; + uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize(); + const char *op_name = m_insn_info->getName (insn.getOpcode ()); + bool update_ra = false; + uint32_t ra_offset = 0; /* - * BNVC rs, rt, offset - * condition <- overflow(GPR[rs] + GPR[rt]) + * BEQZ16 rs, offset + * condition <- (GPR[rs] = 0) + * if condition then + * PC = PC + sign_ext (offset || 0) + * + * BNEZ16 rs, offset + * condition <- (GPR[rs] != 0) + * if condition then + * PC = PC + sign_ext (offset || 0) + * + * BEQZC rs, offset (compact instruction: No delay slot) + * condition <- (GPR[rs] == 0) * if condition then - * PC = PC + sign_ext (offset << 2) + * PC = PC + 4 + sign_ext (offset || 0) */ - 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, dwarf_pc_mips, 0, &success); - if (!success) - return false; + uint32_t rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + int32_t offset = insn.getOperand(1).getImm(); - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); + int32_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); if (!success) return false; - rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success); + int32_t rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); if (!success) return false; - if (! IsAdd64bitOverflow (rs_val, rt_val)) - target = pc + offset; - else - target = pc + 4; + if (!strcasecmp (op_name, "BEQZ16_MM")) + { + if (rs_val == 0) + target = pc + offset; + else + target = pc + current_inst_size + m_next_inst_size; // Skip delay slot instruction. + } + else if (!strcasecmp (op_name, "BNEZ16_MM")) + { + if (rs_val != 0) + target = pc + offset; + else + target = pc + current_inst_size + m_next_inst_size; // Skip delay slot instruction. + } + else if (!strcasecmp (op_name, "BEQZC_MM")) + { + if (rs_val == 0) + target = pc + 4 + offset; + else + target = pc + 4; // 32 bit instruction and does not have delay slot instruction. + } + else if (!strcasecmp (op_name, "BNEZC_MM")) + { + if (rs_val != 0) + target = pc + 4 + offset; + else + target = pc + 4; // 32 bit instruction and does not have delay slot instruction. + } + else if (!strcasecmp (op_name, "BGEZALS_MM")) + { + if (rs_val >= 0) + target = pc + offset; + else + target = pc + 6; // 32 bit instruction with short (2-byte) delay slot + + update_ra = true; + ra_offset = 6; + } + else if (!strcasecmp (op_name, "BLTZALS_MM")) + { + if (rs_val >= 0) + target = pc + offset; + else + target = pc + 6; // 32 bit instruction with short (2-byte) delay slot + + update_ra = true; + ra_offset = 6; + } Context context; context.type = eContextRelativeBranchImmediate; + context.SetImmediate (current_inst_size + offset); if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) return false; + if (update_ra) + { + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + ra_offset)) + return false; + } return true; } +/* Emulate micromips jump instructions. + JALR16,JALRS16 +*/ bool -EmulateInstructionMIPS::Emulate_J (llvm::MCInst& insn) +EmulateInstructionMIPS::Emulate_JALRx16_MM (llvm::MCInst& insn) { bool success = false; - uint32_t offset, pc; + uint32_t ra_offset = 0; + const char *op_name = m_insn_info->getName (insn.getOpcode ()); - /* - * J offset - * offset = sign_ext (offset << 2) - * PC = PC[63-28] | offset - */ - offset = insn.getOperand(0).getImm(); + uint32_t rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); + uint32_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); if (!success) return false; - /* This is a PC-region branch and not PC-relative */ - pc = (pc & 0xF0000000UL) | offset; + uint32_t rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; + + if (!strcasecmp (op_name, "JALR16_MM")) + ra_offset = 6; // 2-byte instruction with 4-byte delay slot. + else if (!strcasecmp (op_name, "JALRS16_MM")) + ra_offset = 4; // 2-byte instruction with 2-byte delay slot. Context context; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, pc)) + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, rs_val)) + return false; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + ra_offset)) return false; return true; } +/* Emulate JALS and JALX instructions. + JALS 32 bit instruction with short (2-byte) delay slot. + JALX 32 bit instruction with 4-byte delay slot. +*/ bool -EmulateInstructionMIPS::Emulate_JAL (llvm::MCInst& insn) +EmulateInstructionMIPS::Emulate_JALx (llvm::MCInst& insn) { bool success = false; - uint32_t offset, target, pc; - + uint32_t offset=0, target=0, pc=0, ra_offset=0; + const char *op_name = m_insn_info->getName (insn.getOpcode ()); + /* - * JAL offset + * JALS target + * RA = PC + 6 + * offset = sign_ext (offset << 1) + * PC = PC[31-27] | offset + * JALX target + * RA = PC + 8 * offset = sign_ext (offset << 2) - * PC = PC[63-28] | offset + * PC = PC[31-28] | offset */ offset = insn.getOperand(0).getImm(); @@ -3280,340 +2019,307 @@ if (!success) return false; - /* This is a PC-region branch and not PC-relative */ - target = (pc & 0xF0000000UL) | offset; + // These are PC-region branches and not PC-relative. + if (!strcasecmp (op_name, "JALS_MM")) + { + // target address is in the “current” 128 MB-aligned region + target = (pc & 0xF8000000UL) | offset; + ra_offset = 6; + } + else if (!strcasecmp (op_name, "JALX_MM")) + { + // target address is in the “current” 256 MB-aligned region + target = (pc & 0xF0000000UL) | offset; + ra_offset = 8; + } Context context; if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) return false; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 8)) + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + ra_offset)) return false; return true; } bool -EmulateInstructionMIPS::Emulate_JALR (llvm::MCInst& insn) +EmulateInstructionMIPS::Emulate_JALRS (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] + uint32_t rs=0, rt=0; + int32_t pc=0, rs_val=0; + + /* + JALRS rt, rs + GPR[rt] <- PC + 6 + PC <- GPR[rs] */ + rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); rs = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); + rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); if (!success) return false; - rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); + pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); if (!success) return false; - + Context context; if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, rs_val)) return false; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips + rt, pc + 8)) + // This is 4-byte instruction with 2-byte delay slot. + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips + rt, pc + 6)) return false; - + return true; } bool -EmulateInstructionMIPS::Emulate_JIALC (llvm::MCInst& insn) +EmulateInstructionMIPS::Emulate_BAL (llvm::MCInst& insn) { bool success = false; - uint32_t rt; - int32_t target, offset, pc, rt_val; + int32_t offset, pc, target; - /* - * JIALC rt, offset - * offset = sign_ext (offset) - * PC = GPR[rt] + offset - * RA = PC + 4 + /* + * BAL offset + * offset = sign_ext (offset << 2) + * RA = PC + 8 + * PC = PC + offset */ - rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(1).getImm(); + offset = insn.getOperand(0).getImm(); pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); if (!success) return false; - rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success); - if (!success) - return false; - - target = rt_val + offset; + target = pc + offset; Context context; if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) return false; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 4)) + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 8)) return false; return true; } bool -EmulateInstructionMIPS::Emulate_JIC (llvm::MCInst& insn) +EmulateInstructionMIPS::Emulate_BALC (llvm::MCInst& insn) { bool success = false; - uint32_t rt; - int32_t target, offset, rt_val; + int32_t offset, pc, target; /* - * JIC rt, offset - * offset = sign_ext (offset) - * PC = GPR[rt] + offset + * BALC offset + * offset = sign_ext (offset << 2) + * RA = PC + 4 + * PC = PC + 4 + offset */ - rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(1).getImm(); + offset = insn.getOperand(0).getImm(); - rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success); + pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); if (!success) return false; - target = rt_val + offset; + target = pc + 4 + offset; Context context; if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) return false; + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 4)) + return false; + return true; } bool -EmulateInstructionMIPS::Emulate_JR (llvm::MCInst& insn) +EmulateInstructionMIPS::Emulate_BC (llvm::MCInst& insn) { bool success = false; - uint32_t rs; - uint32_t rs_val; + int32_t offset, pc, target; /* - * JR rs - * PC = GPR[rs] + * BC offset + * offset = sign_ext (offset << 2) + * PC = PC + 4 + offset */ - rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + offset = insn.getOperand(0).getImm(); - rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); + pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); if (!success) return false; + target = pc + 4 + offset; + Context context; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, rs_val)) + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) return false; return true; } bool -EmulateInstructionMIPS::Emulate_BC1F (llvm::MCInst& insn) +EmulateInstructionMIPS::Emulate_J (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 + uint32_t offset, pc; + + /* + * J offset + * offset = sign_ext (offset << 2) + * PC = PC[63-28] | offset */ - cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(1).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; + offset = insn.getOperand(0).getImm(); - fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success); + pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_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; - + return false; + + /* This is a PC-region branch and not PC-relative */ + pc = (pc & 0xF0000000UL) | offset; + Context context; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, pc)) return false; return true; } bool -EmulateInstructionMIPS::Emulate_BC1T (llvm::MCInst& insn) +EmulateInstructionMIPS::Emulate_JAL (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 + uint32_t offset, target, pc; + + /* + * JAL offset + * offset = sign_ext (offset << 2) + * PC = PC[63-28] | offset */ - cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(1).getImm(); - + offset = insn.getOperand(0).getImm(); + pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); if (!success) return false; - fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success); - if (!success) - return false; + /* This is a PC-region branch and not PC-relative */ + target = (pc & 0xF0000000UL) | offset; - /* 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, dwarf_pc_mips, target)) return false; + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 8)) + return false; + return true; } bool -EmulateInstructionMIPS::Emulate_BC1FL (llvm::MCInst& insn) +EmulateInstructionMIPS::Emulate_JALR (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 + uint32_t rs, rt; + uint32_t pc, rs_val; + + /* + * JALR rt, rs + * GPR[rt] = PC + 8 + * PC = GPR[rs] */ - cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(1).getImm(); - + rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + rs = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); + pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); if (!success) return false; - fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success); + rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 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, dwarf_pc_mips, target)) + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, rs_val)) + return false; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips + rt, pc + 8)) return false; return true; } bool -EmulateInstructionMIPS::Emulate_BC1TL (llvm::MCInst& insn) +EmulateInstructionMIPS::Emulate_JIALC (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 + uint32_t rt; + int32_t target, offset, pc, rt_val; + + /* + * JIALC rt, offset + * offset = sign_ext (offset) + * PC = GPR[rt] + offset + * RA = PC + 4 */ - cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); offset = insn.getOperand(1).getImm(); - + pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); if (!success) return false; - fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success); + rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 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 */ - + target = rt_val + offset; + Context context; if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) return false; + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 4)) + return false; + return true; } bool -EmulateInstructionMIPS::Emulate_BC1EQZ (llvm::MCInst& insn) +EmulateInstructionMIPS::Emulate_JIC (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 + uint32_t rt; + int32_t target, offset, rt_val; + + /* + * JIC rt, offset + * offset = sign_ext (offset) + * PC = GPR[rt] + offset */ - ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); offset = insn.getOperand(1).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; - ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + ft, 0, &success); + rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success); if (!success) return false; - if ((ft_val & 1) == 0) - target = pc + 4 + offset; - else - target = pc + 8; - + target = rt_val + offset; + Context context; if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) @@ -3623,59 +2329,43 @@ } bool -EmulateInstructionMIPS::Emulate_BC1NEZ (llvm::MCInst& insn) +EmulateInstructionMIPS::Emulate_JR (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 + uint32_t rs; + uint32_t rs_val; + + /* + * JR rs + * PC = GPR[rs] */ - ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(1).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; + rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + ft, 0, &success); + rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 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, dwarf_pc_mips, target)) + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, rs_val)) return false; return true; } +/* + Emulate Branch on FP True/False + BC1F, BC1FL : Branch on FP False (L stands for branch likely) + BC1T, BC1TL : Branch on FP True (L stands for branch likely) +*/ bool -EmulateInstructionMIPS::Emulate_BC1ANY2F (llvm::MCInst& insn) +EmulateInstructionMIPS::Emulate_FP_branch (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 - */ + const char *op_name = m_insn_info->getName (insn.getOpcode ()); + cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); offset = insn.getOperand(1).getImm(); @@ -3683,19 +2373,29 @@ if (!success) return false; - fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success); + fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, 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; - + if (!strcasecmp (op_name, "BC1F") || + !strcasecmp (op_name, "BC1FL")) + { + if ((fcsr & (1 << cc)) == 0) + target = pc + offset; + else + target = pc + 8; + } + else if (!strcasecmp (op_name, "BC1T") || + !strcasecmp (op_name, "BC1TL")) + { + if ((fcsr & (1 << cc)) != 0) + target = pc + offset; + else + target = pc + 8; + } Context context; if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) @@ -3705,37 +2405,33 @@ } bool -EmulateInstructionMIPS::Emulate_BC1ANY2T (llvm::MCInst& insn) +EmulateInstructionMIPS::Emulate_BC1EQZ (llvm::MCInst& insn) { bool success = false; - uint32_t cc, fcsr; + uint32_t ft; + uint32_t ft_val; int32_t target, pc, offset; /* - * BC1ANY2T cc, offset - * condition <- (FPConditionCode(cc) == 1 - * || FPConditionCode(cc+1) == 1) + * BC1EQZ ft, offset + * condition <- (FPR[ft].bit0 == 0) * if condition then * offset = sign_ext (offset) - * PC = PC + offset + * PC = PC + 4 + offset */ - cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); offset = insn.getOperand(1).getImm(); pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); if (!success) return false; - fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success); + ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + ft, 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; + if ((ft_val & 1) == 0) + target = pc + 4 + offset; else target = pc + 8; @@ -3748,39 +2444,33 @@ } bool -EmulateInstructionMIPS::Emulate_BC1ANY4F (llvm::MCInst& insn) +EmulateInstructionMIPS::Emulate_BC1NEZ (llvm::MCInst& insn) { bool success = false; - uint32_t cc, fcsr; + uint32_t ft; + uint32_t ft_val; int32_t target, pc, offset; /* - * BC1ANY4F cc, offset - * condition <- (FPConditionCode(cc) == 0 - * || FPConditionCode(cc+1) == 0) - * || FPConditionCode(cc+2) == 0) - * || FPConditionCode(cc+3) == 0) + * BC1NEZ ft, offset + * condition <- (FPR[ft].bit0 != 0) * if condition then * offset = sign_ext (offset) - * PC = PC + offset + * PC = PC + 4 + offset */ - cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); offset = insn.getOperand(1).getImm(); pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); if (!success) return false; - fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success); + ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + ft, 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; + if ((ft_val & 1) != 0) + target = pc + 4 + offset; else target = pc + 8; @@ -3792,23 +2482,19 @@ return true; } +/* + Emulate MIPS-3D Branch instructions + BC1ANY2F, BC1ANY2T : Branch on Any of Two Floating Point Condition Codes False/True + BC1ANY4F, BC1ANY4T : Branch on Any of Four Floating Point Condition Codes False/True +*/ bool -EmulateInstructionMIPS::Emulate_BC1ANY4T (llvm::MCInst& insn) +EmulateInstructionMIPS::Emulate_3D_branch (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 - */ + const char *op_name = m_insn_info->getName (insn.getOpcode ()); + cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); offset = insn.getOperand(1).getImm(); @@ -3823,12 +2509,38 @@ /* 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; - + if (!strcasecmp (op_name, "BC1ANY2F")) + { + /* if any one bit is 0 */ + if (((fcsr >> cc) & 3) != 3) + target = pc + offset; + else + target = pc + 8; + } + else if (!strcasecmp (op_name, "BC1ANY2T")) + { + /* if any one bit is 1 */ + if (((fcsr >> cc) & 3) != 0) + target = pc + offset; + else + target = pc + 8; + } + else if (!strcasecmp (op_name, "BC1ANY4F")) + { + /* if any one bit is 0 */ + if (((fcsr >> cc) & 0xf) != 0xf) + target = pc + offset; + else + target = pc + 8; + } + else if (!strcasecmp (op_name, "BC1ANY4T")) + { + /* if any one bit is 1 */ + if (((fcsr >> cc) & 0xf) != 0) + target = pc + offset; + else + target = pc + 8; + } Context context; if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))