summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/ARC/Disassembler/ARCDisassembler.cpp
diff options
context:
space:
mode:
authorPete Couperus <petecoup@synopsys.com>2017-08-24 15:40:33 +0000
committerPete Couperus <petecoup@synopsys.com>2017-08-24 15:40:33 +0000
commit2d1f6d67c56e56a33ec8f49d584d2352d33a4081 (patch)
tree162897c05802dd0219a882da43ffdd4a39574b4b /llvm/lib/Target/ARC/Disassembler/ARCDisassembler.cpp
parent719f97cf65db83a0bfd72b7e5ce91300314d24bc (diff)
downloadbcm5719-llvm-2d1f6d67c56e56a33ec8f49d584d2352d33a4081.tar.gz
bcm5719-llvm-2d1f6d67c56e56a33ec8f49d584d2352d33a4081.zip
[ARC] Add ARC backend.
Add the ARC backend as an experimental target to lib/Target. Reviewed at: https://reviews.llvm.org/D36331 llvm-svn: 311667
Diffstat (limited to 'llvm/lib/Target/ARC/Disassembler/ARCDisassembler.cpp')
-rw-r--r--llvm/lib/Target/ARC/Disassembler/ARCDisassembler.cpp298
1 files changed, 298 insertions, 0 deletions
diff --git a/llvm/lib/Target/ARC/Disassembler/ARCDisassembler.cpp b/llvm/lib/Target/ARC/Disassembler/ARCDisassembler.cpp
new file mode 100644
index 00000000000..b49658004f7
--- /dev/null
+++ b/llvm/lib/Target/ARC/Disassembler/ARCDisassembler.cpp
@@ -0,0 +1,298 @@
+//===- ARCDisassembler.cpp - Disassembler for ARC ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file is part of the ARC Disassembler.
+///
+//===----------------------------------------------------------------------===//
+
+#include "ARC.h"
+#include "ARCRegisterInfo.h"
+#include "MCTargetDesc/ARCMCTargetDesc.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/MCInstrInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/TargetRegistry.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "arc-disassembler"
+
+using DecodeStatus = MCDisassembler::DecodeStatus;
+
+namespace {
+
+/// \brief A disassembler class for ARC.
+class ARCDisassembler : public MCDisassembler {
+public:
+ std::unique_ptr<MCInstrInfo const> const MCII;
+
+ ARCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
+ MCInstrInfo const *MCII)
+ : MCDisassembler(STI, Ctx), MCII(MCII) {}
+
+ 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 bool readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
+ uint64_t &Size, uint32_t &Insn) {
+ Size = 4;
+ // Read 2 16-bit values, but swap hi/lo parts.
+ Insn =
+ (Bytes[0] << 16) | (Bytes[1] << 24) | (Bytes[2] << 0) | (Bytes[3] << 8);
+ return true;
+}
+
+static bool readInstruction64(ArrayRef<uint8_t> Bytes, uint64_t Address,
+ uint64_t &Size, uint64_t &Insn) {
+ Size = 8;
+ Insn = ((uint64_t)Bytes[0] << 16) | ((uint64_t)Bytes[1] << 24) |
+ ((uint64_t)Bytes[2] << 0) | ((uint64_t)Bytes[3] << 8) |
+ ((uint64_t)Bytes[4] << 48) | ((uint64_t)Bytes[5] << 56) |
+ ((uint64_t)Bytes[6] << 32) | ((uint64_t)Bytes[7] << 40);
+ return true;
+}
+
+static bool readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
+ uint64_t &Size, uint32_t &Insn) {
+ Size = 2;
+ Insn = (Bytes[0] << 0) | (Bytes[1] << 8);
+ return true;
+}
+
+static MCDisassembler::DecodeStatus DecodeS12Operand(MCInst &, unsigned,
+ uint64_t, const void *);
+
+static MCDisassembler::DecodeStatus DecodeS9Operand(MCInst &, unsigned,
+ uint64_t, const void *);
+
+static MCDisassembler::DecodeStatus
+DecodeBranchTargetS9(MCInst &, unsigned, uint64_t, const void *);
+
+static MCDisassembler::DecodeStatus
+DecodeBranchTargetS21(MCInst &, unsigned, uint64_t, const void *);
+
+static MCDisassembler::DecodeStatus
+DecodeBranchTargetS25(MCInst &, unsigned, uint64_t, const void *);
+
+static MCDisassembler::DecodeStatus DecodeMEMrs9(MCInst &, unsigned, uint64_t,
+ const void *);
+
+static MCDisassembler::DecodeStatus
+DecodeLdLImmInstruction(MCInst &, uint64_t, uint64_t, const void *);
+
+static MCDisassembler::DecodeStatus
+DecodeStLImmInstruction(MCInst &, uint64_t, uint64_t, const void *);
+
+static MCDisassembler::DecodeStatus
+DecodeLdRLImmInstruction(MCInst &, uint64_t, uint64_t, const void *);
+
+static const uint16_t GPR32DecoderTable[] = {
+ ARC::R0, ARC::R1, ARC::R2, ARC::R3, ARC::R4, ARC::R5, ARC::R6,
+ ARC::R7, ARC::R8, ARC::R9, ARC::R10, ARC::R11, ARC::R12, ARC::R13,
+ ARC::R14, ARC::R15, ARC::R16, ARC::R17, ARC::R18, ARC::R19, ARC::R20,
+ ARC::R21, ARC::R22, ARC::R23, ARC::R24, ARC::R25, ARC::GP, ARC::FP,
+ ARC::SP, ARC::ILINK, ARC::R30, ARC::BLINK};
+
+static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo,
+ uint64_t Address,
+ const void *Decoder) {
+ if (RegNo >= 32) {
+ DEBUG(dbgs() << "Not a GPR32 register.");
+ return MCDisassembler::Fail;
+ }
+ unsigned Reg = GPR32DecoderTable[RegNo];
+ Inst.addOperand(MCOperand::createReg(Reg));
+ return MCDisassembler::Success;
+}
+
+#include "ARCGenDisassemblerTables.inc"
+
+static unsigned decodeCField(unsigned Insn) {
+ return fieldFromInstruction(Insn, 6, 6);
+}
+
+static unsigned decodeBField(unsigned Insn) {
+ return (fieldFromInstruction(Insn, 12, 3) << 3) |
+ fieldFromInstruction(Insn, 24, 3);
+}
+
+static unsigned decodeAField(unsigned Insn) {
+ return fieldFromInstruction(Insn, 0, 6);
+}
+
+static MCDisassembler::DecodeStatus
+DecodeMEMrs9(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Dec) {
+ // We have the 9-bit immediate in the low bits, 6-bit register in high bits.
+ unsigned S9 = Insn & 0x1ff;
+ unsigned R = (Insn & (0x7fff & ~0x1ff)) >> 9;
+ DecodeGPR32RegisterClass(Inst, R, Address, Dec);
+ Inst.addOperand(MCOperand::createImm(SignExtend32<9>(S9)));
+ return MCDisassembler::Success;
+}
+
+static MCDisassembler::DecodeStatus DecodeS9Operand(MCInst &Inst,
+ unsigned InsnS9,
+ uint64_t Address,
+ const void *Decoder) {
+ Inst.addOperand(MCOperand::createImm(SignExtend32<9>(0x1ff & InsnS9)));
+ return MCDisassembler::Success;
+}
+
+static MCDisassembler::DecodeStatus DecodeS12Operand(MCInst &Inst,
+ unsigned InsnS12,
+ uint64_t Address,
+ const void *Decoder) {
+ Inst.addOperand(MCOperand::createImm(SignExtend32<12>(0xfff & InsnS12)));
+ return MCDisassembler::Success;
+}
+
+static MCDisassembler::DecodeStatus DecodeBranchTargetS9(MCInst &Inst,
+ unsigned S,
+ uint64_t Address,
+ const void *Decoder) {
+ Inst.addOperand(MCOperand::createImm(SignExtend32<9>(S)));
+ return MCDisassembler::Success;
+}
+
+static MCDisassembler::DecodeStatus DecodeBranchTargetS21(MCInst &Inst,
+ unsigned S,
+ uint64_t Address,
+ const void *Decoder) {
+ Inst.addOperand(MCOperand::createImm(SignExtend32<21>(S)));
+ return MCDisassembler::Success;
+}
+
+static MCDisassembler::DecodeStatus DecodeBranchTargetS25(MCInst &Inst,
+ unsigned S,
+ uint64_t Address,
+ const void *Decoder) {
+ Inst.addOperand(MCOperand::createImm(SignExtend32<25>(S)));
+ return MCDisassembler::Success;
+}
+
+static MCDisassembler::DecodeStatus
+DecodeStLImmInstruction(MCInst &Inst, uint64_t Insn, uint64_t Address,
+ const void *Decoder) {
+ unsigned SrcC, DstB, LImm;
+ DstB = decodeBField(Insn);
+ if (DstB != 62) {
+ DEBUG(dbgs() << "Decoding StLImm found non-limm register.");
+ return MCDisassembler::Fail;
+ }
+ SrcC = decodeCField(Insn);
+ DecodeGPR32RegisterClass(Inst, SrcC, Address, Decoder);
+ LImm = (Insn >> 32);
+ Inst.addOperand(MCOperand::createImm(LImm));
+ Inst.addOperand(MCOperand::createImm(0));
+ return MCDisassembler::Success;
+}
+
+static MCDisassembler::DecodeStatus
+DecodeLdLImmInstruction(MCInst &Inst, uint64_t Insn, uint64_t Address,
+ const void *Decoder) {
+ unsigned DstA, SrcB, LImm;
+ DEBUG(dbgs() << "Decoding LdLImm:\n");
+ SrcB = decodeBField(Insn);
+ if (SrcB != 62) {
+ DEBUG(dbgs() << "Decoding LdLImm found non-limm register.");
+ return MCDisassembler::Fail;
+ }
+ DstA = decodeAField(Insn);
+ DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
+ LImm = (Insn >> 32);
+ Inst.addOperand(MCOperand::createImm(LImm));
+ Inst.addOperand(MCOperand::createImm(0));
+ return MCDisassembler::Success;
+}
+
+static MCDisassembler::DecodeStatus
+DecodeLdRLImmInstruction(MCInst &Inst, uint64_t Insn, uint64_t Address,
+ const void *Decoder) {
+ unsigned DstA, SrcB;
+ DEBUG(dbgs() << "Decoding LdRLimm\n");
+ DstA = decodeAField(Insn);
+ DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
+ SrcB = decodeBField(Insn);
+ DecodeGPR32RegisterClass(Inst, SrcB, Address, Decoder);
+ if (decodeCField(Insn) != 62) {
+ DEBUG(dbgs() << "Decoding LdRLimm found non-limm register.");
+ return MCDisassembler::Fail;
+ }
+ Inst.addOperand(MCOperand::createImm((uint32_t)(Insn >> 32)));
+ return MCDisassembler::Success;
+}
+
+MCDisassembler::DecodeStatus ARCDisassembler::getInstruction(
+ MCInst &Instr, uint64_t &Size, ArrayRef<uint8_t> Bytes, uint64_t Address,
+ raw_ostream &vStream, raw_ostream &cStream) const {
+ MCDisassembler::DecodeStatus Result;
+ if (Bytes.size() < 2) {
+ Size = 0;
+ return Fail;
+ }
+ uint8_t DecodeByte = (Bytes[1] & 0xF7) >> 3;
+ // 0x00 -> 0x07 are 32-bit instructions.
+ // 0x08 -> 0x1F are 16-bit instructions.
+ if (DecodeByte < 0x08) {
+ // 32-bit instruction.
+ if (Bytes.size() < 4) {
+ // Did we decode garbage?
+ Size = 0;
+ return Fail;
+ }
+ if (Bytes.size() >= 8) {
+ // Attempt to decode 64-bit instruction.
+ uint64_t Insn64;
+ if (!readInstruction64(Bytes, Address, Size, Insn64))
+ return Fail;
+ Result =
+ decodeInstruction(DecoderTable64, Instr, Insn64, Address, this, STI);
+ if (Result == MCDisassembler::Success) {
+ DEBUG(dbgs() << "Successfully decoded 64-bit instruction.");
+ return MCDisassembler::Success;
+ }
+ DEBUG(dbgs() << "Not a 64-bit instruction, falling back to 32-bit.");
+ }
+ uint32_t Insn32;
+ if (!readInstruction32(Bytes, Address, Size, Insn32)) {
+ return Fail;
+ }
+ // Calling the auto-generated decoder function.
+ return decodeInstruction(DecoderTable32, Instr, Insn32, Address, this, STI);
+ }
+
+ // 16-bit instruction.
+ uint32_t Insn16;
+ if (!readInstruction16(Bytes, Address, Size, Insn16)) {
+ return Fail;
+ }
+ // Calling the auto-generated decoder function.
+ return decodeInstruction(DecoderTable16, Instr, Insn16, Address, this, STI);
+}
+
+static MCDisassembler *createARCDisassembler(const Target &T,
+ const MCSubtargetInfo &STI,
+ MCContext &Ctx) {
+ return new ARCDisassembler(STI, Ctx, T.createMCInstrInfo());
+}
+
+extern "C" void LLVMInitializeARCDisassembler() {
+ // Register the disassembler.
+ TargetRegistry::RegisterMCDisassembler(getTheARCTarget(),
+ createARCDisassembler);
+}
OpenPOWER on IntegriCloud