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:
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)
49 extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
LLVMInitializeSystemZDisassembler()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.
tryAddingSymbolicOperand(int64_t Value,bool IsBranch,uint64_t Address,uint64_t Offset,uint64_t Width,MCInst & MI,const MCDisassembler * Decoder)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
decodeRegisterClass(MCInst & Inst,uint64_t RegNo,const unsigned * Regs,unsigned Size,bool IsAddr=false)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
DecodeGR32BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)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
DecodeGRH32BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)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
DecodeGR64BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)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
DecodeGR128BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)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
DecodeADDR32BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)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
DecodeADDR64BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)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
DecodeFP32BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)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
DecodeFP64BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)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
DecodeFP128BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)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
DecodeVR32BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)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
DecodeVR64BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)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
DecodeVR128BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)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
DecodeAR32BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)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
DecodeCR64BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)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>
decodeUImmOperand(MCInst & Inst,uint64_t Imm)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>
decodeSImmOperand(MCInst & Inst,uint64_t Imm)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
decodeU1ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)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
decodeU2ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)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
decodeU3ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)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
decodeU4ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)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
decodeU8ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)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
decodeU12ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)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
decodeU16ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)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
decodeU32ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)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
decodeS8ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)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
decodeS16ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)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
decodeS20ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)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
decodeS32ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)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>
decodeLenOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)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>
decodePCDBLOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,bool isBranch,const MCDisassembler * Decoder)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
decodePC12DBLBranchOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)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
decodePC16DBLBranchOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)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
decodePC24DBLBranchOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)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
decodePC32DBLBranchOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)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
decodePC32DBLOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)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
getInstruction(MCInst & MI,uint64_t & Size,ArrayRef<uint8_t> Bytes,uint64_t Address,raw_ostream & CS) const326 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