1 //===-- MSP430Disassembler.cpp - Disassembler for MSP430 ------------------===// 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 implements the MSP430Disassembler class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "MCTargetDesc/MSP430MCTargetDesc.h" 14 #include "MSP430.h" 15 #include "TargetInfo/MSP430TargetInfo.h" 16 #include "llvm/MC/MCContext.h" 17 #include "llvm/MC/MCDecoderOps.h" 18 #include "llvm/MC/MCDisassembler/MCDisassembler.h" 19 #include "llvm/MC/MCInst.h" 20 #include "llvm/MC/MCSubtargetInfo.h" 21 #include "llvm/MC/TargetRegistry.h" 22 #include "llvm/Support/Compiler.h" 23 #include "llvm/Support/Endian.h" 24 25 using namespace llvm; 26 27 #define DEBUG_TYPE "msp430-disassembler" 28 29 typedef MCDisassembler::DecodeStatus DecodeStatus; 30 31 namespace { 32 class MSP430Disassembler : public MCDisassembler { 33 DecodeStatus getInstructionI(MCInst &MI, uint64_t &Size, 34 ArrayRef<uint8_t> Bytes, uint64_t Address, 35 raw_ostream &CStream) const; 36 37 DecodeStatus getInstructionII(MCInst &MI, uint64_t &Size, 38 ArrayRef<uint8_t> Bytes, uint64_t Address, 39 raw_ostream &CStream) const; 40 41 DecodeStatus getInstructionCJ(MCInst &MI, uint64_t &Size, 42 ArrayRef<uint8_t> Bytes, uint64_t Address, 43 raw_ostream &CStream) const; 44 45 public: 46 MSP430Disassembler(const MCSubtargetInfo &STI, MCContext &Ctx) 47 : MCDisassembler(STI, Ctx) {} 48 49 DecodeStatus getInstruction(MCInst &MI, uint64_t &Size, 50 ArrayRef<uint8_t> Bytes, uint64_t Address, 51 raw_ostream &CStream) const override; 52 }; 53 } // end anonymous namespace 54 55 static MCDisassembler *createMSP430Disassembler(const Target &T, 56 const MCSubtargetInfo &STI, 57 MCContext &Ctx) { 58 return new MSP430Disassembler(STI, Ctx); 59 } 60 61 extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void 62 LLVMInitializeMSP430Disassembler() { 63 TargetRegistry::RegisterMCDisassembler(getTheMSP430Target(), 64 createMSP430Disassembler); 65 } 66 67 static const unsigned GR8DecoderTable[] = { 68 MSP430::PCB, MSP430::SPB, MSP430::SRB, MSP430::CGB, 69 MSP430::R4B, MSP430::R5B, MSP430::R6B, MSP430::R7B, 70 MSP430::R8B, MSP430::R9B, MSP430::R10B, MSP430::R11B, 71 MSP430::R12B, MSP430::R13B, MSP430::R14B, MSP430::R15B 72 }; 73 74 static DecodeStatus DecodeGR8RegisterClass(MCInst &MI, uint64_t RegNo, 75 uint64_t Address, 76 const MCDisassembler *Decoder) { 77 if (RegNo > 15) 78 return MCDisassembler::Fail; 79 80 unsigned Reg = GR8DecoderTable[RegNo]; 81 MI.addOperand(MCOperand::createReg(Reg)); 82 return MCDisassembler::Success; 83 } 84 85 static const unsigned GR16DecoderTable[] = { 86 MSP430::PC, MSP430::SP, MSP430::SR, MSP430::CG, 87 MSP430::R4, MSP430::R5, MSP430::R6, MSP430::R7, 88 MSP430::R8, MSP430::R9, MSP430::R10, MSP430::R11, 89 MSP430::R12, MSP430::R13, MSP430::R14, MSP430::R15 90 }; 91 92 static DecodeStatus DecodeGR16RegisterClass(MCInst &MI, uint64_t RegNo, 93 uint64_t Address, 94 const MCDisassembler *Decoder) { 95 if (RegNo > 15) 96 return MCDisassembler::Fail; 97 98 unsigned Reg = GR16DecoderTable[RegNo]; 99 MI.addOperand(MCOperand::createReg(Reg)); 100 return MCDisassembler::Success; 101 } 102 103 static DecodeStatus DecodeCGImm(MCInst &MI, uint64_t Bits, uint64_t Address, 104 const MCDisassembler *Decoder); 105 106 static DecodeStatus DecodeMemOperand(MCInst &MI, uint64_t Bits, 107 uint64_t Address, 108 const MCDisassembler *Decoder); 109 110 #include "MSP430GenDisassemblerTables.inc" 111 112 static DecodeStatus DecodeCGImm(MCInst &MI, uint64_t Bits, uint64_t Address, 113 const MCDisassembler *Decoder) { 114 int64_t Imm; 115 switch (Bits) { 116 default: 117 llvm_unreachable("Invalid immediate value"); 118 case 0x22: Imm = 4; break; 119 case 0x32: Imm = 8; break; 120 case 0x03: Imm = 0; break; 121 case 0x13: Imm = 1; break; 122 case 0x23: Imm = 2; break; 123 case 0x33: Imm = -1; break; 124 } 125 MI.addOperand(MCOperand::createImm(Imm)); 126 return MCDisassembler::Success; 127 } 128 129 static DecodeStatus DecodeMemOperand(MCInst &MI, uint64_t Bits, 130 uint64_t Address, 131 const MCDisassembler *Decoder) { 132 unsigned Reg = Bits & 15; 133 unsigned Imm = Bits >> 4; 134 135 if (DecodeGR16RegisterClass(MI, Reg, Address, Decoder) != 136 MCDisassembler::Success) 137 return MCDisassembler::Fail; 138 139 MI.addOperand(MCOperand::createImm((int16_t)Imm)); 140 return MCDisassembler::Success; 141 } 142 143 enum AddrMode { 144 amInvalid = 0, 145 amRegister, 146 amIndexed, 147 amIndirect, 148 amIndirectPost, 149 amSymbolic, 150 amImmediate, 151 amAbsolute, 152 amConstant 153 }; 154 155 static AddrMode DecodeSrcAddrMode(unsigned Rs, unsigned As) { 156 switch (Rs) { 157 case 0: 158 if (As == 1) return amSymbolic; 159 if (As == 2) return amInvalid; 160 if (As == 3) return amImmediate; 161 break; 162 case 2: 163 if (As == 1) return amAbsolute; 164 if (As == 2) return amConstant; 165 if (As == 3) return amConstant; 166 break; 167 case 3: 168 return amConstant; 169 default: 170 break; 171 } 172 switch (As) { 173 case 0: return amRegister; 174 case 1: return amIndexed; 175 case 2: return amIndirect; 176 case 3: return amIndirectPost; 177 default: 178 llvm_unreachable("As out of range"); 179 } 180 } 181 182 static AddrMode DecodeSrcAddrModeI(unsigned Insn) { 183 unsigned Rs = fieldFromInstruction(Insn, 8, 4); 184 unsigned As = fieldFromInstruction(Insn, 4, 2); 185 return DecodeSrcAddrMode(Rs, As); 186 } 187 188 static AddrMode DecodeSrcAddrModeII(unsigned Insn) { 189 unsigned Rs = fieldFromInstruction(Insn, 0, 4); 190 unsigned As = fieldFromInstruction(Insn, 4, 2); 191 return DecodeSrcAddrMode(Rs, As); 192 } 193 194 static AddrMode DecodeDstAddrMode(unsigned Insn) { 195 unsigned Rd = fieldFromInstruction(Insn, 0, 4); 196 unsigned Ad = fieldFromInstruction(Insn, 7, 1); 197 switch (Rd) { 198 case 0: return Ad ? amSymbolic : amRegister; 199 case 2: return Ad ? amAbsolute : amRegister; 200 default: 201 break; 202 } 203 return Ad ? amIndexed : amRegister; 204 } 205 206 static const uint8_t *getDecoderTable(AddrMode SrcAM, unsigned Words) { 207 assert(0 < Words && Words < 4 && "Incorrect number of words"); 208 switch (SrcAM) { 209 default: 210 llvm_unreachable("Invalid addressing mode"); 211 case amRegister: 212 assert(Words < 3 && "Incorrect number of words"); 213 return Words == 2 ? DecoderTableAlpha32 : DecoderTableAlpha16; 214 case amConstant: 215 assert(Words < 3 && "Incorrect number of words"); 216 return Words == 2 ? DecoderTableBeta32 : DecoderTableBeta16; 217 case amIndexed: 218 case amSymbolic: 219 case amImmediate: 220 case amAbsolute: 221 assert(Words > 1 && "Incorrect number of words"); 222 return Words == 2 ? DecoderTableGamma32 : DecoderTableGamma48; 223 case amIndirect: 224 case amIndirectPost: 225 assert(Words < 3 && "Incorrect number of words"); 226 return Words == 2 ? DecoderTableDelta32 : DecoderTableDelta16; 227 } 228 } 229 230 DecodeStatus MSP430Disassembler::getInstructionI(MCInst &MI, uint64_t &Size, 231 ArrayRef<uint8_t> Bytes, 232 uint64_t Address, 233 raw_ostream &CStream) const { 234 uint64_t Insn = support::endian::read16le(Bytes.data()); 235 AddrMode SrcAM = DecodeSrcAddrModeI(Insn); 236 AddrMode DstAM = DecodeDstAddrMode(Insn); 237 if (SrcAM == amInvalid || DstAM == amInvalid) { 238 Size = 2; // skip one word and let disassembler to try further 239 return MCDisassembler::Fail; 240 } 241 242 unsigned Words = 1; 243 switch (SrcAM) { 244 case amIndexed: 245 case amSymbolic: 246 case amImmediate: 247 case amAbsolute: 248 if (Bytes.size() < (Words + 1) * 2) { 249 Size = 2; 250 return DecodeStatus::Fail; 251 } 252 Insn |= (uint64_t)support::endian::read16le(Bytes.data() + 2) << 16; 253 ++Words; 254 break; 255 default: 256 break; 257 } 258 switch (DstAM) { 259 case amIndexed: 260 case amSymbolic: 261 case amAbsolute: 262 if (Bytes.size() < (Words + 1) * 2) { 263 Size = 2; 264 return DecodeStatus::Fail; 265 } 266 Insn |= (uint64_t)support::endian::read16le(Bytes.data() + Words * 2) 267 << (Words * 16); 268 ++Words; 269 break; 270 default: 271 break; 272 } 273 274 DecodeStatus Result = decodeInstruction(getDecoderTable(SrcAM, Words), MI, 275 Insn, Address, this, STI); 276 if (Result != MCDisassembler::Fail) { 277 Size = Words * 2; 278 return Result; 279 } 280 281 Size = 2; 282 return DecodeStatus::Fail; 283 } 284 285 DecodeStatus MSP430Disassembler::getInstructionII(MCInst &MI, uint64_t &Size, 286 ArrayRef<uint8_t> Bytes, 287 uint64_t Address, 288 raw_ostream &CStream) const { 289 uint64_t Insn = support::endian::read16le(Bytes.data()); 290 AddrMode SrcAM = DecodeSrcAddrModeII(Insn); 291 if (SrcAM == amInvalid) { 292 Size = 2; // skip one word and let disassembler to try further 293 return MCDisassembler::Fail; 294 } 295 296 unsigned Words = 1; 297 switch (SrcAM) { 298 case amIndexed: 299 case amSymbolic: 300 case amImmediate: 301 case amAbsolute: 302 if (Bytes.size() < (Words + 1) * 2) { 303 Size = 2; 304 return DecodeStatus::Fail; 305 } 306 Insn |= (uint64_t)support::endian::read16le(Bytes.data() + 2) << 16; 307 ++Words; 308 break; 309 default: 310 break; 311 } 312 313 const uint8_t *DecoderTable = Words == 2 ? DecoderTable32 : DecoderTable16; 314 DecodeStatus Result = decodeInstruction(DecoderTable, MI, Insn, Address, 315 this, STI); 316 if (Result != MCDisassembler::Fail) { 317 Size = Words * 2; 318 return Result; 319 } 320 321 Size = 2; 322 return DecodeStatus::Fail; 323 } 324 325 static MSP430CC::CondCodes getCondCode(unsigned Cond) { 326 switch (Cond) { 327 case 0: return MSP430CC::COND_NE; 328 case 1: return MSP430CC::COND_E; 329 case 2: return MSP430CC::COND_LO; 330 case 3: return MSP430CC::COND_HS; 331 case 4: return MSP430CC::COND_N; 332 case 5: return MSP430CC::COND_GE; 333 case 6: return MSP430CC::COND_L; 334 case 7: return MSP430CC::COND_NONE; 335 default: 336 llvm_unreachable("Cond out of range"); 337 } 338 } 339 340 DecodeStatus MSP430Disassembler::getInstructionCJ(MCInst &MI, uint64_t &Size, 341 ArrayRef<uint8_t> Bytes, 342 uint64_t Address, 343 raw_ostream &CStream) const { 344 uint64_t Insn = support::endian::read16le(Bytes.data()); 345 unsigned Cond = fieldFromInstruction(Insn, 10, 3); 346 unsigned Offset = fieldFromInstruction(Insn, 0, 10); 347 348 MI.addOperand(MCOperand::createImm(SignExtend32(Offset, 10))); 349 350 if (Cond == 7) 351 MI.setOpcode(MSP430::JMP); 352 else { 353 MI.setOpcode(MSP430::JCC); 354 MI.addOperand(MCOperand::createImm(getCondCode(Cond))); 355 } 356 357 Size = 2; 358 return DecodeStatus::Success; 359 } 360 361 DecodeStatus MSP430Disassembler::getInstruction(MCInst &MI, uint64_t &Size, 362 ArrayRef<uint8_t> Bytes, 363 uint64_t Address, 364 raw_ostream &CStream) const { 365 if (Bytes.size() < 2) { 366 Size = 0; 367 return MCDisassembler::Fail; 368 } 369 370 uint64_t Insn = support::endian::read16le(Bytes.data()); 371 unsigned Opc = fieldFromInstruction(Insn, 13, 3); 372 switch (Opc) { 373 case 0: 374 return getInstructionII(MI, Size, Bytes, Address, CStream); 375 case 1: 376 return getInstructionCJ(MI, Size, Bytes, Address, CStream); 377 default: 378 return getInstructionI(MI, Size, Bytes, Address, CStream); 379 } 380 } 381