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