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