[llvm-branch-commits] [llvm] f07fbd5 - [Xtensa] Add basic support of Xtensa disassembler.

Andrei Safronov via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Aug 11 15:40:19 PDT 2020


Author: Andrei Safronov
Date: 2020-07-21T13:25:50+03:00
New Revision: f07fbd56c00c020e5ca1db11eeb5d561287446db

URL: https://github.com/llvm/llvm-project/commit/f07fbd56c00c020e5ca1db11eeb5d561287446db
DIFF: https://github.com/llvm/llvm-project/commit/f07fbd56c00c020e5ca1db11eeb5d561287446db.diff

LOG: [Xtensa] Add basic support of Xtensa disassembler.

Added: 
    llvm/lib/Target/Xtensa/Disassembler/CMakeLists.txt
    llvm/lib/Target/Xtensa/Disassembler/LLVMBuild.txt
    llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp

Modified: 
    llvm/lib/Target/Xtensa/CMakeLists.txt
    llvm/lib/Target/Xtensa/LLVMBuild.txt
    llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp
    llvm/lib/Target/Xtensa/XtensaOperands.td

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/Xtensa/CMakeLists.txt b/llvm/lib/Target/Xtensa/CMakeLists.txt
index d2bdea4cb0f9..28deec14ddb1 100644
--- a/llvm/lib/Target/Xtensa/CMakeLists.txt
+++ b/llvm/lib/Target/Xtensa/CMakeLists.txt
@@ -2,6 +2,7 @@ set(LLVM_TARGET_DEFINITIONS Xtensa.td)
 
 tablegen(LLVM XtensaGenAsmMatcher.inc -gen-asm-matcher)
 tablegen(LLVM XtensaGenAsmWriter.inc -gen-asm-writer)
+tablegen(LLVM XtensaGenDisassemblerTables.inc -gen-disassembler)
 tablegen(LLVM XtensaGenInstrInfo.inc -gen-instr-info)
 tablegen(LLVM XtensaGenMCCodeEmitter.inc -gen-emitter)
 tablegen(LLVM XtensaGenRegisterInfo.inc -gen-register-info)
@@ -14,6 +15,7 @@ add_llvm_target(XtensaCodeGen
   )
 
 add_subdirectory(AsmParser)
+add_subdirectory(Disassembler)
 add_subdirectory(MCTargetDesc)
 add_subdirectory(TargetInfo)
 

diff  --git a/llvm/lib/Target/Xtensa/Disassembler/CMakeLists.txt b/llvm/lib/Target/Xtensa/Disassembler/CMakeLists.txt
new file mode 100644
index 000000000000..541a9ede26a0
--- /dev/null
+++ b/llvm/lib/Target/Xtensa/Disassembler/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_llvm_component_library(LLVMXtensaDisassembler
+  XtensaDisassembler.cpp
+  )

diff  --git a/llvm/lib/Target/Xtensa/Disassembler/LLVMBuild.txt b/llvm/lib/Target/Xtensa/Disassembler/LLVMBuild.txt
new file mode 100644
index 000000000000..417c7338cb9f
--- /dev/null
+++ b/llvm/lib/Target/Xtensa/Disassembler/LLVMBuild.txt
@@ -0,0 +1,24 @@
+;===-- ./lib/Target/Xtensa/Disassembler/LLVMBuild.txt ---------*- Conf -*--===;
+;
+;                     The LLVM Compiler Infrastructure
+;
+; Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+; See https://llvm.org/LICENSE.txt for license information.
+; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+;
+;===------------------------------------------------------------------------===;
+;
+; 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 = XtensaDisassembler
+parent = Xtensa
+required_libraries = MCDisassembler Support XtensaInfo
+add_to_library_groups = Xtensa

