23 #include "llvm-c/Disassembler.h"
24 #include "llvm/MC/MCAsmInfo.h"
25 #include "llvm/MC/MCContext.h"
26 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
27 #include "llvm/MC/MCInst.h"
28 #include "llvm/MC/MCInstrInfo.h"
29 #include "llvm/MC/MCRegisterInfo.h"
30 #include "llvm/MC/MCSubtargetInfo.h"
31 #include "llvm/MC/MCTargetOptions.h"
32 #include "llvm/MC/TargetRegistry.h"
33 #include "llvm/Support/TargetSelect.h"
35 #include "llvm/ADT/STLExtras.h"
45 #define UInt(x) ((uint64_t)x)
46 #define integer int64_t
54 void LLVMInitializeMipsTargetInfo();
55 void LLVMInitializeMipsTarget();
56 void LLVMInitializeMipsAsmPrinter();
57 void LLVMInitializeMipsTargetMC();
58 void LLVMInitializeMipsDisassembler();
68 const llvm::Target *target =
69 llvm::TargetRegistry::lookupTarget(triple.getTriple(),
Status);
81 LLVMInitializeMipsTargetInfo();
82 LLVMInitializeMipsTarget();
83 LLVMInitializeMipsAsmPrinter();
84 LLVMInitializeMipsTargetMC();
85 LLVMInitializeMipsDisassembler();
86 target = llvm::TargetRegistry::lookupTarget(triple.getTriple(),
Status);
95 case ArchSpec::eCore_mips32:
96 case ArchSpec::eCore_mips32el:
99 case ArchSpec::eCore_mips32r2:
100 case ArchSpec::eCore_mips32r2el:
103 case ArchSpec::eCore_mips32r3:
104 case ArchSpec::eCore_mips32r3el:
107 case ArchSpec::eCore_mips32r5:
108 case ArchSpec::eCore_mips32r5el:
111 case ArchSpec::eCore_mips32r6:
112 case ArchSpec::eCore_mips32r6el:
115 case ArchSpec::eCore_mips64:
116 case ArchSpec::eCore_mips64el:
119 case ArchSpec::eCore_mips64r2:
120 case ArchSpec::eCore_mips64r2el:
123 case ArchSpec::eCore_mips64r3:
124 case ArchSpec::eCore_mips64r3el:
127 case ArchSpec::eCore_mips64r5:
128 case ArchSpec::eCore_mips64r5el:
131 case ArchSpec::eCore_mips64r6:
132 case ArchSpec::eCore_mips64r6el:
142 if (arch_flags & ArchSpec::eMIPSAse_msa)
144 if (arch_flags & ArchSpec::eMIPSAse_dsp)
146 if (arch_flags & ArchSpec::eMIPSAse_dspr2)
147 features +=
"+dspr2,";
148 if (arch_flags & ArchSpec::eMIPSAse_mips16)
149 features +=
"+mips16,";
150 if (arch_flags & ArchSpec::eMIPSAse_micromips)
151 features +=
"+micromips,";
153 m_reg_info.reset(target->createMCRegInfo(triple.getTriple()));
159 llvm::MCTargetOptions MCOptions;
161 target->createMCAsmInfo(*
m_reg_info, triple.getTriple(), MCOptions));
163 target->createMCSubtargetInfo(triple.getTriple(), cpu, features));
166 m_context = std::make_unique<llvm::MCContext>(
184 return "Emulate instructions for the MIPS64 architecture.";
192 if (arch.
GetTriple().getArch() == llvm::Triple::mips64 ||
193 arch.
GetTriple().getArch() == llvm::Triple::mips64el) {
202 return arch.
GetTriple().getArch() == llvm::Triple::mips64 ||
203 arch.
GetTriple().getArch() == llvm::Triple::mips64el;
207 bool alternate_name) {
208 if (alternate_name) {
577 RegisterInfo ®_info) {
606 ::memset(®_info, 0,
sizeof(RegisterInfo));
612 reg_info.byte_size = 4;
617 reg_info.byte_size = 8;
622 reg_info.byte_size = 16;
662 "DADDIU rt, rs, immediate"},
664 "ADDIU rt, rs, immediate"},
686 "LB rt, offset(base)"},
688 "LBE rt, offset(base)"},
690 "LBU rt, offset(base)"},
692 "LBUE rt, offset(base)"},
694 "LDC1 ft, offset(base)"},
696 "LDL rt, offset(base)"},
698 "LDR rt, offset(base)"},
700 "LLD rt, offset(base)"},
702 "LDC2 rt, offset(base)"},
704 "LDXC1 fd, index (base)"},
706 "LH rt, offset(base)"},
708 "LHE rt, offset(base)"},
710 "LHU rt, offset(base)"},
712 "LHUE rt, offset(base)"},
714 "LL rt, offset(base)"},
716 "LLE rt, offset(base)"},
718 "LUXC1 fd, index (base)"},
720 "LW rt, offset(rs)"},
722 "LWC1 ft, offset(base)"},
724 "LWC2 rt, offset(base)"},
726 "LWE rt, offset(base)"},
728 "LWL rt, offset(base)"},
730 "LWLE rt, offset(base)"},
732 "LWR rt, offset(base)"},
734 "LWRE rt, offset(base)"},
736 "LWXC1 fd, index (base)"},
739 "SB rt, offset(base)"},
741 "SBE rt, offset(base)"},
743 "SC rt, offset(base)"},
745 "SCE rt, offset(base)"},
747 "SCD rt, offset(base)"},
749 "SDL rt, offset(base)"},
751 "SDR rt, offset(base)"},
753 "SDC1 ft, offset(base)"},
755 "SDC2 rt, offset(base)"},
757 "SDXC1 fs, index (base)"},
759 "SH rt, offset(base)"},
761 "SHE rt, offset(base)"},
763 "SUXC1 fs, index (base)"},
765 "SW rt, offset(rs)"},
767 "SWC1 ft, offset(base)"},
769 "SWC2 rt, offset(base)"},
771 "SWE rt, offset(base)"},
773 "SWL rt, offset(base)"},
775 "SWLE rt, offset(base)"},
777 "SWR rt, offset(base)"},
779 "SWRE rt, offset(base)"},
781 "SWXC1 fs, index (base)"},
789 "BEQL rs,rt,offset"},
791 "BNEL rs,rt,offset"},
793 "BGEZALL rt,offset"},
802 "BLEZALC rs,offset"},
804 "BGEZALC rs,offset"},
806 "BLTZALC rs,offset"},
808 "BGTZALC rs,offset"},
810 "BEQZALC rs,offset"},
812 "BNEZALC rs,offset"},
814 "BEQC rs,rt,offset"},
816 "BEQC rs,rt,offset"},
818 "BNEC rs,rt,offset"},
820 "BNEC rs,rt,offset"},
822 "BLTC rs,rt,offset"},
824 "BLTC rs,rt,offset"},
826 "BGEC rs,rt,offset"},
828 "BGEC rs,rt,offset"},
830 "BLTUC rs,rt,offset"},
832 "BLTUC rs,rt,offset"},
834 "BGEUC rs,rt,offset"},
836 "BGEUC rs,rt,offset"},
873 "BLTZALL rt,offset"},
876 "BOVC rs,rt,offset"},
878 "BNVC rs,rt,offset"},
899 "BC1EQZ ft, offset"},
901 "BC1NEZ ft, offset"},
903 "BC1ANY2F cc, offset"},
905 "BC1ANY2T cc, offset"},
907 "BC1ANY4F cc, offset"},
909 "BC1ANY4T cc, offset"},
923 if (op_name.equals_insensitive(opcode.op_name))
930 bool success =
false;
947 bool success =
false;
948 llvm::MCInst mc_insn;
955 llvm::MCDisassembler::DecodeStatus decode_status;
957 decode_status =
m_disasm->getInstruction(mc_insn, insn_size, raw_insn,
959 if (decode_status != llvm::MCDisassembler::Success)
967 llvm::StringRef op_name =
m_insn_info->getName(mc_insn.getOpcode());
975 if (opcode_data ==
nullptr)
978 uint64_t old_pc = 0, new_pc = 0;
979 const bool auto_advance_pc =
980 evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
982 if (auto_advance_pc) {
990 success = (this->*opcode_data->
callback)(mc_insn);
994 if (auto_advance_pc) {
1001 if (old_pc == new_pc) {
1015 unwind_plan.
Clear();
1019 const bool can_replace =
false;
1066 bool success =
false;
1067 const uint32_t imm16 = insn.getOperand(2).getImm();
1070 dst =
m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1071 src =
m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1099 uint64_t result = src_opd_val + imm;
1100 RegisterInfo reg_info_sp;
1127 RegisterInfo reg_info_base;
1128 RegisterInfo reg_info_src;
1129 bool success =
false;
1130 uint32_t imm16 = insn.getOperand(2).getImm();
1135 src =
m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1136 base =
m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1151 address = address + imm;
1160 uint8_t buffer[RegisterValue::kMaxRegisterByteSize];
1166 if (data_src.
GetAsMemoryData(®_info_src, buffer, reg_info_src.byte_size,
1170 if (!
WriteMemory(context, address, buffer, reg_info_src.byte_size))
1183 bool success =
false;
1185 int64_t imm, address;
1188 src =
m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1189 base =
m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1190 imm = insn.getOperand(2).getImm();
1192 RegisterInfo reg_info_base;
1204 address = address + imm;
1213 RegisterInfo reg_info_src;
1232 const uint32_t imm32 = insn.getOperand(1).getImm() << 16;
1237 rt =
m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1250 bool success =
false;
1252 uint8_t src, dst, rt;
1253 llvm::StringRef op_name =
m_insn_info->getName(insn.getOpcode());
1255 dst =
m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1256 src =
m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1260 rt =
m_reg_info->getEncodingValue(insn.getOperand(2).getReg());
1274 if (op_name.equals_insensitive(
"DSUBU") ||
1275 op_name.equals_insensitive(
"SUBU"))
1276 result = src_opd_val - rt_opd_val;
1278 result = src_opd_val + rt_opd_val;
1281 RegisterInfo reg_info_sp;
1292 rt =
m_reg_info->getEncodingValue(insn.getOperand(2).getReg());
1308 if (op_name.equals_insensitive(
"DSUBU") ||
1309 op_name.equals_insensitive(
"SUBU"))
1310 result = src_opd_val - rt_opd_val;
1312 result = src_opd_val + rt_opd_val;
1331 bool success =
false;
1333 int64_t offset,
pc, rs_val, rt_val, target = 0;
1334 llvm::StringRef op_name =
m_insn_info->getName(insn.getOpcode());
1336 rs =
m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1337 rt =
m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1338 offset = insn.getOperand(2).getImm();
1354 if (op_name.equals_insensitive(
"BEQ") || op_name.equals_insensitive(
"BEQL") ||
1355 op_name.equals_insensitive(
"BEQ64")) {
1356 if (rs_val == rt_val)
1357 target =
pc + offset;
1360 }
else if (op_name.equals_insensitive(
"BNE") ||
1361 op_name.equals_insensitive(
"BNEL") ||
1362 op_name.equals_insensitive(
"BNE64")) {
1363 if (rs_val != rt_val)
1364 target =
pc + offset;
1383 bool success =
false;
1385 int64_t offset,
pc, target = 0;
1387 llvm::StringRef op_name =
m_insn_info->getName(insn.getOpcode());
1389 rs =
m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1390 offset = insn.getOperand(1).getImm();
1401 if (op_name.equals_insensitive(
"BLTZAL") ||
1402 op_name.equals_insensitive(
"BLTZALL")) {
1404 target =
pc + offset;
1407 }
else if (op_name.equals_insensitive(
"BGEZAL") ||
1408 op_name.equals_insensitive(
"BGEZALL")) {
1410 target =
pc + offset;
1429 bool success =
false;
1430 int64_t offset,
pc, target;
1438 offset = insn.getOperand(0).getImm();
1444 target =
pc + offset;
1460 bool success =
false;
1461 int64_t offset,
pc, target;
1469 offset = insn.getOperand(0).getImm();
1475 target =
pc + offset;
1495 bool success =
false;
1497 int64_t offset,
pc, rs_val, target = 0;
1498 llvm::StringRef op_name =
m_insn_info->getName(insn.getOpcode());
1500 rs =
m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1501 offset = insn.getOperand(1).getImm();
1512 if (op_name.equals_insensitive(
"BLEZALC")) {
1514 target =
pc + offset;
1517 }
else if (op_name.equals_insensitive(
"BGEZALC")) {
1519 target =
pc + offset;
1522 }
else if (op_name.equals_insensitive(
"BLTZALC")) {
1524 target =
pc + offset;
1527 }
else if (op_name.equals_insensitive(
"BGTZALC")) {
1529 target =
pc + offset;
1532 }
else if (op_name.equals_insensitive(
"BEQZALC")) {
1534 target =
pc + offset;
1537 }
else if (op_name.equals_insensitive(
"BNEZALC")) {
1539 target =
pc + offset;
1563 bool success =
false;
1565 int64_t offset,
pc, rs_val, target = 0;
1566 llvm::StringRef op_name =
m_insn_info->getName(insn.getOpcode());
1568 rs =
m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1569 offset = insn.getOperand(1).getImm();
1580 if (op_name.equals_insensitive(
"BLTZL") ||
1581 op_name.equals_insensitive(
"BLTZ") ||
1582 op_name.equals_insensitive(
"BLTZ64")) {
1584 target =
pc + offset;
1587 }
else if (op_name.equals_insensitive(
"BGEZL") ||
1588 op_name.equals_insensitive(
"BGEZ") ||
1589 op_name.equals_insensitive(
"BGEZ64")) {
1591 target =
pc + offset;
1594 }
else if (op_name.equals_insensitive(
"BGTZL") ||
1595 op_name.equals_insensitive(
"BGTZ") ||
1596 op_name.equals_insensitive(
"BGTZ64")) {
1598 target =
pc + offset;
1601 }
else if (op_name.equals_insensitive(
"BLEZL") ||
1602 op_name.equals_insensitive(
"BLEZ") ||
1603 op_name.equals_insensitive(
"BLEZ64")) {
1605 target =
pc + offset;
1619 bool success =
false;
1620 int64_t offset,
pc, target;
1627 offset = insn.getOperand(0).getImm();
1633 target =
pc + offset;
1642 int64_t r = (uint64_t)a + (uint64_t)b;
1643 return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0);
1652 bool success =
false;
1654 int64_t offset,
pc, rs_val, rt_val, target = 0;
1655 llvm::StringRef op_name =
m_insn_info->getName(insn.getOpcode());
1658 rs =
m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1659 rt =
m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1660 offset = insn.getOperand(2).getImm();
1676 if (op_name.equals_insensitive(
"BEQC") ||
1677 op_name.equals_insensitive(
"BEQC64")) {
1678 if (rs_val == rt_val)
1679 target =
pc + offset;
1682 }
else if (op_name.equals_insensitive(
"BNEC") ||
1683 op_name.equals_insensitive(
"BNEC64")) {
1684 if (rs_val != rt_val)
1685 target =
pc + offset;
1688 }
else if (op_name.equals_insensitive(
"BLTC") ||
1689 op_name.equals_insensitive(
"BLTC64")) {
1690 if (rs_val < rt_val)
1691 target =
pc + offset;
1694 }
else if (op_name.equals_insensitive(
"BGEC64") ||
1695 op_name.equals_insensitive(
"BGEC")) {
1696 if (rs_val >= rt_val)
1697 target =
pc + offset;
1700 }
else if (op_name.equals_insensitive(
"BLTUC") ||
1701 op_name.equals_insensitive(
"BLTUC64")) {
1702 if (rs_val < rt_val)
1703 target =
pc + offset;
1706 }
else if (op_name.equals_insensitive(
"BGEUC") ||
1707 op_name.equals_insensitive(
"BGEUC64")) {
1709 target =
pc + offset;
1712 }
else if (op_name.equals_insensitive(
"BOVC")) {
1714 target =
pc + offset;
1717 }
else if (op_name.equals_insensitive(
"BNVC")) {
1719 target =
pc + offset;
1737 bool success =
false;
1739 int64_t offset,
pc, target = 0;
1741 llvm::StringRef op_name =
m_insn_info->getName(insn.getOpcode());
1744 rs =
m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1745 offset = insn.getOperand(1).getImm();
1756 if (op_name.equals_insensitive(
"BLTZC") ||
1757 op_name.equals_insensitive(
"BLTZC64")) {
1759 target =
pc + offset;
1762 }
else if (op_name.equals_insensitive(
"BLEZC") ||
1763 op_name.equals_insensitive(
"BLEZC64")) {
1765 target =
pc + offset;
1768 }
else if (op_name.equals_insensitive(
"BGEZC") ||
1769 op_name.equals_insensitive(
"BGEZC64")) {
1771 target =
pc + offset;
1774 }
else if (op_name.equals_insensitive(
"BGTZC") ||
1775 op_name.equals_insensitive(
"BGTZC64")) {
1777 target =
pc + offset;
1780 }
else if (op_name.equals_insensitive(
"BEQZC") ||
1781 op_name.equals_insensitive(
"BEQZC64")) {
1783 target =
pc + offset;
1786 }
else if (op_name.equals_insensitive(
"BNEZC") ||
1787 op_name.equals_insensitive(
"BNEZC64")) {
1789 target =
pc + offset;
1803 bool success =
false;
1804 uint64_t offset,
pc;
1811 offset = insn.getOperand(0).getImm();
1818 pc = (
pc & 0xFFFFFFFFF0000000ULL) | offset;
1827 bool success =
false;
1828 uint64_t offset, target,
pc;
1835 offset = insn.getOperand(0).getImm();
1842 target = (
pc & 0xFFFFFFFFF0000000ULL) | offset;
1858 bool success =
false;
1860 uint64_t
pc, rs_val;
1867 rt =
m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1868 rs =
m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1893 bool success =
false;
1895 int64_t target, offset,
pc, rt_val;
1903 rt =
m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1904 offset = insn.getOperand(1).getImm();
1915 target = rt_val + offset;
1931 bool success =
false;
1933 int64_t target, offset, rt_val;
1940 rt =
m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1941 offset = insn.getOperand(1).getImm();
1948 target = rt_val + offset;
1957 bool success =
false;
1965 rs =
m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1984 bool success =
false;
1986 int64_t
pc, offset, target = 0;
1987 llvm::StringRef op_name =
m_insn_info->getName(insn.getOpcode());
1996 cc =
m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1997 offset = insn.getOperand(1).getImm();
2009 fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
2011 if (op_name.equals_insensitive(
"BC1F") ||
2012 op_name.equals_insensitive(
"BC1FL")) {
2013 if ((fcsr & (1 << cc)) == 0)
2014 target =
pc + offset;
2017 }
else if (op_name.equals_insensitive(
"BC1T") ||
2018 op_name.equals_insensitive(
"BC1TL")) {
2019 if ((fcsr & (1 << cc)) != 0)
2020 target =
pc + offset;
2032 bool success =
false;
2035 int64_t target,
pc, offset;
2044 ft =
m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2045 offset = insn.getOperand(1).getImm();
2056 if ((ft_val & 1) == 0)
2057 target =
pc + 4 + offset;
2068 bool success =
false;
2071 int64_t target,
pc, offset;
2080 ft =
m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2081 offset = insn.getOperand(1).getImm();
2092 if ((ft_val & 1) != 0)
2093 target =
pc + 4 + offset;
2111 bool success =
false;
2113 int64_t
pc, offset, target = 0;
2114 llvm::StringRef op_name =
m_insn_info->getName(insn.getOpcode());
2116 cc =
m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2117 offset = insn.getOperand(1).getImm();
2129 fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
2131 if (op_name.equals_insensitive(
"BC1ANY2F")) {
2133 if (((fcsr >> cc) & 3) != 3)
2134 target =
pc + offset;
2137 }
else if (op_name.equals_insensitive(
"BC1ANY2T")) {
2139 if (((fcsr >> cc) & 3) != 0)
2140 target =
pc + offset;
2143 }
else if (op_name.equals_insensitive(
"BC1ANY4F")) {
2145 if (((fcsr >> cc) & 0xf) != 0xf)
2146 target =
pc + offset;
2149 }
else if (op_name.equals_insensitive(
"BC1ANY4T")) {
2151 if (((fcsr >> cc) & 0xf) != 0)
2152 target =
pc + offset;
2196 int element_byte_size,
2198 bool success =
false, branch_hit =
true;
2201 const uint8_t *ptr =
nullptr;
2204 int64_t offset = insn.getOperand(1).getImm();
2212 ptr = (
const uint8_t *)reg_value.
GetBytes();
2216 for (
int i = 0; i < 16 / element_byte_size; i++) {
2217 switch (element_byte_size) {
2219 if ((*ptr == 0 && bnz) || (*ptr != 0 && !bnz))
2223 if ((*(
const uint16_t *)ptr == 0 && bnz) ||
2224 (*(
const uint16_t *)ptr != 0 && !bnz))
2228 if ((*(
const uint32_t *)ptr == 0 && bnz) ||
2229 (*(
const uint32_t *)ptr != 0 && !bnz))
2233 if ((*(
const uint64_t *)ptr == 0 && bnz) ||
2234 (*(
const uint64_t *)ptr != 0 && !bnz))
2240 ptr = ptr + element_byte_size;
2244 target =
pc + offset;
2265 bool success =
false;
2267 llvm::APInt wr_val = llvm::APInt::getZero(128);
2268 llvm::APInt fail_value = llvm::APInt::getMaxValue(128);
2269 llvm::APInt zero_value = llvm::APInt::getZero(128);
2273 int64_t offset = insn.getOperand(1).getImm();
2285 if ((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) ||
2286 (!llvm::APInt::isSameValue(zero_value, wr_val) && bnz))
2287 target =
pc + offset;
2299 bool success =
false;
2301 int64_t imm, address;
2304 uint32_t num_operands = insn.getNumOperands();
2306 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
2307 imm = insn.getOperand(num_operands - 1).getImm();
2309 RegisterInfo reg_info_base;
2321 address = address + imm;
2332 bool success =
false;
2334 int64_t address, index_address;
2337 uint32_t num_operands = insn.getNumOperands();
2339 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
2341 m_reg_info->getEncodingValue(insn.getOperand(num_operands - 1).getReg());
2343 RegisterInfo reg_info_base, reg_info_index;
2365 address = address + index_address;