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