109467b48Spatrick //===- LanaiDisassembler.cpp - Disassembler for Lanai -----------*- C++ -*-===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This file is part of the Lanai Disassembler.
1009467b48Spatrick //
1109467b48Spatrick //===----------------------------------------------------------------------===//
1209467b48Spatrick
1309467b48Spatrick #include "LanaiDisassembler.h"
1409467b48Spatrick
1509467b48Spatrick #include "LanaiAluCode.h"
1609467b48Spatrick #include "LanaiCondCode.h"
1709467b48Spatrick #include "LanaiInstrInfo.h"
1809467b48Spatrick #include "TargetInfo/LanaiTargetInfo.h"
19*d415bd75Srobert #include "llvm/MC/MCDecoderOps.h"
2009467b48Spatrick #include "llvm/MC/MCInst.h"
2109467b48Spatrick #include "llvm/MC/MCSubtargetInfo.h"
22*d415bd75Srobert #include "llvm/MC/TargetRegistry.h"
2309467b48Spatrick #include "llvm/Support/MathExtras.h"
2409467b48Spatrick
2509467b48Spatrick using namespace llvm;
2609467b48Spatrick
2709467b48Spatrick typedef MCDisassembler::DecodeStatus DecodeStatus;
2809467b48Spatrick
createLanaiDisassembler(const Target &,const MCSubtargetInfo & STI,MCContext & Ctx)2909467b48Spatrick static MCDisassembler *createLanaiDisassembler(const Target & /*T*/,
3009467b48Spatrick const MCSubtargetInfo &STI,
3109467b48Spatrick MCContext &Ctx) {
3209467b48Spatrick return new LanaiDisassembler(STI, Ctx);
3309467b48Spatrick }
3409467b48Spatrick
LLVMInitializeLanaiDisassembler()3509467b48Spatrick extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLanaiDisassembler() {
3609467b48Spatrick // Register the disassembler
3709467b48Spatrick TargetRegistry::RegisterMCDisassembler(getTheLanaiTarget(),
3809467b48Spatrick createLanaiDisassembler);
3909467b48Spatrick }
4009467b48Spatrick
LanaiDisassembler(const MCSubtargetInfo & STI,MCContext & Ctx)4109467b48Spatrick LanaiDisassembler::LanaiDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
4209467b48Spatrick : MCDisassembler(STI, Ctx) {}
4309467b48Spatrick
4409467b48Spatrick // Forward declare because the autogenerated code will reference this.
4509467b48Spatrick // Definition is further down.
4609467b48Spatrick static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo,
4709467b48Spatrick uint64_t Address,
48*d415bd75Srobert const MCDisassembler *Decoder);
4909467b48Spatrick
5009467b48Spatrick static DecodeStatus decodeRiMemoryValue(MCInst &Inst, unsigned Insn,
51*d415bd75Srobert uint64_t Address,
52*d415bd75Srobert const MCDisassembler *Decoder);
5309467b48Spatrick
5409467b48Spatrick static DecodeStatus decodeRrMemoryValue(MCInst &Inst, unsigned Insn,
55*d415bd75Srobert uint64_t Address,
56*d415bd75Srobert const MCDisassembler *Decoder);
5709467b48Spatrick
5809467b48Spatrick static DecodeStatus decodeSplsValue(MCInst &Inst, unsigned Insn,
59*d415bd75Srobert uint64_t Address,
60*d415bd75Srobert const MCDisassembler *Decoder);
6109467b48Spatrick
6209467b48Spatrick static DecodeStatus decodeBranch(MCInst &Inst, unsigned Insn, uint64_t Address,
63*d415bd75Srobert const MCDisassembler *Decoder);
6409467b48Spatrick
6509467b48Spatrick static DecodeStatus decodePredicateOperand(MCInst &Inst, unsigned Val,
6609467b48Spatrick uint64_t Address,
67*d415bd75Srobert const MCDisassembler *Decoder);
6809467b48Spatrick
6909467b48Spatrick static DecodeStatus decodeShiftImm(MCInst &Inst, unsigned Insn,
70*d415bd75Srobert uint64_t Address,
71*d415bd75Srobert const MCDisassembler *Decoder);
7209467b48Spatrick
7309467b48Spatrick #include "LanaiGenDisassemblerTables.inc"
7409467b48Spatrick
readInstruction32(ArrayRef<uint8_t> Bytes,uint64_t & Size,uint32_t & Insn)7509467b48Spatrick static DecodeStatus readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t &Size,
7609467b48Spatrick uint32_t &Insn) {
7709467b48Spatrick // We want to read exactly 4 bytes of data.
7809467b48Spatrick if (Bytes.size() < 4) {
7909467b48Spatrick Size = 0;
8009467b48Spatrick return MCDisassembler::Fail;
8109467b48Spatrick }
8209467b48Spatrick
8309467b48Spatrick // Encoded as big-endian 32-bit word in the stream.
8409467b48Spatrick Insn =
8509467b48Spatrick (Bytes[0] << 24) | (Bytes[1] << 16) | (Bytes[2] << 8) | (Bytes[3] << 0);
8609467b48Spatrick
8709467b48Spatrick return MCDisassembler::Success;
8809467b48Spatrick }
8909467b48Spatrick
PostOperandDecodeAdjust(MCInst & Instr,uint32_t Insn)9009467b48Spatrick static void PostOperandDecodeAdjust(MCInst &Instr, uint32_t Insn) {
9109467b48Spatrick unsigned AluOp = LPAC::ADD;
9209467b48Spatrick // Fix up for pre and post operations.
9309467b48Spatrick int PqShift = -1;
9409467b48Spatrick if (isRMOpcode(Instr.getOpcode()))
9509467b48Spatrick PqShift = 16;
9609467b48Spatrick else if (isSPLSOpcode(Instr.getOpcode()))
9709467b48Spatrick PqShift = 10;
9809467b48Spatrick else if (isRRMOpcode(Instr.getOpcode())) {
9909467b48Spatrick PqShift = 16;
10009467b48Spatrick // Determine RRM ALU op.
10109467b48Spatrick AluOp = (Insn >> 8) & 0x7;
10209467b48Spatrick if (AluOp == 7)
10309467b48Spatrick // Handle JJJJJ
10409467b48Spatrick // 0b10000 or 0b11000
10509467b48Spatrick AluOp |= 0x20 | (((Insn >> 3) & 0xf) << 1);
10609467b48Spatrick }
10709467b48Spatrick
10809467b48Spatrick if (PqShift != -1) {
10909467b48Spatrick unsigned PQ = (Insn >> PqShift) & 0x3;
11009467b48Spatrick switch (PQ) {
11109467b48Spatrick case 0x0:
11209467b48Spatrick if (Instr.getOperand(2).isReg()) {
11309467b48Spatrick Instr.getOperand(2).setReg(Lanai::R0);
11409467b48Spatrick }
11509467b48Spatrick if (Instr.getOperand(2).isImm())
11609467b48Spatrick Instr.getOperand(2).setImm(0);
11709467b48Spatrick break;
11809467b48Spatrick case 0x1:
11909467b48Spatrick AluOp = LPAC::makePostOp(AluOp);
12009467b48Spatrick break;
12109467b48Spatrick case 0x2:
12209467b48Spatrick break;
12309467b48Spatrick case 0x3:
12409467b48Spatrick AluOp = LPAC::makePreOp(AluOp);
12509467b48Spatrick break;
12609467b48Spatrick }
12709467b48Spatrick Instr.addOperand(MCOperand::createImm(AluOp));
12809467b48Spatrick }
12909467b48Spatrick }
13009467b48Spatrick
13109467b48Spatrick DecodeStatus
getInstruction(MCInst & Instr,uint64_t & Size,ArrayRef<uint8_t> Bytes,uint64_t Address,raw_ostream &) const13209467b48Spatrick LanaiDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
13309467b48Spatrick ArrayRef<uint8_t> Bytes, uint64_t Address,
13409467b48Spatrick raw_ostream & /*CStream*/) const {
13509467b48Spatrick uint32_t Insn;
13609467b48Spatrick
13709467b48Spatrick DecodeStatus Result = readInstruction32(Bytes, Size, Insn);
13809467b48Spatrick
13909467b48Spatrick if (Result == MCDisassembler::Fail)
14009467b48Spatrick return MCDisassembler::Fail;
14109467b48Spatrick
14209467b48Spatrick // Call auto-generated decoder function
14309467b48Spatrick Result =
14409467b48Spatrick decodeInstruction(DecoderTableLanai32, Instr, Insn, Address, this, STI);
14509467b48Spatrick
14609467b48Spatrick if (Result != MCDisassembler::Fail) {
14709467b48Spatrick PostOperandDecodeAdjust(Instr, Insn);
14809467b48Spatrick Size = 4;
14909467b48Spatrick return Result;
15009467b48Spatrick }
15109467b48Spatrick
15209467b48Spatrick return MCDisassembler::Fail;
15309467b48Spatrick }
15409467b48Spatrick
15509467b48Spatrick static const unsigned GPRDecoderTable[] = {
15609467b48Spatrick Lanai::R0, Lanai::R1, Lanai::PC, Lanai::R3, Lanai::SP, Lanai::FP,
15709467b48Spatrick Lanai::R6, Lanai::R7, Lanai::RV, Lanai::R9, Lanai::RR1, Lanai::RR2,
15809467b48Spatrick Lanai::R12, Lanai::R13, Lanai::R14, Lanai::RCA, Lanai::R16, Lanai::R17,
15909467b48Spatrick Lanai::R18, Lanai::R19, Lanai::R20, Lanai::R21, Lanai::R22, Lanai::R23,
16009467b48Spatrick Lanai::R24, Lanai::R25, Lanai::R26, Lanai::R27, Lanai::R28, Lanai::R29,
16109467b48Spatrick Lanai::R30, Lanai::R31};
16209467b48Spatrick
DecodeGPRRegisterClass(MCInst & Inst,unsigned RegNo,uint64_t,const MCDisassembler *)16309467b48Spatrick DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo,
16409467b48Spatrick uint64_t /*Address*/,
165*d415bd75Srobert const MCDisassembler * /*Decoder*/) {
16609467b48Spatrick if (RegNo > 31)
16709467b48Spatrick return MCDisassembler::Fail;
16809467b48Spatrick
16909467b48Spatrick unsigned Reg = GPRDecoderTable[RegNo];
17009467b48Spatrick Inst.addOperand(MCOperand::createReg(Reg));
17109467b48Spatrick return MCDisassembler::Success;
17209467b48Spatrick }
17309467b48Spatrick
decodeRiMemoryValue(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)17409467b48Spatrick static DecodeStatus decodeRiMemoryValue(MCInst &Inst, unsigned Insn,
175*d415bd75Srobert uint64_t Address,
176*d415bd75Srobert const MCDisassembler *Decoder) {
17709467b48Spatrick // RI memory values encoded using 23 bits:
17809467b48Spatrick // 5 bit register, 16 bit constant
17909467b48Spatrick unsigned Register = (Insn >> 18) & 0x1f;
18009467b48Spatrick Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
18109467b48Spatrick unsigned Offset = (Insn & 0xffff);
18209467b48Spatrick Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Offset)));
18309467b48Spatrick
18409467b48Spatrick return MCDisassembler::Success;
18509467b48Spatrick }
18609467b48Spatrick
decodeRrMemoryValue(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)18709467b48Spatrick static DecodeStatus decodeRrMemoryValue(MCInst &Inst, unsigned Insn,
188*d415bd75Srobert uint64_t Address,
189*d415bd75Srobert const MCDisassembler *Decoder) {
19009467b48Spatrick // RR memory values encoded using 20 bits:
19109467b48Spatrick // 5 bit register, 5 bit register, 2 bit PQ, 3 bit ALU operator, 5 bit JJJJJ
19209467b48Spatrick unsigned Register = (Insn >> 15) & 0x1f;
19309467b48Spatrick Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
19409467b48Spatrick Register = (Insn >> 10) & 0x1f;
19509467b48Spatrick Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
19609467b48Spatrick
19709467b48Spatrick return MCDisassembler::Success;
19809467b48Spatrick }
19909467b48Spatrick
decodeSplsValue(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)20009467b48Spatrick static DecodeStatus decodeSplsValue(MCInst &Inst, unsigned Insn,
201*d415bd75Srobert uint64_t Address,
202*d415bd75Srobert const MCDisassembler *Decoder) {
20309467b48Spatrick // RI memory values encoded using 17 bits:
20409467b48Spatrick // 5 bit register, 10 bit constant
20509467b48Spatrick unsigned Register = (Insn >> 12) & 0x1f;
20609467b48Spatrick Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
20709467b48Spatrick unsigned Offset = (Insn & 0x3ff);
20809467b48Spatrick Inst.addOperand(MCOperand::createImm(SignExtend32<10>(Offset)));
20909467b48Spatrick
21009467b48Spatrick return MCDisassembler::Success;
21109467b48Spatrick }
21209467b48Spatrick
tryAddingSymbolicOperand(int64_t Value,bool IsBranch,uint64_t Address,uint64_t Offset,uint64_t Width,MCInst & MI,const MCDisassembler * Decoder)21309467b48Spatrick static bool tryAddingSymbolicOperand(int64_t Value, bool IsBranch,
21409467b48Spatrick uint64_t Address, uint64_t Offset,
21509467b48Spatrick uint64_t Width, MCInst &MI,
216*d415bd75Srobert const MCDisassembler *Decoder) {
217*d415bd75Srobert return Decoder->tryAddingSymbolicOperand(MI, Value, Address, IsBranch, Offset,
218*d415bd75Srobert Width, /*InstSize=*/0);
21909467b48Spatrick }
22009467b48Spatrick
decodeBranch(MCInst & MI,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)22109467b48Spatrick static DecodeStatus decodeBranch(MCInst &MI, unsigned Insn, uint64_t Address,
222*d415bd75Srobert const MCDisassembler *Decoder) {
22309467b48Spatrick if (!tryAddingSymbolicOperand(Insn + Address, false, Address, 2, 23, MI,
22409467b48Spatrick Decoder))
22509467b48Spatrick MI.addOperand(MCOperand::createImm(Insn));
22609467b48Spatrick return MCDisassembler::Success;
22709467b48Spatrick }
22809467b48Spatrick
decodeShiftImm(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)22909467b48Spatrick static DecodeStatus decodeShiftImm(MCInst &Inst, unsigned Insn,
230*d415bd75Srobert uint64_t Address,
231*d415bd75Srobert const MCDisassembler *Decoder) {
23209467b48Spatrick unsigned Offset = (Insn & 0xffff);
23309467b48Spatrick Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Offset)));
23409467b48Spatrick
23509467b48Spatrick return MCDisassembler::Success;
23609467b48Spatrick }
23709467b48Spatrick
decodePredicateOperand(MCInst & Inst,unsigned Val,uint64_t Address,const MCDisassembler * Decoder)23809467b48Spatrick static DecodeStatus decodePredicateOperand(MCInst &Inst, unsigned Val,
23909467b48Spatrick uint64_t Address,
240*d415bd75Srobert const MCDisassembler *Decoder) {
24109467b48Spatrick if (Val >= LPCC::UNKNOWN)
24209467b48Spatrick return MCDisassembler::Fail;
24309467b48Spatrick Inst.addOperand(MCOperand::createImm(Val));
24409467b48Spatrick return MCDisassembler::Success;
24509467b48Spatrick }
246