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