//
//===----------------------------------------------------------------------===//
-#include "DisassemblerEmitter.h"
#include "CodeGenTarget.h"
-#include "Record.h"
#include "X86DisassemblerTables.h"
#include "X86RecognizableInstr.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
+
using namespace llvm;
using namespace llvm::X86Disassembler;
/// all cases as a 64-bit instruction with only OPSIZE set. (The XS prefix
/// may have effects on its execution, but does not change the instruction
/// returned.) This allows considerable space savings in other tables.
-/// - Four tables (ONEBYTE_SYM, TWOBYTE_SYM, THREEBYTE38_SYM, and
-/// THREEBYTE3A_SYM) contain the hierarchy that the decoder traverses while
-/// decoding an instruction. At the lowest level of this hierarchy are
-/// instruction UIDs, 16-bit integers that can be used to uniquely identify
-/// the instruction and correspond exactly to its position in the list of
-/// CodeGenInstructions for the target.
+/// - Six tables (ONEBYTE_SYM, TWOBYTE_SYM, THREEBYTE38_SYM, THREEBYTE3A_SYM,
+/// THREEBYTEA6_SYM, and THREEBYTEA7_SYM contain the hierarchy that the
+/// decoder traverses while decoding an instruction. At the lowest level of
+/// this hierarchy are instruction UIDs, 16-bit integers that can be used to
+/// uniquely identify the instruction and correspond exactly to its position
+/// in the list of CodeGenInstructions for the target.
/// - One table (INSTRUCTIONS_SYM) contains information about the operands of
/// each instruction and how to decode them.
///
/// X86RecognizableInstr.cpp contains the implementation for a single
/// instruction.
-void DisassemblerEmitter::run(raw_ostream &OS) {
- CodeGenTarget Target;
+namespace llvm {
+
+extern void EmitFixedLenDecoder(RecordKeeper &RK, raw_ostream &OS,
+ std::string PredicateNamespace,
+ std::string GPrefix,
+ std::string GPostfix,
+ std::string ROK,
+ std::string RFail,
+ std::string L);
- OS << "/*===- TableGen'erated file "
- << "---------------------------------------*- C -*-===*\n"
- << " *\n"
- << " * " << Target.getName() << " Disassembler\n"
- << " *\n"
- << " * Automatically generated file, do not edit!\n"
- << " *\n"
- << " *===---------------------------------------------------------------"
- << "-------===*/\n";
+void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) {
+ CodeGenTarget Target(Records);
+ emitSourceFileHeader(" * " + Target.getName() + " Disassembler", OS);
// X86 uses a custom disassembler.
if (Target.getName() == "X86") {
DisassemblerTables Tables;
-
- std::vector<const CodeGenInstruction*> numberedInstructions;
- Target.getInstructionsByEnumValue(numberedInstructions);
-
+
+ const std::vector<const CodeGenInstruction*> &numberedInstructions =
+ Target.getInstructionsByEnumValue();
+
for (unsigned i = 0, e = numberedInstructions.size(); i != e; ++i)
RecognizableInstr::processInstr(Tables, *numberedInstructions[i], i);
- // FIXME: As long as we are using exceptions, might as well drop this to the
- // actual conflict site.
- if (Tables.hasConflicts())
- throw TGError(Target.getTargetRecord()->getLoc(),
- "Primary decode conflict");
+ if (Tables.hasConflicts()) {
+ PrintError(Target.getTargetRecord()->getLoc(), "Primary decode conflict");
+ return;
+ }
Tables.emit(OS);
return;
}
- throw TGError(Target.getTargetRecord()->getLoc(),
- "Unable to generate disassembler for this target");
+ // ARM and Thumb have a CHECK() macro to deal with DecodeStatuses.
+ if (Target.getName() == "ARM" || Target.getName() == "Thumb" ||
+ Target.getName() == "AArch64" || Target.getName() == "ARM64") {
+ std::string PredicateNamespace = Target.getName();
+ if (PredicateNamespace == "Thumb")
+ PredicateNamespace = "ARM";
+
+ EmitFixedLenDecoder(Records, OS, PredicateNamespace,
+ "if (!Check(S, ", "))",
+ "S", "MCDisassembler::Fail",
+ " MCDisassembler::DecodeStatus S = "
+ "MCDisassembler::Success;\n(void)S;");
+ return;
+ }
+
+ EmitFixedLenDecoder(Records, OS, Target.getName(),
+ "if (", " == MCDisassembler::Fail)",
+ "MCDisassembler::Success", "MCDisassembler::Fail", "");
}
+
+} // End llvm namespace