LanaiDisassembler.cpp revision 360784
1//===- LanaiDisassembler.cpp - Disassembler for Lanai -----------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file is part of the Lanai Disassembler.
10//
11//===----------------------------------------------------------------------===//
12
13#include "LanaiDisassembler.h"
14
15#include "LanaiAluCode.h"
16#include "LanaiCondCode.h"
17#include "LanaiInstrInfo.h"
18#include "TargetInfo/LanaiTargetInfo.h"
19#include "llvm/MC/MCFixedLenDisassembler.h"
20#include "llvm/MC/MCInst.h"
21#include "llvm/MC/MCSubtargetInfo.h"
22#include "llvm/Support/MathExtras.h"
23#include "llvm/Support/TargetRegistry.h"
24
25using namespace llvm;
26
27typedef MCDisassembler::DecodeStatus DecodeStatus;
28
29namespace llvm {
30Target &getTheLanaiTarget();
31}
32
33static MCDisassembler *createLanaiDisassembler(const Target & /*T*/,
34                                               const MCSubtargetInfo &STI,
35                                               MCContext &Ctx) {
36  return new LanaiDisassembler(STI, Ctx);
37}
38
39extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLanaiDisassembler() {
40  // Register the disassembler
41  TargetRegistry::RegisterMCDisassembler(getTheLanaiTarget(),
42                                         createLanaiDisassembler);
43}
44
45LanaiDisassembler::LanaiDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
46    : MCDisassembler(STI, Ctx) {}
47
48// Forward declare because the autogenerated code will reference this.
49// Definition is further down.
50static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo,
51                                           uint64_t Address,
52                                           const void *Decoder);
53
54static DecodeStatus decodeRiMemoryValue(MCInst &Inst, unsigned Insn,
55                                        uint64_t Address, const void *Decoder);
56
57static DecodeStatus decodeRrMemoryValue(MCInst &Inst, unsigned Insn,
58                                        uint64_t Address, const void *Decoder);
59
60static DecodeStatus decodeSplsValue(MCInst &Inst, unsigned Insn,
61                                    uint64_t Address, const void *Decoder);
62
63static DecodeStatus decodeBranch(MCInst &Inst, unsigned Insn, uint64_t Address,
64                                 const void *Decoder);
65
66static DecodeStatus decodePredicateOperand(MCInst &Inst, unsigned Val,
67                                           uint64_t Address,
68                                           const void *Decoder);
69
70static DecodeStatus decodeShiftImm(MCInst &Inst, unsigned Insn,
71                                   uint64_t Address, const void *Decoder);
72
73#include "LanaiGenDisassemblerTables.inc"
74
75static DecodeStatus readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t &Size,
76                                      uint32_t &Insn) {
77  // We want to read exactly 4 bytes of data.
78  if (Bytes.size() < 4) {
79    Size = 0;
80    return MCDisassembler::Fail;
81  }
82
83  // Encoded as big-endian 32-bit word in the stream.
84  Insn =
85      (Bytes[0] << 24) | (Bytes[1] << 16) | (Bytes[2] << 8) | (Bytes[3] << 0);
86
87  return MCDisassembler::Success;
88}
89
90static void PostOperandDecodeAdjust(MCInst &Instr, uint32_t Insn) {
91  unsigned AluOp = LPAC::ADD;
92  // Fix up for pre and post operations.
93  int PqShift = -1;
94  if (isRMOpcode(Instr.getOpcode()))
95    PqShift = 16;
96  else if (isSPLSOpcode(Instr.getOpcode()))
97    PqShift = 10;
98  else if (isRRMOpcode(Instr.getOpcode())) {
99    PqShift = 16;
100    // Determine RRM ALU op.
101    AluOp = (Insn >> 8) & 0x7;
102    if (AluOp == 7)
103      // Handle JJJJJ
104      // 0b10000 or 0b11000
105      AluOp |= 0x20 | (((Insn >> 3) & 0xf) << 1);
106  }
107
108  if (PqShift != -1) {
109    unsigned PQ = (Insn >> PqShift) & 0x3;
110    switch (PQ) {
111    case 0x0:
112      if (Instr.getOperand(2).isReg()) {
113        Instr.getOperand(2).setReg(Lanai::R0);
114      }
115      if (Instr.getOperand(2).isImm())
116        Instr.getOperand(2).setImm(0);
117      break;
118    case 0x1:
119      AluOp = LPAC::makePostOp(AluOp);
120      break;
121    case 0x2:
122      break;
123    case 0x3:
124      AluOp = LPAC::makePreOp(AluOp);
125      break;
126    }
127    Instr.addOperand(MCOperand::createImm(AluOp));
128  }
129}
130
131DecodeStatus
132LanaiDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
133                                  ArrayRef<uint8_t> Bytes, uint64_t Address,
134                                  raw_ostream & /*CStream*/) const {
135  uint32_t Insn;
136
137  DecodeStatus Result = readInstruction32(Bytes, Size, Insn);
138
139  if (Result == MCDisassembler::Fail)
140    return MCDisassembler::Fail;
141
142  // Call auto-generated decoder function
143  Result =
144      decodeInstruction(DecoderTableLanai32, Instr, Insn, Address, this, STI);
145
146  if (Result != MCDisassembler::Fail) {
147    PostOperandDecodeAdjust(Instr, Insn);
148    Size = 4;
149    return Result;
150  }
151
152  return MCDisassembler::Fail;
153}
154
155static const unsigned GPRDecoderTable[] = {
156    Lanai::R0,  Lanai::R1,  Lanai::PC,  Lanai::R3,  Lanai::SP,  Lanai::FP,
157    Lanai::R6,  Lanai::R7,  Lanai::RV,  Lanai::R9,  Lanai::RR1, Lanai::RR2,
158    Lanai::R12, Lanai::R13, Lanai::R14, Lanai::RCA, Lanai::R16, Lanai::R17,
159    Lanai::R18, Lanai::R19, Lanai::R20, Lanai::R21, Lanai::R22, Lanai::R23,
160    Lanai::R24, Lanai::R25, Lanai::R26, Lanai::R27, Lanai::R28, Lanai::R29,
161    Lanai::R30, Lanai::R31};
162
163DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo,
164                                    uint64_t /*Address*/,
165                                    const void * /*Decoder*/) {
166  if (RegNo > 31)
167    return MCDisassembler::Fail;
168
169  unsigned Reg = GPRDecoderTable[RegNo];
170  Inst.addOperand(MCOperand::createReg(Reg));
171  return MCDisassembler::Success;
172}
173
174static DecodeStatus decodeRiMemoryValue(MCInst &Inst, unsigned Insn,
175                                        uint64_t Address, const void *Decoder) {
176  // RI memory values encoded using 23 bits:
177  //   5 bit register, 16 bit constant
178  unsigned Register = (Insn >> 18) & 0x1f;
179  Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
180  unsigned Offset = (Insn & 0xffff);
181  Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Offset)));
182
183  return MCDisassembler::Success;
184}
185
186static DecodeStatus decodeRrMemoryValue(MCInst &Inst, unsigned Insn,
187                                        uint64_t Address, const void *Decoder) {
188  // RR memory values encoded using 20 bits:
189  //   5 bit register, 5 bit register, 2 bit PQ, 3 bit ALU operator, 5 bit JJJJJ
190  unsigned Register = (Insn >> 15) & 0x1f;
191  Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
192  Register = (Insn >> 10) & 0x1f;
193  Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
194
195  return MCDisassembler::Success;
196}
197
198static DecodeStatus decodeSplsValue(MCInst &Inst, unsigned Insn,
199                                    uint64_t Address, const void *Decoder) {
200  // RI memory values encoded using 17 bits:
201  //   5 bit register, 10 bit constant
202  unsigned Register = (Insn >> 12) & 0x1f;
203  Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
204  unsigned Offset = (Insn & 0x3ff);
205  Inst.addOperand(MCOperand::createImm(SignExtend32<10>(Offset)));
206
207  return MCDisassembler::Success;
208}
209
210static bool tryAddingSymbolicOperand(int64_t Value, bool IsBranch,
211                                     uint64_t Address, uint64_t Offset,
212                                     uint64_t Width, MCInst &MI,
213                                     const void *Decoder) {
214  const MCDisassembler *Dis = static_cast<const MCDisassembler *>(Decoder);
215  return Dis->tryAddingSymbolicOperand(MI, Value, Address, IsBranch, Offset,
216                                       Width);
217}
218
219static DecodeStatus decodeBranch(MCInst &MI, unsigned Insn, uint64_t Address,
220                                 const void *Decoder) {
221  if (!tryAddingSymbolicOperand(Insn + Address, false, Address, 2, 23, MI,
222                                Decoder))
223    MI.addOperand(MCOperand::createImm(Insn));
224  return MCDisassembler::Success;
225}
226
227static DecodeStatus decodeShiftImm(MCInst &Inst, unsigned Insn,
228                                   uint64_t Address, const void *Decoder) {
229  unsigned Offset = (Insn & 0xffff);
230  Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Offset)));
231
232  return MCDisassembler::Success;
233}
234
235static DecodeStatus decodePredicateOperand(MCInst &Inst, unsigned Val,
236                                           uint64_t Address,
237                                           const void *Decoder) {
238  if (Val >= LPCC::UNKNOWN)
239    return MCDisassembler::Fail;
240  Inst.addOperand(MCOperand::createImm(Val));
241  return MCDisassembler::Success;
242}
243