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