xref: /freebsd/contrib/llvm-project/llvm/lib/Target/SystemZ/Disassembler/SystemZDisassembler.cpp (revision 770cf0a5f02dc8983a89c6568d741fbc25baa999)
1 //===-- SystemZDisassembler.cpp - Disassembler for SystemZ ------*- 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 #include "MCTargetDesc/SystemZMCTargetDesc.h"
10 #include "TargetInfo/SystemZTargetInfo.h"
11 #include "llvm/MC/MCDecoderOps.h"
12 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
13 #include "llvm/MC/MCInst.h"
14 #include "llvm/MC/MCSubtargetInfo.h"
15 #include "llvm/MC/TargetRegistry.h"
16 #include "llvm/Support/Compiler.h"
17 #include "llvm/Support/MathExtras.h"
18 #include <cassert>
19 #include <cstdint>
20 
21 using namespace llvm;
22 
23 #define DEBUG_TYPE "systemz-disassembler"
24 
25 typedef MCDisassembler::DecodeStatus DecodeStatus;
26 
27 namespace {
28 
29 class SystemZDisassembler : public MCDisassembler {
30 public:
31   SystemZDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
32     : MCDisassembler(STI, Ctx) {}
33   ~SystemZDisassembler() override = default;
34 
35   DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
36                               ArrayRef<uint8_t> Bytes, uint64_t Address,
37                               raw_ostream &CStream) const override;
38 };
39 
40 } // end anonymous namespace
41 
42 static MCDisassembler *createSystemZDisassembler(const Target &T,
43                                                  const MCSubtargetInfo &STI,
44                                                  MCContext &Ctx) {
45   return new SystemZDisassembler(STI, Ctx);
46 }
47 
48 // NOLINTNEXTLINE(readability-identifier-naming)
49 extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
50 LLVMInitializeSystemZDisassembler() {
51   // Register the disassembler.
52   TargetRegistry::RegisterMCDisassembler(getTheSystemZTarget(),
53                                          createSystemZDisassembler);
54 }
55 
56 /// tryAddingSymbolicOperand - trys to add a symbolic operand in place of the
57 /// immediate Value in the MCInst.
58 ///
59 /// @param Value      - The immediate Value, has had any PC adjustment made by
60 ///                     the caller.
61 /// @param isBranch   - If the instruction is a branch instruction
62 /// @param Address    - The starting address of the instruction
63 /// @param Offset     - The byte offset to this immediate in the instruction
64 /// @param Width      - The byte width of this immediate in the instruction
65 ///
66 /// If the getOpInfo() function was set when setupForSymbolicDisassembly() was
67 /// called then that function is called to get any symbolic information for the
68 /// immediate in the instruction using the Address, Offset and Width.  If that
69 /// returns non-zero then the symbolic information it returns is used to create
70 /// an MCExpr and that is added as an operand to the MCInst.  If getOpInfo()
71 /// returns zero and isBranch is true then a symbol look up for immediate Value
72 /// is done and if a symbol is found an MCExpr is created with that, else
73 /// an MCExpr with the immediate Value is created.  This function returns true
74 /// if it adds an operand to the MCInst and false otherwise.
75 static bool tryAddingSymbolicOperand(int64_t Value, bool IsBranch,
76                                      uint64_t Address, uint64_t Offset,
77                                      uint64_t Width, MCInst &MI,
78                                      const MCDisassembler *Decoder) {
79   return Decoder->tryAddingSymbolicOperand(MI, Value, Address, IsBranch, Offset,
80                                            Width, /*InstSize=*/0);
81 }
82 
83 static DecodeStatus decodeRegisterClass(MCInst &Inst, uint64_t RegNo,
84                                         const unsigned *Regs, unsigned Size,
85                                         bool IsAddr = false) {
86   assert(RegNo < Size && "Invalid register");
87   if (IsAddr && RegNo == 0) {
88     RegNo = SystemZ::NoRegister;
89   } else {
90     RegNo = Regs[RegNo];
91     if (RegNo == 0)
92       return MCDisassembler::Fail;
93   }
94   Inst.addOperand(MCOperand::createReg(RegNo));
95   return MCDisassembler::Success;
96 }
97 
98 static DecodeStatus DecodeGR32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
99                                                uint64_t Address,
100                                                const MCDisassembler *Decoder) {
101   return decodeRegisterClass(Inst, RegNo, SystemZMC::GR32Regs, 16);
102 }
103 
104 static DecodeStatus DecodeGRH32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
105                                                 uint64_t Address,
106                                                 const MCDisassembler *Decoder) {
107   return decodeRegisterClass(Inst, RegNo, SystemZMC::GRH32Regs, 16);
108 }
109 
110 static DecodeStatus DecodeGR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
111                                                uint64_t Address,
112                                                const MCDisassembler *Decoder) {
113   return decodeRegisterClass(Inst, RegNo, SystemZMC::GR64Regs, 16);
114 }
115 
116 static DecodeStatus DecodeGR128BitRegisterClass(MCInst &Inst, uint64_t RegNo,
117                                                 uint64_t Address,
118                                                 const MCDisassembler *Decoder) {
119   return decodeRegisterClass(Inst, RegNo, SystemZMC::GR128Regs, 16);
120 }
121 
122 static DecodeStatus
123 DecodeADDR32BitRegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address,
124                              const MCDisassembler *Decoder) {
125   return decodeRegisterClass(Inst, RegNo, SystemZMC::GR32Regs, 16, true);
126 }
127 
128 static DecodeStatus
129 DecodeADDR64BitRegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address,
130                              const MCDisassembler *Decoder) {
131   return decodeRegisterClass(Inst, RegNo, SystemZMC::GR64Regs, 16, true);
132 }
133 
134 static DecodeStatus DecodeFP32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
135                                                uint64_t Address,
136                                                const MCDisassembler *Decoder) {
137   return decodeRegisterClass(Inst, RegNo, SystemZMC::FP32Regs, 16);
138 }
139 
140 static DecodeStatus DecodeFP64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
141                                                uint64_t Address,
142                                                const MCDisassembler *Decoder) {
143   return decodeRegisterClass(Inst, RegNo, SystemZMC::FP64Regs, 16);
144 }
145 
146 static DecodeStatus DecodeFP128BitRegisterClass(MCInst &Inst, uint64_t RegNo,
147                                                 uint64_t Address,
148                                                 const MCDisassembler *Decoder) {
149   return decodeRegisterClass(Inst, RegNo, SystemZMC::FP128Regs, 16);
150 }
151 
152 static DecodeStatus DecodeVR32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
153                                                uint64_t Address,
154                                                const MCDisassembler *Decoder) {
155   return decodeRegisterClass(Inst, RegNo, SystemZMC::VR32Regs, 32);
156 }
157 
158 static DecodeStatus DecodeVR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
159                                                uint64_t Address,
160                                                const MCDisassembler *Decoder) {
161   return decodeRegisterClass(Inst, RegNo, SystemZMC::VR64Regs, 32);
162 }
163 
164 static DecodeStatus DecodeVR128BitRegisterClass(MCInst &Inst, uint64_t RegNo,
165                                                 uint64_t Address,
166                                                 const MCDisassembler *Decoder) {
167   return decodeRegisterClass(Inst, RegNo, SystemZMC::VR128Regs, 32);
168 }
169 
170 static DecodeStatus DecodeAR32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
171                                                uint64_t Address,
172                                                const MCDisassembler *Decoder) {
173   return decodeRegisterClass(Inst, RegNo, SystemZMC::AR32Regs, 16);
174 }
175 
176 static DecodeStatus DecodeCR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
177                                                uint64_t Address,
178                                                const MCDisassembler *Decoder) {
179   return decodeRegisterClass(Inst, RegNo, SystemZMC::CR64Regs, 16);
180 }
181 
182 template<unsigned N>
183 static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm) {
184   if (!isUInt<N>(Imm))
185     return MCDisassembler::Fail;
186   Inst.addOperand(MCOperand::createImm(Imm));
187   return MCDisassembler::Success;
188 }
189 
190 template<unsigned N>
191 static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm) {
192   if (!isUInt<N>(Imm))
193     return MCDisassembler::Fail;
194   Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm)));
195   return MCDisassembler::Success;
196 }
197 
198 static DecodeStatus decodeU1ImmOperand(MCInst &Inst, uint64_t Imm,
199                                        uint64_t Address,
200                                        const MCDisassembler *Decoder) {
201   return decodeUImmOperand<1>(Inst, Imm);
202 }
203 
204 static DecodeStatus decodeU2ImmOperand(MCInst &Inst, uint64_t Imm,
205                                        uint64_t Address,
206                                        const MCDisassembler *Decoder) {
207   return decodeUImmOperand<2>(Inst, Imm);
208 }
209 
210 static DecodeStatus decodeU3ImmOperand(MCInst &Inst, uint64_t Imm,
211                                        uint64_t Address,
212                                        const MCDisassembler *Decoder) {
213   return decodeUImmOperand<3>(Inst, Imm);
214 }
215 
216 static DecodeStatus decodeU4ImmOperand(MCInst &Inst, uint64_t Imm,
217                                        uint64_t Address,
218                                        const MCDisassembler *Decoder) {
219   return decodeUImmOperand<4>(Inst, Imm);
220 }
221 
222 static DecodeStatus decodeU8ImmOperand(MCInst &Inst, uint64_t Imm,
223                                        uint64_t Address,
224                                        const MCDisassembler *Decoder) {
225   return decodeUImmOperand<8>(Inst, Imm);
226 }
227 
228 static DecodeStatus decodeU12ImmOperand(MCInst &Inst, uint64_t Imm,
229                                         uint64_t Address,
230                                         const MCDisassembler *Decoder) {
231   return decodeUImmOperand<12>(Inst, Imm);
232 }
233 
234 static DecodeStatus decodeU16ImmOperand(MCInst &Inst, uint64_t Imm,
235                                         uint64_t Address,
236                                         const MCDisassembler *Decoder) {
237   return decodeUImmOperand<16>(Inst, Imm);
238 }
239 
240 static DecodeStatus decodeU32ImmOperand(MCInst &Inst, uint64_t Imm,
241                                         uint64_t Address,
242                                         const MCDisassembler *Decoder) {
243   return decodeUImmOperand<32>(Inst, Imm);
244 }
245 
246 static DecodeStatus decodeS8ImmOperand(MCInst &Inst, uint64_t Imm,
247                                        uint64_t Address,
248                                        const MCDisassembler *Decoder) {
249   return decodeSImmOperand<8>(Inst, Imm);
250 }
251 
252 static DecodeStatus decodeS16ImmOperand(MCInst &Inst, uint64_t Imm,
253                                         uint64_t Address,
254                                         const MCDisassembler *Decoder) {
255   return decodeSImmOperand<16>(Inst, Imm);
256 }
257 
258 static DecodeStatus decodeS20ImmOperand(MCInst &Inst, uint64_t Imm,
259                                         uint64_t Address,
260                                         const MCDisassembler *Decoder) {
261   return decodeSImmOperand<20>(Inst, Imm);
262 }
263 
264 static DecodeStatus decodeS32ImmOperand(MCInst &Inst, uint64_t Imm,
265                                         uint64_t Address,
266                                         const MCDisassembler *Decoder) {
267   return decodeSImmOperand<32>(Inst, Imm);
268 }
269 
270 template <unsigned N>
271 static DecodeStatus decodeLenOperand(MCInst &Inst, uint64_t Imm,
272                                      uint64_t Address,
273                                      const MCDisassembler *Decoder) {
274   if (!isUInt<N>(Imm))
275     return MCDisassembler::Fail;
276   Inst.addOperand(MCOperand::createImm(Imm + 1));
277   return MCDisassembler::Success;
278 }
279 
280 template <unsigned N>
281 static DecodeStatus decodePCDBLOperand(MCInst &Inst, uint64_t Imm,
282                                        uint64_t Address, bool isBranch,
283                                        const MCDisassembler *Decoder) {
284   assert(isUInt<N>(Imm) && "Invalid PC-relative offset");
285   uint64_t Value = SignExtend64<N>(Imm) * 2;
286 
287   if (!tryAddingSymbolicOperand(Value + Address, isBranch, Address, 2, N / 8,
288                                 Inst, Decoder))
289     Inst.addOperand(MCOperand::createImm(Value));
290 
291   return MCDisassembler::Success;
292 }
293 
294 static DecodeStatus decodePC12DBLBranchOperand(MCInst &Inst, uint64_t Imm,
295                                                uint64_t Address,
296                                                const MCDisassembler *Decoder) {
297   return decodePCDBLOperand<12>(Inst, Imm, Address, true, Decoder);
298 }
299 
300 static DecodeStatus decodePC16DBLBranchOperand(MCInst &Inst, uint64_t Imm,
301                                                uint64_t Address,
302                                                const MCDisassembler *Decoder) {
303   return decodePCDBLOperand<16>(Inst, Imm, Address, true, Decoder);
304 }
305 
306 static DecodeStatus decodePC24DBLBranchOperand(MCInst &Inst, uint64_t Imm,
307                                                uint64_t Address,
308                                                const MCDisassembler *Decoder) {
309   return decodePCDBLOperand<24>(Inst, Imm, Address, true, Decoder);
310 }
311 
312 static DecodeStatus decodePC32DBLBranchOperand(MCInst &Inst, uint64_t Imm,
313                                                uint64_t Address,
314                                                const MCDisassembler *Decoder) {
315   return decodePCDBLOperand<32>(Inst, Imm, Address, true, Decoder);
316 }
317 
318 static DecodeStatus decodePC32DBLOperand(MCInst &Inst, uint64_t Imm,
319                                          uint64_t Address,
320                                          const MCDisassembler *Decoder) {
321   return decodePCDBLOperand<32>(Inst, Imm, Address, false, Decoder);
322 }
323 
324 #include "SystemZGenDisassemblerTables.inc"
325 
326 DecodeStatus SystemZDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
327                                                  ArrayRef<uint8_t> Bytes,
328                                                  uint64_t Address,
329                                                  raw_ostream &CS) const {
330   CommentStream = &CS;
331 
332   // Get the first two bytes of the instruction.
333   Size = 0;
334   if (Bytes.size() < 2)
335     return MCDisassembler::Fail;
336 
337   // The top 2 bits of the first byte specify the size.
338   const uint8_t *Table;
339   if (Bytes[0] < 0x40) {
340     Size = 2;
341     Table = DecoderTable16;
342   } else if (Bytes[0] < 0xc0) {
343     Size = 4;
344     Table = DecoderTable32;
345   } else {
346     Size = 6;
347     Table = DecoderTable48;
348   }
349 
350   // Read any remaining bytes.
351   if (Bytes.size() < Size) {
352     Size = Bytes.size();
353     return MCDisassembler::Fail;
354   }
355 
356   // Construct the instruction.
357   uint64_t Inst = 0;
358   for (uint64_t I = 0; I < Size; ++I)
359     Inst = (Inst << 8) | Bytes[I];
360 
361   return decodeInstruction(Table, MI, Inst, Address, this, STI);
362 }
363