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