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