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