diff  --git a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
new file mode 100644
index 000000000000..2da7b51a8ab9
--- /dev/null
+++ b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
@@ -0,0 +1,207 @@
+//===-- XtensaDisassembler.cpp - Disassembler for Xtensa ------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the XtensaDisassembler class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/XtensaMCTargetDesc.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 "Xtensa-disassembler"
+
+using DecodeStatus = MCDisassembler::DecodeStatus;
+
+namespace {
+
+class XtensaDisassembler : public MCDisassembler {
+  bool IsLittleEndian;
+
+public:
+  XtensaDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, bool isLE)
+      : MCDisassembler(STI, Ctx), IsLittleEndian(isLE) {}
+
+  bool hasDensity() const {
+    return STI.getFeatureBits()[Xtensa::FeatureDensity];
+  }
+
+  DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
+                              ArrayRef<uint8_t> Bytes, uint64_t Address,
+                              raw_ostream &CStream) const override;
+};
+} // end anonymous namespace
+
+static MCDisassembler *createXtensaDisassembler(const Target &T,
+                                                const MCSubtargetInfo &STI,
+                                                MCContext &Ctx) {
+  return new XtensaDisassembler(STI, Ctx, true);
+}
+
+extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaDisassembler() {
+  TargetRegistry::RegisterMCDisassembler(TheXtensaTarget,
+                                         createXtensaDisassembler);
+}
+
+static const unsigned ARDecoderTable[] = {
+    Xtensa::A0,  Xtensa::SP,  Xtensa::A2,  Xtensa::A3, Xtensa::A4,  Xtensa::A5,
+    Xtensa::A6,  Xtensa::A7,  Xtensa::A8,  Xtensa::A9, Xtensa::A10, Xtensa::A11,
+    Xtensa::A12, Xtensa::A13, Xtensa::A14, Xtensa::A15};
+
+static DecodeStatus DecodeARRegisterClass(MCInst &Inst, uint64_t RegNo,
+                                          uint64_t Address,
+                                          const void *Decoder) {
+  if (RegNo >= array_lengthof(ARDecoderTable))
+    return MCDisassembler::Fail;
+
+  unsigned Reg = ARDecoderTable[RegNo];
+  Inst.addOperand(MCOperand::createReg(Reg));
+  return MCDisassembler::Success;
+}
+
+static const unsigned SRDecoderTable[] = {Xtensa::SAR, 3};
+
+static DecodeStatus DecodeSRRegisterClass(MCInst &Inst, uint64_t RegNo,
+                                          uint64_t Address,
+                                          const void *Decoder) {
+  if (RegNo > 255)
+    return MCDisassembler::Fail;
+
+  for (unsigned i = 0; i < array_lengthof(SRDecoderTable); i += 2) {
+    if (SRDecoderTable[i + 1] == RegNo) {
+      unsigned Reg = SRDecoderTable[i];
+      Inst.addOperand(MCOperand::createReg(Reg));
+      return MCDisassembler::Success;
+    }
+  }
+
+  return MCDisassembler::Fail;
+}
+
+static DecodeStatus decodeImm8Operand(MCInst &Inst, uint64_t Imm,
+                                      int64_t Address, const void *Decoder) {
+  assert(isUInt<8>(Imm) && "Invalid immediate");
+  Inst.addOperand(MCOperand::createImm(SignExtend64<8>(Imm)));
+  return MCDisassembler::Success;
+}
+
+static DecodeStatus decodeImm8_sh8Operand(MCInst &Inst, uint64_t Imm,
+                                          int64_t Address,
+                                          const void *Decoder) {
+  assert(isUInt<8>(Imm) && "Invalid immediate");
+  Inst.addOperand(MCOperand::createImm(SignExtend64<16>(Imm << 8)));
+  return MCDisassembler::Success;
+}
+
+static DecodeStatus decodeImm12Operand(MCInst &Inst, uint64_t Imm,
+                                       int64_t Address, const void *Decoder) {
+  assert(isUInt<12>(Imm) && "Invalid immediate");
+  Inst.addOperand(MCOperand::createImm(SignExtend64<12>(Imm)));
+  return MCDisassembler::Success;
+}
+
+static DecodeStatus decodeUimm4Operand(MCInst &Inst, uint64_t Imm,
+                                       int64_t Address, const void *Decoder) {
+  assert(isUInt<4>(Imm) && "Invalid immediate");
+  Inst.addOperand(MCOperand::createImm(Imm));
+  return MCDisassembler::Success;
+}
+
+static DecodeStatus decodeUimm5Operand(MCInst &Inst, uint64_t Imm,
+                                       int64_t Address, const void *Decoder) {
+  assert(isUInt<5>(Imm) && "Invalid immediate");
+  Inst.addOperand(MCOperand::createImm(Imm));
+  return MCDisassembler::Success;
+}
+
+static DecodeStatus decodeImm1_16Operand(MCInst &Inst, uint64_t Imm,
+                                         int64_t Address, const void *Decoder) {
+  assert(isUInt<4>(Imm) && "Invalid immediate");
+  Inst.addOperand(MCOperand::createImm(Imm + 1));
+  return MCDisassembler::Success;
+}
+
+static DecodeStatus decodeShimm1_31Operand(MCInst &Inst, uint64_t Imm,
+                                           int64_t Address,
+                                           const void *Decoder) {
+  assert(isUInt<5>(Imm) && "Invalid immediate");
+  Inst.addOperand(MCOperand::createImm(32 - Imm));
+  return MCDisassembler::Success;
+}
+
+static DecodeStatus decodeMem8Operand(MCInst &Inst, uint64_t Imm,
+                                      int64_t Address, const void *Decoder) {
+  assert(isUInt<12>(Imm) && "Invalid immediate");
+  DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);
+  Inst.addOperand(MCOperand::createImm((Imm >> 4) & 0xff));
+  return MCDisassembler::Success;
+}
+
+static DecodeStatus decodeMem16Operand(MCInst &Inst, uint64_t Imm,
+                                       int64_t Address, const void *Decoder) {
+  assert(isUInt<12>(Imm) && "Invalid immediate");
+  DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);
+  Inst.addOperand(MCOperand::createImm((Imm >> 3) & 0x1fe));
+  return MCDisassembler::Success;
+}
+
+static DecodeStatus decodeMem32Operand(MCInst &Inst, uint64_t Imm,
+                                       int64_t Address, const void *Decoder) {
+  assert(isUInt<12>(Imm) && "Invalid immediate");
+  DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);
+  Inst.addOperand(MCOperand::createImm((Imm >> 2) & 0x3fc));
+  return MCDisassembler::Success;
+}
+
+/// Read four bytes from the ArrayRef and return 24 bit data sorted
+/// according to the given endianness.
+static DecodeStatus readInstruction24(ArrayRef<uint8_t> Bytes, uint64_t Address,
+                                      uint64_t &Size, uint32_t &Insn,
+                                      bool IsLittleEndian) {
+  // We want to read exactly 3 Bytes of data.
+  if (Bytes.size() < 3) {
+    Size = 0;
+    return MCDisassembler::Fail;
+  }
+
+  if (!IsLittleEndian) {
+    llvm_unreachable("Big-endian mode currently is not supported!");
+  } else {
+    Insn = (Bytes[2] << 16) | (Bytes[1] << 8) | (Bytes[0] << 0);
+  }
+
+  return MCDisassembler::Success;
+}
+
+#include "XtensaGenDisassemblerTables.inc"
+
+DecodeStatus XtensaDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
+                                                ArrayRef<uint8_t> Bytes,
+                                                uint64_t Address,
+                                                raw_ostream &CS) const {
+  uint32_t Insn;
+  DecodeStatus Result;
+
+  Result = readInstruction24(Bytes, Address, Size, Insn, IsLittleEndian);
+  if (Result == MCDisassembler::Fail)
+    return MCDisassembler::Fail;
+  LLVM_DEBUG(dbgs() << "Trying Xtensa 24-bit instruction table :\n");
+  Result = decodeInstruction(DecoderTable24, MI, Insn, Address, this, STI);
+  Size = 3;
+  return Result;
+}

