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