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 { return STI.hasFeature(Xtensa::FeatureDensity); } 42 43 DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, 44 ArrayRef<uint8_t> Bytes, uint64_t Address, 45 raw_ostream &CStream) const override; 46 }; 47 } // end anonymous namespace 48 49 static MCDisassembler *createXtensaDisassembler(const Target &T, 50 const MCSubtargetInfo &STI, 51 MCContext &Ctx) { 52 return new XtensaDisassembler(STI, Ctx, true); 53 } 54 55 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaDisassembler() { 56 TargetRegistry::RegisterMCDisassembler(getTheXtensaTarget(), 57 createXtensaDisassembler); 58 } 59 60 static const unsigned ARDecoderTable[] = { 61 Xtensa::A0, Xtensa::SP, Xtensa::A2, Xtensa::A3, Xtensa::A4, Xtensa::A5, 62 Xtensa::A6, Xtensa::A7, Xtensa::A8, Xtensa::A9, Xtensa::A10, Xtensa::A11, 63 Xtensa::A12, Xtensa::A13, Xtensa::A14, Xtensa::A15}; 64 65 static DecodeStatus DecodeARRegisterClass(MCInst &Inst, uint64_t RegNo, 66 uint64_t Address, 67 const void *Decoder) { 68 if (RegNo >= std::size(ARDecoderTable)) 69 return MCDisassembler::Fail; 70 71 unsigned Reg = ARDecoderTable[RegNo]; 72 Inst.addOperand(MCOperand::createReg(Reg)); 73 return MCDisassembler::Success; 74 } 75 76 static const unsigned SRDecoderTable[] = {Xtensa::SAR, 3}; 77 78 static DecodeStatus DecodeSRRegisterClass(MCInst &Inst, uint64_t RegNo, 79 uint64_t Address, 80 const void *Decoder) { 81 if (RegNo > 255) 82 return MCDisassembler::Fail; 83 84 for (unsigned i = 0; i < std::size(SRDecoderTable); i += 2) { 85 if (SRDecoderTable[i + 1] == RegNo) { 86 unsigned Reg = SRDecoderTable[i]; 87 Inst.addOperand(MCOperand::createReg(Reg)); 88 return MCDisassembler::Success; 89 } 90 } 91 92 return MCDisassembler::Fail; 93 } 94 95 static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch, 96 uint64_t Address, uint64_t Offset, 97 uint64_t InstSize, MCInst &MI, 98 const void *Decoder) { 99 const MCDisassembler *Dis = static_cast<const MCDisassembler *>(Decoder); 100 return Dis->tryAddingSymbolicOperand(MI, Value, Address, isBranch, Offset, 101 /*OpSize=*/0, InstSize); 102 } 103 104 static DecodeStatus decodeCallOperand(MCInst &Inst, uint64_t Imm, 105 int64_t Address, const void *Decoder) { 106 assert(isUInt<18>(Imm) && "Invalid immediate"); 107 Inst.addOperand(MCOperand::createImm(SignExtend64<20>(Imm << 2))); 108 return MCDisassembler::Success; 109 } 110 111 static DecodeStatus decodeJumpOperand(MCInst &Inst, uint64_t Imm, 112 int64_t Address, const void *Decoder) { 113 assert(isUInt<18>(Imm) && "Invalid immediate"); 114 Inst.addOperand(MCOperand::createImm(SignExtend64<18>(Imm))); 115 return MCDisassembler::Success; 116 } 117 118 static DecodeStatus decodeBranchOperand(MCInst &Inst, uint64_t Imm, 119 int64_t Address, const void *Decoder) { 120 switch (Inst.getOpcode()) { 121 case Xtensa::BEQZ: 122 case Xtensa::BGEZ: 123 case Xtensa::BLTZ: 124 case Xtensa::BNEZ: 125 assert(isUInt<12>(Imm) && "Invalid immediate"); 126 if (!tryAddingSymbolicOperand(SignExtend64<12>(Imm) + 4 + Address, true, 127 Address, 0, 3, Inst, Decoder)) 128 Inst.addOperand(MCOperand::createImm(SignExtend64<12>(Imm))); 129 break; 130 default: 131 assert(isUInt<8>(Imm) && "Invalid immediate"); 132 if (!tryAddingSymbolicOperand(SignExtend64<8>(Imm) + 4 + Address, true, 133 Address, 0, 3, Inst, Decoder)) 134 Inst.addOperand(MCOperand::createImm(SignExtend64<8>(Imm))); 135 } 136 return MCDisassembler::Success; 137 } 138 139 static DecodeStatus decodeL32ROperand(MCInst &Inst, uint64_t Imm, 140 int64_t Address, const void *Decoder) { 141 142 assert(isUInt<16>(Imm) && "Invalid immediate"); 143 Inst.addOperand(MCOperand::createImm( 144 SignExtend64<17>((Imm << 2) + 0x40000 + (Address & 0x3)))); 145 return MCDisassembler::Success; 146 } 147 148 static DecodeStatus decodeImm8Operand(MCInst &Inst, uint64_t Imm, 149 int64_t Address, const void *Decoder) { 150 assert(isUInt<8>(Imm) && "Invalid immediate"); 151 Inst.addOperand(MCOperand::createImm(SignExtend64<8>(Imm))); 152 return MCDisassembler::Success; 153 } 154 155 static DecodeStatus decodeImm8_sh8Operand(MCInst &Inst, uint64_t Imm, 156 int64_t Address, 157 const void *Decoder) { 158 assert(isUInt<8>(Imm) && "Invalid immediate"); 159 Inst.addOperand(MCOperand::createImm(SignExtend64<16>(Imm << 8))); 160 return MCDisassembler::Success; 161 } 162 163 static DecodeStatus decodeImm12Operand(MCInst &Inst, uint64_t Imm, 164 int64_t Address, const void *Decoder) { 165 assert(isUInt<12>(Imm) && "Invalid immediate"); 166 Inst.addOperand(MCOperand::createImm(SignExtend64<12>(Imm))); 167 return MCDisassembler::Success; 168 } 169 170 static DecodeStatus decodeUimm4Operand(MCInst &Inst, uint64_t Imm, 171 int64_t Address, const void *Decoder) { 172 assert(isUInt<4>(Imm) && "Invalid immediate"); 173 Inst.addOperand(MCOperand::createImm(Imm)); 174 return MCDisassembler::Success; 175 } 176 177 static DecodeStatus decodeUimm5Operand(MCInst &Inst, uint64_t Imm, 178 int64_t Address, const void *Decoder) { 179 assert(isUInt<5>(Imm) && "Invalid immediate"); 180 Inst.addOperand(MCOperand::createImm(Imm)); 181 return MCDisassembler::Success; 182 } 183 184 static DecodeStatus decodeImm1_16Operand(MCInst &Inst, uint64_t Imm, 185 int64_t Address, const void *Decoder) { 186 assert(isUInt<4>(Imm) && "Invalid immediate"); 187 Inst.addOperand(MCOperand::createImm(Imm + 1)); 188 return MCDisassembler::Success; 189 } 190 191 static DecodeStatus decodeImm1n_15Operand(MCInst &Inst, uint64_t Imm, 192 int64_t Address, 193 const void *Decoder) { 194 assert(isUInt<4>(Imm) && "Invalid immediate"); 195 if (!Imm) 196 Inst.addOperand(MCOperand::createImm(-1)); 197 else 198 Inst.addOperand(MCOperand::createImm(Imm)); 199 return MCDisassembler::Success; 200 } 201 202 static DecodeStatus decodeImm32n_95Operand(MCInst &Inst, uint64_t Imm, 203 int64_t Address, 204 const void *Decoder) { 205 assert(isUInt<7>(Imm) && "Invalid immediate"); 206 if ((Imm & 0x60) == 0x60) 207 Inst.addOperand(MCOperand::createImm((~0x1f) | Imm)); 208 else 209 Inst.addOperand(MCOperand::createImm(Imm)); 210 return MCDisassembler::Success; 211 } 212 213 static DecodeStatus decodeShimm1_31Operand(MCInst &Inst, uint64_t Imm, 214 int64_t Address, 215 const void *Decoder) { 216 assert(isUInt<5>(Imm) && "Invalid immediate"); 217 Inst.addOperand(MCOperand::createImm(32 - Imm)); 218 return MCDisassembler::Success; 219 } 220 221 static int64_t TableB4const[16] = {-1, 1, 2, 3, 4, 5, 6, 7, 222 8, 10, 12, 16, 32, 64, 128, 256}; 223 static DecodeStatus decodeB4constOperand(MCInst &Inst, uint64_t Imm, 224 int64_t Address, const void *Decoder) { 225 assert(isUInt<4>(Imm) && "Invalid immediate"); 226 227 Inst.addOperand(MCOperand::createImm(TableB4const[Imm])); 228 return MCDisassembler::Success; 229 } 230 231 static int64_t TableB4constu[16] = {32768, 65536, 2, 3, 4, 5, 6, 7, 232 8, 10, 12, 16, 32, 64, 128, 256}; 233 static DecodeStatus decodeB4constuOperand(MCInst &Inst, uint64_t Imm, 234 int64_t Address, 235 const void *Decoder) { 236 assert(isUInt<4>(Imm) && "Invalid immediate"); 237 238 Inst.addOperand(MCOperand::createImm(TableB4constu[Imm])); 239 return MCDisassembler::Success; 240 } 241 242 static DecodeStatus decodeMem8Operand(MCInst &Inst, uint64_t Imm, 243 int64_t Address, const void *Decoder) { 244 assert(isUInt<12>(Imm) && "Invalid immediate"); 245 DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder); 246 Inst.addOperand(MCOperand::createImm((Imm >> 4) & 0xff)); 247 return MCDisassembler::Success; 248 } 249 250 static DecodeStatus decodeMem16Operand(MCInst &Inst, uint64_t Imm, 251 int64_t Address, const void *Decoder) { 252 assert(isUInt<12>(Imm) && "Invalid immediate"); 253 DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder); 254 Inst.addOperand(MCOperand::createImm((Imm >> 3) & 0x1fe)); 255 return MCDisassembler::Success; 256 } 257 258 static DecodeStatus decodeMem32Operand(MCInst &Inst, uint64_t Imm, 259 int64_t Address, const void *Decoder) { 260 assert(isUInt<12>(Imm) && "Invalid immediate"); 261 DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder); 262 Inst.addOperand(MCOperand::createImm((Imm >> 2) & 0x3fc)); 263 return MCDisassembler::Success; 264 } 265 266 static DecodeStatus decodeMem32nOperand(MCInst &Inst, uint64_t Imm, 267 int64_t Address, const void *Decoder) { 268 assert(isUInt<8>(Imm) && "Invalid immediate"); 269 DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder); 270 Inst.addOperand(MCOperand::createImm((Imm >> 2) & 0x3c)); 271 return MCDisassembler::Success; 272 } 273 274 /// Read two bytes from the ArrayRef and return 16 bit data sorted 275 /// according to the given endianness. 276 static DecodeStatus readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address, 277 uint64_t &Size, uint64_t &Insn, 278 bool IsLittleEndian) { 279 // We want to read exactly 2 Bytes of data. 280 if (Bytes.size() < 2) { 281 Size = 0; 282 return MCDisassembler::Fail; 283 } 284 285 if (!IsLittleEndian) { 286 report_fatal_error("Big-endian mode currently is not supported!"); 287 } else { 288 Insn = (Bytes[1] << 8) | Bytes[0]; 289 } 290 291 return MCDisassembler::Success; 292 } 293 294 /// Read three bytes from the ArrayRef and return 24 bit data 295 static DecodeStatus readInstruction24(ArrayRef<uint8_t> Bytes, uint64_t Address, 296 uint64_t &Size, uint64_t &Insn, 297 bool IsLittleEndian) { 298 // We want to read exactly 3 Bytes of data. 299 if (Bytes.size() < 3) { 300 Size = 0; 301 return MCDisassembler::Fail; 302 } 303 304 if (!IsLittleEndian) { 305 report_fatal_error("Big-endian mode currently is not supported!"); 306 } else { 307 Insn = (Bytes[2] << 16) | (Bytes[1] << 8) | (Bytes[0] << 0); 308 } 309 310 return MCDisassembler::Success; 311 } 312 313 #include "XtensaGenDisassemblerTables.inc" 314 315 DecodeStatus XtensaDisassembler::getInstruction(MCInst &MI, uint64_t &Size, 316 ArrayRef<uint8_t> Bytes, 317 uint64_t Address, 318 raw_ostream &CS) const { 319 uint64_t Insn; 320 DecodeStatus Result; 321 322 // Parse 16-bit instructions 323 if (hasDensity()) { 324 Result = readInstruction16(Bytes, Address, Size, Insn, IsLittleEndian); 325 if (Result == MCDisassembler::Fail) 326 return MCDisassembler::Fail; 327 LLVM_DEBUG(dbgs() << "Trying Xtensa 16-bit instruction table :\n"); 328 Result = decodeInstruction(DecoderTable16, MI, Insn, Address, this, STI); 329 if (Result != MCDisassembler::Fail) { 330 Size = 2; 331 return Result; 332 } 333 } 334 335 // Parse Core 24-bit instructions 336 Result = readInstruction24(Bytes, Address, Size, Insn, IsLittleEndian); 337 if (Result == MCDisassembler::Fail) 338 return MCDisassembler::Fail; 339 LLVM_DEBUG(dbgs() << "Trying Xtensa 24-bit instruction table :\n"); 340 Result = decodeInstruction(DecoderTable24, MI, Insn, Address, this, STI); 341 if (Result != MCDisassembler::Fail) { 342 Size = 3; 343 return Result; 344 } 345 return Result; 346 } 347