diff  --git a/llvm/lib/Target/Xtensa/LLVMBuild.txt b/llvm/lib/Target/Xtensa/LLVMBuild.txt
index 360a01479840..90b88fc4c1b6 100644
--- a/llvm/lib/Target/Xtensa/LLVMBuild.txt
+++ b/llvm/lib/Target/Xtensa/LLVMBuild.txt
@@ -15,7 +15,7 @@
 ;===------------------------------------------------------------------------===;
 
 [common]
-subdirectories = AsmParser TargetInfo MCTargetDesc
+subdirectories = AsmParser Disassembler TargetInfo MCTargetDesc
 
 [component_0]
 type = TargetGroup
@@ -23,6 +23,7 @@ name = Xtensa
 parent = Target
 has_asmparser = 1
 has_asmprinter = 1
+has_disassembler = 1
 
 [component_1]
 type = Library

diff  --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp
index 865d98f1e6cf..f18da6b7462c 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp
@@ -81,11 +81,11 @@ void XtensaInstPrinter::printOperand(const MCInst *MI, int OpNum,
   printOperand(MI->getOperand(OpNum), O);
 }
 
-void XtensaInstPrinter::printMemOperand(const MCInst *MI, int opNum,
+void XtensaInstPrinter::printMemOperand(const MCInst *MI, int OpNum,
                                         raw_ostream &OS) {
-  OS << getRegisterName(MI->getOperand(opNum).getReg());
+  OS << getRegisterName(MI->getOperand(OpNum).getReg());
   OS << ", ";
-  printOperand(MI, opNum + 1, OS);
+  printOperand(MI, OpNum + 1, OS);
 }
 
 void XtensaInstPrinter::printImm8_AsmOperand(const MCInst *MI, int OpNum,

diff  --git a/llvm/lib/Target/Xtensa/XtensaOperands.td b/llvm/lib/Target/Xtensa/XtensaOperands.td
index 817bbeeb1313..735cb10b23e1 100644
--- a/llvm/lib/Target/Xtensa/XtensaOperands.td
+++ b/llvm/lib/Target/Xtensa/XtensaOperands.td
@@ -27,6 +27,7 @@ class Immediate<ValueType vt, code pred, string asmop>
 def Imm8_AsmOperand: ImmAsmOperand<"Imm8">;
 def imm8: Immediate<i32, [{ return Imm >= -128 && Imm <= 127; }], "Imm8_AsmOperand"> {
   let EncoderMethod = "getImm8OpValue";
+  let DecoderMethod = "decodeImm8Operand";
 }
 
 // imm8_sh8 predicate - Immediate in the range [-32768,32512] with (bits[7-0] == 0)
@@ -34,42 +35,49 @@ def imm8: Immediate<i32, [{ return Imm >= -128 && Imm <= 127; }], "Imm8_AsmOpera
 def Imm8_sh8_AsmOperand: ImmAsmOperand<"Imm8_sh8">;
 def imm8_sh8: Immediate<i32, [{ return Imm >= -32768 && Imm <= 32512 && ((Imm & 0xFF) == 0); }], "Imm8_sh8_AsmOperand"> {
   let EncoderMethod = "getImm8_sh8OpValue";
+  let DecoderMethod = "decodeImm8_sh8Operand";
 }
 
 // imm12 predicate - Immediate in the range [-2048,2047]
 def Imm12_AsmOperand: ImmAsmOperand<"Imm12">;
 def imm12: Immediate<i32, [{ return Imm >= -2048 && Imm <= 2047; }], "Imm12_AsmOperand"> {
   let EncoderMethod = "getImm12OpValue";
+  let DecoderMethod = "decodeImm12Operand";
 }
 
 // imm12m predicate - Immediate for MOV operation
 def Imm12m_AsmOperand: ImmAsmOperand<"Imm12m">;
 def imm12m: Immediate<i32, [{ return Imm >= -2048 && Imm <= 2047; }], "Imm12m_AsmOperand"> {
   let EncoderMethod = "getImm12OpValue";
+  let DecoderMethod = "decodeImm12Operand";
 }
 
 // uimm4 predicate - Immediate in the range [0,15]
 def Uimm4_AsmOperand: ImmAsmOperand<"Uimm4">;
 def uimm4: Immediate<i32, [{ return Imm >= 0 && Imm <= 15; }], "Uimm4_AsmOperand"> {
   let EncoderMethod = "getUimm4OpValue";
+  let DecoderMethod = "decodeUimm4Operand";
 }
 
 // uimm5 predicate - Immediate in the range [0,31]
 def Uimm5_AsmOperand: ImmAsmOperand<"Uimm5">;
 def uimm5: Immediate<i32, [{ return Imm >= 0 && Imm <= 31; }], "Uimm5_AsmOperand"> {
   let EncoderMethod = "getUimm5OpValue";
+  let DecoderMethod = "decodeUimm5Operand";
 }
 
 // imm1_16 predicate - Immediate in the range [1,16]
 def Imm1_16_AsmOperand: ImmAsmOperand<"Imm1_16">;
 def imm1_16: Immediate<i32, [{ return Imm >= 1 && Imm <= 16; }], "Imm1_16_AsmOperand"> {
   let EncoderMethod = "getImm1_16OpValue";
+  let DecoderMethod = "decodeImm1_16Operand";
 }
 
 // shimm1_31 predicate - Immediate in the range [1,31]
 def Shimm1_31_AsmOperand: ImmAsmOperand<"Shimm1_31">;
 def shimm1_31: Immediate<i32, [{ return Imm >= 1 && Imm <= 31; }], "Shimm1_31_AsmOperand"> {
   let EncoderMethod = "getShimm1_31OpValue";
+  let DecoderMethod = "decodeShimm1_31Operand";
 }
 
 // Memory offset 0..255 for 8-bit memory accesses
@@ -107,13 +115,25 @@ class mem<Operand offset> : Operand<i32>
   let PrintMethod = "printMemOperand";
 }
 
-def mem8: mem<offset8m8>;
+def mem8: mem<offset8m8>
+{
+  let DecoderMethod = "decodeMem8Operand";
+}
 
-def mem16: mem<offset8m16>;
+def mem16: mem<offset8m16>
+{
+  let DecoderMethod = "decodeMem16Operand";
+}
 
-def mem32: mem<offset8m32>;
+def mem32: mem<offset8m32>
+{
+  let DecoderMethod = "decodeMem32Operand";
+}
 
-def mem32n: mem<offset4m32>;
+def mem32n: mem<offset4m32>
+{
+  let DecoderMethod = "decodeMem32nOperand";
+}
 
 //Add patterns for future use in stack addressing mode
 def addr_ish1: ComplexPattern<iPTR, 2, "selectMemRegAddrISH1", [frameindex]>;


        


More information about the llvm-branch-commits mailing list