summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/RISCV/CMakeLists.txt3
-rw-r--r--llvm/lib/Target/RISCV/Disassembler/CMakeLists.txt3
-rw-r--r--llvm/lib/Target/RISCV/Disassembler/LLVMBuild.txt24
-rw-r--r--llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp135
-rw-r--r--llvm/lib/Target/RISCV/LLVMBuild.txt3
-rw-r--r--llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp20
-rw-r--r--llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp4
-rw-r--r--llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h3
-rw-r--r--llvm/lib/Target/RISCV/RISCVInstrFormats.td5
-rw-r--r--llvm/lib/Target/RISCV/RISCVInstrInfo.td8
10 files changed, 207 insertions, 1 deletions
diff --git a/llvm/lib/Target/RISCV/CMakeLists.txt b/llvm/lib/Target/RISCV/CMakeLists.txt
index 6cc55fd3a17..b9f3fc110c7 100644
--- a/llvm/lib/Target/RISCV/CMakeLists.txt
+++ b/llvm/lib/Target/RISCV/CMakeLists.txt
@@ -5,6 +5,8 @@ tablegen(LLVM RISCVGenInstrInfo.inc -gen-instr-info)
tablegen(LLVM RISCVGenMCCodeEmitter.inc -gen-emitter)
tablegen(LLVM RISCVGenAsmMatcher.inc -gen-asm-matcher)
tablegen(LLVM RISCVGenAsmWriter.inc -gen-asm-writer)
+tablegen(LLVM RISCVGenSubtargetInfo.inc -gen-subtarget)
+tablegen(LLVM RISCVGenDisassemblerTables.inc -gen-disassembler)
add_public_tablegen_target(RISCVCommonTableGen)
@@ -13,6 +15,7 @@ add_llvm_target(RISCVCodeGen
)
add_subdirectory(AsmParser)
+add_subdirectory(Disassembler)
add_subdirectory(InstPrinter)
add_subdirectory(MCTargetDesc)
add_subdirectory(TargetInfo)
diff --git a/llvm/lib/Target/RISCV/Disassembler/CMakeLists.txt b/llvm/lib/Target/RISCV/Disassembler/CMakeLists.txt
new file mode 100644
index 00000000000..39bd2b7669f
--- /dev/null
+++ b/llvm/lib/Target/RISCV/Disassembler/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_llvm_library(LLVMRISCVDisassembler
+ RISCVDisassembler.cpp
+ )
diff --git a/llvm/lib/Target/RISCV/Disassembler/LLVMBuild.txt b/llvm/lib/Target/RISCV/Disassembler/LLVMBuild.txt
new file mode 100644
index 00000000000..340e89d4cf3
--- /dev/null
+++ b/llvm/lib/Target/RISCV/Disassembler/LLVMBuild.txt
@@ -0,0 +1,24 @@
+;===- ./lib/Target/RISCV/Disassembler/LLVMBuild.txt ------------*- Conf -*--===;
+;
+; The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+; http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = RISCVDisassembler
+parent = RISCV
+required_libraries = MCDisassembler RISCVInfo Support
+add_to_library_groups = RISCV
+
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
new file mode 100644
index 00000000000..e64d875a567
--- /dev/null
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -0,0 +1,135 @@
+//===-- RISCVDisassembler.cpp - Disassembler for RISCV --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the RISCVDisassembler class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/RISCVMCTargetDesc.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDisassembler/MCDisassembler.h"
+#include "llvm/MC/MCFixedLenDisassembler.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/TargetRegistry.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "riscv-disassembler"
+
+typedef MCDisassembler::DecodeStatus DecodeStatus;
+
+namespace {
+class RISCVDisassembler : public MCDisassembler {
+
+public:
+ RISCVDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
+ : MCDisassembler(STI, Ctx) {}
+
+ DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
+ ArrayRef<uint8_t> Bytes, uint64_t Address,
+ raw_ostream &VStream,
+ raw_ostream &CStream) const override;
+};
+} // end anonymous namespace
+
+static MCDisassembler *createRISCVDisassembler(const Target &T,
+ const MCSubtargetInfo &STI,
+ MCContext &Ctx) {
+ return new RISCVDisassembler(STI, Ctx);
+}
+
+extern "C" void LLVMInitializeRISCVDisassembler() {
+ // Register the disassembler for each target.
+ TargetRegistry::RegisterMCDisassembler(getTheRISCV32Target(),
+ createRISCVDisassembler);
+ TargetRegistry::RegisterMCDisassembler(getTheRISCV64Target(),
+ createRISCVDisassembler);
+}
+
+static const unsigned GPRDecoderTable[] = {
+ RISCV::X0_32, RISCV::X1_32, RISCV::X2_32, RISCV::X3_32,
+ RISCV::X4_32, RISCV::X5_32, RISCV::X6_32, RISCV::X7_32,
+ RISCV::X8_32, RISCV::X9_32, RISCV::X10_32, RISCV::X11_32,
+ RISCV::X12_32, RISCV::X13_32, RISCV::X14_32, RISCV::X15_32,
+ RISCV::X16_32, RISCV::X17_32, RISCV::X18_32, RISCV::X19_32,
+ RISCV::X20_32, RISCV::X21_32, RISCV::X22_32, RISCV::X23_32,
+ RISCV::X24_32, RISCV::X25_32, RISCV::X26_32, RISCV::X27_32,
+ RISCV::X28_32, RISCV::X29_32, RISCV::X30_32, RISCV::X31_32
+};
+
+static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint64_t RegNo,
+ uint64_t Address,
+ const void *Decoder) {
+ if (RegNo > sizeof(GPRDecoderTable)) {
+ return MCDisassembler::Fail;
+ }
+
+ // We must define our own mapping from RegNo to register identifier.
+ // Accessing index RegNo in the register class will work in the case that
+ // registers were added in ascending order, but not in general.
+ unsigned Reg = GPRDecoderTable[RegNo];
+ Inst.addOperand(MCOperand::createReg(Reg));
+ return MCDisassembler::Success;
+}
+
+template <unsigned N>
+static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm,
+ int64_t Address, const void *Decoder) {
+ assert(isUInt<N>(Imm) && "Invalid immediate");
+ Inst.addOperand(MCOperand::createImm(Imm));
+ return MCDisassembler::Success;
+}
+
+template <unsigned N>
+static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm,
+ int64_t Address, const void *Decoder) {
+ assert(isUInt<N>(Imm) && "Invalid immediate");
+ // Sign-extend the number in the bottom N bits of Imm
+ Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm)));
+ return MCDisassembler::Success;
+}
+
+template <unsigned N>
+static DecodeStatus decodeSImmOperandAndLsl1(MCInst &Inst, uint64_t Imm,
+ int64_t Address,
+ const void *Decoder) {
+ assert(isUInt<N>(Imm) && "Invalid immediate");
+ // Sign-extend the number in the bottom N bits of Imm after accounting for
+ // the fact that the N bit immediate is stored in N-1 bits (the LSB is
+ // always zero)
+ Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm << 1)));
+ return MCDisassembler::Success;
+}
+
+#include "RISCVGenDisassemblerTables.inc"
+
+DecodeStatus RISCVDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
+ ArrayRef<uint8_t> Bytes,
+ uint64_t Address,
+ raw_ostream &OS,
+ raw_ostream &CS) const {
+ // TODO: although assuming 4-byte instructions is sufficient for RV32 and
+ // RV64, this will need modification when supporting the compressed
+ // instruction set extension (RVC) which uses 16-bit instructions. Other
+ // instruction set extensions have the option of defining instructions up to
+ // 176 bits wide.
+ Size = 4;
+ if (Bytes.size() < 4) {
+ Size = 0;
+ return MCDisassembler::Fail;
+ }
+
+ // Get the four bytes of the instruction.
+ uint32_t Inst = support::endian::read32le(Bytes.data());
+
+ return decodeInstruction(DecoderTable32, MI, Inst, Address, this, STI);
+}
diff --git a/llvm/lib/Target/RISCV/LLVMBuild.txt b/llvm/lib/Target/RISCV/LLVMBuild.txt
index 933fed1856b..e15963b5bd7 100644
--- a/llvm/lib/Target/RISCV/LLVMBuild.txt
+++ b/llvm/lib/Target/RISCV/LLVMBuild.txt
@@ -16,7 +16,7 @@
;===------------------------------------------------------------------------===;
[common]
-subdirectories = AsmParser InstPrinter TargetInfo MCTargetDesc
+subdirectories = AsmParser Disassembler InstPrinter TargetInfo MCTargetDesc
[component_0]
type = TargetGroup
@@ -24,6 +24,7 @@ name = RISCV
parent = Target
has_asmparser = 1
has_asmprinter = 1
+has_disassembler = 1
[component_1]
type = Library
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
index eb0beb028ad..f4eaf06f622 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
@@ -59,6 +59,9 @@ public:
unsigned getImmOpValueAsr1(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+ unsigned getImmOpValue(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
};
} // end anonymous namespace
@@ -105,6 +108,23 @@ RISCVMCCodeEmitter::getImmOpValueAsr1(const MCInst &MI, unsigned OpNo,
}
llvm_unreachable("Unhandled expression!");
+
+ return 0;
+}
+
+unsigned RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+
+ const MCOperand &MO = MI.getOperand(OpNo);
+
+ // If the destination is an immediate, there is nothing to do
+ if (MO.isImm())
+ return MO.getImm();
+
+ llvm_unreachable("Unhandled expression!");
+
+ return 0;
}
#include "RISCVGenMCCodeEmitter.inc"
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp
index 0f68dd7aa05..2b35eab577b 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp
@@ -29,6 +29,9 @@
#define GET_REGINFO_MC_DESC
#include "RISCVGenRegisterInfo.inc"
+#define GET_SUBTARGETINFO_MC_DESC
+#include "RISCVGenSubtargetInfo.inc"
+
using namespace llvm;
static MCInstrInfo *createRISCVMCInstrInfo() {
@@ -64,5 +67,6 @@ extern "C" void LLVMInitializeRISCVTargetMC() {
TargetRegistry::RegisterMCAsmBackend(*T, createRISCVAsmBackend);
TargetRegistry::RegisterMCCodeEmitter(*T, createRISCVMCCodeEmitter);
TargetRegistry::RegisterMCInstPrinter(*T, createRISCVMCInstPrinter);
+ TargetRegistry::RegisterMCSubtargetInfo(*T, createRISCVMCSubtargetInfoImpl);
}
}
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h
index 7c98b1c8f32..9891fd52b2f 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h
@@ -55,4 +55,7 @@ MCObjectWriter *createRISCVELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI,
#define GET_INSTRINFO_ENUM
#include "RISCVGenInstrInfo.inc"
+#define GET_SUBTARGETINFO_ENUM
+#include "RISCVGenSubtargetInfo.inc"
+
#endif
diff --git a/llvm/lib/Target/RISCV/RISCVInstrFormats.td b/llvm/lib/Target/RISCV/RISCVInstrFormats.td
index 3fab7122f6f..d77f3874c7d 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrFormats.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrFormats.td
@@ -28,6 +28,11 @@
class RISCVInst<dag outs, dag ins, string asmstr, list<dag> pattern>
: Instruction {
field bits<32> Inst;
+ // SoftFail is a field the disassembler can use to provide a way for
+ // instructions to not match without killing the whole decode process. It is
+ // mainly used for ARM, but Tablegen expects this field to exist or it fails
+ // to build the decode table.
+ field bits<32> SoftFail = 0;
let Size = 4;
bits<7> Opcode = 0;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index 78b1c907f33..e84e4dabb94 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -36,34 +36,42 @@ def FenceArg : AsmOperandClass {
def fencearg : Operand<i32> {
let ParserMatchClass = FenceArg;
let PrintMethod = "printFenceArg";
+ let DecoderMethod = "decodeUImmOperand<4>";
}
def uimm5 : Operand<i32> {
let ParserMatchClass = UImmAsmOperand<5>;
+ let DecoderMethod = "decodeUImmOperand<5>";
}
def simm12 : Operand<i32> {
let ParserMatchClass = SImmAsmOperand<12>;
+ let DecoderMethod = "decodeSImmOperand<12>";
}
def uimm12 : Operand<i32> {
let ParserMatchClass = UImmAsmOperand<12>;
+ let DecoderMethod = "decodeUImmOperand<12>";
}
// A 13-bit signed immediate where the least significant bit is zero.
def simm13_lsb0 : Operand<i32> {
let ParserMatchClass = SImmAsmOperand<13, "Lsb0">;
let EncoderMethod = "getImmOpValueAsr1";
+ let DecoderMethod = "decodeSImmOperandAndLsl1<13>";
}
def uimm20 : Operand<i32> {
let ParserMatchClass = UImmAsmOperand<20>;
+ let EncoderMethod = "getImmOpValue";
+ let DecoderMethod = "decodeUImmOperand<20>";
}
// A 21-bit signed immediate where the least significant bit is zero.
def simm21_lsb0 : Operand<i32> {
let ParserMatchClass = SImmAsmOperand<21, "Lsb0">;
let EncoderMethod = "getImmOpValueAsr1";
+ let DecoderMethod = "decodeSImmOperandAndLsl1<21>";
}
// As noted in RISCVRegisterInfo.td, the hope is that support for
OpenPOWER on IntegriCloud