Index: source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h =================================================================== --- source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h +++ source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h @@ -127,6 +127,12 @@ Emulate_ADDiu (llvm::MCInst& insn); bool + Emulate_SUBU_ADDU (llvm::MCInst& insn); + + bool + Emulate_LUI (llvm::MCInst& insn); + + bool Emulate_SW (llvm::MCInst& insn); bool Index: source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp =================================================================== --- source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp +++ source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp @@ -494,9 +494,13 @@ //---------------------------------------------------------------------- // Prologue/Epilogue instructions //---------------------------------------------------------------------- - { "ADDiu", &EmulateInstructionMIPS::Emulate_ADDiu, "ADDIU rt,rs,immediate" }, - { "SW", &EmulateInstructionMIPS::Emulate_SW, "SW rt,offset(rs)" }, - { "LW", &EmulateInstructionMIPS::Emulate_LW, "LW rt,offset(base)" }, + { "ADDiu", &EmulateInstructionMIPS::Emulate_ADDiu, "ADDIU rt, rs, immediate" }, + { "SW", &EmulateInstructionMIPS::Emulate_SW, "SW rt, offset(rs)" }, + { "LW", &EmulateInstructionMIPS::Emulate_LW, "LW rt, offset(base)" }, + { "SUBU", &EmulateInstructionMIPS::Emulate_SUBU_ADDU, "SUBU rd, rs, rt" }, + { "ADDU", &EmulateInstructionMIPS::Emulate_SUBU_ADDU, "ADDU rd, rs, rt" }, + { "LUI", &EmulateInstructionMIPS::Emulate_LUI, "LUI rt, immediate" }, + //---------------------------------------------------------------------- // MicroMIPS Prologue/Epilogue instructions //---------------------------------------------------------------------- @@ -904,36 +908,57 @@ bool EmulateInstructionMIPS::Emulate_ADDiu (llvm::MCInst& insn) { + // ADDIU rt, rs, immediate + // GPR[rt] <- GPR[rs] + sign_extend(immediate) + + uint8_t dst, src; bool success = false; const uint32_t imm16 = insn.getOperand(2).getImm(); - uint32_t imm = SignedBits(imm16, 15, 0); - uint64_t result; - uint32_t src, dst; + int64_t imm = SignedBits(imm16, 15, 0); dst = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); src = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); - /* Check if this is addiu sp,,imm16 */ - if (dst == dwarf_sp_mips) + // If immediate value is greater then 2^16 - 1 then clang generate + // LUI, ADDIU, SUBU instructions in prolog. + // Example + // lui $1, 0x2 + // addiu $1, $1, -0x5920 + // subu $sp, $sp, $1 + // In this case, ADDIU dst and src will be same and not equal to sp + if (dst == src) { + Context context; + /* read register */ - uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success); + const int64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success); if (!success) return false; - result = src_opd_val + imm; + /* Check if this is daddiu sp, sp, imm16 */ + if (dst == dwarf_sp_mips) + { + uint64_t result = src_opd_val + imm; + RegisterInfo reg_info_sp; - Context context; - RegisterInfo reg_info_sp; - if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp)) - context.SetRegisterPlusOffset (reg_info_sp, imm); + if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp)) + context.SetRegisterPlusOffset (reg_info_sp, imm); - /* We are allocating bytes on stack */ - context.type = eContextAdjustStackPointer; + /* We are allocating bytes on stack */ + context.type = eContextAdjustStackPointer; - WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips, result); + WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips, result); + return true; + } + + imm += src_opd_val; + context.SetImmediateSigned (imm); + context.type = eContextImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips + dst, imm)) + return false; } - + return true; } @@ -968,7 +993,7 @@ WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address); /* We look for sp based non-volatile register stores */ - if (base == dwarf_sp_mips && nonvolatile_reg_p (src)) + if (nonvolatile_reg_p (src)) { RegisterInfo reg_info_src; @@ -1027,7 +1052,7 @@ bad_vaddr_context.type = eContextInvalid; WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address); - if (base == dwarf_sp_mips && nonvolatile_reg_p (src)) + if (nonvolatile_reg_p (src)) { RegisterValue data_src; RegisterInfo reg_info_src; @@ -1049,6 +1074,105 @@ } bool +EmulateInstructionMIPS::Emulate_SUBU_ADDU (llvm::MCInst& insn) +{ + // SUBU sp, , + // ADDU sp, , + // ADDU dst, sp, + + bool success = false; + uint64_t result; + uint8_t src, dst, rt; + const char *op_name = m_insn_info->getName (insn.getOpcode ()); + + dst = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + src = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); + + /* Check if sp is destination register */ + if (dst == dwarf_sp_mips) + { + rt = m_reg_info->getEncodingValue (insn.getOperand(2).getReg()); + + /* read register */ + uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success); + if (!success) + return false; + + /* read register */ + uint64_t rt_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success); + if (!success) + return false; + + if (!strcasecmp (op_name, "SUBU")) + result = src_opd_val - rt_opd_val; + else + result = src_opd_val + rt_opd_val; + + Context context; + RegisterInfo reg_info_sp; + if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp)) + context.SetRegisterPlusOffset (reg_info_sp, rt_opd_val); + + /* We are allocating bytes on stack */ + context.type = eContextAdjustStackPointer; + + WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips, result); + + return true; + } + else if (src == dwarf_sp_mips) + { + rt = m_reg_info->getEncodingValue (insn.getOperand(2).getReg()); + + /* read register */ + uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success); + if (!success) + return false; + + /* read register */ + uint64_t rt_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success); + if (!success) + return false; + + Context context; + + if (!strcasecmp (op_name, "SUBU")) + result = src_opd_val - rt_opd_val; + else + result = src_opd_val + rt_opd_val; + + context.SetImmediateSigned (result); + context.type = eContextImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips + dst, result)) + return false; + } + + return true; +} + +bool +EmulateInstructionMIPS::Emulate_LUI (llvm::MCInst& insn) +{ + // LUI rt, immediate + // GPR[rt] <- sign_extend(immediate << 16) + + const uint32_t imm32 = insn.getOperand(1).getImm() << 16; + int64_t imm = SignedBits(imm32, 31, 0); + uint8_t rt; + Context context; + + rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + context.SetImmediateSigned (imm); + context.type = eContextImmediate; + + if (WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips + rt, imm)) + return true; + + return false; +} + +bool EmulateInstructionMIPS::Emulate_ADDIUSP (llvm::MCInst& insn) { bool success = false; Index: source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h =================================================================== --- source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h +++ source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h @@ -121,6 +121,12 @@ Emulate_DADDiu (llvm::MCInst& insn); bool + Emulate_DSUBU_DADDU (llvm::MCInst& insn); + + bool + Emulate_LUI (llvm::MCInst& insn); + + bool Emulate_SD (llvm::MCInst& insn); bool Index: source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp =================================================================== --- source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp +++ source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp @@ -482,10 +482,15 @@ //---------------------------------------------------------------------- // Prologue/Epilogue instructions //---------------------------------------------------------------------- - { "DADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu, "DADDIU rt,rs,immediate" }, - { "ADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu, "ADDIU rt,rs,immediate" }, - { "SD", &EmulateInstructionMIPS64::Emulate_SD, "SD rt,offset(rs)" }, - { "LD", &EmulateInstructionMIPS64::Emulate_LD, "LD rt,offset(base)" }, + { "DADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu, "DADDIU rt, rs, immediate" }, + { "ADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu, "ADDIU rt, rs, immediate" }, + { "SD", &EmulateInstructionMIPS64::Emulate_SD, "SD rt, offset(rs)" }, + { "LD", &EmulateInstructionMIPS64::Emulate_LD, "LD rt, offset(base)" }, + { "DSUBU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU, "DSUBU rd, rs, rt" }, + { "SUBU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU, "SUBU rd, rs, rt" }, + { "DADDU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU, "DADDU rd, rs, rt" }, + { "ADDU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU, "ADDU rd, rs, rt" }, + { "LUI", &EmulateInstructionMIPS64::Emulate_LUI, "LUI rt, immediate" }, @@ -771,36 +776,57 @@ bool EmulateInstructionMIPS64::Emulate_DADDiu (llvm::MCInst& insn) { + // DADDIU rt, rs, immediate + // GPR[rt] <- GPR[rs] + sign_extend(immediate) + + uint8_t dst, src; bool success = false; const uint32_t imm16 = insn.getOperand(2).getImm(); - uint64_t imm = SignedBits(imm16, 15, 0); - uint64_t result; - uint32_t src, dst; + int64_t imm = SignedBits(imm16, 15, 0); dst = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); src = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); - /* Check if this is daddiu sp,,imm16 */ - if (dst == dwarf_sp_mips64) + // If immediate is greater than 2^16 - 1 then clang generate + // LUI, (D)ADDIU,(D)SUBU instructions in prolog. + // Example + // lui $1, 0x2 + // daddiu $1, $1, -0x5920 + // dsubu $sp, $sp, $1 + // In this case, (D)ADDIU dst and src will be same and not equal to sp + if (dst == src) { + Context context; + /* read register */ - uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success); + const int64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success); if (!success) return false; - result = src_opd_val + imm; + /* Check if this is daddiu sp, sp, imm16 */ + if (dst == dwarf_sp_mips64) + { + uint64_t result = src_opd_val + imm; + RegisterInfo reg_info_sp; - Context context; - RegisterInfo reg_info_sp; - if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips64, reg_info_sp)) - context.SetRegisterPlusOffset (reg_info_sp, imm); + if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips64, reg_info_sp)) + context.SetRegisterPlusOffset (reg_info_sp, imm); - /* We are allocating bytes on stack */ - context.type = eContextAdjustStackPointer; + /* We are allocating bytes on stack */ + context.type = eContextAdjustStackPointer; - WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips64, result); + WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips64, result); + return true; + } + + imm += src_opd_val; + context.SetImmediateSigned (imm); + context.type = eContextImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips64 + dst, imm)) + return false; } - + return true; } @@ -832,7 +858,7 @@ address = address + imm; /* We look for sp based non-volatile register stores */ - if (base == dwarf_sp_mips64 && nonvolatile_reg_p (src)) + if (nonvolatile_reg_p (src)) { Context context; RegisterValue data_src; @@ -888,7 +914,7 @@ WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64, address); - if (base == dwarf_sp_mips64 && nonvolatile_reg_p (src)) + if (nonvolatile_reg_p (src)) { RegisterValue data_src; RegisterInfo reg_info_src; @@ -908,6 +934,104 @@ return false; } +bool +EmulateInstructionMIPS64::Emulate_LUI (llvm::MCInst& insn) +{ + // LUI rt, immediate + // GPR[rt] <- sign_extend(immediate << 16) + + const uint32_t imm32 = insn.getOperand(1).getImm() << 16; + int64_t imm = SignedBits(imm32, 31, 0); + uint8_t rt; + Context context; + + rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + context.SetImmediateSigned (imm); + context.type = eContextImmediate; + + if (WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips64 + rt, imm)) + return true; + + return false; +} + +bool +EmulateInstructionMIPS64::Emulate_DSUBU_DADDU (llvm::MCInst& insn) +{ + // DSUBU sp, , + // DADDU sp, , + // DADDU dst, sp, + + bool success = false; + uint64_t result; + uint8_t src, dst, rt; + const char *op_name = m_insn_info->getName (insn.getOpcode ()); + + dst = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + src = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); + + /* Check if sp is destination register */ + if (dst == dwarf_sp_mips64) + { + rt = m_reg_info->getEncodingValue (insn.getOperand(2).getReg()); + + /* read register */ + uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success); + if (!success) + return false; + + /* read register */ + uint64_t rt_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success); + if (!success) + return false; + + if (!strcasecmp (op_name, "DSUBU") || !strcasecmp (op_name, "SUBU")) + result = src_opd_val - rt_opd_val; + else + result = src_opd_val + rt_opd_val; + + Context context; + RegisterInfo reg_info_sp; + if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips64, reg_info_sp)) + context.SetRegisterPlusOffset (reg_info_sp, rt_opd_val); + + /* We are allocating bytes on stack */ + context.type = eContextAdjustStackPointer; + + WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips64, result); + + return true; + } + else if (src == dwarf_sp_mips64) + { + rt = m_reg_info->getEncodingValue (insn.getOperand(2).getReg()); + + /* read register */ + uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success); + if (!success) + return false; + + /* read register */ + uint64_t rt_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success); + if (!success) + return false; + + Context context; + + if (!strcasecmp (op_name, "DSUBU") || !strcasecmp (op_name, "SUBU")) + result = src_opd_val - rt_opd_val; + else + result = src_opd_val + rt_opd_val; + + context.SetImmediateSigned (result); + context.type = eContextImmediate; + + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips64 + dst, result)) + return false; + } + + return true; +} /* Emulate below MIPS branch instructions.