1 //===-- XtensaDisassembler.cpp - Disassembler for Xtensa ------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 6 // See https://llvm.org/LICENSE.txt for license information. 7 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 8 // 9 //===----------------------------------------------------------------------===// 10 // 11 // This file implements the XtensaDisassembler class. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "MCTargetDesc/XtensaMCTargetDesc.h" 16 #include "TargetInfo/XtensaTargetInfo.h" 17 #include "llvm/MC/MCContext.h" 18 #include "llvm/MC/MCDecoderOps.h" 19 #include "llvm/MC/MCDisassembler/MCDisassembler.h" 20 #include "llvm/MC/MCInst.h" 21 #include "llvm/MC/MCRegisterInfo.h" 22 #include "llvm/MC/MCSubtargetInfo.h" 23 #include "llvm/MC/TargetRegistry.h" 24 #include "llvm/Support/Endian.h" 25 26 using namespace llvm; 27 28 #define DEBUG_TYPE "Xtensa-disassembler" 29 30 using DecodeStatus = MCDisassembler::DecodeStatus; 31 32 namespace { 33 34 class XtensaDisassembler : public MCDisassembler { 35 bool IsLittleEndian; 36 37 public: 38 XtensaDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, bool isLE) 39 : MCDisassembler(STI, Ctx), IsLittleEndian(isLE) {} 40 41 bool hasDensity() const { 42 return STI.getFeatureBits()[Xtensa::FeatureDensity]; 43 } 44 45 DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, 46 ArrayRef<uint8_t> Bytes, uint64_t Address, 47 raw_ostream &CStream) const override; 48 }; 49 } // end anonymous namespace 50 51 static MCDisassembler *createXtensaDisassembler(const Target &T, 52 const MCSubtargetInfo &STI, 53 MCContext &Ctx) { 54 return new XtensaDisassembler(STI, Ctx, true); 55 } 56 57 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaDisassembler() { 58 TargetRegistry::RegisterMCDisassembler(getTheXtensaTarget(), 59 createXtensaDisassembler); 60 } 61 62 static const unsigned ARDecoderTable[] = { 63 Xtensa::A0, Xtensa::SP, Xtensa::A2, Xtensa::A3, Xtensa::A4, Xtensa::A5, 64 Xtensa::A6, Xtensa::A7, Xtensa::A8, Xtensa::A9, Xtensa::A10, Xtensa::A11, 65 Xtensa::A12, Xtensa::A13, Xtensa::A14, Xtensa::A15}; 66 67 static DecodeStatus DecodeARRegisterClass(MCInst &Inst, uint64_t RegNo, 68 uint64_t Address, 69 const void *Decoder) { 70 if (RegNo >= std::size(ARDecoderTable)) 71 return MCDisassembler::Fail; 72 73 unsigned Reg = ARDecoderTable[RegNo]; 74 Inst.addOperand(MCOperand::createReg(Reg)); 75 return MCDisassembler::Success; 76 } 77 78 static const unsigned SRDecoderTable[] = {Xtensa::SAR, 3}; 79 80 static DecodeStatus DecodeSRRegisterClass(MCInst &Inst, uint64_t RegNo, 81 uint64_t Address, 82 const void *Decoder) { 83 if (RegNo > 255) 84 return MCDisassembler::Fail; 85 86 for (unsigned i = 0; i < std::size(SRDecoderTable); i += 2) { 87 if (SRDecoderTable[i + 1] == RegNo) { 88 unsigned Reg = SRDecoderTable[i]; 89 Inst.addOperand(MCOperand::createReg(Reg)); 90 return MCDisassembler::Success; 91 } 92 } 93 94 return MCDisassembler::Fail; 95 } 96 97 static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch, 98 uint64_t Address, uint64_t Offset, 99 uint64_t InstSize, MCInst &MI, 100 const void *Decoder) { 101 const MCDisassembler *Dis = static_cast<const MCDisassembler *>(Decoder); 102 return Dis->tryAddingSymbolicOperand(MI, Value, Address, isBranch, Offset, /*OpSize=*/0, 103 InstSize); 104 } 105 106 static DecodeStatus decodeCallOperand(MCInst &Inst, uint64_t Imm, 107 int64_t Address, const void *Decoder) { 108 assert(isUInt<18>(Imm) && "Invalid immediate"); 109 Inst.addOperand(MCOperand::createImm(SignExtend64<20>(Imm << 2))); 110 return MCDisassembler::Success; 111 } 112 113 static DecodeStatus decodeJumpOperand(MCInst &Inst, uint64_t Imm, 114 int64_t Address, const void *Decoder) { 115 assert(isUInt<18>(Imm) && "Invalid immediate"); 116 Inst.addOperand(MCOperand::createImm(SignExtend64<18>(Imm))); 117 return MCDisassembler::Success; 118 } 119 120 static DecodeStatus decodeBranchOperand(MCInst &Inst, uint64_t Imm, 121 int64_t Address, const void *Decoder) { 122 switch (Inst.getOpcode()) { 123 case Xtensa::BEQZ: 124 case Xtensa::BGEZ: 125 case Xtensa::BLTZ: 126 case Xtensa::BNEZ: 127 assert(isUInt<12>(Imm) && "Invalid immediate"); 128 if (!tryAddingSymbolicOperand(SignExtend64<12>(Imm) + 4 + Address, true, 129 Address, 0, 3, Inst, Decoder)) 130 Inst.addOperand(MCOperand::createImm(SignExtend64<12>(Imm))); 131 break; 132 default: 133 assert(isUInt<8>(Imm) && "Invalid immediate"); 134 if (!tryAddingSymbolicOperand(SignExtend64<8>(Imm) + 4 + Address, true, 135 Address, 0, 3, Inst, Decoder)) 136 Inst.addOperand(MCOperand::createImm(SignExtend64<8>(Imm))); 137 } 138 return MCDisassembler::Success; 139 } 140 141 static DecodeStatus decodeL32ROperand(MCInst &Inst, uint64_t Imm, 142 int64_t Address, const void *Decoder) { 143 144 assert(isUInt<16>(Imm) && "Invalid immediate"); 145 Inst.addOperand(MCOperand::createImm( 146 SignExtend64<17>((Imm << 2) + 0x40000 + (Address & 0x3)))); 147 return MCDisassembler::Success; 148 } 149 150 static DecodeStatus decodeImm8Operand(MCInst &Inst, uint64_t Imm, 151 int64_t Address, const void *Decoder) { 152 assert(isUInt<8>(Imm) && "Invalid immediate"); 153 Inst.addOperand(MCOperand::createImm(SignExtend64<8>(Imm))); 154 return MCDisassembler::Success; 155 } 156 157 static DecodeStatus decodeImm8_sh8Operand(MCInst &Inst, uint64_t Imm, 158 int64_t Address, 159 const void *Decoder) { 160 assert(isUInt<8>(Imm) && "Invalid immediate"); 161 Inst.addOperand(MCOperand::createImm(SignExtend64<16>(Imm << 8))); 162 return MCDisassembler::Success; 163 } 164 165 static DecodeStatus decodeImm12Operand(MCInst &Inst, uint64_t Imm, 166 int64_t Address, const void *Decoder) { 167 assert(isUInt<12>(Imm) && "Invalid immediate"); 168 Inst.addOperand(MCOperand::createImm(SignExtend64<12>(Imm))); 169 return MCDisassembler::Success; 170 } 171 172 static DecodeStatus decodeUimm4Operand(MCInst &Inst, uint64_t Imm, 173 int64_t Address, const void *Decoder) { 174 assert(isUInt<4>(Imm) && "Invalid immediate"); 175 Inst.addOperand(MCOperand::createImm(Imm)); 176 return MCDisassembler::Success; 177 } 178 179 static DecodeStatus decodeUimm5Operand(MCInst &Inst, uint64_t Imm, 180 int64_t Address, const void *Decoder) { 181 assert(isUInt<5>(Imm) && "Invalid immediate"); 182 Inst.addOperand(MCOperand::createImm(Imm)); 183 return MCDisassembler::Success; 184 } 185 186 static DecodeStatus decodeImm1_16Operand(MCInst &Inst, uint64_t Imm, 187 int64_t Address, const void *Decoder) { 188 assert(isUInt<4>(Imm) && "Invalid immediate"); 189 Inst.addOperand(MCOperand::createImm(Imm + 1)); 190 return MCDisassembler::Success; 191 } 192 193 static DecodeStatus decodeShimm1_31Operand(MCInst &Inst, uint64_t Imm, 194 int64_t Address, 195 const void *Decoder) { 196 assert(isUInt<5>(Imm) && "Invalid immediate"); 197 Inst.addOperand(MCOperand::createImm(32 - Imm)); 198 return MCDisassembler::Success; 199 } 200 201 static int64_t TableB4const[16] = {-1, 1, 2, 3, 4, 5, 6, 7, 202 8, 10, 12, 16, 32, 64, 128, 256}; 203 static DecodeStatus decodeB4constOperand(MCInst &Inst, uint64_t Imm, 204 int64_t Address, const void *Decoder) { 205 assert(isUInt<4>(Imm) && "Invalid immediate"); 206 207 Inst.addOperand(MCOperand::createImm(TableB4const[Imm])); 208 return MCDisassembler::Success; 209 } 210 211 static int64_t TableB4constu[16] = {32768, 65536, 2, 3, 4, 5, 6, 7, 212 8, 10, 12, 16, 32, 64, 128, 256}; 213 static DecodeStatus decodeB4constuOperand(MCInst &Inst, uint64_t Imm, 214 int64_t Address, 215 const void *Decoder) { 216 assert(isUInt<4>(Imm) && "Invalid immediate"); 217 218 Inst.addOperand(MCOperand::createImm(TableB4constu[Imm])); 219 return MCDisassembler::Success; 220 } 221 222 static DecodeStatus decodeMem8Operand(MCInst &Inst, uint64_t Imm, 223 int64_t Address, const void *Decoder) { 224 assert(isUInt<12>(Imm) && "Invalid immediate"); 225 DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder); 226 Inst.addOperand(MCOperand::createImm((Imm >> 4) & 0xff)); 227 return MCDisassembler::Success; 228 } 229 230 static DecodeStatus decodeMem16Operand(MCInst &Inst, uint64_t Imm, 231 int64_t Address, const void *Decoder) { 232 assert(isUInt<12>(Imm) && "Invalid immediate"); 233 DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder); 234 Inst.addOperand(MCOperand::createImm((Imm >> 3) & 0x1fe)); 235 return MCDisassembler::Success; 236 } 237 238 static DecodeStatus decodeMem32Operand(MCInst &Inst, uint64_t Imm, 239 int64_t Address, const void *Decoder) { 240 assert(isUInt<12>(Imm) && "Invalid immediate"); 241 DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder); 242 Inst.addOperand(MCOperand::createImm((Imm >> 2) & 0x3fc)); 243 return MCDisassembler::Success; 244 } 245 246 /// Read three bytes from the ArrayRef and return 24 bit data 247 static DecodeStatus readInstruction24(ArrayRef<uint8_t> Bytes, uint64_t Address, 248 uint64_t &Size, uint32_t &Insn, 249 bool IsLittleEndian) { 250 // We want to read exactly 3 Bytes of data. 251 if (Bytes.size() < 3) { 252 Size = 0; 253 return MCDisassembler::Fail; 254 } 255 256 if (!IsLittleEndian) { 257 report_fatal_error("Big-endian mode currently is not supported!"); 258 } else { 259 Insn = (Bytes[2] << 16) | (Bytes[1] << 8) | (Bytes[0] << 0); 260 } 261 262 Size = 3; 263 return MCDisassembler::Success; 264 } 265 266 #include "XtensaGenDisassemblerTables.inc" 267 268 DecodeStatus XtensaDisassembler::getInstruction(MCInst &MI, uint64_t &Size, 269 ArrayRef<uint8_t> Bytes, 270 uint64_t Address, 271 raw_ostream &CS) const { 272 uint32_t Insn; 273 DecodeStatus Result; 274 275 Result = readInstruction24(Bytes, Address, Size, Insn, IsLittleEndian); 276 if (Result == MCDisassembler::Fail) 277 return MCDisassembler::Fail; 278 LLVM_DEBUG(dbgs() << "Trying Xtensa 24-bit instruction table :\n"); 279 Result = decodeInstruction(DecoderTable24, MI, Insn, Address, this, STI); 280 return Result; 281 } 282