[InstCombine] Signed saturation patterns
[llvm-core.git] / lib / Target / MSP430 / Disassembler / MSP430Disassembler.cpp
blob59c12e24e8bf87be0c52716445d95911368335b5
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.
11 //===----------------------------------------------------------------------===//
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"
25 using namespace llvm;
27 #define DEBUG_TYPE "msp430-disassembler"
29 typedef MCDisassembler::DecodeStatus DecodeStatus;
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;
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;
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;
48 public:
49 MSP430Disassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
50 : MCDisassembler(STI, Ctx) {}
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;
57 } // end anonymous namespace
59 static MCDisassembler *createMSP430Disassembler(const Target &T,
60 const MCSubtargetInfo &STI,
61 MCContext &Ctx) {
62 return new MSP430Disassembler(STI, Ctx);
65 extern "C" void LLVMInitializeMSP430Disassembler() {
66 TargetRegistry::RegisterMCDisassembler(getTheMSP430Target(),
67 createMSP430Disassembler);
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
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;
83 unsigned Reg = GR8DecoderTable[RegNo];
84 MI.addOperand(MCOperand::createReg(Reg));
85 return MCDisassembler::Success;
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
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;
101 unsigned Reg = GR16DecoderTable[RegNo];
102 MI.addOperand(MCOperand::createReg(Reg));
103 return MCDisassembler::Success;
106 static DecodeStatus DecodeCGImm(MCInst &MI, uint64_t Bits, uint64_t Address,
107 const void *Decoder);
109 static DecodeStatus DecodeMemOperand(MCInst &MI, uint64_t Bits,
110 uint64_t Address,
111 const void *Decoder);
113 #include "MSP430GenDisassemblerTables.inc"
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;
128 MI.addOperand(MCOperand::createImm(Imm));
129 return MCDisassembler::Success;
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;
138 if (DecodeGR16RegisterClass(MI, Reg, Address, Decoder) !=
139 MCDisassembler::Success)
140 return MCDisassembler::Fail;
142 MI.addOperand(MCOperand::createImm((int16_t)Imm));
143 return MCDisassembler::Success;
146 enum AddrMode {
147 amInvalid = 0,
148 amRegister,
149 amIndexed,
150 amIndirect,
151 amIndirectPost,
152 amSymbolic,
153 amImmediate,
154 amAbsolute,
155 amConstant
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;
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");
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);
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);
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;
206 return Ad ? amIndexed : amRegister;
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;
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;
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;
256 Insn |= (uint64_t)support::endian::read16le(Bytes.data() + 2) << 16;
257 ++Words;
258 break;
259 default:
260 break;
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;
270 Insn |= (uint64_t)support::endian::read16le(Bytes.data() + Words * 2)
271 << (Words * 16);
272 ++Words;
273 break;
274 default:
275 break;
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;
285 Size = 2;
286 return DecodeStatus::Fail;
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;
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;
311 Insn |= (uint64_t)support::endian::read16le(Bytes.data() + 2) << 16;
312 ++Words;
313 break;
314 default:
315 break;
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;
326 Size = 2;
327 return DecodeStatus::Fail;
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");
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);
354 MI.addOperand(MCOperand::createImm(SignExtend32(Offset, 10)));
356 if (Cond == 7)
357 MI.setOpcode(MSP430::JMP);
358 else {
359 MI.setOpcode(MSP430::JCC);
360 MI.addOperand(MCOperand::createImm(getCondCode(Cond)));
363 Size = 2;
364 return DecodeStatus::Success;
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;
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);