xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/Lanai/Disassembler/LanaiDisassembler.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
10b57cec5SDimitry Andric //===- LanaiDisassembler.cpp - Disassembler for Lanai -----------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file is part of the Lanai Disassembler.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "LanaiDisassembler.h"
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "LanaiAluCode.h"
160b57cec5SDimitry Andric #include "LanaiCondCode.h"
170b57cec5SDimitry Andric #include "LanaiInstrInfo.h"
180b57cec5SDimitry Andric #include "TargetInfo/LanaiTargetInfo.h"
19*81ad6265SDimitry Andric #include "llvm/MC/MCDecoderOps.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
22349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
230b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric using namespace llvm;
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric typedef MCDisassembler::DecodeStatus DecodeStatus;
280b57cec5SDimitry Andric 
createLanaiDisassembler(const Target &,const MCSubtargetInfo & STI,MCContext & Ctx)290b57cec5SDimitry Andric static MCDisassembler *createLanaiDisassembler(const Target & /*T*/,
300b57cec5SDimitry Andric                                                const MCSubtargetInfo &STI,
310b57cec5SDimitry Andric                                                MCContext &Ctx) {
320b57cec5SDimitry Andric   return new LanaiDisassembler(STI, Ctx);
330b57cec5SDimitry Andric }
340b57cec5SDimitry Andric 
LLVMInitializeLanaiDisassembler()35480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLanaiDisassembler() {
360b57cec5SDimitry Andric   // Register the disassembler
370b57cec5SDimitry Andric   TargetRegistry::RegisterMCDisassembler(getTheLanaiTarget(),
380b57cec5SDimitry Andric                                          createLanaiDisassembler);
390b57cec5SDimitry Andric }
400b57cec5SDimitry Andric 
LanaiDisassembler(const MCSubtargetInfo & STI,MCContext & Ctx)410b57cec5SDimitry Andric LanaiDisassembler::LanaiDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
420b57cec5SDimitry Andric     : MCDisassembler(STI, Ctx) {}
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric // Forward declare because the autogenerated code will reference this.
450b57cec5SDimitry Andric // Definition is further down.
460b57cec5SDimitry Andric static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo,
470b57cec5SDimitry Andric                                            uint64_t Address,
48*81ad6265SDimitry Andric                                            const MCDisassembler *Decoder);
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric static DecodeStatus decodeRiMemoryValue(MCInst &Inst, unsigned Insn,
51*81ad6265SDimitry Andric                                         uint64_t Address,
52*81ad6265SDimitry Andric                                         const MCDisassembler *Decoder);
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric static DecodeStatus decodeRrMemoryValue(MCInst &Inst, unsigned Insn,
55*81ad6265SDimitry Andric                                         uint64_t Address,
56*81ad6265SDimitry Andric                                         const MCDisassembler *Decoder);
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric static DecodeStatus decodeSplsValue(MCInst &Inst, unsigned Insn,
59*81ad6265SDimitry Andric                                     uint64_t Address,
60*81ad6265SDimitry Andric                                     const MCDisassembler *Decoder);
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric static DecodeStatus decodeBranch(MCInst &Inst, unsigned Insn, uint64_t Address,
63*81ad6265SDimitry Andric                                  const MCDisassembler *Decoder);
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric static DecodeStatus decodePredicateOperand(MCInst &Inst, unsigned Val,
660b57cec5SDimitry Andric                                            uint64_t Address,
67*81ad6265SDimitry Andric                                            const MCDisassembler *Decoder);
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric static DecodeStatus decodeShiftImm(MCInst &Inst, unsigned Insn,
70*81ad6265SDimitry Andric                                    uint64_t Address,
71*81ad6265SDimitry Andric                                    const MCDisassembler *Decoder);
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric #include "LanaiGenDisassemblerTables.inc"
740b57cec5SDimitry Andric 
readInstruction32(ArrayRef<uint8_t> Bytes,uint64_t & Size,uint32_t & Insn)750b57cec5SDimitry Andric static DecodeStatus readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t &Size,
760b57cec5SDimitry Andric                                       uint32_t &Insn) {
770b57cec5SDimitry Andric   // We want to read exactly 4 bytes of data.
780b57cec5SDimitry Andric   if (Bytes.size() < 4) {
790b57cec5SDimitry Andric     Size = 0;
800b57cec5SDimitry Andric     return MCDisassembler::Fail;
810b57cec5SDimitry Andric   }
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   // Encoded as big-endian 32-bit word in the stream.
840b57cec5SDimitry Andric   Insn =
850b57cec5SDimitry Andric       (Bytes[0] << 24) | (Bytes[1] << 16) | (Bytes[2] << 8) | (Bytes[3] << 0);
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   return MCDisassembler::Success;
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric 
PostOperandDecodeAdjust(MCInst & Instr,uint32_t Insn)900b57cec5SDimitry Andric static void PostOperandDecodeAdjust(MCInst &Instr, uint32_t Insn) {
910b57cec5SDimitry Andric   unsigned AluOp = LPAC::ADD;
920b57cec5SDimitry Andric   // Fix up for pre and post operations.
930b57cec5SDimitry Andric   int PqShift = -1;
940b57cec5SDimitry Andric   if (isRMOpcode(Instr.getOpcode()))
950b57cec5SDimitry Andric     PqShift = 16;
960b57cec5SDimitry Andric   else if (isSPLSOpcode(Instr.getOpcode()))
970b57cec5SDimitry Andric     PqShift = 10;
980b57cec5SDimitry Andric   else if (isRRMOpcode(Instr.getOpcode())) {
990b57cec5SDimitry Andric     PqShift = 16;
1000b57cec5SDimitry Andric     // Determine RRM ALU op.
1010b57cec5SDimitry Andric     AluOp = (Insn >> 8) & 0x7;
1020b57cec5SDimitry Andric     if (AluOp == 7)
1030b57cec5SDimitry Andric       // Handle JJJJJ
1040b57cec5SDimitry Andric       // 0b10000 or 0b11000
1050b57cec5SDimitry Andric       AluOp |= 0x20 | (((Insn >> 3) & 0xf) << 1);
1060b57cec5SDimitry Andric   }
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric   if (PqShift != -1) {
1090b57cec5SDimitry Andric     unsigned PQ = (Insn >> PqShift) & 0x3;
1100b57cec5SDimitry Andric     switch (PQ) {
1110b57cec5SDimitry Andric     case 0x0:
1120b57cec5SDimitry Andric       if (Instr.getOperand(2).isReg()) {
1130b57cec5SDimitry Andric         Instr.getOperand(2).setReg(Lanai::R0);
1140b57cec5SDimitry Andric       }
1150b57cec5SDimitry Andric       if (Instr.getOperand(2).isImm())
1160b57cec5SDimitry Andric         Instr.getOperand(2).setImm(0);
1170b57cec5SDimitry Andric       break;
1180b57cec5SDimitry Andric     case 0x1:
1190b57cec5SDimitry Andric       AluOp = LPAC::makePostOp(AluOp);
1200b57cec5SDimitry Andric       break;
1210b57cec5SDimitry Andric     case 0x2:
1220b57cec5SDimitry Andric       break;
1230b57cec5SDimitry Andric     case 0x3:
1240b57cec5SDimitry Andric       AluOp = LPAC::makePreOp(AluOp);
1250b57cec5SDimitry Andric       break;
1260b57cec5SDimitry Andric     }
1270b57cec5SDimitry Andric     Instr.addOperand(MCOperand::createImm(AluOp));
1280b57cec5SDimitry Andric   }
1290b57cec5SDimitry Andric }
1300b57cec5SDimitry Andric 
131480093f4SDimitry Andric DecodeStatus
getInstruction(MCInst & Instr,uint64_t & Size,ArrayRef<uint8_t> Bytes,uint64_t Address,raw_ostream &) const132480093f4SDimitry Andric LanaiDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
133480093f4SDimitry Andric                                   ArrayRef<uint8_t> Bytes, uint64_t Address,
134480093f4SDimitry Andric                                   raw_ostream & /*CStream*/) const {
1350b57cec5SDimitry Andric   uint32_t Insn;
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric   DecodeStatus Result = readInstruction32(Bytes, Size, Insn);
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric   if (Result == MCDisassembler::Fail)
1400b57cec5SDimitry Andric     return MCDisassembler::Fail;
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric   // Call auto-generated decoder function
1430b57cec5SDimitry Andric   Result =
1440b57cec5SDimitry Andric       decodeInstruction(DecoderTableLanai32, Instr, Insn, Address, this, STI);
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric   if (Result != MCDisassembler::Fail) {
1470b57cec5SDimitry Andric     PostOperandDecodeAdjust(Instr, Insn);
1480b57cec5SDimitry Andric     Size = 4;
1490b57cec5SDimitry Andric     return Result;
1500b57cec5SDimitry Andric   }
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric   return MCDisassembler::Fail;
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric static const unsigned GPRDecoderTable[] = {
1560b57cec5SDimitry Andric     Lanai::R0,  Lanai::R1,  Lanai::PC,  Lanai::R3,  Lanai::SP,  Lanai::FP,
1570b57cec5SDimitry Andric     Lanai::R6,  Lanai::R7,  Lanai::RV,  Lanai::R9,  Lanai::RR1, Lanai::RR2,
1580b57cec5SDimitry Andric     Lanai::R12, Lanai::R13, Lanai::R14, Lanai::RCA, Lanai::R16, Lanai::R17,
1590b57cec5SDimitry Andric     Lanai::R18, Lanai::R19, Lanai::R20, Lanai::R21, Lanai::R22, Lanai::R23,
1600b57cec5SDimitry Andric     Lanai::R24, Lanai::R25, Lanai::R26, Lanai::R27, Lanai::R28, Lanai::R29,
1610b57cec5SDimitry Andric     Lanai::R30, Lanai::R31};
1620b57cec5SDimitry Andric 
DecodeGPRRegisterClass(MCInst & Inst,unsigned RegNo,uint64_t,const MCDisassembler *)1630b57cec5SDimitry Andric DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo,
1640b57cec5SDimitry Andric                                     uint64_t /*Address*/,
165*81ad6265SDimitry Andric                                     const MCDisassembler * /*Decoder*/) {
1660b57cec5SDimitry Andric   if (RegNo > 31)
1670b57cec5SDimitry Andric     return MCDisassembler::Fail;
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric   unsigned Reg = GPRDecoderTable[RegNo];
1700b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createReg(Reg));
1710b57cec5SDimitry Andric   return MCDisassembler::Success;
1720b57cec5SDimitry Andric }
1730b57cec5SDimitry Andric 
decodeRiMemoryValue(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)1740b57cec5SDimitry Andric static DecodeStatus decodeRiMemoryValue(MCInst &Inst, unsigned Insn,
175*81ad6265SDimitry Andric                                         uint64_t Address,
176*81ad6265SDimitry Andric                                         const MCDisassembler *Decoder) {
1770b57cec5SDimitry Andric   // RI memory values encoded using 23 bits:
1780b57cec5SDimitry Andric   //   5 bit register, 16 bit constant
1790b57cec5SDimitry Andric   unsigned Register = (Insn >> 18) & 0x1f;
1800b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
1810b57cec5SDimitry Andric   unsigned Offset = (Insn & 0xffff);
1820b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Offset)));
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric   return MCDisassembler::Success;
1850b57cec5SDimitry Andric }
1860b57cec5SDimitry Andric 
decodeRrMemoryValue(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)1870b57cec5SDimitry Andric static DecodeStatus decodeRrMemoryValue(MCInst &Inst, unsigned Insn,
188*81ad6265SDimitry Andric                                         uint64_t Address,
189*81ad6265SDimitry Andric                                         const MCDisassembler *Decoder) {
1900b57cec5SDimitry Andric   // RR memory values encoded using 20 bits:
1910b57cec5SDimitry Andric   //   5 bit register, 5 bit register, 2 bit PQ, 3 bit ALU operator, 5 bit JJJJJ
1920b57cec5SDimitry Andric   unsigned Register = (Insn >> 15) & 0x1f;
1930b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
1940b57cec5SDimitry Andric   Register = (Insn >> 10) & 0x1f;
1950b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric   return MCDisassembler::Success;
1980b57cec5SDimitry Andric }
1990b57cec5SDimitry Andric 
decodeSplsValue(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)2000b57cec5SDimitry Andric static DecodeStatus decodeSplsValue(MCInst &Inst, unsigned Insn,
201*81ad6265SDimitry Andric                                     uint64_t Address,
202*81ad6265SDimitry Andric                                     const MCDisassembler *Decoder) {
2030b57cec5SDimitry Andric   // RI memory values encoded using 17 bits:
2040b57cec5SDimitry Andric   //   5 bit register, 10 bit constant
2050b57cec5SDimitry Andric   unsigned Register = (Insn >> 12) & 0x1f;
2060b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
2070b57cec5SDimitry Andric   unsigned Offset = (Insn & 0x3ff);
2080b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createImm(SignExtend32<10>(Offset)));
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric   return MCDisassembler::Success;
2110b57cec5SDimitry Andric }
2120b57cec5SDimitry Andric 
tryAddingSymbolicOperand(int64_t Value,bool IsBranch,uint64_t Address,uint64_t Offset,uint64_t Width,MCInst & MI,const MCDisassembler * Decoder)2130b57cec5SDimitry Andric static bool tryAddingSymbolicOperand(int64_t Value, bool IsBranch,
2140b57cec5SDimitry Andric                                      uint64_t Address, uint64_t Offset,
2150b57cec5SDimitry Andric                                      uint64_t Width, MCInst &MI,
216*81ad6265SDimitry Andric                                      const MCDisassembler *Decoder) {
217*81ad6265SDimitry Andric   return Decoder->tryAddingSymbolicOperand(MI, Value, Address, IsBranch, Offset,
218*81ad6265SDimitry Andric                                            Width, /*InstSize=*/0);
2190b57cec5SDimitry Andric }
2200b57cec5SDimitry Andric 
decodeBranch(MCInst & MI,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)2210b57cec5SDimitry Andric static DecodeStatus decodeBranch(MCInst &MI, unsigned Insn, uint64_t Address,
222*81ad6265SDimitry Andric                                  const MCDisassembler *Decoder) {
2230b57cec5SDimitry Andric   if (!tryAddingSymbolicOperand(Insn + Address, false, Address, 2, 23, MI,
2240b57cec5SDimitry Andric                                 Decoder))
2250b57cec5SDimitry Andric     MI.addOperand(MCOperand::createImm(Insn));
2260b57cec5SDimitry Andric   return MCDisassembler::Success;
2270b57cec5SDimitry Andric }
2280b57cec5SDimitry Andric 
decodeShiftImm(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)2290b57cec5SDimitry Andric static DecodeStatus decodeShiftImm(MCInst &Inst, unsigned Insn,
230*81ad6265SDimitry Andric                                    uint64_t Address,
231*81ad6265SDimitry Andric                                    const MCDisassembler *Decoder) {
2320b57cec5SDimitry Andric   unsigned Offset = (Insn & 0xffff);
2330b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Offset)));
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric   return MCDisassembler::Success;
2360b57cec5SDimitry Andric }
2370b57cec5SDimitry Andric 
decodePredicateOperand(MCInst & Inst,unsigned Val,uint64_t Address,const MCDisassembler * Decoder)2380b57cec5SDimitry Andric static DecodeStatus decodePredicateOperand(MCInst &Inst, unsigned Val,
2390b57cec5SDimitry Andric                                            uint64_t Address,
240*81ad6265SDimitry Andric                                            const MCDisassembler *Decoder) {
2410b57cec5SDimitry Andric   if (Val >= LPCC::UNKNOWN)
2420b57cec5SDimitry Andric     return MCDisassembler::Fail;
2430b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createImm(Val));
2440b57cec5SDimitry Andric   return MCDisassembler::Success;
2450b57cec5SDimitry Andric }
246