summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/Lanai/Disassembler/LanaiDisassembler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/Lanai/Disassembler/LanaiDisassembler.cpp')
-rw-r--r--llvm/lib/Target/Lanai/Disassembler/LanaiDisassembler.cpp228
1 files changed, 228 insertions, 0 deletions
diff --git a/llvm/lib/Target/Lanai/Disassembler/LanaiDisassembler.cpp b/llvm/lib/Target/Lanai/Disassembler/LanaiDisassembler.cpp
new file mode 100644
index 00000000000..3a71b80b2ba
--- /dev/null
+++ b/llvm/lib/Target/Lanai/Disassembler/LanaiDisassembler.cpp
@@ -0,0 +1,228 @@
+//===- LanaiDisassembler.cpp - Disassembler for Lanai -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is part of the Lanai Disassembler.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LanaiDisassembler.h"
+
+#include "Lanai.h"
+#include "LanaiSubtarget.h"
+#include "llvm/MC/MCFixedLenDisassembler.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/MemoryObject.h"
+#include "llvm/Support/TargetRegistry.h"
+
+using namespace llvm;
+
+typedef MCDisassembler::DecodeStatus DecodeStatus;
+
+namespace llvm {
+extern Target TheLanaiTarget;
+}
+
+static MCDisassembler *createLanaiDisassembler(const Target &T,
+ const MCSubtargetInfo &STI,
+ MCContext &Ctx) {
+ return new LanaiDisassembler(STI, Ctx);
+}
+
+extern "C" void LLVMInitializeLanaiDisassembler() {
+ // Register the disassembler
+ TargetRegistry::RegisterMCDisassembler(TheLanaiTarget,
+ createLanaiDisassembler);
+}
+
+LanaiDisassembler::LanaiDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
+ : MCDisassembler(STI, Ctx) {}
+
+// Forward declare because the autogenerated code will reference this.
+// Definition is further down.
+DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo,
+ uint64_t Address, const void *Decoder);
+
+static DecodeStatus decodeRiMemoryValue(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+
+static DecodeStatus decodeRrMemoryValue(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+
+static DecodeStatus decodeSplsValue(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+
+static DecodeStatus decodeBranch(MCInst &Inst, unsigned Insn, uint64_t Address,
+ const void *Decoder);
+
+static DecodeStatus decodeShiftImm(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+
+#include "LanaiGenDisassemblerTables.inc"
+
+static DecodeStatus readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
+ uint64_t &Size, uint32_t &Insn) {
+ // We want to read exactly 4 bytes of data.
+ if (Bytes.size() < 4) {
+ Size = 0;
+ return MCDisassembler::Fail;
+ }
+
+ // Encoded as big-endian 32-bit word in the stream.
+ Insn =
+ (Bytes[0] << 24) | (Bytes[1] << 16) | (Bytes[2] << 8) | (Bytes[3] << 0);
+
+ return MCDisassembler::Success;
+}
+
+static void PostOperandDecodeAdjust(MCInst &Instr, uint32_t Insn) {
+ unsigned AluOp = LPAC::ADD;
+ // Fix up for pre and post operations.
+ int PqShift = -1;
+ if (isRMOpcode(Instr.getOpcode()))
+ PqShift = 16;
+ else if (isSPLSOpcode(Instr.getOpcode()))
+ PqShift = 10;
+ else if (isRRMOpcode(Instr.getOpcode())) {
+ PqShift = 16;
+ // Determine RRM ALU op.
+ AluOp = (Insn >> 8) & 0x7;
+ if (AluOp == 7)
+ // Handle JJJJJ
+ // 0b10000 or 0b11000
+ AluOp |= 0x20 | (((Insn >> 3) & 0xf) << 1);
+ }
+
+ if (PqShift != -1) {
+ unsigned PQ = (Insn >> PqShift) & 0x3;
+ switch (PQ) {
+ case 0x0:
+ if (Instr.getOperand(2).isReg()) {
+ Instr.getOperand(2).setReg(Lanai::R0);
+ }
+ if (Instr.getOperand(2).isImm())
+ Instr.getOperand(2).setImm(0);
+ break;
+ case 0x1:
+ AluOp = LPAC::makePostOp(AluOp);
+ break;
+ case 0x2:
+ break;
+ case 0x3:
+ AluOp = LPAC::makePreOp(AluOp);
+ break;
+ }
+ Instr.addOperand(MCOperand::createImm(AluOp));
+ }
+}
+
+DecodeStatus LanaiDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
+ ArrayRef<uint8_t> Bytes,
+ uint64_t Address,
+ raw_ostream &VStream,
+ raw_ostream &CStream) const {
+ uint32_t Insn;
+
+ DecodeStatus Result = readInstruction32(Bytes, Address, Size, Insn);
+
+ if (Result == MCDisassembler::Fail)
+ return MCDisassembler::Fail;
+
+ // Call auto-generated decoder function
+ Result =
+ decodeInstruction(DecoderTableLanai32, Instr, Insn, Address, this, STI);
+
+ if (Result != MCDisassembler::Fail) {
+ PostOperandDecodeAdjust(Instr, Insn);
+ Size = 4;
+ return Result;
+ }
+
+ return MCDisassembler::Fail;
+}
+
+static const unsigned GPRDecoderTable[] = {
+ Lanai::R0, Lanai::R1, Lanai::PC, Lanai::R3, Lanai::SP, Lanai::FP,
+ Lanai::R6, Lanai::R7, Lanai::RV, Lanai::R9, Lanai::RR1, Lanai::RR2,
+ Lanai::R12, Lanai::R13, Lanai::R14, Lanai::RCA, Lanai::R16, Lanai::R17,
+ Lanai::R18, Lanai::R19, Lanai::R20, Lanai::R21, Lanai::R22, Lanai::R23,
+ Lanai::R24, Lanai::R25, Lanai::R26, Lanai::R27, Lanai::R28, Lanai::R29,
+ Lanai::R30, Lanai::R31};
+
+DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo,
+ uint64_t Address, const void *Decoder) {
+ if (RegNo > 31)
+ return MCDisassembler::Fail;
+
+ unsigned Reg = GPRDecoderTable[RegNo];
+ Inst.addOperand(MCOperand::createReg(Reg));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus decodeRiMemoryValue(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ // RI memory values encoded using 23 bits:
+ // 5 bit register, 16 bit constant
+ unsigned Register = (Insn >> 18) & 0x1f;
+ Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
+ unsigned Offset = (Insn & 0xffff);
+ Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Offset)));
+
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus decodeRrMemoryValue(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ // RR memory values encoded using 20 bits:
+ // 5 bit register, 5 bit register, 2 bit PQ, 3 bit ALU operator, 5 bit JJJJJ
+ unsigned Register = (Insn >> 15) & 0x1f;
+ Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
+ Register = (Insn >> 10) & 0x1f;
+ Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
+
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus decodeSplsValue(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ // RI memory values encoded using 17 bits:
+ // 5 bit register, 10 bit constant
+ unsigned Register = (Insn >> 12) & 0x1f;
+ Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
+ unsigned Offset = (Insn & 0x3ff);
+ Inst.addOperand(MCOperand::createImm(SignExtend32<10>(Offset)));
+
+ return MCDisassembler::Success;
+}
+
+static bool tryAddingSymbolicOperand(int64_t Value, bool IsBranch,
+ uint64_t Address, uint64_t Offset,
+ uint64_t Width, MCInst &MI,
+ const void *Decoder) {
+ const MCDisassembler *Dis = static_cast<const MCDisassembler *>(Decoder);
+ return Dis->tryAddingSymbolicOperand(MI, Value, Address, IsBranch, Offset,
+ Width);
+}
+
+static DecodeStatus decodeBranch(MCInst &MI, unsigned Insn, uint64_t Address,
+ const void *Decoder) {
+ if (!tryAddingSymbolicOperand(Insn + Address, false, Address, 2, 23, MI,
+ Decoder))
+ MI.addOperand(MCOperand::createImm(Insn));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus decodeShiftImm(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ unsigned Offset = (Insn & 0xffff);
+ Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Offset)));
+
+ return MCDisassembler::Success;
+}
OpenPOWER on IntegriCloud