xref: /llvm-project/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp (revision 4cce10743d2275710d3d2e0de8013386a9799092)
1 //===-- M68kDisassembler.cpp - Disassembler for M68k ------------*- C++ -*-===//
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 is part of the M68k Disassembler.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "M68k.h"
14 #include "M68kRegisterInfo.h"
15 #include "M68kSubtarget.h"
16 #include "MCTargetDesc/M68kMCCodeEmitter.h"
17 #include "MCTargetDesc/M68kMCTargetDesc.h"
18 #include "TargetInfo/M68kTargetInfo.h"
19 
20 #include "llvm/MC/MCAsmInfo.h"
21 #include "llvm/MC/MCContext.h"
22 #include "llvm/MC/MCDecoderOps.h"
23 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
24 #include "llvm/MC/MCInst.h"
25 #include "llvm/MC/TargetRegistry.h"
26 #include "llvm/Support/Endian.h"
27 #include "llvm/Support/ErrorHandling.h"
28 
29 using namespace llvm;
30 
31 #define DEBUG_TYPE "m68k-disassembler"
32 
33 typedef MCDisassembler::DecodeStatus DecodeStatus;
34 
35 static const unsigned RegisterDecode[] = {
36     M68k::D0,    M68k::D1,  M68k::D2,  M68k::D3,  M68k::D4,  M68k::D5,
37     M68k::D6,    M68k::D7,  M68k::A0,  M68k::A1,  M68k::A2,  M68k::A3,
38     M68k::A4,    M68k::A5,  M68k::A6,  M68k::SP,  M68k::FP0, M68k::FP1,
39     M68k::FP2,   M68k::FP3, M68k::FP4, M68k::FP5, M68k::FP6, M68k::FP7,
40     M68k::FPIAR, M68k::FPS, M68k::FPC};
41 
42 static DecodeStatus DecodeRegisterClass(MCInst &Inst, uint64_t RegNo,
43                                         uint64_t Address, const void *Decoder) {
44   if (RegNo >= 24)
45     return DecodeStatus::Fail;
46   Inst.addOperand(MCOperand::createReg(RegisterDecode[RegNo]));
47   return DecodeStatus::Success;
48 }
49 
50 static DecodeStatus DecodeDR32RegisterClass(MCInst &Inst, uint64_t RegNo,
51                                             uint64_t Address,
52                                             const void *Decoder) {
53   return DecodeRegisterClass(Inst, RegNo, Address, Decoder);
54 }
55 
56 static DecodeStatus DecodeDR16RegisterClass(MCInst &Inst, uint64_t RegNo,
57                                             uint64_t Address,
58                                             const void *Decoder) {
59   return DecodeRegisterClass(Inst, RegNo, Address, Decoder);
60 }
61 
62 static DecodeStatus DecodeDR8RegisterClass(MCInst &Inst, uint64_t RegNo,
63                                            uint64_t Address,
64                                            const void *Decoder) {
65   return DecodeRegisterClass(Inst, RegNo, Address, Decoder);
66 }
67 
68 static DecodeStatus DecodeAR32RegisterClass(MCInst &Inst, uint64_t RegNo,
69                                             uint64_t Address,
70                                             const void *Decoder) {
71   return DecodeRegisterClass(Inst, RegNo | 8ULL, Address, Decoder);
72 }
73 
74 static DecodeStatus DecodeAR16RegisterClass(MCInst &Inst, uint64_t RegNo,
75                                             uint64_t Address,
76                                             const void *Decoder) {
77   return DecodeRegisterClass(Inst, RegNo | 8ULL, Address, Decoder);
78 }
79 
80 static DecodeStatus DecodeXR32RegisterClass(MCInst &Inst, uint64_t RegNo,
81                                             uint64_t Address,
82                                             const void *Decoder) {
83   return DecodeRegisterClass(Inst, RegNo, Address, Decoder);
84 }
85 
86 static DecodeStatus DecodeXR32RegisterClass(MCInst &Inst, APInt RegNo,
87                                             uint64_t Address,
88                                             const void *Decoder) {
89   return DecodeRegisterClass(Inst, RegNo.getZExtValue(), Address, Decoder);
90 }
91 
92 static DecodeStatus DecodeXR16RegisterClass(MCInst &Inst, uint64_t RegNo,
93                                             uint64_t Address,
94                                             const void *Decoder) {
95   return DecodeRegisterClass(Inst, RegNo, Address, Decoder);
96 }
97 
98 static DecodeStatus DecodeFPDRRegisterClass(MCInst &Inst, uint64_t RegNo,
99                                             uint64_t Address,
100                                             const void *Decoder) {
101   return DecodeRegisterClass(Inst, RegNo | 16ULL, Address, Decoder);
102 }
103 #define DecodeFPDR32RegisterClass DecodeFPDRRegisterClass
104 #define DecodeFPDR64RegisterClass DecodeFPDRRegisterClass
105 #define DecodeFPDR80RegisterClass DecodeFPDRRegisterClass
106 
107 static DecodeStatus DecodeFPCSCRegisterClass(MCInst &Inst, uint64_t RegNo,
108                                              uint64_t Address,
109                                              const void *Decoder) {
110   return DecodeRegisterClass(Inst, (RegNo >> 1) + 24, Address, Decoder);
111 }
112 #define DecodeFPICRegisterClass DecodeFPCSCRegisterClass
113 
114 static DecodeStatus DecodeCCRCRegisterClass(MCInst &Inst, APInt &Insn,
115                                             uint64_t Address,
116                                             const void *Decoder) {
117   llvm_unreachable("unimplemented");
118 }
119 
120 static DecodeStatus DecodeImm32(MCInst &Inst, uint64_t Imm, uint64_t Address,
121                                 const void *Decoder) {
122   Inst.addOperand(MCOperand::createImm(M68k::swapWord<uint32_t>(Imm)));
123   return DecodeStatus::Success;
124 }
125 
126 #include "M68kGenDisassemblerTable.inc"
127 
128 #undef DecodeFPDR32RegisterClass
129 #undef DecodeFPDR64RegisterClass
130 #undef DecodeFPDR80RegisterClass
131 #undef DecodeFPICRegisterClass
132 
133 /// A disassembler class for M68k.
134 struct M68kDisassembler : public MCDisassembler {
135   M68kDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
136       : MCDisassembler(STI, Ctx) {}
137   virtual ~M68kDisassembler() {}
138 
139   DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
140                               ArrayRef<uint8_t> Bytes, uint64_t Address,
141                               raw_ostream &CStream) const override;
142 };
143 
144 DecodeStatus M68kDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
145                                               ArrayRef<uint8_t> Bytes,
146                                               uint64_t Address,
147                                               raw_ostream &CStream) const {
148   DecodeStatus Result;
149   auto MakeUp = [&](APInt &Insn, unsigned InstrBits) {
150     unsigned Idx = Insn.getBitWidth() >> 3;
151     unsigned RoundUp = alignTo(InstrBits, Align(16));
152     if (RoundUp > Insn.getBitWidth())
153       Insn = Insn.zext(RoundUp);
154     RoundUp = RoundUp >> 3;
155     for (; Idx < RoundUp; Idx += 2) {
156       Insn.insertBits(support::endian::read16be(&Bytes[Idx]), Idx * 8, 16);
157     }
158   };
159   APInt Insn(16, support::endian::read16be(Bytes.data()));
160   // 2 bytes of data are consumed, so set Size to 2
161   // If we don't do this, disassembler may generate result even
162   // the encoding is invalid. We need to let it fail correctly.
163   Size = 2;
164   Result = decodeInstruction(DecoderTable80, Instr, Insn, Address, this, STI,
165                              MakeUp);
166   if (Result == DecodeStatus::Success)
167     Size = InstrLenTable[Instr.getOpcode()] >> 3;
168   return Result;
169 }
170 
171 static MCDisassembler *createM68kDisassembler(const Target &T,
172                                               const MCSubtargetInfo &STI,
173                                               MCContext &Ctx) {
174   return new M68kDisassembler(STI, Ctx);
175 }
176 
177 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kDisassembler() {
178   // Register the disassembler.
179   TargetRegistry::RegisterMCDisassembler(getTheM68kTarget(),
180                                          createM68kDisassembler);
181 }
182