mirror of
https://github.com/hedge-dev/XenonRecomp.git
synced 2025-06-06 18:31:03 +00:00
3162 lines
109 KiB
Diff
3162 lines
109 KiB
Diff
![]() |
From 3373228170bbc2324d223bdeca761de3b4565508 Mon Sep 17 00:00:00 2001
|
||
|
From: fanfuqiang <feqin1023@gmail.com>
|
||
|
Date: Sun, 17 Feb 2019 06:08:44 +0800
|
||
|
Subject: [PATCH] capstone riscv patchs
|
||
|
|
||
|
---
|
||
|
...apstone-generate-GenRegisterInfo.inc.patch | 338 +++++++++++++
|
||
|
...pstone-generate-GenSubtargetInfo.inc.patch | 86 ++++
|
||
|
...3-capstone-generate-GenInstrInfo.inc.patch | 130 +++++
|
||
|
...e-generate-GenDisassemblerTables.inc.patch | 472 ++++++++++++++++++
|
||
|
...5-capstone-generate-GenAsmWriter.inc.patch | 225 +++++++++
|
||
|
...06-capstone-generate-MappingInsn.inc.patch | 174 +++++++
|
||
|
...apstone-generate-GenInsnNameMaps.inc.patch | 110 ++++
|
||
|
llvm/lib/Target/RISCV/CMakeLists.txt | 2 +
|
||
|
llvm/utils/TableGen/AsmWriterEmitter.cpp | 103 +++-
|
||
|
llvm/utils/TableGen/AsmWriterInst.cpp | 4 +
|
||
|
llvm/utils/TableGen/DisassemblerEmitter.cpp | 12 +-
|
||
|
.../utils/TableGen/FixedLenDecoderEmitter.cpp | 398 ++++++++++++++-
|
||
|
llvm/utils/TableGen/InstrInfoEmitter.cpp | 173 ++++++-
|
||
|
llvm/utils/TableGen/RegisterInfoEmitter.cpp | 130 ++++-
|
||
|
llvm/utils/TableGen/SubtargetEmitter.cpp | 28 +-
|
||
|
llvm/utils/TableGen/TableGen.cpp | 12 +
|
||
|
llvm/utils/TableGen/TableGenBackends.h | 2 +
|
||
|
17 files changed, 2349 insertions(+), 50 deletions(-)
|
||
|
create mode 100644 llvm/0001-capstone-generate-GenRegisterInfo.inc.patch
|
||
|
create mode 100644 llvm/0002-capstone-generate-GenSubtargetInfo.inc.patch
|
||
|
create mode 100644 llvm/0003-capstone-generate-GenInstrInfo.inc.patch
|
||
|
create mode 100644 llvm/0004-capstone-generate-GenDisassemblerTables.inc.patch
|
||
|
create mode 100644 llvm/0005-capstone-generate-GenAsmWriter.inc.patch
|
||
|
create mode 100644 llvm/0006-capstone-generate-MappingInsn.inc.patch
|
||
|
create mode 100644 llvm/0007-capstone-generate-GenInsnNameMaps.inc.patch
|
||
|
|
||
|
diff --git a/llvm/0001-capstone-generate-GenRegisterInfo.inc.patch b/llvm/0001-capstone-generate-GenRegisterInfo.inc.patch
|
||
|
new file mode 100644
|
||
|
index 000000000..b51aa515a
|
||
|
--- /dev/null
|
||
|
+++ b/llvm/0001-capstone-generate-GenRegisterInfo.inc.patch
|
||
|
@@ -0,0 +1,338 @@
|
||
|
+From 5d631cb16e7ba5dd0380ff1ee9dda192b1cdad18 Mon Sep 17 00:00:00 2001
|
||
|
+From: mephi42 <mephi42@gmail.com>
|
||
|
+Date: Tue, 7 Aug 2018 17:02:40 +0200
|
||
|
+Subject: [PATCH 1/7] capstone: generate *GenRegisterInfo.inc
|
||
|
+
|
||
|
+---
|
||
|
+ utils/TableGen/RegisterInfoEmitter.cpp | 130 ++++++++++++++++++++++---
|
||
|
+ 1 file changed, 115 insertions(+), 15 deletions(-)
|
||
|
+
|
||
|
+diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp
|
||
|
+index 49016cca799..6ebb7148b1b 100644
|
||
|
+--- a/utils/TableGen/RegisterInfoEmitter.cpp
|
||
|
++++ b/utils/TableGen/RegisterInfoEmitter.cpp
|
||
|
+@@ -99,6 +99,12 @@ private:
|
||
|
+
|
||
|
+ } // end anonymous namespace
|
||
|
+
|
||
|
++#ifdef CAPSTONE
|
||
|
++#define NAME_PREFIX Target.getName() << "_" <<
|
||
|
++#else
|
||
|
++#define NAME_PREFIX
|
||
|
++#endif
|
||
|
++
|
||
|
+ // runEnums - Print out enum values for all of the registers.
|
||
|
+ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
|
||
|
+ CodeGenTarget &Target, CodeGenRegBank &Bank) {
|
||
|
+@@ -107,13 +113,22 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
|
||
|
+ // Register enums are stored as uint16_t in the tables. Make sure we'll fit.
|
||
|
+ assert(Registers.size() <= 0xffff && "Too many regs to fit in tables");
|
||
|
+
|
||
|
++#ifndef CAPSTONE
|
||
|
+ StringRef Namespace = Registers.front().TheDef->getValueAsString("Namespace");
|
||
|
++#endif
|
||
|
+
|
||
|
+ emitSourceFileHeader("Target Register Enum Values", OS);
|
||
|
+
|
||
|
++#ifdef CAPSTONE
|
||
|
++ OS << "/* Capstone Disassembly Engine */\n"
|
||
|
++ "/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */\n"
|
||
|
++ "\n";
|
||
|
++#endif
|
||
|
++
|
||
|
+ OS << "\n#ifdef GET_REGINFO_ENUM\n";
|
||
|
+ OS << "#undef GET_REGINFO_ENUM\n\n";
|
||
|
+
|
||
|
++#ifndef CAPSTONE
|
||
|
+ OS << "namespace llvm {\n\n";
|
||
|
+
|
||
|
+ OS << "class MCRegisterClass;\n"
|
||
|
+@@ -122,16 +137,20 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
|
||
|
+
|
||
|
+ if (!Namespace.empty())
|
||
|
+ OS << "namespace " << Namespace << " {\n";
|
||
|
+- OS << "enum {\n NoRegister,\n";
|
||
|
++#endif
|
||
|
++
|
||
|
++ OS << "enum {\n " << NAME_PREFIX "NoRegister,\n";
|
||
|
+
|
||
|
+ for (const auto &Reg : Registers)
|
||
|
+- OS << " " << Reg.getName() << " = " << Reg.EnumValue << ",\n";
|
||
|
++ OS << " " << NAME_PREFIX Reg.getName() << " = " << Reg.EnumValue << ",\n";
|
||
|
+ assert(Registers.size() == Registers.back().EnumValue &&
|
||
|
+ "Register enum value mismatch!");
|
||
|
+- OS << " NUM_TARGET_REGS \t// " << Registers.size()+1 << "\n";
|
||
|
++ OS << " " << NAME_PREFIX "NUM_TARGET_REGS \t// " << Registers.size()+1 << "\n";
|
||
|
+ OS << "};\n";
|
||
|
++#ifndef CAPSTONE
|
||
|
+ if (!Namespace.empty())
|
||
|
+ OS << "} // end namespace " << Namespace << "\n";
|
||
|
++#endif
|
||
|
+
|
||
|
+ const auto &RegisterClasses = Bank.getRegClasses();
|
||
|
+ if (!RegisterClasses.empty()) {
|
||
|
+@@ -140,18 +159,29 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
|
||
|
+ assert(RegisterClasses.size() <= 0xffff &&
|
||
|
+ "Too many register classes to fit in tables");
|
||
|
+
|
||
|
+- OS << "\n// Register classes\n\n";
|
||
|
++ OS << "\n// Register classes\n";
|
||
|
++#ifndef CAPSTONE
|
||
|
++ OS << "\n";
|
||
|
+ if (!Namespace.empty())
|
||
|
+ OS << "namespace " << Namespace << " {\n";
|
||
|
++#endif
|
||
|
+ OS << "enum {\n";
|
||
|
+ for (const auto &RC : RegisterClasses)
|
||
|
+- OS << " " << RC.getName() << "RegClassID"
|
||
|
++ OS << " " << NAME_PREFIX RC.getName() << "RegClassID"
|
||
|
+ << " = " << RC.EnumValue << ",\n";
|
||
|
+- OS << "\n };\n";
|
||
|
++#ifdef CAPSTONE
|
||
|
++ OS
|
||
|
++#else
|
||
|
++ OS << "\n "
|
||
|
++#endif
|
||
|
++ << "};\n";
|
||
|
++#ifndef CAPSTONE
|
||
|
+ if (!Namespace.empty())
|
||
|
+ OS << "} // end namespace " << Namespace << "\n\n";
|
||
|
++#endif
|
||
|
+ }
|
||
|
+
|
||
|
++#ifndef CAPSTONE
|
||
|
+ const std::vector<Record*> &RegAltNameIndices = Target.getRegAltNameIndices();
|
||
|
+ // If the only definition is the default NoRegAltName, we don't need to
|
||
|
+ // emit anything.
|
||
|
+@@ -182,8 +212,11 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
|
||
|
+ if (!Namespace.empty())
|
||
|
+ OS << "} // end namespace " << Namespace << "\n\n";
|
||
|
+ }
|
||
|
++#endif
|
||
|
+
|
||
|
++#ifndef CAPSTONE
|
||
|
+ OS << "} // end namespace llvm\n\n";
|
||
|
++#endif
|
||
|
+ OS << "#endif // GET_REGINFO_ENUM\n\n";
|
||
|
+ }
|
||
|
+
|
||
|
+@@ -830,7 +863,9 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||
|
+
|
||
|
+ const auto &Regs = RegBank.getRegisters();
|
||
|
+
|
||
|
++#ifndef CAPSTONE
|
||
|
+ auto &SubRegIndices = RegBank.getSubRegIndices();
|
||
|
++#endif
|
||
|
+ // The lists of sub-registers and super-registers go in the same array. That
|
||
|
+ // allows us to share suffixes.
|
||
|
+ typedef std::vector<const CodeGenRegister*> RegVec;
|
||
|
+@@ -922,25 +957,40 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||
|
+ LaneMaskSeqs.layout();
|
||
|
+ SubRegIdxSeqs.layout();
|
||
|
+
|
||
|
++#ifndef CAPSTONE
|
||
|
+ OS << "namespace llvm {\n\n";
|
||
|
++#endif
|
||
|
+
|
||
|
+ const std::string &TargetName = Target.getName();
|
||
|
+
|
||
|
+ // Emit the shared table of differential lists.
|
||
|
+- OS << "extern const MCPhysReg " << TargetName << "RegDiffLists[] = {\n";
|
||
|
++#ifdef CAPSTONE
|
||
|
++ OS << "static"
|
||
|
++#else
|
||
|
++ OS << "extern"
|
||
|
++#endif
|
||
|
++ << " const MCPhysReg " << TargetName << "RegDiffLists[] = {\n";
|
||
|
+ DiffSeqs.emit(OS, printDiff16);
|
||
|
+ OS << "};\n\n";
|
||
|
+
|
||
|
++#ifndef CAPSTONE
|
||
|
+ // Emit the shared table of regunit lane mask sequences.
|
||
|
+ OS << "extern const LaneBitmask " << TargetName << "LaneMaskLists[] = {\n";
|
||
|
+ LaneMaskSeqs.emit(OS, printMask, "LaneBitmask::getAll()");
|
||
|
+ OS << "};\n\n";
|
||
|
++#endif
|
||
|
+
|
||
|
+ // Emit the table of sub-register indexes.
|
||
|
+- OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[] = {\n";
|
||
|
++#ifdef CAPSTONE
|
||
|
++ OS << "static"
|
||
|
++#else
|
||
|
++ OS << "extern"
|
||
|
++#endif
|
||
|
++ << " const uint16_t " << TargetName << "SubRegIdxLists[] = {\n";
|
||
|
+ SubRegIdxSeqs.emit(OS, printSubRegIndex);
|
||
|
+ OS << "};\n\n";
|
||
|
+
|
||
|
++#ifndef CAPSTONE
|
||
|
+ // Emit the table of sub-register index sizes.
|
||
|
+ OS << "extern const MCRegisterInfo::SubRegCoveredBits "
|
||
|
+ << TargetName << "SubRegIdxRanges[] = {\n";
|
||
|
+@@ -950,14 +1000,22 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||
|
+ << Idx.getName() << "\n";
|
||
|
+ }
|
||
|
+ OS << "};\n\n";
|
||
|
++#endif
|
||
|
+
|
||
|
+ // Emit the string table.
|
||
|
+ RegStrings.layout();
|
||
|
++#ifndef CAPSTONE
|
||
|
+ OS << "extern const char " << TargetName << "RegStrings[] = {\n";
|
||
|
+ RegStrings.emit(OS, printChar);
|
||
|
+ OS << "};\n\n";
|
||
|
++#endif
|
||
|
+
|
||
|
+- OS << "extern const MCRegisterDesc " << TargetName
|
||
|
++#ifdef CAPSTONE
|
||
|
++ OS << "static"
|
||
|
++#else
|
||
|
++ OS << "extern"
|
||
|
++#endif
|
||
|
++ << " const MCRegisterDesc " << TargetName
|
||
|
+ << "RegDesc[] = { // Descriptors\n";
|
||
|
+ OS << " { " << RegStrings.get("") << ", 0, 0, 0, 0, 0 },\n";
|
||
|
+
|
||
|
+@@ -973,6 +1031,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||
|
+ }
|
||
|
+ OS << "};\n\n"; // End of register descriptors...
|
||
|
+
|
||
|
++#ifndef CAPSTONE
|
||
|
+ // Emit the table of register unit roots. Each regunit has one or two root
|
||
|
+ // registers.
|
||
|
+ OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2] = {\n";
|
||
|
+@@ -986,11 +1045,14 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||
|
+ OS << " },\n";
|
||
|
+ }
|
||
|
+ OS << "};\n\n";
|
||
|
++#endif
|
||
|
+
|
||
|
+ const auto &RegisterClasses = RegBank.getRegClasses();
|
||
|
+
|
||
|
+ // Loop over all of the register classes... emitting each one.
|
||
|
++#ifndef CAPSTONE
|
||
|
+ OS << "namespace { // Register classes...\n";
|
||
|
++#endif
|
||
|
+
|
||
|
+ SequenceToOffsetTable<std::string> RegClassStrings;
|
||
|
+
|
||
|
+@@ -1005,15 +1067,28 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||
|
+
|
||
|
+ // Emit the register list now.
|
||
|
+ OS << " // " << Name << " Register Class...\n"
|
||
|
+- << " const MCPhysReg " << Name
|
||
|
++ << " "
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << "static "
|
||
|
++#endif
|
||
|
++ << "const MCPhysReg " << Name
|
||
|
+ << "[] = {\n ";
|
||
|
+ for (Record *Reg : Order) {
|
||
|
+- OS << getQualifiedName(Reg) << ", ";
|
||
|
++#ifdef CAPSTONE
|
||
|
++ OS << NAME_PREFIX Reg->getName()
|
||
|
++#else
|
||
|
++ OS << getQualifiedName(Reg)
|
||
|
++#endif
|
||
|
++ << ", ";
|
||
|
+ }
|
||
|
+ OS << "\n };\n\n";
|
||
|
+
|
||
|
+ OS << " // " << Name << " Bit set.\n"
|
||
|
+- << " const uint8_t " << Name
|
||
|
++ << " "
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << "static "
|
||
|
++#endif
|
||
|
++ << "const uint8_t " << Name
|
||
|
+ << "Bits[] = {\n ";
|
||
|
+ BitVectorEmitter BVE;
|
||
|
+ for (Record *Reg : Order) {
|
||
|
+@@ -1023,14 +1098,23 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||
|
+ OS << "\n };\n\n";
|
||
|
+
|
||
|
+ }
|
||
|
++#ifndef CAPSTONE
|
||
|
+ OS << "} // end anonymous namespace\n\n";
|
||
|
++#endif
|
||
|
+
|
||
|
+ RegClassStrings.layout();
|
||
|
++#ifndef CAPSTONE
|
||
|
+ OS << "extern const char " << TargetName << "RegClassStrings[] = {\n";
|
||
|
+ RegClassStrings.emit(OS, printChar);
|
||
|
+ OS << "};\n\n";
|
||
|
++#endif
|
||
|
+
|
||
|
+- OS << "extern const MCRegisterClass " << TargetName
|
||
|
++#ifdef CAPSTONE
|
||
|
++ OS << "static"
|
||
|
++#else
|
||
|
++ OS << "extern"
|
||
|
++#endif
|
||
|
++ << " const MCRegisterClass " << TargetName
|
||
|
+ << "MCRegisterClasses[] = {\n";
|
||
|
+
|
||
|
+ for (const auto &RC : RegisterClasses) {
|
||
|
+@@ -1041,7 +1125,12 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||
|
+ OS << " { " << RC.getName() << ", " << RC.getName() << "Bits, "
|
||
|
+ << RegClassStrings.get(RC.getName()) << ", "
|
||
|
+ << RC.getOrder().size() << ", sizeof(" << RC.getName() << "Bits), "
|
||
|
+- << RC.getQualifiedName() + "RegClassID" << ", "
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << NAME_PREFIX RC.getName()
|
||
|
++#else
|
||
|
++ << RC.getQualifiedName()
|
||
|
++#endif
|
||
|
++ << "RegClassID" << ", "
|
||
|
+ << RegSize/8 << ", "
|
||
|
+ << RC.CopyCost << ", "
|
||
|
+ << ( RC.Allocatable ? "true" : "false" ) << " },\n";
|
||
|
+@@ -1049,6 +1138,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||
|
+
|
||
|
+ OS << "};\n\n";
|
||
|
+
|
||
|
++#ifndef CAPSTONE
|
||
|
+ EmitRegMappingTables(OS, Regs, false);
|
||
|
+
|
||
|
+ // Emit Reg encoding table
|
||
|
+@@ -1067,7 +1157,9 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||
|
+ OS << " " << Value << ",\n";
|
||
|
+ }
|
||
|
+ OS << "};\n"; // End of HW encoding table
|
||
|
++#endif
|
||
|
+
|
||
|
++#ifndef CAPSTONE
|
||
|
+ // MCRegisterInfo initialization routine.
|
||
|
+ OS << "static inline void Init" << TargetName
|
||
|
+ << "MCRegisterInfo(MCRegisterInfo *RI, unsigned RA, "
|
||
|
+@@ -1088,7 +1180,12 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||
|
+ OS << "}\n\n";
|
||
|
+
|
||
|
+ OS << "} // end namespace llvm\n\n";
|
||
|
+- OS << "#endif // GET_REGINFO_MC_DESC\n\n";
|
||
|
++#endif
|
||
|
++ OS << "#endif // GET_REGINFO_MC_DESC\n"
|
||
|
++#ifndef CAPSTONE
|
||
|
++ << "\n"
|
||
|
++#endif
|
||
|
++ ;
|
||
|
+ }
|
||
|
+
|
||
|
+ void
|
||
|
+@@ -1568,10 +1665,13 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||
|
+
|
||
|
+ void RegisterInfoEmitter::run(raw_ostream &OS) {
|
||
|
+ CodeGenRegBank &RegBank = Target.getRegBank();
|
||
|
++
|
||
|
+ runEnums(OS, Target, RegBank);
|
||
|
+ runMCDesc(OS, Target, RegBank);
|
||
|
++#ifndef CAPSTONE
|
||
|
+ runTargetHeader(OS, Target, RegBank);
|
||
|
+ runTargetDesc(OS, Target, RegBank);
|
||
|
++#endif
|
||
|
+
|
||
|
+ if (RegisterInfoDebug)
|
||
|
+ debugDump(errs());
|
||
|
+--
|
||
|
+2.19.1
|
||
|
+
|
||
|
diff --git a/llvm/0002-capstone-generate-GenSubtargetInfo.inc.patch b/llvm/0002-capstone-generate-GenSubtargetInfo.inc.patch
|
||
|
new file mode 100644
|
||
|
index 000000000..56ad28256
|
||
|
--- /dev/null
|
||
|
+++ b/llvm/0002-capstone-generate-GenSubtargetInfo.inc.patch
|
||
|
@@ -0,0 +1,86 @@
|
||
|
+From 46ca491e1bbbc9ace2a91fe6a7b112c83b9b88cc Mon Sep 17 00:00:00 2001
|
||
|
+From: mephi42 <mephi42@gmail.com>
|
||
|
+Date: Tue, 7 Aug 2018 17:42:59 +0200
|
||
|
+Subject: [PATCH 2/7] capstone: generate *GenSubtargetInfo.inc
|
||
|
+
|
||
|
+---
|
||
|
+ utils/TableGen/SubtargetEmitter.cpp | 28 +++++++++++++++++++++++++++-
|
||
|
+ 1 file changed, 27 insertions(+), 1 deletion(-)
|
||
|
+
|
||
|
+diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp
|
||
|
+index c5da8d8142f..98ab3240472 100644
|
||
|
+--- a/utils/TableGen/SubtargetEmitter.cpp
|
||
|
++++ b/utils/TableGen/SubtargetEmitter.cpp
|
||
|
+@@ -147,7 +147,9 @@ void SubtargetEmitter::Enumeration(raw_ostream &OS) {
|
||
|
+ if (N > MAX_SUBTARGET_FEATURES)
|
||
|
+ PrintFatalError("Too many subtarget features! Bump MAX_SUBTARGET_FEATURES.");
|
||
|
+
|
||
|
++#ifndef CAPSTONE
|
||
|
+ OS << "namespace " << Target << " {\n";
|
||
|
++#endif
|
||
|
+
|
||
|
+ // Open enumeration.
|
||
|
+ OS << "enum {\n";
|
||
|
+@@ -158,12 +160,22 @@ void SubtargetEmitter::Enumeration(raw_ostream &OS) {
|
||
|
+ Record *Def = DefList[i];
|
||
|
+
|
||
|
+ // Get and emit name
|
||
|
+- OS << " " << Def->getName() << " = " << i << ",\n";
|
||
|
++ OS << " "
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << Target << "_"
|
||
|
++#endif
|
||
|
++ << Def->getName() << " = "
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << "1ULL << "
|
||
|
++#endif
|
||
|
++ << i << ",\n";
|
||
|
+ }
|
||
|
+
|
||
|
+ // Close enumeration and namespace
|
||
|
+ OS << "};\n";
|
||
|
++#ifndef CAPSTONE
|
||
|
+ OS << "} // end namespace " << Target << "\n";
|
||
|
++#endif
|
||
|
+ }
|
||
|
+
|
||
|
+ //
|
||
|
+@@ -1709,14 +1721,27 @@ void SubtargetEmitter::emitGenMCSubtargetInfo(raw_ostream &OS) {
|
||
|
+ void SubtargetEmitter::run(raw_ostream &OS) {
|
||
|
+ emitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
|
||
|
+
|
||
|
++#ifdef CAPSTONE
|
||
|
++ OS << "/* Capstone Disassembly Engine, http://www.capstone-engine.org */\n"
|
||
|
++ "/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */\n"
|
||
|
++ "\n";
|
||
|
++#endif
|
||
|
++
|
||
|
+ OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n";
|
||
|
+ OS << "#undef GET_SUBTARGETINFO_ENUM\n\n";
|
||
|
+
|
||
|
++#ifndef CAPSTONE
|
||
|
+ OS << "namespace llvm {\n";
|
||
|
++#endif
|
||
|
+ Enumeration(OS);
|
||
|
++#ifdef CAPSTONE
|
||
|
++ OS << "\n";
|
||
|
++#else
|
||
|
+ OS << "} // end namespace llvm\n\n";
|
||
|
++#endif
|
||
|
+ OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";
|
||
|
+
|
||
|
++#ifndef CAPSTONE
|
||
|
+ OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n";
|
||
|
+ OS << "#undef GET_SUBTARGETINFO_MC_DESC\n\n";
|
||
|
+
|
||
|
+@@ -1857,6 +1882,7 @@ void SubtargetEmitter::run(raw_ostream &OS) {
|
||
|
+ OS << "} // end namespace llvm\n\n";
|
||
|
+
|
||
|
+ OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n";
|
||
|
++#endif
|
||
|
+ }
|
||
|
+
|
||
|
+ namespace llvm {
|
||
|
+--
|
||
|
+2.19.1
|
||
|
+
|
||
|
diff --git a/llvm/0003-capstone-generate-GenInstrInfo.inc.patch b/llvm/0003-capstone-generate-GenInstrInfo.inc.patch
|
||
|
new file mode 100644
|
||
|
index 000000000..2baa59fc9
|
||
|
--- /dev/null
|
||
|
+++ b/llvm/0003-capstone-generate-GenInstrInfo.inc.patch
|
||
|
@@ -0,0 +1,130 @@
|
||
|
+From a73fe8ac18d3ca81fa7a8d8c404cd7e0faf92ddc Mon Sep 17 00:00:00 2001
|
||
|
+From: mephi42 <mephi42@gmail.com>
|
||
|
+Date: Tue, 7 Aug 2018 17:59:43 +0200
|
||
|
+Subject: [PATCH 3/7] capstone: generate *GenInstrInfo.inc
|
||
|
+
|
||
|
+---
|
||
|
+ utils/TableGen/InstrInfoEmitter.cpp | 49 ++++++++++++++++++++++++++---
|
||
|
+ 1 file changed, 44 insertions(+), 5 deletions(-)
|
||
|
+
|
||
|
+diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp
|
||
|
+index 0aff1aa6f94..2f3a2729262 100644
|
||
|
+--- a/utils/TableGen/InstrInfoEmitter.cpp
|
||
|
++++ b/utils/TableGen/InstrInfoEmitter.cpp
|
||
|
+@@ -92,6 +92,7 @@ private:
|
||
|
+
|
||
|
+ } // end anonymous namespace
|
||
|
+
|
||
|
++#ifndef CAPSTONE
|
||
|
+ static void PrintDefList(const std::vector<Record*> &Uses,
|
||
|
+ unsigned Num, raw_ostream &OS) {
|
||
|
+ OS << "static const MCPhysReg ImplicitList" << Num << "[] = { ";
|
||
|
+@@ -99,6 +100,7 @@ static void PrintDefList(const std::vector<Record*> &Uses,
|
||
|
+ OS << getQualifiedName(U) << ", ";
|
||
|
+ OS << "0 };\n";
|
||
|
+ }
|
||
|
++#endif
|
||
|
+
|
||
|
+ //===----------------------------------------------------------------------===//
|
||
|
+ // Operand Info Emission.
|
||
|
+@@ -426,8 +428,17 @@ void InstrInfoEmitter::emitTIIHelperMethods(raw_ostream &OS) {
|
||
|
+ // run - Emit the main instruction description records for the target...
|
||
|
+ void InstrInfoEmitter::run(raw_ostream &OS) {
|
||
|
+ emitSourceFileHeader("Target Instruction Enum Values and Descriptors", OS);
|
||
|
++
|
||
|
++#ifdef CAPSTONE
|
||
|
++ OS << "/* Capstone Disassembly Engine */\n"
|
||
|
++ "/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */\n"
|
||
|
++ "\n"
|
||
|
++ "\n";
|
||
|
++#endif
|
||
|
++
|
||
|
+ emitEnums(OS);
|
||
|
+
|
||
|
++#ifndef CAPSTONE
|
||
|
+ OS << "#ifdef GET_INSTRINFO_MC_DESC\n";
|
||
|
+ OS << "#undef GET_INSTRINFO_MC_DESC\n";
|
||
|
+
|
||
|
+@@ -545,6 +556,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
|
||
|
+ emitOperandTypesEnum(OS, Target);
|
||
|
+
|
||
|
+ emitMCIIHelperMethods(OS);
|
||
|
++#endif
|
||
|
+ }
|
||
|
+
|
||
|
+ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
|
||
|
+@@ -659,7 +671,9 @@ void InstrInfoEmitter::emitEnums(raw_ostream &OS) {
|
||
|
+ OS << "#ifdef GET_INSTRINFO_ENUM\n";
|
||
|
+ OS << "#undef GET_INSTRINFO_ENUM\n";
|
||
|
+
|
||
|
++#ifndef CAPSTONE
|
||
|
+ OS << "namespace llvm {\n\n";
|
||
|
++#endif
|
||
|
+
|
||
|
+ CodeGenTarget Target(Records);
|
||
|
+
|
||
|
+@@ -669,17 +683,39 @@ void InstrInfoEmitter::emitEnums(raw_ostream &OS) {
|
||
|
+ if (Namespace.empty())
|
||
|
+ PrintFatalError("No instructions defined!");
|
||
|
+
|
||
|
++#ifndef CAPSTONE
|
||
|
+ OS << "namespace " << Namespace << " {\n";
|
||
|
+- OS << " enum {\n";
|
||
|
++#endif
|
||
|
++#ifdef CAPSTONE
|
||
|
++ OS << "\n"
|
||
|
++#else
|
||
|
++ OS << " "
|
||
|
++#endif
|
||
|
++ << "enum {\n";
|
||
|
+ unsigned Num = 0;
|
||
|
+ for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue())
|
||
|
+- OS << " " << Inst->TheDef->getName() << "\t= " << Num++ << ",\n";
|
||
|
+- OS << " INSTRUCTION_LIST_END = " << Num << "\n";
|
||
|
++ OS << " "
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << Target.getName() << "_"
|
||
|
++#endif
|
||
|
++ << Inst->TheDef->getName() << "\t= " << Num++ << ",\n";
|
||
|
++ OS << " "
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << Target.getName() << "_"
|
||
|
++#endif
|
||
|
++ << "INSTRUCTION_LIST_END = " << Num << "\n";
|
||
|
+ OS << " };\n\n";
|
||
|
++#ifndef CAPSTONE
|
||
|
+ OS << "} // end " << Namespace << " namespace\n";
|
||
|
+ OS << "} // end llvm namespace\n";
|
||
|
+- OS << "#endif // GET_INSTRINFO_ENUM\n\n";
|
||
|
+-
|
||
|
++#endif
|
||
|
++ OS << "#endif // GET_INSTRINFO_ENUM\n"
|
||
|
++#ifndef CAPSTONE
|
||
|
++ << "\n"
|
||
|
++#endif
|
||
|
++ ;
|
||
|
++
|
||
|
++#ifndef CAPSTONE
|
||
|
+ OS << "#ifdef GET_INSTRINFO_SCHED_ENUM\n";
|
||
|
+ OS << "#undef GET_INSTRINFO_SCHED_ENUM\n";
|
||
|
+ OS << "namespace llvm {\n\n";
|
||
|
+@@ -696,13 +732,16 @@ void InstrInfoEmitter::emitEnums(raw_ostream &OS) {
|
||
|
+ OS << "} // end llvm namespace\n";
|
||
|
+
|
||
|
+ OS << "#endif // GET_INSTRINFO_SCHED_ENUM\n\n";
|
||
|
++#endif
|
||
|
+ }
|
||
|
+
|
||
|
+ namespace llvm {
|
||
|
+
|
||
|
+ void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS) {
|
||
|
+ InstrInfoEmitter(RK).run(OS);
|
||
|
++#ifndef CAPSTONE
|
||
|
+ EmitMapTable(RK, OS);
|
||
|
++#endif
|
||
|
+ }
|
||
|
+
|
||
|
+ } // end llvm namespace
|
||
|
+--
|
||
|
+2.19.1
|
||
|
+
|
||
|
diff --git a/llvm/0004-capstone-generate-GenDisassemblerTables.inc.patch b/llvm/0004-capstone-generate-GenDisassemblerTables.inc.patch
|
||
|
new file mode 100644
|
||
|
index 000000000..0002b81b4
|
||
|
--- /dev/null
|
||
|
+++ b/llvm/0004-capstone-generate-GenDisassemblerTables.inc.patch
|
||
|
@@ -0,0 +1,472 @@
|
||
|
+From 29da4c6929679b8ac4019767ab4ebcd83c9894b4 Mon Sep 17 00:00:00 2001
|
||
|
+From: mephi42 <mephi42@gmail.com>
|
||
|
+Date: Tue, 7 Aug 2018 18:20:17 +0200
|
||
|
+Subject: [PATCH 4/7] capstone: generate *GenDisassemblerTables.inc
|
||
|
+
|
||
|
+---
|
||
|
+ utils/TableGen/DisassemblerEmitter.cpp | 12 +-
|
||
|
+ utils/TableGen/FixedLenDecoderEmitter.cpp | 248 ++++++++++++++++++++--
|
||
|
+ 2 files changed, 239 insertions(+), 21 deletions(-)
|
||
|
+
|
||
|
+diff --git a/utils/TableGen/DisassemblerEmitter.cpp b/utils/TableGen/DisassemblerEmitter.cpp
|
||
|
+index b99a0a973a2..2ac6d89645c 100644
|
||
|
+--- a/utils/TableGen/DisassemblerEmitter.cpp
|
||
|
++++ b/utils/TableGen/DisassemblerEmitter.cpp
|
||
|
+@@ -106,6 +106,11 @@ extern void EmitFixedLenDecoder(RecordKeeper &RK, raw_ostream &OS,
|
||
|
+ void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) {
|
||
|
+ CodeGenTarget Target(Records);
|
||
|
+ emitSourceFileHeader(" * " + Target.getName().str() + " Disassembler", OS);
|
||
|
++#ifdef CAPSTONE
|
||
|
++ OS << "/* Capstone Disassembly Engine */\n"
|
||
|
++ "/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */\n"
|
||
|
++ "\n";
|
||
|
++#endif
|
||
|
+
|
||
|
+ // X86 uses a custom disassembler.
|
||
|
+ if (Target.getName() == "X86") {
|
||
|
+@@ -150,7 +155,12 @@ void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) {
|
||
|
+ }
|
||
|
+
|
||
|
+ EmitFixedLenDecoder(Records, OS, Target.getName(),
|
||
|
+- "if (", " == MCDisassembler::Fail)",
|
||
|
++ "if (",
|
||
|
++#ifdef CAPSTONE
|
||
|
++ " == MCDisassembler_Fail)",
|
||
|
++#else
|
||
|
++ " == MCDisassembler::Fail)",
|
||
|
++#endif
|
||
|
+ "MCDisassembler::Success", "MCDisassembler::Fail", "");
|
||
|
+ }
|
||
|
+
|
||
|
+diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp
|
||
|
+index fcecc764d44..36845d960d8 100644
|
||
|
+--- a/utils/TableGen/FixedLenDecoderEmitter.cpp
|
||
|
++++ b/utils/TableGen/FixedLenDecoderEmitter.cpp
|
||
|
+@@ -730,7 +730,13 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
|
||
|
+ ++I;
|
||
|
+ unsigned Start = *I++;
|
||
|
+ unsigned Len = *I++;
|
||
|
+- OS.indent(Indentation) << "MCD::OPC_ExtractField, " << Start << ", "
|
||
|
++ OS.indent(Indentation)
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << "MCD_OPC_ExtractField"
|
||
|
++#else
|
||
|
++ << "MCD::OPC_ExtractField"
|
||
|
++#endif
|
||
|
++ << ", " << Start << ", "
|
||
|
+ << Len << ", // Inst{";
|
||
|
+ if (Len > 1)
|
||
|
+ OS << (Start + Len - 1) << "-";
|
||
|
+@@ -739,7 +745,13 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
|
||
|
+ }
|
||
|
+ case MCD::OPC_FilterValue: {
|
||
|
+ ++I;
|
||
|
+- OS.indent(Indentation) << "MCD::OPC_FilterValue, ";
|
||
|
++ OS.indent(Indentation)
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << "MCD_OPC_FilterValue"
|
||
|
++#else
|
||
|
++ << "MCD::OPC_FilterValue"
|
||
|
++#endif
|
||
|
++ << ", ";
|
||
|
+ // The filter value is ULEB128 encoded.
|
||
|
+ while (*I >= 128)
|
||
|
+ OS << (unsigned)*I++ << ", ";
|
||
|
+@@ -759,7 +771,13 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
|
||
|
+ ++I;
|
||
|
+ unsigned Start = *I++;
|
||
|
+ unsigned Len = *I++;
|
||
|
+- OS.indent(Indentation) << "MCD::OPC_CheckField, " << Start << ", "
|
||
|
++ OS.indent(Indentation)
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << "MCD_OPC_CheckField"
|
||
|
++#else
|
||
|
++ << "MCD::OPC_CheckField"
|
||
|
++#endif
|
||
|
++ << ", " << Start << ", "
|
||
|
+ << Len << ", ";// << Val << ", " << NumToSkip << ",\n";
|
||
|
+ // ULEB128 encoded field value.
|
||
|
+ for (; *I >= 128; ++I)
|
||
|
+@@ -777,7 +795,13 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
|
||
|
+ }
|
||
|
+ case MCD::OPC_CheckPredicate: {
|
||
|
+ ++I;
|
||
|
+- OS.indent(Indentation) << "MCD::OPC_CheckPredicate, ";
|
||
|
++ OS.indent(Indentation)
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << "MCD_OPC_CheckPredicate"
|
||
|
++#else
|
||
|
++ << "MCD::OPC_CheckPredicate"
|
||
|
++#endif
|
||
|
++ << ", ";
|
||
|
+ for (; *I >= 128; ++I)
|
||
|
+ OS << (unsigned)*I << ", ";
|
||
|
+ OS << (unsigned)*I++ << ", ";
|
||
|
+@@ -803,7 +827,13 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
|
||
|
+ && "ULEB128 value too large!");
|
||
|
+ // Decode the Opcode value.
|
||
|
+ unsigned Opc = decodeULEB128(Buffer);
|
||
|
+- OS.indent(Indentation) << "MCD::OPC_" << (IsTry ? "Try" : "")
|
||
|
++ OS.indent(Indentation)
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << "MCD_OPC_"
|
||
|
++#else
|
||
|
++ << "MCD::OPC_"
|
||
|
++#endif
|
||
|
++ << (IsTry ? "Try" : "")
|
||
|
+ << "Decode, ";
|
||
|
+ for (p = Buffer; *p >= 128; ++p)
|
||
|
+ OS << (unsigned)*p << ", ";
|
||
|
+@@ -837,7 +867,12 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
|
||
|
+ }
|
||
|
+ case MCD::OPC_SoftFail: {
|
||
|
+ ++I;
|
||
|
+- OS.indent(Indentation) << "MCD::OPC_SoftFail";
|
||
|
++ OS.indent(Indentation)
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << "MCD_OPC_SoftFail";
|
||
|
++#else
|
||
|
++ << "MCD::OPC_SoftFail";
|
||
|
++#endif
|
||
|
+ // Positive mask
|
||
|
+ uint64_t Value = 0;
|
||
|
+ unsigned Shift = 0;
|
||
|
+@@ -869,7 +904,13 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
|
||
|
+ }
|
||
|
+ case MCD::OPC_Fail: {
|
||
|
+ ++I;
|
||
|
+- OS.indent(Indentation) << "MCD::OPC_Fail,\n";
|
||
|
++ OS.indent(Indentation)
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << "MCD_OPC_Fail"
|
||
|
++#else
|
||
|
++ << "MCD::OPC_Fail"
|
||
|
++#endif
|
||
|
++ << ",\n";
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ }
|
||
|
+@@ -884,23 +925,46 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
|
||
|
+ void FixedLenDecoderEmitter::
|
||
|
+ emitPredicateFunction(formatted_raw_ostream &OS, PredicateSet &Predicates,
|
||
|
+ unsigned Indentation) const {
|
||
|
++#ifdef CAPSTONE
|
||
|
++ OS.indent(Indentation) << "static bool getbool(uint64_t b)\n";
|
||
|
++ OS.indent(Indentation) << "{\n";
|
||
|
++ OS.indent(Indentation) << "\treturn b != 0;\n";
|
||
|
++ OS.indent(Indentation) << "}\n\n";
|
||
|
++#endif
|
||
|
++
|
||
|
+ // The predicate function is just a big switch statement based on the
|
||
|
+ // input predicate index.
|
||
|
+ OS.indent(Indentation) << "static bool checkDecoderPredicate(unsigned Idx, "
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << "uint64_t Bits)\n{\n";
|
||
|
++#else
|
||
|
+ << "const FeatureBitset& Bits) {\n";
|
||
|
++#endif
|
||
|
+ Indentation += 2;
|
||
|
+ if (!Predicates.empty()) {
|
||
|
+ OS.indent(Indentation) << "switch (Idx) {\n";
|
||
|
+- OS.indent(Indentation) << "default: llvm_unreachable(\"Invalid index!\");\n";
|
||
|
++ OS.indent(Indentation) << "default: "
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << "// "
|
||
|
++#endif
|
||
|
++ << "llvm_unreachable(\"Invalid index!\");\n";
|
||
|
+ unsigned Index = 0;
|
||
|
+ for (const auto &Predicate : Predicates) {
|
||
|
+ OS.indent(Indentation) << "case " << Index++ << ":\n";
|
||
|
+- OS.indent(Indentation+2) << "return (" << Predicate << ");\n";
|
||
|
++ OS.indent(Indentation+2) << "return "
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << "getbool"
|
||
|
++#endif
|
||
|
++ << "(" << Predicate << ");\n";
|
||
|
+ }
|
||
|
+ OS.indent(Indentation) << "}\n";
|
||
|
+ } else {
|
||
|
+ // No case statement to emit
|
||
|
+- OS.indent(Indentation) << "llvm_unreachable(\"Invalid index!\");\n";
|
||
|
++ OS.indent(Indentation)
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << "// "
|
||
|
++#endif
|
||
|
++ << "llvm_unreachable(\"Invalid index!\");\n";
|
||
|
+ }
|
||
|
+ Indentation -= 2;
|
||
|
+ OS.indent(Indentation) << "}\n\n";
|
||
|
+@@ -911,23 +975,39 @@ emitDecoderFunction(formatted_raw_ostream &OS, DecoderSet &Decoders,
|
||
|
+ unsigned Indentation) const {
|
||
|
+ // The decoder function is just a big switch statement based on the
|
||
|
+ // input decoder index.
|
||
|
++#ifdef CAPSTONE
|
||
|
++#define EDF_EOL " \\\n"
|
||
|
++ OS.indent(Indentation) << "#define DecodeToMCInst(fname,fieldname, InsnType) \\\n";
|
||
|
++ OS.indent(Indentation) << "static DecodeStatus fname(DecodeStatus S, unsigned Idx, InsnType insn, MCInst *MI, \\\n";
|
||
|
++ OS.indent(Indentation) << " uint64_t Address, const void *Decoder) \\\n";
|
||
|
++ OS.indent(Indentation) << "{ \\\n";
|
||
|
++#else
|
||
|
++#define EDF_EOL "\n"
|
||
|
+ OS.indent(Indentation) << "template<typename InsnType>\n";
|
||
|
+ OS.indent(Indentation) << "static DecodeStatus decodeToMCInst(DecodeStatus S,"
|
||
|
+ << " unsigned Idx, InsnType insn, MCInst &MI,\n";
|
||
|
+ OS.indent(Indentation) << " uint64_t "
|
||
|
+ << "Address, const void *Decoder, bool &DecodeComplete) {\n";
|
||
|
++#endif
|
||
|
+ Indentation += 2;
|
||
|
++#ifndef CAPSTONE
|
||
|
+ OS.indent(Indentation) << "DecodeComplete = true;\n";
|
||
|
+- OS.indent(Indentation) << "InsnType tmp;\n";
|
||
|
+- OS.indent(Indentation) << "switch (Idx) {\n";
|
||
|
+- OS.indent(Indentation) << "default: llvm_unreachable(\"Invalid index!\");\n";
|
||
|
++#endif
|
||
|
++ OS.indent(Indentation) << "InsnType tmp;" EDF_EOL;
|
||
|
++ OS.indent(Indentation) << "switch (Idx) {" EDF_EOL;
|
||
|
++ OS.indent(Indentation) << "default:"
|
||
|
++#ifndef CAPSTONE
|
||
|
++ << " llvm_unreachable(\"Invalid index!\");\n";
|
||
|
++#else
|
||
|
++ << " \\\n";
|
||
|
++#endif
|
||
|
+ unsigned Index = 0;
|
||
|
+ for (const auto &Decoder : Decoders) {
|
||
|
+- OS.indent(Indentation) << "case " << Index++ << ":\n";
|
||
|
++ OS.indent(Indentation) << "case " << Index++ << ":" EDF_EOL;
|
||
|
+ OS << Decoder;
|
||
|
+- OS.indent(Indentation+2) << "return S;\n";
|
||
|
++ OS.indent(Indentation+2) << "return S;" EDF_EOL;
|
||
|
+ }
|
||
|
+- OS.indent(Indentation) << "}\n";
|
||
|
++ OS.indent(Indentation) << "}" EDF_EOL;
|
||
|
+ Indentation -= 2;
|
||
|
+ OS.indent(Indentation) << "}\n\n";
|
||
|
+ }
|
||
|
+@@ -1054,16 +1134,21 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation,
|
||
|
+ const std::string &Decoder = OpInfo.Decoder;
|
||
|
+
|
||
|
+ if (OpInfo.numFields() != 1)
|
||
|
+- o.indent(Indentation) << "tmp = 0;\n";
|
||
|
++ o.indent(Indentation) << "tmp = 0;" EDF_EOL;
|
||
|
+
|
||
|
+ for (const EncodingField &EF : OpInfo) {
|
||
|
+ o.indent(Indentation) << "tmp ";
|
||
|
+ if (OpInfo.numFields() != 1) o << '|';
|
||
|
+- o << "= fieldFromInstruction"
|
||
|
++ o << "= "
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << "fieldname"
|
||
|
++#else
|
||
|
++ << "fieldFromInstruction"
|
||
|
++#endif
|
||
|
+ << "(insn, " << EF.Base << ", " << EF.Width << ')';
|
||
|
+ if (OpInfo.numFields() != 1 || EF.Offset != 0)
|
||
|
+ o << " << " << EF.Offset;
|
||
|
+- o << ";\n";
|
||
|
++ o << ";" EDF_EOL;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (Decoder != "") {
|
||
|
+@@ -1071,8 +1156,12 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation,
|
||
|
+ o.indent(Indentation) << Emitter->GuardPrefix << Decoder
|
||
|
+ << "(MI, tmp, Address, Decoder)"
|
||
|
+ << Emitter->GuardPostfix
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << " return MCDisassembler_Fail; \\\n";
|
||
|
++#else
|
||
|
+ << " { " << (OpHasCompleteDecoder ? "" : "DecodeComplete = false; ")
|
||
|
+ << "return MCDisassembler::Fail; }\n";
|
||
|
++#endif
|
||
|
+ } else {
|
||
|
+ OpHasCompleteDecoder = true;
|
||
|
+ o.indent(Indentation) << "MI.addOperand(MCOperand::createImm(tmp));\n";
|
||
|
+@@ -1091,7 +1180,13 @@ void FilterChooser::emitDecoder(raw_ostream &OS, unsigned Indentation,
|
||
|
+ << "(MI, insn, Address, Decoder)"
|
||
|
+ << Emitter->GuardPostfix
|
||
|
+ << " { " << (HasCompleteDecoder ? "" : "DecodeComplete = false; ")
|
||
|
+- << "return MCDisassembler::Fail; }\n";
|
||
|
++ << "return "
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << "MCDisassembler_Fail"
|
||
|
++#else
|
||
|
++ << "MCDisassembler::Fail"
|
||
|
++#endif
|
||
|
++ << "; }\n";
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
+@@ -1129,10 +1224,19 @@ unsigned FilterChooser::getDecoderIndex(DecoderSet &Decoders,
|
||
|
+ static void emitSinglePredicateMatch(raw_ostream &o, StringRef str,
|
||
|
+ const std::string &PredicateNamespace) {
|
||
|
+ if (str[0] == '!')
|
||
|
++#ifdef CAPSTONE
|
||
|
++ o << "~(Bits & " << PredicateNamespace << "_"
|
||
|
++ << str.slice(1,str.size()) << ")";
|
||
|
++#else
|
||
|
+ o << "!Bits[" << PredicateNamespace << "::"
|
||
|
+ << str.slice(1,str.size()) << "]";
|
||
|
++#endif
|
||
|
+ else
|
||
|
++#ifdef CAPSTONE
|
||
|
++ o << "(Bits & " << PredicateNamespace << "_" << str << ")";
|
||
|
++#else
|
||
|
+ o << "Bits[" << PredicateNamespace << "::" << str << "]";
|
||
|
++#endif
|
||
|
+ }
|
||
|
+
|
||
|
+ bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation,
|
||
|
+@@ -2047,6 +2151,17 @@ static bool populateInstruction(CodeGenTarget &Target,
|
||
|
+ // fieldFromInstruction().
|
||
|
+ static void emitFieldFromInstruction(formatted_raw_ostream &OS) {
|
||
|
+ OS << "// Helper function for extracting fields from encoded instructions.\n"
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << "#define FieldFromInstruction(fname, InsnType) \\\n"
|
||
|
++ << "static InsnType fname(InsnType insn, unsigned startBit, unsigned numBits) \\\n"
|
||
|
++ << "{ \\\n"
|
||
|
++ << " InsnType fieldMask; \\\n"
|
||
|
++ << " if (numBits == sizeof(InsnType)*8) \\\n"
|
||
|
++ << " fieldMask = (InsnType)(-1LL); \\\n"
|
||
|
++ << " else \\\n"
|
||
|
++ << " fieldMask = (((InsnType)1 << numBits) - 1) << startBit; \\\n"
|
||
|
++ << " return (insn & fieldMask) >> startBit; \\\n"
|
||
|
++#else
|
||
|
+ << "template<typename InsnType>\n"
|
||
|
+ << "static InsnType fieldFromInstruction(InsnType insn, unsigned startBit,\n"
|
||
|
+ << " unsigned numBits) {\n"
|
||
|
+@@ -2058,12 +2173,92 @@ static void emitFieldFromInstruction(formatted_raw_ostream &OS) {
|
||
|
+ << " else\n"
|
||
|
+ << " fieldMask = (((InsnType)1 << numBits) - 1) << startBit;\n"
|
||
|
+ << " return (insn & fieldMask) >> startBit;\n"
|
||
|
++#endif
|
||
|
+ << "}\n\n";
|
||
|
+ }
|
||
|
+
|
||
|
+ // emitDecodeInstruction - Emit the templated helper function
|
||
|
+ // decodeInstruction().
|
||
|
+ static void emitDecodeInstruction(formatted_raw_ostream &OS) {
|
||
|
++#ifdef CAPSTONE
|
||
|
++ OS << "#define DecodeInstruction(fname, fieldname, decoder, InsnType) \\\n"
|
||
|
++ << "static DecodeStatus fname(const uint8_t DecodeTable[], MCInst *MI, \\\n"
|
||
|
++ << " InsnType insn, uint64_t Address, const MCRegisterInfo *MRI, int feature) \\\n"
|
||
|
++ << "{ \\\n"
|
||
|
++ << " uint64_t Bits = getFeatureBits(feature); \\\n"
|
||
|
++ << " const uint8_t *Ptr = DecodeTable; \\\n"
|
||
|
++ << " uint32_t CurFieldValue = 0, ExpectedValue; \\\n"
|
||
|
++ << " DecodeStatus S = MCDisassembler_Success; \\\n"
|
||
|
++ << " unsigned Start, Len, NumToSkip, PIdx, Opc, DecodeIdx; \\\n"
|
||
|
++ << " InsnType Val, FieldValue, PositiveMask, NegativeMask; \\\n"
|
||
|
++ << " bool Pred, Fail; \\\n"
|
||
|
++ << " for (;;) { \\\n"
|
||
|
++ << " switch (*Ptr) { \\\n"
|
||
|
++ << " default: \\\n"
|
||
|
++ << " return MCDisassembler_Fail; \\\n"
|
||
|
++ << " case MCD_OPC_ExtractField: { \\\n"
|
||
|
++ << " Start = *++Ptr; \\\n"
|
||
|
++ << " Len = *++Ptr; \\\n"
|
||
|
++ << " ++Ptr; \\\n"
|
||
|
++ << " CurFieldValue = (uint32_t)fieldname(insn, Start, Len); \\\n"
|
||
|
++ << " break; \\\n"
|
||
|
++ << " } \\\n"
|
||
|
++ << " case MCD_OPC_FilterValue: { \\\n"
|
||
|
++ << " Val = (InsnType)decodeULEB128(++Ptr, &Len); \\\n"
|
||
|
++ << " Ptr += Len; \\\n"
|
||
|
++ << " NumToSkip = *Ptr++; \\\n"
|
||
|
++ << " NumToSkip |= (*Ptr++) << 8; \\\n"
|
||
|
++ << " if (Val != CurFieldValue) \\\n"
|
||
|
++ << " Ptr += NumToSkip; \\\n"
|
||
|
++ << " break; \\\n"
|
||
|
++ << " } \\\n"
|
||
|
++ << " case MCD_OPC_CheckField: { \\\n"
|
||
|
++ << " Start = *++Ptr; \\\n"
|
||
|
++ << " Len = *++Ptr; \\\n"
|
||
|
++ << " FieldValue = fieldname(insn, Start, Len); \\\n"
|
||
|
++ << " ExpectedValue = (uint32_t)decodeULEB128(++Ptr, &Len); \\\n"
|
||
|
++ << " Ptr += Len; \\\n"
|
||
|
++ << " NumToSkip = *Ptr++; \\\n"
|
||
|
++ << " NumToSkip |= (*Ptr++) << 8; \\\n"
|
||
|
++ << " if (ExpectedValue != FieldValue) \\\n"
|
||
|
++ << " Ptr += NumToSkip; \\\n"
|
||
|
++ << " break; \\\n"
|
||
|
++ << " } \\\n"
|
||
|
++ << " case MCD_OPC_CheckPredicate: { \\\n"
|
||
|
++ << " PIdx = (uint32_t)decodeULEB128(++Ptr, &Len); \\\n"
|
||
|
++ << " Ptr += Len; \\\n"
|
||
|
++ << " NumToSkip = *Ptr++; \\\n"
|
||
|
++ << " NumToSkip |= (*Ptr++) << 8; \\\n"
|
||
|
++ << " Pred = checkDecoderPredicate(PIdx, Bits); \\\n"
|
||
|
++ << " if (!Pred) \\\n"
|
||
|
++ << " Ptr += NumToSkip; \\\n"
|
||
|
++ << " (void)Pred; \\\n"
|
||
|
++ << " break; \\\n"
|
||
|
++ << " } \\\n"
|
||
|
++ << " case MCD_OPC_Decode: { \\\n"
|
||
|
++ << " Opc = (unsigned)decodeULEB128(++Ptr, &Len); \\\n"
|
||
|
++ << " Ptr += Len; \\\n"
|
||
|
++ << " DecodeIdx = (unsigned)decodeULEB128(Ptr, &Len); \\\n"
|
||
|
++ << " Ptr += Len; \\\n"
|
||
|
++ << " MCInst_setOpcode(MI, Opc); \\\n"
|
||
|
++ << " return decoder(S, DecodeIdx, insn, MI, Address, MRI); \\\n"
|
||
|
++ << " } \\\n"
|
||
|
++ << " case MCD_OPC_SoftFail: { \\\n"
|
||
|
++ << " PositiveMask = (InsnType)decodeULEB128(++Ptr, &Len); \\\n"
|
||
|
++ << " Ptr += Len; \\\n"
|
||
|
++ << " NegativeMask = (InsnType)decodeULEB128(Ptr, &Len); \\\n"
|
||
|
++ << " Ptr += Len; \\\n"
|
||
|
++ << " Fail = (insn & PositiveMask) || (~insn & NegativeMask); \\\n"
|
||
|
++ << " if (Fail) \\\n"
|
||
|
++ << " S = MCDisassembler_SoftFail; \\\n"
|
||
|
++ << " break; \\\n"
|
||
|
++ << " } \\\n"
|
||
|
++ << " case MCD_OPC_Fail: { \\\n"
|
||
|
++ << " return MCDisassembler_Fail; \\\n"
|
||
|
++ << " } \\\n"
|
||
|
++ << " } \\\n"
|
||
|
++ << " } \\\n"
|
||
|
++#else
|
||
|
+ OS << "template<typename InsnType>\n"
|
||
|
+ << "static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], "
|
||
|
+ "MCInst &MI,\n"
|
||
|
+@@ -2240,12 +2435,18 @@ static void emitDecodeInstruction(formatted_raw_ostream &OS) {
|
||
|
+ << " }\n"
|
||
|
+ << " llvm_unreachable(\"bogosity detected in disassembler state "
|
||
|
+ "machine!\");\n"
|
||
|
++#endif
|
||
|
+ << "}\n\n";
|
||
|
+ }
|
||
|
+
|
||
|
+ // Emits disassembler code for instruction decoding.
|
||
|
+ void FixedLenDecoderEmitter::run(raw_ostream &o) {
|
||
|
+ formatted_raw_ostream OS(o);
|
||
|
++#ifdef CAPSTONE
|
||
|
++ OS << "#include \"../../MCInst.h\"\n";
|
||
|
++ OS << "#include \"../../LEB128.h\"\n";
|
||
|
++ OS << "\n";
|
||
|
++#else
|
||
|
+ OS << "#include \"llvm/MC/MCInst.h\"\n";
|
||
|
+ OS << "#include \"llvm/Support/Debug.h\"\n";
|
||
|
+ OS << "#include \"llvm/Support/DataTypes.h\"\n";
|
||
|
+@@ -2254,6 +2455,7 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) {
|
||
|
+ OS << "#include <assert.h>\n";
|
||
|
+ OS << '\n';
|
||
|
+ OS << "namespace llvm {\n\n";
|
||
|
++#endif
|
||
|
+
|
||
|
+ emitFieldFromInstruction(OS);
|
||
|
+
|
||
|
+@@ -2322,7 +2524,13 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) {
|
||
|
+ // Emit the main entry point for the decoder, decodeInstruction().
|
||
|
+ emitDecodeInstruction(OS);
|
||
|
+
|
||
|
++#ifdef CAPSTONE
|
||
|
++ OS << "FieldFromInstruction(fieldFromInstruction, uint64_t)\n";
|
||
|
++ OS << "DecodeToMCInst(decodeToMCInst, fieldFromInstruction, uint64_t)\n";
|
||
|
++ OS << "DecodeInstruction(decodeInstruction, fieldFromInstruction, decodeToMCInst, uint64_t)\n";
|
||
|
++#else
|
||
|
+ OS << "\n} // End llvm namespace\n";
|
||
|
++#endif
|
||
|
+ }
|
||
|
+
|
||
|
+ namespace llvm {
|
||
|
+--
|
||
|
+2.19.1
|
||
|
+
|
||
|
diff --git a/llvm/0005-capstone-generate-GenAsmWriter.inc.patch b/llvm/0005-capstone-generate-GenAsmWriter.inc.patch
|
||
|
new file mode 100644
|
||
|
index 000000000..cd1353eb7
|
||
|
--- /dev/null
|
||
|
+++ b/llvm/0005-capstone-generate-GenAsmWriter.inc.patch
|
||
|
@@ -0,0 +1,225 @@
|
||
|
+From 5569e48b9cb34a33910e1e850fbfabc999f016a2 Mon Sep 17 00:00:00 2001
|
||
|
+From: mephi42 <mephi42@gmail.com>
|
||
|
+Date: Tue, 7 Aug 2018 20:00:08 +0200
|
||
|
+Subject: [PATCH 5/7] capstone: generate *GenAsmWriter.inc
|
||
|
+
|
||
|
+---
|
||
|
+ utils/TableGen/AsmWriterEmitter.cpp | 89 +++++++++++++++++++++++++++--
|
||
|
+ utils/TableGen/AsmWriterInst.cpp | 4 ++
|
||
|
+ 2 files changed, 87 insertions(+), 6 deletions(-)
|
||
|
+
|
||
|
+diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp
|
||
|
+index 3c4c9c8e5c6..133800d217c 100644
|
||
|
+--- a/utils/TableGen/AsmWriterEmitter.cpp
|
||
|
++++ b/utils/TableGen/AsmWriterEmitter.cpp
|
||
|
+@@ -272,16 +272,22 @@ static void UnescapeString(std::string &Str) {
|
||
|
+ /// clearing the Instructions vector.
|
||
|
+ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
|
||
|
+ Record *AsmWriter = Target.getAsmWriter();
|
||
|
++#ifndef CAPSTONE
|
||
|
+ StringRef ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
|
||
|
++#endif
|
||
|
+ bool PassSubtarget = AsmWriter->getValueAsInt("PassSubtarget");
|
||
|
+
|
||
|
+ O <<
|
||
|
+ "/// printInstruction - This method is automatically generated by tablegen\n"
|
||
|
+ "/// from the instruction set description.\n"
|
||
|
++#ifdef CAPSTONE
|
||
|
++ "static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI)\n{\n";
|
||
|
++#else
|
||
|
+ "void " << Target.getName() << ClassName
|
||
|
+ << "::printInstruction(const MCInst *MI, "
|
||
|
+ << (PassSubtarget ? "const MCSubtargetInfo &STI, " : "")
|
||
|
+ << "raw_ostream &O) {\n";
|
||
|
++#endif
|
||
|
+
|
||
|
+ // Build an aggregate string, and build a table of offsets into it.
|
||
|
+ SequenceToOffsetTable<std::string> StringTable;
|
||
|
+@@ -379,9 +385,16 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
|
||
|
+ }
|
||
|
+
|
||
|
+ // Emit the string table itself.
|
||
|
++#ifdef CAPSTONE
|
||
|
++ O << "#ifndef CAPSTONE_DIET\n";
|
||
|
++#endif
|
||
|
+ O << " static const char AsmStrs[] = {\n";
|
||
|
+ StringTable.emit(O, printChar);
|
||
|
+- O << " };\n\n";
|
||
|
++ O << " };\n"
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << "#endif\n"
|
||
|
++#endif
|
||
|
++ << "\n";
|
||
|
+
|
||
|
+ // Emit the lookup tables in pieces to minimize wasted bytes.
|
||
|
+ unsigned BytesNeeded = ((OpcodeInfoBits - BitsLeft) + 7) / 8;
|
||
|
+@@ -409,21 +422,45 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
|
||
|
+ // If the total bits is more than 32-bits we need to use a 64-bit type.
|
||
|
+ if (BitsLeft < (OpcodeInfoBits - 32))
|
||
|
+ BitsOS << "(uint64_t)";
|
||
|
+- BitsOS << "OpInfo" << Table << "[MI->getOpcode()] << " << Shift << ";\n";
|
||
|
++ BitsOS << "OpInfo" << Table << "["
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << "MCInst_getOpcode(MI)"
|
||
|
++#else
|
||
|
++ << "MI->getOpcode()"
|
||
|
++#endif
|
||
|
++ << "] << " << Shift << ";\n";
|
||
|
+ // Prepare the shift for the next iteration and increment the table count.
|
||
|
+ Shift += TableSize;
|
||
|
+ ++Table;
|
||
|
+ }
|
||
|
+
|
||
|
+ // Emit the initial tab character.
|
||
|
++#ifndef CAPSTONE
|
||
|
+ O << " O << \"\\t\";\n\n";
|
||
|
++#endif
|
||
|
+
|
||
|
+ O << " // Emit the opcode for the instruction.\n";
|
||
|
+ O << BitsString;
|
||
|
+
|
||
|
+ // Emit the starting string.
|
||
|
+- O << " assert(Bits != 0 && \"Cannot print this instruction.\");\n"
|
||
|
+- << " O << AsmStrs+(Bits & " << (1 << AsmStrBits)-1 << ")-1;\n\n";
|
||
|
++ O << " "
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << "// "
|
||
|
++#endif
|
||
|
++ << "assert(Bits != 0 && \"Cannot print this instruction.\");\n"
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << "#ifndef CAPSTONE_DIET\n"
|
||
|
++ << " SStream_concat0(O, "
|
||
|
++#else
|
||
|
++ << " O << "
|
||
|
++#endif
|
||
|
++ << "AsmStrs+(Bits & " << (1 << AsmStrBits)-1 << ")-1"
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << ");\n"
|
||
|
++ << "#endif\n\n";
|
||
|
++#else
|
||
|
++ << ");\n\n";
|
||
|
++#endif
|
||
|
+
|
||
|
+ // Output the table driven operand information.
|
||
|
+ BitsLeft = OpcodeInfoBits-AsmStrBits;
|
||
|
+@@ -455,7 +492,11 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
|
||
|
+ O << " switch ((Bits >> "
|
||
|
+ << (OpcodeInfoBits-BitsLeft) << ") & "
|
||
|
+ << ((1 << NumBits)-1) << ") {\n"
|
||
|
+- << " default: llvm_unreachable(\"Invalid command number.\");\n";
|
||
|
++ << " default: "
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << "// "
|
||
|
++#endif
|
||
|
++ << "llvm_unreachable(\"Invalid command number.\");\n";
|
||
|
+
|
||
|
+ // Print out all the cases.
|
||
|
+ for (unsigned j = 0, e = Commands.size(); j != e; ++j) {
|
||
|
+@@ -536,6 +577,9 @@ emitRegisterNameString(raw_ostream &O, StringRef AltName,
|
||
|
+ }
|
||
|
+
|
||
|
+ StringTable.layout();
|
||
|
++#ifdef CAPSTONE
|
||
|
++ O << "#ifndef CAPSTONE_DIET\n";
|
||
|
++#endif
|
||
|
+ O << " static const char AsmStrs" << AltName << "[] = {\n";
|
||
|
+ StringTable.emit(O, printChar);
|
||
|
+ O << " };\n\n";
|
||
|
+@@ -552,8 +596,10 @@ emitRegisterNameString(raw_ostream &O, StringRef AltName,
|
||
|
+ }
|
||
|
+
|
||
|
+ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
|
||
|
++#ifndef CAPSTONE
|
||
|
+ Record *AsmWriter = Target.getAsmWriter();
|
||
|
+ StringRef ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
|
||
|
++#endif
|
||
|
+ const auto &Registers = Target.getRegBank().getRegisters();
|
||
|
+ const std::vector<Record*> &AltNameIndices = Target.getRegAltNameIndices();
|
||
|
+ bool hasAltNames = AltNameIndices.size() > 1;
|
||
|
+@@ -563,12 +609,20 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
|
||
|
+ "\n\n/// getRegisterName - This method is automatically generated by tblgen\n"
|
||
|
+ "/// from the register set description. This returns the assembler name\n"
|
||
|
+ "/// for the specified register.\n"
|
||
|
++#ifdef CAPSTONE
|
||
|
++ "static const char *getRegisterName(unsigned RegNo)\n{\n";
|
||
|
++#else
|
||
|
+ "const char *" << Target.getName() << ClassName << "::";
|
||
|
+ if (hasAltNames)
|
||
|
+ O << "\ngetRegisterName(unsigned RegNo, unsigned AltIdx) {\n";
|
||
|
+ else
|
||
|
+ O << "getRegisterName(unsigned RegNo) {\n";
|
||
|
+- O << " assert(RegNo && RegNo < " << (Registers.size()+1)
|
||
|
++#endif
|
||
|
++ O << " "
|
||
|
++#ifdef CAPSTONE
|
||
|
++ << "// "
|
||
|
++#endif
|
||
|
++ << "assert(RegNo && RegNo < " << (Registers.size()+1)
|
||
|
+ << " && \"Invalid register number!\");\n"
|
||
|
+ << "\n";
|
||
|
+
|
||
|
+@@ -595,10 +649,22 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
|
||
|
+ }
|
||
|
+ O << " }\n";
|
||
|
+ } else {
|
||
|
++#ifdef CAPSTONE
|
||
|
++ O << " //int i;\n"
|
||
|
++ << " //for (i = 0; i < sizeof(RegAsmOffset); i++)\n"
|
||
|
++ << " // printf(\"%s = %u\\n\", AsmStrs+RegAsmOffset[i], i + 1);\n"
|
||
|
++ << " //printf(\"*************************\\n\");\n"
|
||
|
++#else
|
||
|
+ O << " assert (*(AsmStrs+RegAsmOffset[RegNo-1]) &&\n"
|
||
|
+ << " \"Invalid alt name index for register!\");\n"
|
||
|
++#endif
|
||
|
+ << " return AsmStrs+RegAsmOffset[RegNo-1];\n";
|
||
|
+ }
|
||
|
++#ifdef CAPSTONE
|
||
|
++ O << "#else\n"
|
||
|
++ << " return NULL;\n"
|
||
|
++ << "#endif\n";
|
||
|
++#endif
|
||
|
+ O << "}\n";
|
||
|
+ }
|
||
|
+
|
||
|
+@@ -1135,9 +1201,20 @@ AsmWriterEmitter::AsmWriterEmitter(RecordKeeper &R) : Records(R), Target(R) {
|
||
|
+ }
|
||
|
+
|
||
|
+ void AsmWriterEmitter::run(raw_ostream &O) {
|
||
|
++#ifdef CAPSTONE
|
||
|
++ O << "/* Capstone Disassembly Engine */\n"
|
||
|
++ "/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */\n"
|
||
|
++ "\n"
|
||
|
++ "#include <stdio.h>\t// debug\n"
|
||
|
++ "#include <capstone/platform.h>\n"
|
||
|
++ "\n"
|
||
|
++ "\n";
|
||
|
++#endif
|
||
|
+ EmitPrintInstruction(O);
|
||
|
+ EmitGetRegisterName(O);
|
||
|
++#ifndef CAPSTONE
|
||
|
+ EmitPrintAliasInstruction(O);
|
||
|
++#endif
|
||
|
+ }
|
||
|
+
|
||
|
+ namespace llvm {
|
||
|
+diff --git a/utils/TableGen/AsmWriterInst.cpp b/utils/TableGen/AsmWriterInst.cpp
|
||
|
+index 2c19e5d663d..6fa751e50df 100644
|
||
|
+--- a/utils/TableGen/AsmWriterInst.cpp
|
||
|
++++ b/utils/TableGen/AsmWriterInst.cpp
|
||
|
+@@ -28,9 +28,13 @@ static bool isIdentChar(char C) {
|
||
|
+
|
||
|
+ std::string AsmWriterOperand::getCode(bool PassSubtarget) const {
|
||
|
+ if (OperandType == isLiteralTextOperand) {
|
||
|
++#ifdef CAPSTONE
|
||
|
++ return "SStream_concat0(O, \"" + Str + "\");";
|
||
|
++#else
|
||
|
+ if (Str.size() == 1)
|
||
|
+ return "O << '" + Str + "';";
|
||
|
+ return "O << \"" + Str + "\";";
|
||
|
++#endif
|
||
|
+ }
|
||
|
+
|
||
|
+ if (OperandType == isLiteralStatementOperand)
|
||
|
+--
|
||
|
+2.19.1
|
||
|
+
|
||
|
diff --git a/llvm/0006-capstone-generate-MappingInsn.inc.patch b/llvm/0006-capstone-generate-MappingInsn.inc.patch
|
||
|
new file mode 100644
|
||
|
index 000000000..7ee22d787
|
||
|
--- /dev/null
|
||
|
+++ b/llvm/0006-capstone-generate-MappingInsn.inc.patch
|
||
|
@@ -0,0 +1,174 @@
|
||
|
+From 7a436110ef15c803dc8524af2fb5612bcacbb126 Mon Sep 17 00:00:00 2001
|
||
|
+From: mephi42 <mephi42@gmail.com>
|
||
|
+Date: Tue, 7 Aug 2018 20:55:32 +0200
|
||
|
+Subject: [PATCH 6/7] capstone: generate *MappingInsn.inc
|
||
|
+
|
||
|
+---
|
||
|
+ lib/Target/SystemZ/CMakeLists.txt | 1 +
|
||
|
+ utils/TableGen/InstrInfoEmitter.cpp | 95 +++++++++++++++++++++++++++++
|
||
|
+ utils/TableGen/TableGen.cpp | 6 ++
|
||
|
+ utils/TableGen/TableGenBackends.h | 1 +
|
||
|
+ 4 files changed, 103 insertions(+)
|
||
|
+
|
||
|
+diff --git a/lib/Target/SystemZ/CMakeLists.txt b/lib/Target/SystemZ/CMakeLists.txt
|
||
|
+index f83b4242fb4..4b5d9c4a3b2 100644
|
||
|
+--- a/lib/Target/SystemZ/CMakeLists.txt
|
||
|
++++ b/lib/Target/SystemZ/CMakeLists.txt
|
||
|
+@@ -6,6 +6,7 @@ tablegen(LLVM SystemZGenCallingConv.inc -gen-callingconv)
|
||
|
+ tablegen(LLVM SystemZGenDAGISel.inc -gen-dag-isel)
|
||
|
+ tablegen(LLVM SystemZGenDisassemblerTables.inc -gen-disassembler)
|
||
|
+ tablegen(LLVM SystemZGenInstrInfo.inc -gen-instr-info)
|
||
|
++tablegen(LLVM SystemZMappingInsn.inc -mapping-insn)
|
||
|
+ tablegen(LLVM SystemZGenMCCodeEmitter.inc -gen-emitter)
|
||
|
+ tablegen(LLVM SystemZGenRegisterInfo.inc -gen-register-info)
|
||
|
+ tablegen(LLVM SystemZGenSubtargetInfo.inc -gen-subtarget)
|
||
|
+diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp
|
||
|
+index 2f3a2729262..14ab1ea8a72 100644
|
||
|
+--- a/utils/TableGen/InstrInfoEmitter.cpp
|
||
|
++++ b/utils/TableGen/InstrInfoEmitter.cpp
|
||
|
+@@ -744,4 +744,99 @@ void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS) {
|
||
|
+ #endif
|
||
|
+ }
|
||
|
+
|
||
|
++#ifdef CAPSTONE
|
||
|
++std::string GetPublicName(const CodeGenInstruction *Inst) {
|
||
|
++ std::string Name = Inst->TheDef->getName();
|
||
|
++ // Apply backward compatibility fixups.
|
||
|
++ // BRNLE -> BNLER.
|
||
|
++ if (Name.length() >= 5 && Name.substr(0, 5) == "BRAsm") {
|
||
|
++ Name = "B" + Name.substr(5, Name.length() - 5) + "R";
|
||
|
++ }
|
||
|
++ // SSKEOpt -> SSKE.
|
||
|
++ while (Name.length() >= 3 && Name.substr(Name.length() - 3, 3) == "Opt") {
|
||
|
++ Name = Name.substr(0, Name.length() - 3);
|
||
|
++ }
|
||
|
++ // BRCLAsm -> BRCL.
|
||
|
++ while (true) {
|
||
|
++ size_t pos = Name.find("Asm");
|
||
|
++ if (pos == std::string::npos) {
|
||
|
++ break;
|
||
|
++ }
|
||
|
++ Name = Name.substr(0, pos) + Name.substr(pos + 3);
|
||
|
++ }
|
||
|
++ // CPSDRxx -> CPSDR.
|
||
|
++ if (Name.length() >= 2) {
|
||
|
++ std::string Suffix2 = Name.substr(Name.length() - 2, 2);
|
||
|
++ if (Suffix2 == "dd" || Suffix2 == "ds" ||
|
||
|
++ Suffix2 == "sd" || Suffix2 == "ss") {
|
||
|
++ Name = Name.substr(0, Name.length() - 2);
|
||
|
++ }
|
||
|
++ }
|
||
|
++ return "SYSZ_INS_" + Name;
|
||
|
++}
|
||
|
++
|
||
|
++std::string GetRegisterName(Record *Reg) {
|
||
|
++ std::string Name = Reg->getName();
|
||
|
++ for (char& c : Name) {
|
||
|
++ c = toupper(c);
|
||
|
++ }
|
||
|
++ // R0L, R0D -> R0.
|
||
|
++ if (Name.length() >= 3 &&
|
||
|
++ Name[Name.length() - 3] == 'R' &&
|
||
|
++ (Name[Name.length() - 1] == 'L' ||
|
||
|
++ Name[Name.length() - 1] == 'D')) {
|
||
|
++ Name = Name.substr(0, Name.length() - 3) + Name[Name.length() - 2];
|
||
|
++ }
|
||
|
++ return "SYSZ_REG_" + Name;
|
||
|
++}
|
||
|
++
|
||
|
++std::string GetGroupName(Record *Pred) {
|
||
|
++ std::string Name = Pred->getName();
|
||
|
++ for (char& c : Name) {
|
||
|
++ c = toupper(c);
|
||
|
++ }
|
||
|
++ if (Name.length() >= 7 && Name.substr(0, 7) == "FEATURE") {
|
||
|
++ Name = Name.substr(7);
|
||
|
++ }
|
||
|
++ return "SYSZ_GRP_" + Name;
|
||
|
++}
|
||
|
++
|
||
|
++void EmitMappingInsn(RecordKeeper &RK, raw_ostream &OS) {
|
||
|
++ OS << "// This is auto-gen data for Capstone engine (www.capstone-engine.org)\n"
|
||
|
++ "// By Nguyen Anh Quynh <aquynh@gmail.com>\n"
|
||
|
++ "\n";
|
||
|
++ CodeGenTarget Target(RK);
|
||
|
++ for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
|
||
|
++ if (Inst->TheDef->getValueAsBit("isPseudo") ||
|
||
|
++ Inst->TheDef->getValueAsBit("isCodeGenOnly")) {
|
||
|
++ continue;
|
||
|
++ }
|
||
|
++ OS << "{\n"
|
||
|
++ << "\t" << Target.getName() << "_" << Inst->TheDef->getName() << ", "
|
||
|
++ << GetPublicName(Inst) << ",\n"
|
||
|
++ << "#ifndef CAPSTONE_DIET\n"
|
||
|
++ << "\t{ ";
|
||
|
++ for (Record *Use : Inst->TheDef->getValueAsListOfDefs("Uses")) {
|
||
|
++ OS << GetRegisterName(Use) << ", ";
|
||
|
++ }
|
||
|
++ OS << "0 }, { ";
|
||
|
++ for (Record *Def : Inst->TheDef->getValueAsListOfDefs("Defs")) {
|
||
|
++ OS << GetRegisterName(Def) << ", ";
|
||
|
++ }
|
||
|
++ OS << "0 }, { ";
|
||
|
++ ListInit *Predicates = Inst->TheDef->getValueAsListInit("Predicates");
|
||
|
++ for (unsigned i = 0; i < Predicates->size(); ++i) {
|
||
|
++ OS << GetGroupName(Predicates->getElementAsRecord(i)) << ", ";
|
||
|
++ }
|
||
|
++ OS << "0 }, "
|
||
|
++ << Inst->TheDef->getValueAsBit("isBranch")
|
||
|
++ << ", "
|
||
|
++ << Inst->TheDef->getValueAsBit("isIndirectBranch")
|
||
|
++ << "\n"
|
||
|
++ << "#endif\n"
|
||
|
++ << "},\n";
|
||
|
++ }
|
||
|
++}
|
||
|
++#endif
|
||
|
++
|
||
|
+ } // end llvm namespace
|
||
|
+diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp
|
||
|
+index cf1404d8769..bbb4e860536 100644
|
||
|
+--- a/utils/TableGen/TableGen.cpp
|
||
|
++++ b/utils/TableGen/TableGen.cpp
|
||
|
+@@ -27,6 +27,7 @@ enum ActionType {
|
||
|
+ GenEmitter,
|
||
|
+ GenRegisterInfo,
|
||
|
+ GenInstrInfo,
|
||
|
++ MappingInsn,
|
||
|
+ GenInstrDocs,
|
||
|
+ GenAsmWriter,
|
||
|
+ GenAsmMatcher,
|
||
|
+@@ -65,6 +66,8 @@ namespace {
|
||
|
+ "Generate registers and register classes info"),
|
||
|
+ clEnumValN(GenInstrInfo, "gen-instr-info",
|
||
|
+ "Generate instruction descriptions"),
|
||
|
++ clEnumValN(MappingInsn, "mapping-insn",
|
||
|
++ ""),
|
||
|
+ clEnumValN(GenInstrDocs, "gen-instr-docs",
|
||
|
+ "Generate instruction documentation"),
|
||
|
+ clEnumValN(GenCallingConv, "gen-callingconv",
|
||
|
+@@ -135,6 +138,9 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
|
||
|
+ case GenInstrInfo:
|
||
|
+ EmitInstrInfo(Records, OS);
|
||
|
+ break;
|
||
|
++ case MappingInsn:
|
||
|
++ EmitMappingInsn(Records, OS);
|
||
|
++ break;
|
||
|
+ case GenInstrDocs:
|
||
|
+ EmitInstrDocs(Records, OS);
|
||
|
+ break;
|
||
|
+diff --git a/utils/TableGen/TableGenBackends.h b/utils/TableGen/TableGenBackends.h
|
||
|
+index 1329a6d833f..a41e46b1db0 100644
|
||
|
+--- a/utils/TableGen/TableGenBackends.h
|
||
|
++++ b/utils/TableGen/TableGenBackends.h
|
||
|
+@@ -75,6 +75,7 @@ void EmitDFAPacketizer(RecordKeeper &RK, raw_ostream &OS);
|
||
|
+ void EmitDisassembler(RecordKeeper &RK, raw_ostream &OS);
|
||
|
+ void EmitFastISel(RecordKeeper &RK, raw_ostream &OS);
|
||
|
+ void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS);
|
||
|
++void EmitMappingInsn(RecordKeeper &RK, raw_ostream &OS);
|
||
|
+ void EmitInstrDocs(RecordKeeper &RK, raw_ostream &OS);
|
||
|
+ void EmitPseudoLowering(RecordKeeper &RK, raw_ostream &OS);
|
||
|
+ void EmitCompressInst(RecordKeeper &RK, raw_ostream &OS);
|
||
|
+--
|
||
|
+2.19.1
|
||
|
+
|
||
|
diff --git a/llvm/0007-capstone-generate-GenInsnNameMaps.inc.patch b/llvm/0007-capstone-generate-GenInsnNameMaps.inc.patch
|
||
|
new file mode 100644
|
||
|
index 000000000..019540d65
|
||
|
--- /dev/null
|
||
|
+++ b/llvm/0007-capstone-generate-GenInsnNameMaps.inc.patch
|
||
|
@@ -0,0 +1,110 @@
|
||
|
+From b42f9f2014ec49a22077b6610863d9341a74e142 Mon Sep 17 00:00:00 2001
|
||
|
+From: mephi42 <mephi42@gmail.com>
|
||
|
+Date: Fri, 17 Aug 2018 11:07:39 +0200
|
||
|
+Subject: [PATCH 7/7] capstone: generate *GenInsnNameMaps.inc
|
||
|
+
|
||
|
+---
|
||
|
+ lib/Target/SystemZ/CMakeLists.txt | 1 +
|
||
|
+ utils/TableGen/InstrInfoEmitter.cpp | 29 +++++++++++++++++++++++++++++
|
||
|
+ utils/TableGen/TableGen.cpp | 6 ++++++
|
||
|
+ utils/TableGen/TableGenBackends.h | 1 +
|
||
|
+ 4 files changed, 37 insertions(+)
|
||
|
+
|
||
|
+diff --git a/lib/Target/SystemZ/CMakeLists.txt b/lib/Target/SystemZ/CMakeLists.txt
|
||
|
+index 4b5d9c4a3b2..2c64e0a94b8 100644
|
||
|
+--- a/lib/Target/SystemZ/CMakeLists.txt
|
||
|
++++ b/lib/Target/SystemZ/CMakeLists.txt
|
||
|
+@@ -7,6 +7,7 @@ tablegen(LLVM SystemZGenDAGISel.inc -gen-dag-isel)
|
||
|
+ tablegen(LLVM SystemZGenDisassemblerTables.inc -gen-disassembler)
|
||
|
+ tablegen(LLVM SystemZGenInstrInfo.inc -gen-instr-info)
|
||
|
+ tablegen(LLVM SystemZMappingInsn.inc -mapping-insn)
|
||
|
++tablegen(LLVM SystemZGenInsnNameMaps.inc -gen-insn-name-maps)
|
||
|
+ tablegen(LLVM SystemZGenMCCodeEmitter.inc -gen-emitter)
|
||
|
+ tablegen(LLVM SystemZGenRegisterInfo.inc -gen-register-info)
|
||
|
+ tablegen(LLVM SystemZGenSubtargetInfo.inc -gen-subtarget)
|
||
|
+diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp
|
||
|
+index 14ab1ea8a72..ccf8170ca62 100644
|
||
|
+--- a/utils/TableGen/InstrInfoEmitter.cpp
|
||
|
++++ b/utils/TableGen/InstrInfoEmitter.cpp
|
||
|
+@@ -837,6 +837,35 @@ void EmitMappingInsn(RecordKeeper &RK, raw_ostream &OS) {
|
||
|
+ << "},\n";
|
||
|
+ }
|
||
|
+ }
|
||
|
++
|
||
|
++std::string GetMnemonic(const CodeGenInstruction *Inst) {
|
||
|
++ std::string Mnemonic = Inst->AsmString;
|
||
|
++
|
||
|
++ for (size_t i = 0; i < Mnemonic.length(); i++) {
|
||
|
++ if (Mnemonic[i] == '\t') {
|
||
|
++ return Mnemonic.substr(0, i);
|
||
|
++ }
|
||
|
++ }
|
||
|
++ return Mnemonic;
|
||
|
++}
|
||
|
++
|
||
|
++void EmitInsnNameMaps(RecordKeeper &RK, raw_ostream &OS) {
|
||
|
++ OS << "// This is auto-gen data for Capstone engine (www.capstone-engine.org)\n"
|
||
|
++ "// By Nguyen Anh Quynh <aquynh@gmail.com>\n"
|
||
|
++ "\n";
|
||
|
++ CodeGenTarget Target(RK);
|
||
|
++ std::map<std::string, std::string> M;
|
||
|
++ for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
|
||
|
++ if (Inst->TheDef->getValueAsBit("isPseudo") ||
|
||
|
++ Inst->TheDef->getValueAsBit("isCodeGenOnly")) {
|
||
|
++ continue;
|
||
|
++ }
|
||
|
++ M[GetPublicName(Inst)] = GetMnemonic(Inst);
|
||
|
++ }
|
||
|
++ for (auto &P : M) {
|
||
|
++ OS << "\t{ " << P.first << ", \"" << P.second << "\" },\n";
|
||
|
++ }
|
||
|
++}
|
||
|
+ #endif
|
||
|
+
|
||
|
+ } // end llvm namespace
|
||
|
+diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp
|
||
|
+index bbb4e860536..27c6603de5a 100644
|
||
|
+--- a/utils/TableGen/TableGen.cpp
|
||
|
++++ b/utils/TableGen/TableGen.cpp
|
||
|
+@@ -28,6 +28,7 @@ enum ActionType {
|
||
|
+ GenRegisterInfo,
|
||
|
+ GenInstrInfo,
|
||
|
+ MappingInsn,
|
||
|
++ GenInsnNameMaps,
|
||
|
+ GenInstrDocs,
|
||
|
+ GenAsmWriter,
|
||
|
+ GenAsmMatcher,
|
||
|
+@@ -68,6 +69,8 @@ namespace {
|
||
|
+ "Generate instruction descriptions"),
|
||
|
+ clEnumValN(MappingInsn, "mapping-insn",
|
||
|
+ ""),
|
||
|
++ clEnumValN(GenInsnNameMaps, "gen-insn-name-maps",
|
||
|
++ ""),
|
||
|
+ clEnumValN(GenInstrDocs, "gen-instr-docs",
|
||
|
+ "Generate instruction documentation"),
|
||
|
+ clEnumValN(GenCallingConv, "gen-callingconv",
|
||
|
+@@ -141,6 +144,9 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
|
||
|
+ case MappingInsn:
|
||
|
+ EmitMappingInsn(Records, OS);
|
||
|
+ break;
|
||
|
++ case GenInsnNameMaps:
|
||
|
++ EmitInsnNameMaps(Records, OS);
|
||
|
++ break;
|
||
|
+ case GenInstrDocs:
|
||
|
+ EmitInstrDocs(Records, OS);
|
||
|
+ break;
|
||
|
+diff --git a/utils/TableGen/TableGenBackends.h b/utils/TableGen/TableGenBackends.h
|
||
|
+index a41e46b1db0..5656e5be849 100644
|
||
|
+--- a/utils/TableGen/TableGenBackends.h
|
||
|
++++ b/utils/TableGen/TableGenBackends.h
|
||
|
+@@ -76,6 +76,7 @@ void EmitDisassembler(RecordKeeper &RK, raw_ostream &OS);
|
||
|
+ void EmitFastISel(RecordKeeper &RK, raw_ostream &OS);
|
||
|
+ void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS);
|
||
|
+ void EmitMappingInsn(RecordKeeper &RK, raw_ostream &OS);
|
||
|
++void EmitInsnNameMaps(RecordKeeper &RK, raw_ostream &OS);
|
||
|
+ void EmitInstrDocs(RecordKeeper &RK, raw_ostream &OS);
|
||
|
+ void EmitPseudoLowering(RecordKeeper &RK, raw_ostream &OS);
|
||
|
+ void EmitCompressInst(RecordKeeper &RK, raw_ostream &OS);
|
||
|
+--
|
||
|
+2.19.1
|
||
|
+
|
||
|
diff --git a/llvm/lib/Target/RISCV/CMakeLists.txt b/llvm/lib/Target/RISCV/CMakeLists.txt
|
||
|
index 07c32cb31..1821f4b01 100644
|
||
|
--- a/llvm/lib/Target/RISCV/CMakeLists.txt
|
||
|
+++ b/llvm/lib/Target/RISCV/CMakeLists.txt
|
||
|
@@ -6,6 +6,8 @@ tablegen(LLVM RISCVGenCompressInstEmitter.inc -gen-compress-inst-emitter)
|
||
|
tablegen(LLVM RISCVGenDAGISel.inc -gen-dag-isel)
|
||
|
tablegen(LLVM RISCVGenDisassemblerTables.inc -gen-disassembler)
|
||
|
tablegen(LLVM RISCVGenInstrInfo.inc -gen-instr-info)
|
||
|
+tablegen(LLVM RISCVGenMappingInsn.inc -gen-mapping-insn)
|
||
|
+tablegen(LLVM RISCVGenInsnNameMaps.inc -gen-insn-name-maps)
|
||
|
tablegen(LLVM RISCVGenMCCodeEmitter.inc -gen-emitter)
|
||
|
tablegen(LLVM RISCVGenMCPseudoLowering.inc -gen-pseudo-lowering)
|
||
|
tablegen(LLVM RISCVGenRegisterInfo.inc -gen-register-info)
|
||
|
diff --git a/llvm/utils/TableGen/AsmWriterEmitter.cpp b/llvm/utils/TableGen/AsmWriterEmitter.cpp
|
||
|
index 24e16f9c4..c24dc6052 100644
|
||
|
--- a/llvm/utils/TableGen/AsmWriterEmitter.cpp
|
||
|
+++ b/llvm/utils/TableGen/AsmWriterEmitter.cpp
|
||
|
@@ -271,16 +271,22 @@ static void UnescapeString(std::string &Str) {
|
||
|
/// clearing the Instructions vector.
|
||
|
void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
|
||
|
Record *AsmWriter = Target.getAsmWriter();
|
||
|
+#ifndef CAPSTONE
|
||
|
StringRef ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
|
||
|
+#endif
|
||
|
bool PassSubtarget = AsmWriter->getValueAsInt("PassSubtarget");
|
||
|
|
||
|
O <<
|
||
|
"/// printInstruction - This method is automatically generated by tablegen\n"
|
||
|
"/// from the instruction set description.\n"
|
||
|
+#ifdef CAPSTONE
|
||
|
+ "static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI)\n{\n";
|
||
|
+#else
|
||
|
"void " << Target.getName() << ClassName
|
||
|
<< "::printInstruction(const MCInst *MI, "
|
||
|
<< (PassSubtarget ? "const MCSubtargetInfo &STI, " : "")
|
||
|
<< "raw_ostream &O) {\n";
|
||
|
+#endif
|
||
|
|
||
|
// Build an aggregate string, and build a table of offsets into it.
|
||
|
SequenceToOffsetTable<std::string> StringTable;
|
||
|
@@ -378,9 +384,16 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
|
||
|
}
|
||
|
|
||
|
// Emit the string table itself.
|
||
|
+#ifdef CAPSTONE
|
||
|
+ O << "#ifndef CAPSTONE_DIET\n";
|
||
|
+#endif
|
||
|
O << " static const char AsmStrs[] = {\n";
|
||
|
StringTable.emit(O, printChar);
|
||
|
- O << " };\n\n";
|
||
|
+ O << " };\n"
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << "#endif\n"
|
||
|
+#endif
|
||
|
+ << "\n";
|
||
|
|
||
|
// Emit the lookup tables in pieces to minimize wasted bytes.
|
||
|
unsigned BytesNeeded = ((OpcodeInfoBits - BitsLeft) + 7) / 8;
|
||
|
@@ -408,21 +421,45 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
|
||
|
// If the total bits is more than 32-bits we need to use a 64-bit type.
|
||
|
if (BitsLeft < (OpcodeInfoBits - 32))
|
||
|
BitsOS << "(uint64_t)";
|
||
|
- BitsOS << "OpInfo" << Table << "[MI->getOpcode()] << " << Shift << ";\n";
|
||
|
+ BitsOS << "OpInfo" << Table << "["
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << "MCInst_getOpcode(MI)"
|
||
|
+#else
|
||
|
+ << "MI->getOpcode()"
|
||
|
+#endif
|
||
|
+ << "] << " << Shift << ";\n";
|
||
|
// Prepare the shift for the next iteration and increment the table count.
|
||
|
Shift += TableSize;
|
||
|
++Table;
|
||
|
}
|
||
|
|
||
|
// Emit the initial tab character.
|
||
|
+#ifndef CAPSTONE
|
||
|
O << " O << \"\\t\";\n\n";
|
||
|
+#endif
|
||
|
|
||
|
O << " // Emit the opcode for the instruction.\n";
|
||
|
O << BitsString;
|
||
|
|
||
|
// Emit the starting string.
|
||
|
- O << " assert(Bits != 0 && \"Cannot print this instruction.\");\n"
|
||
|
- << " O << AsmStrs+(Bits & " << (1 << AsmStrBits)-1 << ")-1;\n\n";
|
||
|
+ O << " "
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << "// "
|
||
|
+#endif
|
||
|
+ << "assert(Bits != 0 && \"Cannot print this instruction.\");\n"
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << "#ifndef CAPSTONE_DIET\n"
|
||
|
+ << " SStream_concat0(O, "
|
||
|
+#else
|
||
|
+ << " O << "
|
||
|
+#endif
|
||
|
+ << "AsmStrs+(Bits & " << (1 << AsmStrBits)-1 << ")-1"
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << ");\n"
|
||
|
+ << "#endif\n\n";
|
||
|
+#else
|
||
|
+ << ");\n\n";
|
||
|
+#endif
|
||
|
|
||
|
// Output the table driven operand information.
|
||
|
BitsLeft = OpcodeInfoBits-AsmStrBits;
|
||
|
@@ -454,7 +491,11 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
|
||
|
O << " switch ((Bits >> "
|
||
|
<< (OpcodeInfoBits-BitsLeft) << ") & "
|
||
|
<< ((1 << NumBits)-1) << ") {\n"
|
||
|
- << " default: llvm_unreachable(\"Invalid command number.\");\n";
|
||
|
+ << " default: "
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << "assert(0);\n"
|
||
|
+#endif
|
||
|
+ << "llvm_unreachable(\"Invalid command number.\");\n";
|
||
|
|
||
|
// Print out all the cases.
|
||
|
for (unsigned j = 0, e = Commands.size(); j != e; ++j) {
|
||
|
@@ -535,6 +576,9 @@ emitRegisterNameString(raw_ostream &O, StringRef AltName,
|
||
|
}
|
||
|
|
||
|
StringTable.layout();
|
||
|
+#ifdef CAPSTONE
|
||
|
+ O << "#ifndef CAPSTONE_DIET\n";
|
||
|
+#endif
|
||
|
O << " static const char AsmStrs" << AltName << "[] = {\n";
|
||
|
StringTable.emit(O, printChar);
|
||
|
O << " };\n\n";
|
||
|
@@ -551,8 +595,10 @@ emitRegisterNameString(raw_ostream &O, StringRef AltName,
|
||
|
}
|
||
|
|
||
|
void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
|
||
|
+#ifndef CAPSTONE
|
||
|
Record *AsmWriter = Target.getAsmWriter();
|
||
|
StringRef ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
|
||
|
+#endif
|
||
|
const auto &Registers = Target.getRegBank().getRegisters();
|
||
|
const std::vector<Record*> &AltNameIndices = Target.getRegAltNameIndices();
|
||
|
bool hasAltNames = AltNameIndices.size() > 1;
|
||
|
@@ -562,12 +608,22 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
|
||
|
"\n\n/// getRegisterName - This method is automatically generated by tblgen\n"
|
||
|
"/// from the register set description. This returns the assembler name\n"
|
||
|
"/// for the specified register.\n"
|
||
|
+#ifdef CAPSTONE
|
||
|
+ //"static const char *getRegisterName(unsigned RegNo)\n{\n";
|
||
|
+ "static const char *";
|
||
|
+ if (hasAltNames)
|
||
|
+ O << "\ngetRegisterName(unsigned RegNo, unsigned AltIdx)\n{\n";
|
||
|
+ else
|
||
|
+ O << "\ngetRegisterName(unsigned RegNo)\n{\n";
|
||
|
+#else
|
||
|
"const char *" << Target.getName() << ClassName << "::";
|
||
|
if (hasAltNames)
|
||
|
O << "\ngetRegisterName(unsigned RegNo, unsigned AltIdx) {\n";
|
||
|
else
|
||
|
O << "getRegisterName(unsigned RegNo) {\n";
|
||
|
- O << " assert(RegNo && RegNo < " << (Registers.size()+1)
|
||
|
+#endif
|
||
|
+ O << " "
|
||
|
+ << "assert(RegNo && RegNo < " << (Registers.size()+1)
|
||
|
<< " && \"Invalid register number!\");\n"
|
||
|
<< "\n";
|
||
|
|
||
|
@@ -579,12 +635,21 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
|
||
|
|
||
|
if (hasAltNames) {
|
||
|
O << " switch(AltIdx) {\n"
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << " default: assert(0);\n";
|
||
|
+#else
|
||
|
<< " default: llvm_unreachable(\"Invalid register alt name index!\");\n";
|
||
|
+#endif
|
||
|
for (const Record *R : AltNameIndices) {
|
||
|
StringRef AltName = R->getName();
|
||
|
O << " case ";
|
||
|
if (!Namespace.empty())
|
||
|
- O << Namespace << "::";
|
||
|
+ O << Namespace
|
||
|
+#ifndef CAPSTONE
|
||
|
+ << "::";
|
||
|
+#else
|
||
|
+ << "_";
|
||
|
+#endif
|
||
|
O << AltName << ":\n"
|
||
|
<< " assert(*(AsmStrs" << AltName << "+RegAsmOffset" << AltName
|
||
|
<< "[RegNo-1]) &&\n"
|
||
|
@@ -594,10 +659,22 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
|
||
|
}
|
||
|
O << " }\n";
|
||
|
} else {
|
||
|
+#ifdef CAPSTONE
|
||
|
+ O << " //int i;\n"
|
||
|
+ << " //for (i = 0; i < sizeof(RegAsmOffset); i++)\n"
|
||
|
+ << " // printf(\"%s = %u\\n\", AsmStrs+RegAsmOffset[i], i + 1);\n"
|
||
|
+ << " //printf(\"*************************\\n\");\n"
|
||
|
+#else
|
||
|
O << " assert (*(AsmStrs+RegAsmOffset[RegNo-1]) &&\n"
|
||
|
<< " \"Invalid alt name index for register!\");\n"
|
||
|
+#endif
|
||
|
<< " return AsmStrs+RegAsmOffset[RegNo-1];\n";
|
||
|
}
|
||
|
+#ifdef CAPSTONE
|
||
|
+ O << "#else\n"
|
||
|
+ << " return NULL;\n"
|
||
|
+ << "#endif\n";
|
||
|
+#endif
|
||
|
O << "}\n";
|
||
|
}
|
||
|
|
||
|
@@ -1139,9 +1216,21 @@ AsmWriterEmitter::AsmWriterEmitter(RecordKeeper &R) : Records(R), Target(R) {
|
||
|
}
|
||
|
|
||
|
void AsmWriterEmitter::run(raw_ostream &O) {
|
||
|
+#ifdef CAPSTONE
|
||
|
+ O << "/* Capstone Disassembly Engine */\n"
|
||
|
+ "/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */\n"
|
||
|
+ "\n"
|
||
|
+ "#include <stdio.h>\t// debug\n"
|
||
|
+ "#include <capstone/platform.h>\n"
|
||
|
+ "#include <assert.h>\n"
|
||
|
+ "\n"
|
||
|
+ "\n";
|
||
|
+#endif
|
||
|
EmitPrintInstruction(O);
|
||
|
EmitGetRegisterName(O);
|
||
|
+#ifndef CAPSTONE
|
||
|
EmitPrintAliasInstruction(O);
|
||
|
+#endif
|
||
|
}
|
||
|
|
||
|
namespace llvm {
|
||
|
diff --git a/llvm/utils/TableGen/AsmWriterInst.cpp b/llvm/utils/TableGen/AsmWriterInst.cpp
|
||
|
index d065a4209..7266d1eda 100644
|
||
|
--- a/llvm/utils/TableGen/AsmWriterInst.cpp
|
||
|
+++ b/llvm/utils/TableGen/AsmWriterInst.cpp
|
||
|
@@ -27,9 +27,13 @@ static bool isIdentChar(char C) {
|
||
|
|
||
|
std::string AsmWriterOperand::getCode(bool PassSubtarget) const {
|
||
|
if (OperandType == isLiteralTextOperand) {
|
||
|
+#ifdef CAPSTONE
|
||
|
+ return "SStream_concat0(O, \"" + Str + "\");";
|
||
|
+#else
|
||
|
if (Str.size() == 1)
|
||
|
return "O << '" + Str + "';";
|
||
|
return "O << \"" + Str + "\";";
|
||
|
+#endif
|
||
|
}
|
||
|
|
||
|
if (OperandType == isLiteralStatementOperand)
|
||
|
diff --git a/llvm/utils/TableGen/DisassemblerEmitter.cpp b/llvm/utils/TableGen/DisassemblerEmitter.cpp
|
||
|
index 9e75c7fba..1bc0cfa0d 100644
|
||
|
--- a/llvm/utils/TableGen/DisassemblerEmitter.cpp
|
||
|
+++ b/llvm/utils/TableGen/DisassemblerEmitter.cpp
|
||
|
@@ -105,6 +105,11 @@ extern void EmitFixedLenDecoder(RecordKeeper &RK, raw_ostream &OS,
|
||
|
void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) {
|
||
|
CodeGenTarget Target(Records);
|
||
|
emitSourceFileHeader(" * " + Target.getName().str() + " Disassembler", OS);
|
||
|
+#ifdef CAPSTONE
|
||
|
+ OS << "/* Capstone Disassembly Engine */\n"
|
||
|
+ "/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */\n"
|
||
|
+ "\n";
|
||
|
+#endif
|
||
|
|
||
|
// X86 uses a custom disassembler.
|
||
|
if (Target.getName() == "X86") {
|
||
|
@@ -149,7 +154,12 @@ void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) {
|
||
|
}
|
||
|
|
||
|
EmitFixedLenDecoder(Records, OS, Target.getName(),
|
||
|
- "if (", " == MCDisassembler::Fail)",
|
||
|
+ "if (",
|
||
|
+#ifdef CAPSTONE
|
||
|
+ " == MCDisassembler_Fail)",
|
||
|
+#else
|
||
|
+ " == MCDisassembler::Fail)",
|
||
|
+#endif
|
||
|
"MCDisassembler::Success", "MCDisassembler::Fail", "");
|
||
|
}
|
||
|
|
||
|
diff --git a/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp b/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
|
||
|
index ea28e06cc..3db428dfa 100644
|
||
|
--- a/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
|
||
|
+++ b/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
|
||
|
@@ -741,7 +741,13 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
|
||
|
++I;
|
||
|
unsigned Start = *I++;
|
||
|
unsigned Len = *I++;
|
||
|
- OS.indent(Indentation) << "MCD::OPC_ExtractField, " << Start << ", "
|
||
|
+ OS.indent(Indentation)
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << "MCD_OPC_ExtractField"
|
||
|
+#else
|
||
|
+ << "MCD::OPC_ExtractField"
|
||
|
+#endif
|
||
|
+ << ", " << Start << ", "
|
||
|
<< Len << ", // Inst{";
|
||
|
if (Len > 1)
|
||
|
OS << (Start + Len - 1) << "-";
|
||
|
@@ -750,7 +756,13 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
|
||
|
}
|
||
|
case MCD::OPC_FilterValue: {
|
||
|
++I;
|
||
|
- OS.indent(Indentation) << "MCD::OPC_FilterValue, ";
|
||
|
+ OS.indent(Indentation)
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << "MCD_OPC_FilterValue"
|
||
|
+#else
|
||
|
+ << "MCD::OPC_FilterValue"
|
||
|
+#endif
|
||
|
+ << ", ";
|
||
|
// The filter value is ULEB128 encoded.
|
||
|
while (*I >= 128)
|
||
|
OS << (unsigned)*I++ << ", ";
|
||
|
@@ -773,7 +785,13 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
|
||
|
++I;
|
||
|
unsigned Start = *I++;
|
||
|
unsigned Len = *I++;
|
||
|
- OS.indent(Indentation) << "MCD::OPC_CheckField, " << Start << ", "
|
||
|
+ OS.indent(Indentation)
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << "MCD_OPC_CheckField"
|
||
|
+#else
|
||
|
+ << "MCD::OPC_CheckField"
|
||
|
+#endif
|
||
|
+ << ", " << Start << ", "
|
||
|
<< Len << ", ";// << Val << ", " << NumToSkip << ",\n";
|
||
|
// ULEB128 encoded field value.
|
||
|
for (; *I >= 128; ++I)
|
||
|
@@ -794,7 +812,13 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
|
||
|
}
|
||
|
case MCD::OPC_CheckPredicate: {
|
||
|
++I;
|
||
|
- OS.indent(Indentation) << "MCD::OPC_CheckPredicate, ";
|
||
|
+ OS.indent(Indentation)
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << "MCD_OPC_CheckPredicate"
|
||
|
+#else
|
||
|
+ << "MCD::OPC_CheckPredicate"
|
||
|
+#endif
|
||
|
+ << ", ";
|
||
|
for (; *I >= 128; ++I)
|
||
|
OS << (unsigned)*I << ", ";
|
||
|
OS << (unsigned)*I++ << ", ";
|
||
|
@@ -823,7 +847,13 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
|
||
|
&& "ULEB128 value too large!");
|
||
|
// Decode the Opcode value.
|
||
|
unsigned Opc = decodeULEB128(Buffer);
|
||
|
- OS.indent(Indentation) << "MCD::OPC_" << (IsTry ? "Try" : "")
|
||
|
+ OS.indent(Indentation)
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << "MCD_OPC_"
|
||
|
+#else
|
||
|
+ << "MCD::OPC_"
|
||
|
+#endif
|
||
|
+ << (IsTry ? "Try" : "")
|
||
|
<< "Decode, ";
|
||
|
for (p = Buffer; *p >= 128; ++p)
|
||
|
OS << (unsigned)*p << ", ";
|
||
|
@@ -858,7 +888,12 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
|
||
|
}
|
||
|
case MCD::OPC_SoftFail: {
|
||
|
++I;
|
||
|
- OS.indent(Indentation) << "MCD::OPC_SoftFail";
|
||
|
+ OS.indent(Indentation)
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << "MCD_OPC_SoftFail";
|
||
|
+#else
|
||
|
+ << "MCD::OPC_SoftFail";
|
||
|
+#endif
|
||
|
// Positive mask
|
||
|
uint64_t Value = 0;
|
||
|
unsigned Shift = 0;
|
||
|
@@ -890,7 +925,13 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
|
||
|
}
|
||
|
case MCD::OPC_Fail: {
|
||
|
++I;
|
||
|
- OS.indent(Indentation) << "MCD::OPC_Fail,\n";
|
||
|
+ OS.indent(Indentation)
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << "MCD_OPC_Fail"
|
||
|
+#else
|
||
|
+ << "MCD::OPC_Fail"
|
||
|
+#endif
|
||
|
+ << ",\n";
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
@@ -905,23 +946,46 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
|
||
|
void FixedLenDecoderEmitter::
|
||
|
emitPredicateFunction(formatted_raw_ostream &OS, PredicateSet &Predicates,
|
||
|
unsigned Indentation) const {
|
||
|
+#ifdef CAPSTONE
|
||
|
+ OS.indent(Indentation) << "static bool getbool(uint64_t b)\n";
|
||
|
+ OS.indent(Indentation) << "{\n";
|
||
|
+ OS.indent(Indentation) << "\treturn b != 0;\n";
|
||
|
+ OS.indent(Indentation) << "}\n\n";
|
||
|
+#endif
|
||
|
+
|
||
|
// The predicate function is just a big switch statement based on the
|
||
|
// input predicate index.
|
||
|
OS.indent(Indentation) << "static bool checkDecoderPredicate(unsigned Idx, "
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << "uint64_t Bits)\n{\n";
|
||
|
+#else
|
||
|
<< "const FeatureBitset& Bits) {\n";
|
||
|
+#endif
|
||
|
Indentation += 2;
|
||
|
if (!Predicates.empty()) {
|
||
|
OS.indent(Indentation) << "switch (Idx) {\n";
|
||
|
- OS.indent(Indentation) << "default: llvm_unreachable(\"Invalid index!\");\n";
|
||
|
+ OS.indent(Indentation) << "default: "
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << "assert(0);\n"
|
||
|
+#endif
|
||
|
+ << "llvm_unreachable(\"Invalid index!\");\n";
|
||
|
unsigned Index = 0;
|
||
|
for (const auto &Predicate : Predicates) {
|
||
|
OS.indent(Indentation) << "case " << Index++ << ":\n";
|
||
|
- OS.indent(Indentation+2) << "return (" << Predicate << ");\n";
|
||
|
+ OS.indent(Indentation+2) << "return "
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << "getbool"
|
||
|
+#endif
|
||
|
+ << "(" << Predicate << ");\n";
|
||
|
}
|
||
|
OS.indent(Indentation) << "}\n";
|
||
|
} else {
|
||
|
// No case statement to emit
|
||
|
- OS.indent(Indentation) << "llvm_unreachable(\"Invalid index!\");\n";
|
||
|
+ OS.indent(Indentation)
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << "assert(0);\n"
|
||
|
+#endif
|
||
|
+ << "llvm_unreachable(\"Invalid index!\");\n";
|
||
|
}
|
||
|
Indentation -= 2;
|
||
|
OS.indent(Indentation) << "}\n\n";
|
||
|
@@ -932,23 +996,39 @@ emitDecoderFunction(formatted_raw_ostream &OS, DecoderSet &Decoders,
|
||
|
unsigned Indentation) const {
|
||
|
// The decoder function is just a big switch statement based on the
|
||
|
// input decoder index.
|
||
|
+#ifdef CAPSTONE
|
||
|
+#define EDF_EOL " \\\n"
|
||
|
+ OS.indent(Indentation) << "#define DecodeToMCInst(fname,fieldname, InsnType) \\\n";
|
||
|
+ OS.indent(Indentation) << "static DecodeStatus fname(DecodeStatus S, unsigned Idx, InsnType insn, MCInst *MI, \\\n";
|
||
|
+ OS.indent(Indentation) << " uint64_t Address, const void *Decoder) \\\n";
|
||
|
+ OS.indent(Indentation) << "{ \\\n";
|
||
|
+#else
|
||
|
+#define EDF_EOL "\n"
|
||
|
OS.indent(Indentation) << "template<typename InsnType>\n";
|
||
|
OS.indent(Indentation) << "static DecodeStatus decodeToMCInst(DecodeStatus S,"
|
||
|
<< " unsigned Idx, InsnType insn, MCInst &MI,\n";
|
||
|
OS.indent(Indentation) << " uint64_t "
|
||
|
<< "Address, const void *Decoder, bool &DecodeComplete) {\n";
|
||
|
+#endif
|
||
|
Indentation += 2;
|
||
|
+#ifndef CAPSTONE
|
||
|
OS.indent(Indentation) << "DecodeComplete = true;\n";
|
||
|
- OS.indent(Indentation) << "InsnType tmp;\n";
|
||
|
- OS.indent(Indentation) << "switch (Idx) {\n";
|
||
|
- OS.indent(Indentation) << "default: llvm_unreachable(\"Invalid index!\");\n";
|
||
|
+#endif
|
||
|
+ OS.indent(Indentation) << "InsnType tmp;" EDF_EOL;
|
||
|
+ OS.indent(Indentation) << "switch (Idx) {" EDF_EOL;
|
||
|
+ OS.indent(Indentation) << "default:"
|
||
|
+#ifndef CAPSTONE
|
||
|
+ << " llvm_unreachable(\"Invalid index!\");\n";
|
||
|
+#else
|
||
|
+ << " assert(0);\\\n";
|
||
|
+#endif
|
||
|
unsigned Index = 0;
|
||
|
for (const auto &Decoder : Decoders) {
|
||
|
- OS.indent(Indentation) << "case " << Index++ << ":\n";
|
||
|
+ OS.indent(Indentation) << "case " << Index++ << ":" EDF_EOL;
|
||
|
OS << Decoder;
|
||
|
- OS.indent(Indentation+2) << "return S;\n";
|
||
|
+ OS.indent(Indentation+2) << "return S;" EDF_EOL;
|
||
|
}
|
||
|
- OS.indent(Indentation) << "}\n";
|
||
|
+ OS.indent(Indentation) << "}" EDF_EOL;
|
||
|
Indentation -= 2;
|
||
|
OS.indent(Indentation) << "}\n\n";
|
||
|
}
|
||
|
@@ -1075,16 +1155,21 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation,
|
||
|
const std::string &Decoder = OpInfo.Decoder;
|
||
|
|
||
|
if (OpInfo.numFields() != 1)
|
||
|
- o.indent(Indentation) << "tmp = 0;\n";
|
||
|
+ o.indent(Indentation) << "tmp = 0;" EDF_EOL;
|
||
|
|
||
|
for (const EncodingField &EF : OpInfo) {
|
||
|
o.indent(Indentation) << "tmp ";
|
||
|
if (OpInfo.numFields() != 1) o << '|';
|
||
|
- o << "= fieldFromInstruction"
|
||
|
+ o << "= "
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << "fieldname"
|
||
|
+#else
|
||
|
+ << "fieldFromInstruction"
|
||
|
+#endif
|
||
|
<< "(insn, " << EF.Base << ", " << EF.Width << ')';
|
||
|
if (OpInfo.numFields() != 1 || EF.Offset != 0)
|
||
|
o << " << " << EF.Offset;
|
||
|
- o << ";\n";
|
||
|
+ o << ";" EDF_EOL;
|
||
|
}
|
||
|
|
||
|
if (Decoder != "") {
|
||
|
@@ -1092,8 +1177,12 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation,
|
||
|
o.indent(Indentation) << Emitter->GuardPrefix << Decoder
|
||
|
<< "(MI, tmp, Address, Decoder)"
|
||
|
<< Emitter->GuardPostfix
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << " return MCDisassembler_Fail; \\\n";
|
||
|
+#else
|
||
|
<< " { " << (OpHasCompleteDecoder ? "" : "DecodeComplete = false; ")
|
||
|
<< "return MCDisassembler::Fail; }\n";
|
||
|
+#endif
|
||
|
} else {
|
||
|
OpHasCompleteDecoder = true;
|
||
|
o.indent(Indentation) << "MI.addOperand(MCOperand::createImm(tmp));\n";
|
||
|
@@ -1112,7 +1201,13 @@ void FilterChooser::emitDecoder(raw_ostream &OS, unsigned Indentation,
|
||
|
<< "(MI, insn, Address, Decoder)"
|
||
|
<< Emitter->GuardPostfix
|
||
|
<< " { " << (HasCompleteDecoder ? "" : "DecodeComplete = false; ")
|
||
|
- << "return MCDisassembler::Fail; }\n";
|
||
|
+ << "return "
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << "MCDisassembler_Fail"
|
||
|
+#else
|
||
|
+ << "MCDisassembler::Fail"
|
||
|
+#endif
|
||
|
+ << "; }\n";
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
@@ -1150,10 +1245,19 @@ unsigned FilterChooser::getDecoderIndex(DecoderSet &Decoders,
|
||
|
static void emitSinglePredicateMatch(raw_ostream &o, StringRef str,
|
||
|
const std::string &PredicateNamespace) {
|
||
|
if (str[0] == '!')
|
||
|
+#ifdef CAPSTONE
|
||
|
+ o << "~(Bits & " << PredicateNamespace << "_"
|
||
|
+ << str.slice(1,str.size()) << ")";
|
||
|
+#else
|
||
|
o << "!Bits[" << PredicateNamespace << "::"
|
||
|
<< str.slice(1,str.size()) << "]";
|
||
|
+#endif
|
||
|
else
|
||
|
+#ifdef CAPSTONE
|
||
|
+ o << "(Bits & " << PredicateNamespace << "_" << str << ")";
|
||
|
+#else
|
||
|
o << "Bits[" << PredicateNamespace << "::" << str << "]";
|
||
|
+#endif
|
||
|
}
|
||
|
|
||
|
bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation,
|
||
|
@@ -2090,7 +2194,18 @@ static void emitFieldFromInstruction(formatted_raw_ostream &OS) {
|
||
|
<< "// * Support shift (<<, >>) with signed and unsigned integers on the "
|
||
|
"RHS\n"
|
||
|
<< "// * Support put (<<) to raw_ostream&\n"
|
||
|
- << "template<typename InsnType>\n"
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << "#define FieldFromInstruction(fname, InsnType) \\\n"
|
||
|
+ << "static InsnType fname(InsnType insn, unsigned startBit, unsigned numBits) \\\n"
|
||
|
+ << "{ \\\n"
|
||
|
+ << " InsnType fieldMask; \\\n"
|
||
|
+ << " if (numBits == sizeof(InsnType)*8) \\\n"
|
||
|
+ << " fieldMask = (InsnType)(-1LL); \\\n"
|
||
|
+ << " else \\\n"
|
||
|
+ << " fieldMask = (((InsnType)1 << numBits) - 1) << startBit; \\\n"
|
||
|
+ << " return (insn & fieldMask) >> startBit; \\\n"
|
||
|
+#else
|
||
|
+ << "template<typename InsnType>\n"
|
||
|
<< "#if defined(_MSC_VER) && !defined(__clang__)\n"
|
||
|
<< "__declspec(noinline)\n"
|
||
|
<< "#endif\n"
|
||
|
@@ -2127,12 +2242,239 @@ static void emitFieldFromInstruction(formatted_raw_ostream &OS) {
|
||
|
<< " unsigned numBits) {\n"
|
||
|
<< " return fieldFromInstruction(insn, startBit, numBits, "
|
||
|
"std::is_integral<InsnType>());\n"
|
||
|
+#endif
|
||
|
<< "}\n\n";
|
||
|
}
|
||
|
|
||
|
// emitDecodeInstruction - Emit the templated helper function
|
||
|
// decodeInstruction().
|
||
|
static void emitDecodeInstruction(formatted_raw_ostream &OS) {
|
||
|
+
|
||
|
+#if 0
|
||
|
+ OS << "#define DecodeInstruction(fname, fieldname, decoder, InsnType) \\\n"
|
||
|
+ << "static DecodeStatus fname(const uint8_t DecodeTable[], MCInst *MI, \\\n"
|
||
|
+ << " InsnType insn, uint64_t Address, const MCRegisterInfo *MRI, int feature) \\\n"
|
||
|
+ << "{ \\\n"
|
||
|
+ << " uint64_t Bits = getFeatureBits(feature); \\\n"
|
||
|
+ << " const uint8_t *Ptr = DecodeTable; \\\n"
|
||
|
+ << " uint32_t CurFieldValue = 0, ExpectedValue; \\\n"
|
||
|
+ << " DecodeStatus S = MCDisassembler_Success; \\\n"
|
||
|
+ << " unsigned Start, Len, NumToSkip, PIdx, Opc, DecodeIdx; \\\n"
|
||
|
+ << " InsnType Val, FieldValue, PositiveMask, NegativeMask; \\\n"
|
||
|
+ << " bool Pred, Fail; \\\n"
|
||
|
+ << " for (;;) { \\\n"
|
||
|
+ << " switch (*Ptr) { \\\n"
|
||
|
+ << " default: \\\n"
|
||
|
+ << " return MCDisassembler_Fail; \\\n"
|
||
|
+ << " case MCD_OPC_ExtractField: { \\\n"
|
||
|
+ << " Start = *++Ptr; \\\n"
|
||
|
+ << " Len = *++Ptr; \\\n"
|
||
|
+ << " ++Ptr; \\\n"
|
||
|
+ << " CurFieldValue = (uint32_t)fieldname(insn, Start, Len); \\\n"
|
||
|
+ << " break; \\\n"
|
||
|
+ << " } \\\n"
|
||
|
+ << " case MCD_OPC_FilterValue: { \\\n"
|
||
|
+ << " Val = (InsnType)decodeULEB128(++Ptr, &Len); \\\n"
|
||
|
+ << " Ptr += Len; \\\n"
|
||
|
+ << " NumToSkip = *Ptr++; \\\n"
|
||
|
+ << " NumToSkip |= (*Ptr++) << 8; \\\n"
|
||
|
+ << " if (Val != CurFieldValue) \\\n"
|
||
|
+ << " Ptr += NumToSkip; \\\n"
|
||
|
+ << " break; \\\n"
|
||
|
+ << " } \\\n"
|
||
|
+ << " case MCD_OPC_CheckField: { \\\n"
|
||
|
+ << " Start = *++Ptr; \\\n"
|
||
|
+ << " Len = *++Ptr; \\\n"
|
||
|
+ << " FieldValue = fieldname(insn, Start, Len); \\\n"
|
||
|
+ << " ExpectedValue = (uint32_t)decodeULEB128(++Ptr, &Len); \\\n"
|
||
|
+ << " Ptr += Len; \\\n"
|
||
|
+ << " NumToSkip = *Ptr++; \\\n"
|
||
|
+ << " NumToSkip |= (*Ptr++) << 8; \\\n"
|
||
|
+ << " if (ExpectedValue != FieldValue) \\\n"
|
||
|
+ << " Ptr += NumToSkip; \\\n"
|
||
|
+ << " break; \\\n"
|
||
|
+ << " } \\\n"
|
||
|
+ << " case MCD_OPC_CheckPredicate: { \\\n"
|
||
|
+ << " PIdx = (uint32_t)decodeULEB128(++Ptr, &Len); \\\n"
|
||
|
+ << " Ptr += Len; \\\n"
|
||
|
+ << " NumToSkip = *Ptr++; \\\n"
|
||
|
+ << " NumToSkip |= (*Ptr++) << 8; \\\n"
|
||
|
+ << " Pred = checkDecoderPredicate(PIdx, Bits); \\\n"
|
||
|
+ << " if (!Pred) \\\n"
|
||
|
+ << " Ptr += NumToSkip; \\\n"
|
||
|
+ << " (void)Pred; \\\n"
|
||
|
+ << " break; \\\n"
|
||
|
+ << " } \\\n"
|
||
|
+ << " case MCD_OPC_Decode: { \\\n"
|
||
|
+ << " Opc = (unsigned)decodeULEB128(++Ptr, &Len); \\\n"
|
||
|
+ << " Ptr += Len; \\\n"
|
||
|
+ << " DecodeIdx = (unsigned)decodeULEB128(Ptr, &Len); \\\n"
|
||
|
+ << " Ptr += Len; \\\n"
|
||
|
+ << " MCInst_setOpcode(MI, Opc); \\\n"
|
||
|
+ << " return decoder(S, DecodeIdx, insn, MI, Address, MRI); \\\n"
|
||
|
+ << " } \\\n"
|
||
|
+ << " case MCD_OPC_SoftFail: { \\\n"
|
||
|
+ << " PositiveMask = (InsnType)decodeULEB128(++Ptr, &Len); \\\n"
|
||
|
+ << " Ptr += Len; \\\n"
|
||
|
+ << " NegativeMask = (InsnType)decodeULEB128(Ptr, &Len); \\\n"
|
||
|
+ << " Ptr += Len; \\\n"
|
||
|
+ << " Fail = (insn & PositiveMask) || (~insn & NegativeMask); \\\n"
|
||
|
+ << " if (Fail) \\\n"
|
||
|
+ << " S = MCDisassembler_SoftFail; \\\n"
|
||
|
+ << " break; \\\n"
|
||
|
+ << " } \\\n"
|
||
|
+ << " case MCD_OPC_Fail: { \\\n"
|
||
|
+ << " return MCDisassembler_Fail; \\\n"
|
||
|
+ << " } \\\n"
|
||
|
+ << " } \\\n"
|
||
|
+ << " } \\\n"
|
||
|
+#endif
|
||
|
+
|
||
|
+#ifdef CAPSTONE
|
||
|
+ OS << "static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], "
|
||
|
+
|
||
|
+ "MCInst *MI,\\\n"
|
||
|
+ << " InsnType insn, uint64_t "
|
||
|
+ "Address,\\\n"
|
||
|
+ << " const void *DisAsm,\\\n"
|
||
|
+ << " int feature) {\\\n"
|
||
|
+ << " uint64_t Bits = getFeatureBits(feature); \\\n"
|
||
|
+ //<< " const FeatureBitset& Bits = STI.getFeatureBits();\n"
|
||
|
+ << "\\\n"
|
||
|
+ << " const uint8_t *Ptr = DecodeTable;\\\n"
|
||
|
+ << " uint32_t CurFieldValue = 0;\\\n"
|
||
|
+ << " DecodeStatus S = MCDisassembler_Success;\\\n"
|
||
|
+ << " while (true) {\\\n"
|
||
|
+ << " ptrdiff_t Loc = Ptr - DecodeTable;\\\n"
|
||
|
+ << " switch (*Ptr) {\\\n"
|
||
|
+ << " default:\\\n"
|
||
|
+ << " return MCDisassembler_Fail;\\\n"
|
||
|
+ << " case MCD_OPC_ExtractField: {\\\n"
|
||
|
+ << " unsigned Start = *++Ptr;\\\n"
|
||
|
+ << " unsigned Len = *++Ptr;\\\n"
|
||
|
+ << " ++Ptr;\\\n"
|
||
|
+ << " CurFieldValue = fieldFromInstruction(insn, Start, Len);\\\n"
|
||
|
+ << " break;\\\n"
|
||
|
+ << " }\\\n"
|
||
|
+ << " case MCD_OPC_FilterValue: {\\\n"
|
||
|
+ << " // Decode the field value.\\\n"
|
||
|
+ << " unsigned Len;\\\n"
|
||
|
+ << " InsnType Val = decodeULEB128(++Ptr, &Len);\\\n"
|
||
|
+ << " Ptr += Len;\\\n"
|
||
|
+ << " // NumToSkip is a plain 24-bit integer.\\\n"
|
||
|
+ << " unsigned NumToSkip = *Ptr++;\\\n"
|
||
|
+ << " NumToSkip |= (*Ptr++) << 8;\\\n"
|
||
|
+ << " NumToSkip |= (*Ptr++) << 16;\\\n"
|
||
|
+ << "\\\n"
|
||
|
+ << " // Perform the filter operation.\\\n"
|
||
|
+ << " if (Val != CurFieldValue)\\\n"
|
||
|
+ << " Ptr += NumToSkip;\\\n"
|
||
|
+ << "\\\n"
|
||
|
+ << " break;\\\n"
|
||
|
+ << " }\\\n"
|
||
|
+ << " case MCD_OPC_CheckField: {\\\n"
|
||
|
+ << " unsigned Start = *++Ptr;\\\n"
|
||
|
+ << " unsigned Len = *++Ptr;\\\n"
|
||
|
+ << " InsnType FieldValue = fieldFromInstruction(insn, Start, Len);\\\n"
|
||
|
+ << " // Decode the field value.\\\n"
|
||
|
+ << " uint32_t ExpectedValue = decodeULEB128(++Ptr, &Len);\\\n"
|
||
|
+ << " Ptr += Len;\\\n"
|
||
|
+ << " // NumToSkip is a plain 24-bit integer.\\\n"
|
||
|
+ << " unsigned NumToSkip = *Ptr++;\\\n"
|
||
|
+ << " NumToSkip |= (*Ptr++) << 8;\\\n"
|
||
|
+ << " NumToSkip |= (*Ptr++) << 16;\\\n"
|
||
|
+ << "\\\n"
|
||
|
+ << " // If the actual and expected values don't match, skip.\\\n"
|
||
|
+ << " if (ExpectedValue != FieldValue)\\\n"
|
||
|
+ << " Ptr += NumToSkip;\\\n"
|
||
|
+ << " break;\\\n"
|
||
|
+ << " }\\\n"
|
||
|
+ << " case MCD_OPC_CheckPredicate: {\\\n"
|
||
|
+ << " unsigned Len;\\\n"
|
||
|
+ << " // Decode the Predicate Index value.\\\n"
|
||
|
+ << " unsigned PIdx = decodeULEB128(++Ptr, &Len);\\\n"
|
||
|
+ << " Ptr += Len;\\\n"
|
||
|
+ << " // NumToSkip is a plain 24-bit integer.\\\n"
|
||
|
+ << " unsigned NumToSkip = *Ptr++;\\\n"
|
||
|
+ << " NumToSkip |= (*Ptr++) << 8;\\\n"
|
||
|
+ << " NumToSkip |= (*Ptr++) << 16;\\\n"
|
||
|
+ << " // Check the predicate.\\\n"
|
||
|
+ << " bool Pred;\\\n"
|
||
|
+ << " if (!(Pred = checkDecoderPredicate(PIdx, Bits)))\\\n"
|
||
|
+ << " Ptr += NumToSkip;\\\n"
|
||
|
+ << " (void)Pred;\\\n"
|
||
|
+ << " break;\\\n"
|
||
|
+ << " }\\\n"
|
||
|
+ << " case MCD_OPC_Decode: {\\\n"
|
||
|
+ << " unsigned Len;\\\n"
|
||
|
+ << " // Decode the Opcode value.\\\n"
|
||
|
+ << " unsigned Opc = decodeULEB128(++Ptr, &Len);\\\n"
|
||
|
+ << " Ptr += Len;\\\n"
|
||
|
+ << " unsigned DecodeIdx = decodeULEB128(Ptr, &Len);\\\n"
|
||
|
+ << " Ptr += Len;\\\n"
|
||
|
+ << "\\\n"
|
||
|
+ << " MCInst_clear(MI);\\\n"
|
||
|
+ << " MCInst_setOpcode(MI, Opc);\\\n"
|
||
|
+ << " bool DecodeComplete;\\\n"
|
||
|
+ << " S = decodeToMCInst(S, DecodeIdx, insn, MI, Address, DisAsm, "
|
||
|
+ "DecodeComplete);\\\n"
|
||
|
+ << " assert(DecodeComplete);\\\n"
|
||
|
+ << "\\\n"
|
||
|
+ << " return S;\\\n"
|
||
|
+ << " }\\\n"
|
||
|
+ << " case MCD_OPC_TryDecode: {\\\n"
|
||
|
+ << " unsigned Len;\\\n"
|
||
|
+ << " // Decode the Opcode value.\\\n"
|
||
|
+ << " unsigned Opc = decodeULEB128(++Ptr, &Len);\\\n"
|
||
|
+ << " Ptr += Len;\\\n"
|
||
|
+ << " unsigned DecodeIdx = decodeULEB128(Ptr, &Len);\\\n"
|
||
|
+ << " Ptr += Len;\\\n"
|
||
|
+ << " // NumToSkip is a plain 24-bit integer.\\\n"
|
||
|
+ << " unsigned NumToSkip = *Ptr++;\\\n"
|
||
|
+ << " NumToSkip |= (*Ptr++) << 8;\\\n"
|
||
|
+ << " NumToSkip |= (*Ptr++) << 16;\\\n"
|
||
|
+ << "\\\n"
|
||
|
+ << " // Perform the decode operation.\\\n"
|
||
|
+ << " MCInst TmpMI;\\\n"
|
||
|
+ << " MCInst_setOpcode(&TmpMI, Opc);\\\n"
|
||
|
+ << " bool DecodeComplete;\n"
|
||
|
+ << " S = decodeToMCInst(S, DecodeIdx, insn, &TmpMI, Address, DisAsm, "
|
||
|
+ "DecodeComplete);\\\n"
|
||
|
+ << " if (DecodeComplete) {\\\n"
|
||
|
+ << " // Decoding complete.\\\n"
|
||
|
+ << " MI = &TmpMI;\\\n"
|
||
|
+ << " return S;\\\n"
|
||
|
+ << " } else {\\\n"
|
||
|
+ << " assert(S == MCDisassembler_Fail);\\\n"
|
||
|
+ << " // If the decoding was incomplete, skip.\\\n"
|
||
|
+ << " Ptr += NumToSkip;\\\n"
|
||
|
+ << " // Reset decode status. This also drops a SoftFail status "
|
||
|
+ "that could be\\\n"
|
||
|
+ << " // set before the decode attempt.\\\n"
|
||
|
+ << " S = MCDisassembler_Success;\\\n"
|
||
|
+ << " }\\\n"
|
||
|
+ << " break;\\\n"
|
||
|
+ << " }\\\n"
|
||
|
+ << " case MCD_OPC_SoftFail: {\\\n"
|
||
|
+ << " // Decode the mask values.\\\n"
|
||
|
+ << " unsigned Len;\\\n"
|
||
|
+ << " InsnType PositiveMask = decodeULEB128(++Ptr, &Len);\\\n"
|
||
|
+ << " Ptr += Len;\\\n"
|
||
|
+ << " InsnType NegativeMask = decodeULEB128(Ptr, &Len);\\\n"
|
||
|
+ << " Ptr += Len;\\\n"
|
||
|
+ << " bool Fail = (insn & PositiveMask) || (~insn & NegativeMask);\\\n"
|
||
|
+ << " if (Fail)\\\n"
|
||
|
+ << " S = MCDisassembler_SoftFail;\\\n"
|
||
|
+ << " break;\\\n"
|
||
|
+ << " }\\\n"
|
||
|
+ << " case MCD_OPC_Fail: {\\\n"
|
||
|
+ << " return MCDisassembler_Fail;\\\n"
|
||
|
+ << " }\\\n"
|
||
|
+ << " }\\\n"
|
||
|
+ << " }\\\n"
|
||
|
+ << " assert(0);\\\n"
|
||
|
+
|
||
|
+#else
|
||
|
OS << "template<typename InsnType>\n"
|
||
|
<< "static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], "
|
||
|
"MCInst &MI,\n"
|
||
|
@@ -2313,12 +2655,19 @@ static void emitDecodeInstruction(formatted_raw_ostream &OS) {
|
||
|
<< " }\n"
|
||
|
<< " llvm_unreachable(\"bogosity detected in disassembler state "
|
||
|
"machine!\");\n"
|
||
|
+#endif
|
||
|
<< "}\n\n";
|
||
|
}
|
||
|
|
||
|
// Emits disassembler code for instruction decoding.
|
||
|
void FixedLenDecoderEmitter::run(raw_ostream &o) {
|
||
|
formatted_raw_ostream OS(o);
|
||
|
+#ifdef CAPSTONE
|
||
|
+ OS << "#include \"../../MCInst.h\"\n";
|
||
|
+ OS << "#include \"../../LEB128.h\"\n";
|
||
|
+ OS << "#include <assert.h>\n";
|
||
|
+ OS << "\n";
|
||
|
+#else
|
||
|
OS << "#include \"llvm/MC/MCInst.h\"\n";
|
||
|
OS << "#include \"llvm/Support/Debug.h\"\n";
|
||
|
OS << "#include \"llvm/Support/DataTypes.h\"\n";
|
||
|
@@ -2327,6 +2676,7 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) {
|
||
|
OS << "#include <assert.h>\n";
|
||
|
OS << '\n';
|
||
|
OS << "namespace llvm {\n\n";
|
||
|
+#endif
|
||
|
|
||
|
emitFieldFromInstruction(OS);
|
||
|
|
||
|
@@ -2401,7 +2751,13 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) {
|
||
|
// Emit the main entry point for the decoder, decodeInstruction().
|
||
|
emitDecodeInstruction(OS);
|
||
|
|
||
|
+#ifdef CAPSTONE
|
||
|
+ OS << "FieldFromInstruction(fieldFromInstruction, uint64_t)\n";
|
||
|
+ OS << "DecodeToMCInst(decodeToMCInst, fieldFromInstruction, uint64_t)\n";
|
||
|
+ OS << "DecodeInstruction(decodeInstruction, fieldFromInstruction, decodeToMCInst, uint64_t)\n";
|
||
|
+#else
|
||
|
OS << "\n} // End llvm namespace\n";
|
||
|
+#endif
|
||
|
}
|
||
|
|
||
|
namespace llvm {
|
||
|
diff --git a/llvm/utils/TableGen/InstrInfoEmitter.cpp b/llvm/utils/TableGen/InstrInfoEmitter.cpp
|
||
|
index fd8775023..797f42a50 100644
|
||
|
--- a/llvm/utils/TableGen/InstrInfoEmitter.cpp
|
||
|
+++ b/llvm/utils/TableGen/InstrInfoEmitter.cpp
|
||
|
@@ -92,6 +92,7 @@ private:
|
||
|
|
||
|
} // end anonymous namespace
|
||
|
|
||
|
+#ifndef CAPSTONE
|
||
|
static void PrintDefList(const std::vector<Record*> &Uses,
|
||
|
unsigned Num, raw_ostream &OS) {
|
||
|
OS << "static const MCPhysReg ImplicitList" << Num << "[] = { ";
|
||
|
@@ -99,6 +100,7 @@ static void PrintDefList(const std::vector<Record*> &Uses,
|
||
|
OS << getQualifiedName(U) << ", ";
|
||
|
OS << "0 };\n";
|
||
|
}
|
||
|
+#endif
|
||
|
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
// Operand Info Emission.
|
||
|
@@ -434,8 +436,17 @@ void InstrInfoEmitter::emitTIIHelperMethods(raw_ostream &OS,
|
||
|
// run - Emit the main instruction description records for the target...
|
||
|
void InstrInfoEmitter::run(raw_ostream &OS) {
|
||
|
emitSourceFileHeader("Target Instruction Enum Values and Descriptors", OS);
|
||
|
+
|
||
|
+#ifdef CAPSTONE
|
||
|
+ OS << "/* Capstone Disassembly Engine */\n"
|
||
|
+ "/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */\n"
|
||
|
+ "\n"
|
||
|
+ "\n";
|
||
|
+#endif
|
||
|
+
|
||
|
emitEnums(OS);
|
||
|
|
||
|
+#ifndef CAPSTONE
|
||
|
OS << "#ifdef GET_INSTRINFO_MC_DESC\n";
|
||
|
OS << "#undef GET_INSTRINFO_MC_DESC\n";
|
||
|
|
||
|
@@ -563,6 +574,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
|
||
|
emitOperandTypesEnum(OS, Target);
|
||
|
|
||
|
emitMCIIHelperMethods(OS, TargetName);
|
||
|
+#endif
|
||
|
}
|
||
|
|
||
|
void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
|
||
|
@@ -680,7 +692,9 @@ void InstrInfoEmitter::emitEnums(raw_ostream &OS) {
|
||
|
OS << "#ifdef GET_INSTRINFO_ENUM\n";
|
||
|
OS << "#undef GET_INSTRINFO_ENUM\n";
|
||
|
|
||
|
+#ifndef CAPSTONE
|
||
|
OS << "namespace llvm {\n\n";
|
||
|
+#endif
|
||
|
|
||
|
CodeGenTarget Target(Records);
|
||
|
|
||
|
@@ -690,17 +704,39 @@ void InstrInfoEmitter::emitEnums(raw_ostream &OS) {
|
||
|
if (Namespace.empty())
|
||
|
PrintFatalError("No instructions defined!");
|
||
|
|
||
|
+#ifndef CAPSTONE
|
||
|
OS << "namespace " << Namespace << " {\n";
|
||
|
- OS << " enum {\n";
|
||
|
+#endif
|
||
|
+#ifdef CAPSTONE
|
||
|
+ OS << "\n"
|
||
|
+#else
|
||
|
+ OS << " "
|
||
|
+#endif
|
||
|
+ << "enum {\n";
|
||
|
unsigned Num = 0;
|
||
|
for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue())
|
||
|
- OS << " " << Inst->TheDef->getName() << "\t= " << Num++ << ",\n";
|
||
|
- OS << " INSTRUCTION_LIST_END = " << Num << "\n";
|
||
|
+ OS << " "
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << Target.getName() << "_"
|
||
|
+#endif
|
||
|
+ << Inst->TheDef->getName() << "\t= " << Num++ << ",\n";
|
||
|
+ OS << " "
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << Target.getName() << "_"
|
||
|
+#endif
|
||
|
+ << "INSTRUCTION_LIST_END = " << Num << "\n";
|
||
|
OS << " };\n\n";
|
||
|
+#ifndef CAPSTONE
|
||
|
OS << "} // end " << Namespace << " namespace\n";
|
||
|
OS << "} // end llvm namespace\n";
|
||
|
- OS << "#endif // GET_INSTRINFO_ENUM\n\n";
|
||
|
-
|
||
|
+#endif
|
||
|
+ OS << "#endif // GET_INSTRINFO_ENUM\n"
|
||
|
+#ifndef CAPSTONE
|
||
|
+ << "\n"
|
||
|
+#endif
|
||
|
+ ;
|
||
|
+
|
||
|
+#ifndef CAPSTONE
|
||
|
OS << "#ifdef GET_INSTRINFO_SCHED_ENUM\n";
|
||
|
OS << "#undef GET_INSTRINFO_SCHED_ENUM\n";
|
||
|
OS << "namespace llvm {\n\n";
|
||
|
@@ -717,13 +753,140 @@ void InstrInfoEmitter::emitEnums(raw_ostream &OS) {
|
||
|
OS << "} // end llvm namespace\n";
|
||
|
|
||
|
OS << "#endif // GET_INSTRINFO_SCHED_ENUM\n\n";
|
||
|
+#endif
|
||
|
}
|
||
|
|
||
|
namespace llvm {
|
||
|
|
||
|
void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS) {
|
||
|
InstrInfoEmitter(RK).run(OS);
|
||
|
+#ifndef CAPSTONE
|
||
|
EmitMapTable(RK, OS);
|
||
|
+#endif
|
||
|
+}
|
||
|
+
|
||
|
+#ifdef CAPSTONE
|
||
|
+std::string GetPublicName(const CodeGenInstruction *Inst) {
|
||
|
+ std::string Name = Inst->TheDef->getName();
|
||
|
+ // Apply backward compatibility fixups.
|
||
|
+ // BRNLE -> BNLER.
|
||
|
+ if (Name.length() >= 5 && Name.substr(0, 5) == "BRAsm") {
|
||
|
+ Name = "B" + Name.substr(5, Name.length() - 5) + "R";
|
||
|
+ }
|
||
|
+ // SSKEOpt -> SSKE.
|
||
|
+ while (Name.length() >= 3 && Name.substr(Name.length() - 3, 3) == "Opt") {
|
||
|
+ Name = Name.substr(0, Name.length() - 3);
|
||
|
+ }
|
||
|
+ // BRCLAsm -> BRCL.
|
||
|
+ while (true) {
|
||
|
+ size_t pos = Name.find("Asm");
|
||
|
+ if (pos == std::string::npos) {
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ Name = Name.substr(0, pos) + Name.substr(pos + 3);
|
||
|
+ }
|
||
|
+ // CPSDRxx -> CPSDR.
|
||
|
+ if (Name.length() >= 2) {
|
||
|
+ std::string Suffix2 = Name.substr(Name.length() - 2, 2);
|
||
|
+ if (Suffix2 == "dd" || Suffix2 == "ds" ||
|
||
|
+ Suffix2 == "sd" || Suffix2 == "ss") {
|
||
|
+ Name = Name.substr(0, Name.length() - 2);
|
||
|
+ }
|
||
|
+ }
|
||
|
+ return "SYSZ_INS_" + Name;
|
||
|
+}
|
||
|
+
|
||
|
+std::string GetRegisterName(Record *Reg) {
|
||
|
+ std::string Name = Reg->getName();
|
||
|
+ for (char& c : Name) {
|
||
|
+ c = toupper(c);
|
||
|
+ }
|
||
|
+ // R0L, R0D -> R0.
|
||
|
+ if (Name.length() >= 3 &&
|
||
|
+ Name[Name.length() - 3] == 'R' &&
|
||
|
+ (Name[Name.length() - 1] == 'L' ||
|
||
|
+ Name[Name.length() - 1] == 'D')) {
|
||
|
+ Name = Name.substr(0, Name.length() - 3) + Name[Name.length() - 2];
|
||
|
+ }
|
||
|
+ return "SYSZ_REG_" + Name;
|
||
|
+}
|
||
|
+
|
||
|
+std::string GetGroupName(Record *Pred) {
|
||
|
+ std::string Name = Pred->getName();
|
||
|
+ for (char& c : Name) {
|
||
|
+ c = toupper(c);
|
||
|
+ }
|
||
|
+ if (Name.length() >= 7 && Name.substr(0, 7) == "FEATURE") {
|
||
|
+ Name = Name.substr(7);
|
||
|
+ }
|
||
|
+ return "SYSZ_GRP_" + Name;
|
||
|
+}
|
||
|
+
|
||
|
+void EmitMappingInsn(RecordKeeper &RK, raw_ostream &OS) {
|
||
|
+ OS << "// This is auto-gen data for Capstone engine (www.capstone-engine.org)\n"
|
||
|
+ "// By Nguyen Anh Quynh <aquynh@gmail.com>\n"
|
||
|
+ "\n";
|
||
|
+ CodeGenTarget Target(RK);
|
||
|
+ for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
|
||
|
+ if (Inst->TheDef->getValueAsBit("isPseudo") ||
|
||
|
+ Inst->TheDef->getValueAsBit("isCodeGenOnly")) {
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+ OS << "{\n"
|
||
|
+ << "\t" << Target.getName() << "_" << Inst->TheDef->getName() << ", "
|
||
|
+ << GetPublicName(Inst) << ",\n"
|
||
|
+ << "#ifndef CAPSTONE_DIET\n"
|
||
|
+ << "\t{ ";
|
||
|
+ for (Record *Use : Inst->TheDef->getValueAsListOfDefs("Uses")) {
|
||
|
+ OS << GetRegisterName(Use) << ", ";
|
||
|
+ }
|
||
|
+ OS << "0 }, { ";
|
||
|
+ for (Record *Def : Inst->TheDef->getValueAsListOfDefs("Defs")) {
|
||
|
+ OS << GetRegisterName(Def) << ", ";
|
||
|
+ }
|
||
|
+ OS << "0 }, { ";
|
||
|
+ ListInit *Predicates = Inst->TheDef->getValueAsListInit("Predicates");
|
||
|
+ for (unsigned i = 0; i < Predicates->size(); ++i) {
|
||
|
+ OS << GetGroupName(Predicates->getElementAsRecord(i)) << ", ";
|
||
|
+ }
|
||
|
+ OS << "0 }, "
|
||
|
+ << Inst->TheDef->getValueAsBit("isBranch")
|
||
|
+ << ", "
|
||
|
+ << Inst->TheDef->getValueAsBit("isIndirectBranch")
|
||
|
+ << "\n"
|
||
|
+ << "#endif\n"
|
||
|
+ << "},\n";
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+std::string GetMnemonic(const CodeGenInstruction *Inst) {
|
||
|
+ std::string Mnemonic = Inst->AsmString;
|
||
|
+
|
||
|
+ for (size_t i = 0; i < Mnemonic.length(); i++) {
|
||
|
+ if (Mnemonic[i] == '\t') {
|
||
|
+ return Mnemonic.substr(0, i);
|
||
|
+ }
|
||
|
+ }
|
||
|
+ return Mnemonic;
|
||
|
+}
|
||
|
+
|
||
|
+void EmitInsnNameMaps(RecordKeeper &RK, raw_ostream &OS) {
|
||
|
+ OS << "// This is auto-gen data for Capstone engine (www.capstone-engine.org)\n"
|
||
|
+ "// By Nguyen Anh Quynh <aquynh@gmail.com>\n"
|
||
|
+ "\n";
|
||
|
+ CodeGenTarget Target(RK);
|
||
|
+ std::map<std::string, std::string> M;
|
||
|
+ for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
|
||
|
+ if (Inst->TheDef->getValueAsBit("isPseudo") ||
|
||
|
+ Inst->TheDef->getValueAsBit("isCodeGenOnly")) {
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+ M[GetPublicName(Inst)] = GetMnemonic(Inst);
|
||
|
+ }
|
||
|
+ for (auto &P : M) {
|
||
|
+ OS << "\t{ " << P.first << ", \"" << P.second << "\" },\n";
|
||
|
+ }
|
||
|
}
|
||
|
+#endif
|
||
|
|
||
|
} // end llvm namespace
|
||
|
diff --git a/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/llvm/utils/TableGen/RegisterInfoEmitter.cpp
|
||
|
index 1b619072c..0df306680 100644
|
||
|
--- a/llvm/utils/TableGen/RegisterInfoEmitter.cpp
|
||
|
+++ b/llvm/utils/TableGen/RegisterInfoEmitter.cpp
|
||
|
@@ -98,6 +98,12 @@ private:
|
||
|
|
||
|
} // end anonymous namespace
|
||
|
|
||
|
+#ifdef CAPSTONE
|
||
|
+#define NAME_PREFIX Target.getName() << "_" <<
|
||
|
+#else
|
||
|
+#define NAME_PREFIX
|
||
|
+#endif
|
||
|
+
|
||
|
// runEnums - Print out enum values for all of the registers.
|
||
|
void RegisterInfoEmitter::runEnums(raw_ostream &OS,
|
||
|
CodeGenTarget &Target, CodeGenRegBank &Bank) {
|
||
|
@@ -106,13 +112,22 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
|
||
|
// Register enums are stored as uint16_t in the tables. Make sure we'll fit.
|
||
|
assert(Registers.size() <= 0xffff && "Too many regs to fit in tables");
|
||
|
|
||
|
+#ifndef CAPSTONE
|
||
|
StringRef Namespace = Registers.front().TheDef->getValueAsString("Namespace");
|
||
|
+#endif
|
||
|
|
||
|
emitSourceFileHeader("Target Register Enum Values", OS);
|
||
|
|
||
|
+#ifdef CAPSTONE
|
||
|
+ OS << "/* Capstone Disassembly Engine */\n"
|
||
|
+ "/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */\n"
|
||
|
+ "\n";
|
||
|
+#endif
|
||
|
+
|
||
|
OS << "\n#ifdef GET_REGINFO_ENUM\n";
|
||
|
OS << "#undef GET_REGINFO_ENUM\n\n";
|
||
|
|
||
|
+#ifndef CAPSTONE
|
||
|
OS << "namespace llvm {\n\n";
|
||
|
|
||
|
OS << "class MCRegisterClass;\n"
|
||
|
@@ -121,16 +136,20 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
|
||
|
|
||
|
if (!Namespace.empty())
|
||
|
OS << "namespace " << Namespace << " {\n";
|
||
|
- OS << "enum {\n NoRegister,\n";
|
||
|
+#endif
|
||
|
+
|
||
|
+ OS << "enum {\n " << NAME_PREFIX "NoRegister,\n";
|
||
|
|
||
|
for (const auto &Reg : Registers)
|
||
|
- OS << " " << Reg.getName() << " = " << Reg.EnumValue << ",\n";
|
||
|
+ OS << " " << NAME_PREFIX Reg.getName() << " = " << Reg.EnumValue << ",\n";
|
||
|
assert(Registers.size() == Registers.back().EnumValue &&
|
||
|
"Register enum value mismatch!");
|
||
|
- OS << " NUM_TARGET_REGS \t// " << Registers.size()+1 << "\n";
|
||
|
+ OS << " " << NAME_PREFIX "NUM_TARGET_REGS \t// " << Registers.size()+1 << "\n";
|
||
|
OS << "};\n";
|
||
|
+#ifndef CAPSTONE
|
||
|
if (!Namespace.empty())
|
||
|
OS << "} // end namespace " << Namespace << "\n";
|
||
|
+#endif
|
||
|
|
||
|
const auto &RegisterClasses = Bank.getRegClasses();
|
||
|
if (!RegisterClasses.empty()) {
|
||
|
@@ -139,18 +158,29 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
|
||
|
assert(RegisterClasses.size() <= 0xffff &&
|
||
|
"Too many register classes to fit in tables");
|
||
|
|
||
|
- OS << "\n// Register classes\n\n";
|
||
|
+ OS << "\n// Register classes\n";
|
||
|
+#ifndef CAPSTONE
|
||
|
+ OS << "\n";
|
||
|
if (!Namespace.empty())
|
||
|
OS << "namespace " << Namespace << " {\n";
|
||
|
+#endif
|
||
|
OS << "enum {\n";
|
||
|
for (const auto &RC : RegisterClasses)
|
||
|
- OS << " " << RC.getName() << "RegClassID"
|
||
|
+ OS << " " << NAME_PREFIX RC.getName() << "RegClassID"
|
||
|
<< " = " << RC.EnumValue << ",\n";
|
||
|
- OS << "\n };\n";
|
||
|
+#ifdef CAPSTONE
|
||
|
+ OS
|
||
|
+#else
|
||
|
+ OS << "\n "
|
||
|
+#endif
|
||
|
+ << "};\n";
|
||
|
+#ifndef CAPSTONE
|
||
|
if (!Namespace.empty())
|
||
|
OS << "} // end namespace " << Namespace << "\n\n";
|
||
|
+#endif
|
||
|
}
|
||
|
|
||
|
+#ifndef CAPSTONE
|
||
|
const std::vector<Record*> &RegAltNameIndices = Target.getRegAltNameIndices();
|
||
|
// If the only definition is the default NoRegAltName, we don't need to
|
||
|
// emit anything.
|
||
|
@@ -181,8 +211,11 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
|
||
|
if (!Namespace.empty())
|
||
|
OS << "} // end namespace " << Namespace << "\n\n";
|
||
|
}
|
||
|
+#endif
|
||
|
|
||
|
+#ifndef CAPSTONE
|
||
|
OS << "} // end namespace llvm\n\n";
|
||
|
+#endif
|
||
|
OS << "#endif // GET_REGINFO_ENUM\n\n";
|
||
|
}
|
||
|
|
||
|
@@ -869,7 +902,9 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||
|
|
||
|
const auto &Regs = RegBank.getRegisters();
|
||
|
|
||
|
+#ifndef CAPSTONE
|
||
|
auto &SubRegIndices = RegBank.getSubRegIndices();
|
||
|
+#endif
|
||
|
// The lists of sub-registers and super-registers go in the same array. That
|
||
|
// allows us to share suffixes.
|
||
|
typedef std::vector<const CodeGenRegister*> RegVec;
|
||
|
@@ -961,25 +996,40 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||
|
LaneMaskSeqs.layout();
|
||
|
SubRegIdxSeqs.layout();
|
||
|
|
||
|
+#ifndef CAPSTONE
|
||
|
OS << "namespace llvm {\n\n";
|
||
|
+#endif
|
||
|
|
||
|
const std::string &TargetName = Target.getName();
|
||
|
|
||
|
// Emit the shared table of differential lists.
|
||
|
- OS << "extern const MCPhysReg " << TargetName << "RegDiffLists[] = {\n";
|
||
|
+#ifdef CAPSTONE
|
||
|
+ OS << "static"
|
||
|
+#else
|
||
|
+ OS << "extern"
|
||
|
+#endif
|
||
|
+ << " const MCPhysReg " << TargetName << "RegDiffLists[] = {\n";
|
||
|
DiffSeqs.emit(OS, printDiff16);
|
||
|
OS << "};\n\n";
|
||
|
|
||
|
+#ifndef CAPSTONE
|
||
|
// Emit the shared table of regunit lane mask sequences.
|
||
|
OS << "extern const LaneBitmask " << TargetName << "LaneMaskLists[] = {\n";
|
||
|
LaneMaskSeqs.emit(OS, printMask, "LaneBitmask::getAll()");
|
||
|
OS << "};\n\n";
|
||
|
+#endif
|
||
|
|
||
|
// Emit the table of sub-register indexes.
|
||
|
- OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[] = {\n";
|
||
|
+#ifdef CAPSTONE
|
||
|
+ OS << "static"
|
||
|
+#else
|
||
|
+ OS << "extern"
|
||
|
+#endif
|
||
|
+ << " const uint16_t " << TargetName << "SubRegIdxLists[] = {\n";
|
||
|
SubRegIdxSeqs.emit(OS, printSubRegIndex);
|
||
|
OS << "};\n\n";
|
||
|
|
||
|
+#ifndef CAPSTONE
|
||
|
// Emit the table of sub-register index sizes.
|
||
|
OS << "extern const MCRegisterInfo::SubRegCoveredBits "
|
||
|
<< TargetName << "SubRegIdxRanges[] = {\n";
|
||
|
@@ -989,14 +1039,22 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||
|
<< Idx.getName() << "\n";
|
||
|
}
|
||
|
OS << "};\n\n";
|
||
|
+#endif
|
||
|
|
||
|
// Emit the string table.
|
||
|
RegStrings.layout();
|
||
|
+#ifndef CAPSTONE
|
||
|
OS << "extern const char " << TargetName << "RegStrings[] = {\n";
|
||
|
RegStrings.emit(OS, printChar);
|
||
|
OS << "};\n\n";
|
||
|
+#endif
|
||
|
|
||
|
- OS << "extern const MCRegisterDesc " << TargetName
|
||
|
+#ifdef CAPSTONE
|
||
|
+ OS << "static"
|
||
|
+#else
|
||
|
+ OS << "extern"
|
||
|
+#endif
|
||
|
+ << " const MCRegisterDesc " << TargetName
|
||
|
<< "RegDesc[] = { // Descriptors\n";
|
||
|
OS << " { " << RegStrings.get("") << ", 0, 0, 0, 0, 0 },\n";
|
||
|
|
||
|
@@ -1012,6 +1070,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||
|
}
|
||
|
OS << "};\n\n"; // End of register descriptors...
|
||
|
|
||
|
+#ifndef CAPSTONE
|
||
|
// Emit the table of register unit roots. Each regunit has one or two root
|
||
|
// registers.
|
||
|
OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2] = {\n";
|
||
|
@@ -1025,11 +1084,14 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||
|
OS << " },\n";
|
||
|
}
|
||
|
OS << "};\n\n";
|
||
|
+#endif
|
||
|
|
||
|
const auto &RegisterClasses = RegBank.getRegClasses();
|
||
|
|
||
|
// Loop over all of the register classes... emitting each one.
|
||
|
+#ifndef CAPSTONE
|
||
|
OS << "namespace { // Register classes...\n";
|
||
|
+#endif
|
||
|
|
||
|
SequenceToOffsetTable<std::string> RegClassStrings;
|
||
|
|
||
|
@@ -1044,15 +1106,28 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||
|
|
||
|
// Emit the register list now.
|
||
|
OS << " // " << Name << " Register Class...\n"
|
||
|
- << " const MCPhysReg " << Name
|
||
|
+ << " "
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << "static "
|
||
|
+#endif
|
||
|
+ << "const MCPhysReg " << Name
|
||
|
<< "[] = {\n ";
|
||
|
for (Record *Reg : Order) {
|
||
|
- OS << getQualifiedName(Reg) << ", ";
|
||
|
+#ifdef CAPSTONE
|
||
|
+ OS << NAME_PREFIX Reg->getName()
|
||
|
+#else
|
||
|
+ OS << getQualifiedName(Reg)
|
||
|
+#endif
|
||
|
+ << ", ";
|
||
|
}
|
||
|
OS << "\n };\n\n";
|
||
|
|
||
|
OS << " // " << Name << " Bit set.\n"
|
||
|
- << " const uint8_t " << Name
|
||
|
+ << " "
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << "static "
|
||
|
+#endif
|
||
|
+ << "const uint8_t " << Name
|
||
|
<< "Bits[] = {\n ";
|
||
|
BitVectorEmitter BVE;
|
||
|
for (Record *Reg : Order) {
|
||
|
@@ -1062,14 +1137,23 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||
|
OS << "\n };\n\n";
|
||
|
|
||
|
}
|
||
|
+#ifndef CAPSTONE
|
||
|
OS << "} // end anonymous namespace\n\n";
|
||
|
+#endif
|
||
|
|
||
|
RegClassStrings.layout();
|
||
|
+#ifndef CAPSTONE
|
||
|
OS << "extern const char " << TargetName << "RegClassStrings[] = {\n";
|
||
|
RegClassStrings.emit(OS, printChar);
|
||
|
OS << "};\n\n";
|
||
|
+#endif
|
||
|
|
||
|
- OS << "extern const MCRegisterClass " << TargetName
|
||
|
+#ifdef CAPSTONE
|
||
|
+ OS << "static"
|
||
|
+#else
|
||
|
+ OS << "extern"
|
||
|
+#endif
|
||
|
+ << " const MCRegisterClass " << TargetName
|
||
|
<< "MCRegisterClasses[] = {\n";
|
||
|
|
||
|
for (const auto &RC : RegisterClasses) {
|
||
|
@@ -1077,13 +1161,20 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||
|
OS << " { " << RC.getName() << ", " << RC.getName() << "Bits, "
|
||
|
<< RegClassStrings.get(RC.getName()) << ", "
|
||
|
<< RC.getOrder().size() << ", sizeof(" << RC.getName() << "Bits), "
|
||
|
- << RC.getQualifiedName() + "RegClassID" << ", "
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << NAME_PREFIX RC.getName()
|
||
|
+#else
|
||
|
+ << RC.getQualifiedName()
|
||
|
+#endif
|
||
|
+ << "RegClassID" << ", "
|
||
|
+ //<< RegSize/8 << ", "
|
||
|
<< RC.CopyCost << ", "
|
||
|
<< ( RC.Allocatable ? "true" : "false" ) << " },\n";
|
||
|
}
|
||
|
|
||
|
OS << "};\n\n";
|
||
|
|
||
|
+#ifndef CAPSTONE
|
||
|
EmitRegMappingTables(OS, Regs, false);
|
||
|
|
||
|
// Emit Reg encoding table
|
||
|
@@ -1102,7 +1193,9 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||
|
OS << " " << Value << ",\n";
|
||
|
}
|
||
|
OS << "};\n"; // End of HW encoding table
|
||
|
+#endif
|
||
|
|
||
|
+#ifndef CAPSTONE
|
||
|
// MCRegisterInfo initialization routine.
|
||
|
OS << "static inline void Init" << TargetName
|
||
|
<< "MCRegisterInfo(MCRegisterInfo *RI, unsigned RA, "
|
||
|
@@ -1123,7 +1216,12 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||
|
OS << "}\n\n";
|
||
|
|
||
|
OS << "} // end namespace llvm\n\n";
|
||
|
- OS << "#endif // GET_REGINFO_MC_DESC\n\n";
|
||
|
+#endif
|
||
|
+ OS << "#endif // GET_REGINFO_MC_DESC\n"
|
||
|
+#ifndef CAPSTONE
|
||
|
+ << "\n"
|
||
|
+#endif
|
||
|
+ ;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
@@ -1605,8 +1703,10 @@ void RegisterInfoEmitter::run(raw_ostream &OS) {
|
||
|
CodeGenRegBank &RegBank = Target.getRegBank();
|
||
|
runEnums(OS, Target, RegBank);
|
||
|
runMCDesc(OS, Target, RegBank);
|
||
|
+#ifndef CAPSTONE
|
||
|
runTargetHeader(OS, Target, RegBank);
|
||
|
runTargetDesc(OS, Target, RegBank);
|
||
|
+#endif
|
||
|
|
||
|
if (RegisterInfoDebug)
|
||
|
debugDump(errs());
|
||
|
diff --git a/llvm/utils/TableGen/SubtargetEmitter.cpp b/llvm/utils/TableGen/SubtargetEmitter.cpp
|
||
|
index 792c957ea..3ddfd1371 100644
|
||
|
--- a/llvm/utils/TableGen/SubtargetEmitter.cpp
|
||
|
+++ b/llvm/utils/TableGen/SubtargetEmitter.cpp
|
||
|
@@ -149,7 +149,9 @@ void SubtargetEmitter::Enumeration(raw_ostream &OS) {
|
||
|
if (N > MAX_SUBTARGET_FEATURES)
|
||
|
PrintFatalError("Too many subtarget features! Bump MAX_SUBTARGET_FEATURES.");
|
||
|
|
||
|
+#ifndef CAPSTONE
|
||
|
OS << "namespace " << Target << " {\n";
|
||
|
+#endif
|
||
|
|
||
|
// Open enumeration.
|
||
|
OS << "enum {\n";
|
||
|
@@ -160,12 +162,22 @@ void SubtargetEmitter::Enumeration(raw_ostream &OS) {
|
||
|
Record *Def = DefList[i];
|
||
|
|
||
|
// Get and emit name
|
||
|
- OS << " " << Def->getName() << " = " << i << ",\n";
|
||
|
+ OS << " "
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << Target << "_"
|
||
|
+#endif
|
||
|
+ << Def->getName() << " = "
|
||
|
+#ifdef CAPSTONE
|
||
|
+ << "1ULL << "
|
||
|
+#endif
|
||
|
+ << i << ",\n";
|
||
|
}
|
||
|
|
||
|
// Close enumeration and namespace
|
||
|
OS << "};\n";
|
||
|
+#ifndef CAPSTONE
|
||
|
OS << "} // end namespace " << Target << "\n";
|
||
|
+#endif
|
||
|
}
|
||
|
|
||
|
//
|
||
|
@@ -1786,14 +1798,27 @@ void SubtargetEmitter::EmitMCInstrAnalysisPredicateFunctions(raw_ostream &OS) {
|
||
|
void SubtargetEmitter::run(raw_ostream &OS) {
|
||
|
emitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
|
||
|
|
||
|
+#ifdef CAPSTONE
|
||
|
+ OS << "/* Capstone Disassembly Engine, http://www.capstone-engine.org */\n"
|
||
|
+ "/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */\n"
|
||
|
+ "\n";
|
||
|
+#endif
|
||
|
+
|
||
|
OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n";
|
||
|
OS << "#undef GET_SUBTARGETINFO_ENUM\n\n";
|
||
|
|
||
|
+#ifndef CAPSTONE
|
||
|
OS << "namespace llvm {\n";
|
||
|
+#endif
|
||
|
Enumeration(OS);
|
||
|
+#ifdef CAPSTONE
|
||
|
+ OS << "\n";
|
||
|
+#else
|
||
|
OS << "} // end namespace llvm\n\n";
|
||
|
+#endif
|
||
|
OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";
|
||
|
|
||
|
+#ifndef CAPSTONE
|
||
|
OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n";
|
||
|
OS << "#undef GET_SUBTARGETINFO_MC_DESC\n\n";
|
||
|
|
||
|
@@ -1942,6 +1967,7 @@ void SubtargetEmitter::run(raw_ostream &OS) {
|
||
|
OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n";
|
||
|
|
||
|
EmitMCInstrAnalysisPredicateFunctions(OS);
|
||
|
+#endif
|
||
|
}
|
||
|
|
||
|
namespace llvm {
|
||
|
diff --git a/llvm/utils/TableGen/TableGen.cpp b/llvm/utils/TableGen/TableGen.cpp
|
||
|
index 38f81dc39..abe172be2 100644
|
||
|
--- a/llvm/utils/TableGen/TableGen.cpp
|
||
|
+++ b/llvm/utils/TableGen/TableGen.cpp
|
||
|
@@ -27,6 +27,8 @@ enum ActionType {
|
||
|
GenEmitter,
|
||
|
GenRegisterInfo,
|
||
|
GenInstrInfo,
|
||
|
+ GenMappingInsn,
|
||
|
+ GenInsnNameMaps,
|
||
|
GenInstrDocs,
|
||
|
GenAsmWriter,
|
||
|
GenAsmMatcher,
|
||
|
@@ -68,6 +70,10 @@ namespace {
|
||
|
"Generate registers and register classes info"),
|
||
|
clEnumValN(GenInstrInfo, "gen-instr-info",
|
||
|
"Generate instruction descriptions"),
|
||
|
+ clEnumValN(GenMappingInsn, "gen-mapping-insn",
|
||
|
+ ""),
|
||
|
+ clEnumValN(GenInsnNameMaps, "gen-insn-name-maps",
|
||
|
+ ""),
|
||
|
clEnumValN(GenInstrDocs, "gen-instr-docs",
|
||
|
"Generate instruction documentation"),
|
||
|
clEnumValN(GenCallingConv, "gen-callingconv",
|
||
|
@@ -143,6 +149,12 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
|
||
|
case GenInstrInfo:
|
||
|
EmitInstrInfo(Records, OS);
|
||
|
break;
|
||
|
+ case GenMappingInsn:
|
||
|
+ EmitMappingInsn(Records, OS);
|
||
|
+ break;
|
||
|
+ case GenInsnNameMaps:
|
||
|
+ EmitInsnNameMaps(Records, OS);
|
||
|
+ break;
|
||
|
case GenInstrDocs:
|
||
|
EmitInstrDocs(Records, OS);
|
||
|
break;
|
||
|
diff --git a/llvm/utils/TableGen/TableGenBackends.h b/llvm/utils/TableGen/TableGenBackends.h
|
||
|
index 135ec65c0..82f787dba 100644
|
||
|
--- a/llvm/utils/TableGen/TableGenBackends.h
|
||
|
+++ b/llvm/utils/TableGen/TableGenBackends.h
|
||
|
@@ -74,6 +74,8 @@ void EmitDFAPacketizer(RecordKeeper &RK, raw_ostream &OS);
|
||
|
void EmitDisassembler(RecordKeeper &RK, raw_ostream &OS);
|
||
|
void EmitFastISel(RecordKeeper &RK, raw_ostream &OS);
|
||
|
void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS);
|
||
|
+void EmitMappingInsn(RecordKeeper &RK, raw_ostream &OS);
|
||
|
+void EmitInsnNameMaps(RecordKeeper &RK, raw_ostream &OS);
|
||
|
void EmitInstrDocs(RecordKeeper &RK, raw_ostream &OS);
|
||
|
void EmitPseudoLowering(RecordKeeper &RK, raw_ostream &OS);
|
||
|
void EmitCompressInst(RecordKeeper &RK, raw_ostream &OS);
|
||
|
--
|
||
|
2.20.1
|
||
|
|