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
21using namespace llvm;
22
23#define DEBUG_TYPE "systemz-disassembler"
24
25typedef MCDisassembler::DecodeStatus DecodeStatus;
26
27namespace {
28
29class SystemZDisassembler : public MCDisassembler {
30public:
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
42static 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)
49extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
50LLVMInitializeSystemZDisassembler() {
51 // Register the disassembler.
52 TargetRegistry::RegisterMCDisassembler(T&: getTheSystemZTarget(),
53 Fn: 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.
75static 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(Inst&: MI, Value, Address, IsBranch, Offset,
80 OpSize: Width, /*InstSize=*/0);
81}
82
83static 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(Op: MCOperand::createReg(Reg: RegNo));
95 return MCDisassembler::Success;
96}
97
98static DecodeStatus DecodeGR32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
99 uint64_t Address,
100 const MCDisassembler *Decoder) {
101 return decodeRegisterClass(Inst, RegNo, Regs: SystemZMC::GR32Regs, Size: 16);
102}
103
104static DecodeStatus DecodeGRH32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
105 uint64_t Address,
106 const MCDisassembler *Decoder) {
107 return decodeRegisterClass(Inst, RegNo, Regs: SystemZMC::GRH32Regs, Size: 16);
108}
109
110static DecodeStatus DecodeGR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
111 uint64_t Address,
112 const MCDisassembler *Decoder) {
113 return decodeRegisterClass(Inst, RegNo, Regs: SystemZMC::GR64Regs, Size: 16);
114}
115
116static DecodeStatus DecodeGR128BitRegisterClass(MCInst &Inst, uint64_t RegNo,
117 uint64_t Address,
118 const MCDisassembler *Decoder) {
119 return decodeRegisterClass(Inst, RegNo, Regs: SystemZMC::GR128Regs, Size: 16);
120}
121
122static DecodeStatus
123DecodeADDR32BitRegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address,
124 const MCDisassembler *Decoder) {
125 return decodeRegisterClass(Inst, RegNo, Regs: SystemZMC::GR32Regs, Size: 16, IsAddr: true);
126}
127
128static DecodeStatus
129DecodeADDR64BitRegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address,
130 const MCDisassembler *Decoder) {
131 return decodeRegisterClass(Inst, RegNo, Regs: SystemZMC::GR64Regs, Size: 16, IsAddr: true);
132}
133
134static DecodeStatus DecodeFP32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
135 uint64_t Address,
136 const MCDisassembler *Decoder) {
137 return decodeRegisterClass(Inst, RegNo, Regs: SystemZMC::FP32Regs, Size: 16);
138}
139
140static DecodeStatus DecodeFP64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
141 uint64_t Address,
142 const MCDisassembler *Decoder) {
143 return decodeRegisterClass(Inst, RegNo, Regs: SystemZMC::FP64Regs, Size: 16);
144}
145
146static DecodeStatus DecodeFP128BitRegisterClass(MCInst &Inst, uint64_t RegNo,
147 uint64_t Address,
148 const MCDisassembler *Decoder) {
149 return decodeRegisterClass(Inst, RegNo, Regs: SystemZMC::FP128Regs, Size: 16);
150}
151
152static DecodeStatus DecodeVR32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
153 uint64_t Address,
154 const MCDisassembler *Decoder) {
155 return decodeRegisterClass(Inst, RegNo, Regs: SystemZMC::VR32Regs, Size: 32);
156}
157
158static DecodeStatus DecodeVR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
159 uint64_t Address,
160 const MCDisassembler *Decoder) {
161 return decodeRegisterClass(Inst, RegNo, Regs: SystemZMC::VR64Regs, Size: 32);
162}
163
164static DecodeStatus DecodeVR128BitRegisterClass(MCInst &Inst, uint64_t RegNo,
165 uint64_t Address,
166 const MCDisassembler *Decoder) {
167 return decodeRegisterClass(Inst, RegNo, Regs: SystemZMC::VR128Regs, Size: 32);
168}
169
170static DecodeStatus DecodeAR32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
171 uint64_t Address,
172 const MCDisassembler *Decoder) {
173 return decodeRegisterClass(Inst, RegNo, Regs: SystemZMC::AR32Regs, Size: 16);
174}
175
176static DecodeStatus DecodeCR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
177 uint64_t Address,
178 const MCDisassembler *Decoder) {
179 return decodeRegisterClass(Inst, RegNo, Regs: SystemZMC::CR64Regs, Size: 16);
180}
181
182template<unsigned N>
183static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm) {
184 if (!isUInt<N>(Imm))
185 return MCDisassembler::Fail;
186 Inst.addOperand(Op: MCOperand::createImm(Val: Imm));
187 return MCDisassembler::Success;
188}
189
190template<unsigned N>
191static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm) {
192 if (!isUInt<N>(Imm))
193 return MCDisassembler::Fail;
194 Inst.addOperand(Op: MCOperand::createImm(Val: SignExtend64<N>(Imm)));
195 return MCDisassembler::Success;
196}
197
198static DecodeStatus decodeU1ImmOperand(MCInst &Inst, uint64_t Imm,
199 uint64_t Address,
200 const MCDisassembler *Decoder) {
201 return decodeUImmOperand<1>(Inst, Imm);
202}
203
204static DecodeStatus decodeU2ImmOperand(MCInst &Inst, uint64_t Imm,
205 uint64_t Address,
206 const MCDisassembler *Decoder) {
207 return decodeUImmOperand<2>(Inst, Imm);
208}
209
210static DecodeStatus decodeU3ImmOperand(MCInst &Inst, uint64_t Imm,
211 uint64_t Address,
212 const MCDisassembler *Decoder) {
213 return decodeUImmOperand<3>(Inst, Imm);
214}
215
216static DecodeStatus decodeU4ImmOperand(MCInst &Inst, uint64_t Imm,
217 uint64_t Address,
218 const MCDisassembler *Decoder) {
219 return decodeUImmOperand<4>(Inst, Imm);
220}
221
222static DecodeStatus decodeU8ImmOperand(MCInst &Inst, uint64_t Imm,
223 uint64_t Address,
224 const MCDisassembler *Decoder) {
225 return decodeUImmOperand<8>(Inst, Imm);
226}
227
228static DecodeStatus decodeU12ImmOperand(MCInst &Inst, uint64_t Imm,
229 uint64_t Address,
230 const MCDisassembler *Decoder) {
231 return decodeUImmOperand<12>(Inst, Imm);
232}
233
234static DecodeStatus decodeU16ImmOperand(MCInst &Inst, uint64_t Imm,
235 uint64_t Address,
236 const MCDisassembler *Decoder) {
237 return decodeUImmOperand<16>(Inst, Imm);
238}
239
240static DecodeStatus decodeU32ImmOperand(MCInst &Inst, uint64_t Imm,
241 uint64_t Address,
242 const MCDisassembler *Decoder) {
243 return decodeUImmOperand<32>(Inst, Imm);
244}
245
246static DecodeStatus decodeS8ImmOperand(MCInst &Inst, uint64_t Imm,
247 uint64_t Address,
248 const MCDisassembler *Decoder) {
249 return decodeSImmOperand<8>(Inst, Imm);
250}
251
252static DecodeStatus decodeS16ImmOperand(MCInst &Inst, uint64_t Imm,
253 uint64_t Address,
254 const MCDisassembler *Decoder) {
255 return decodeSImmOperand<16>(Inst, Imm);
256}
257
258static DecodeStatus decodeS20ImmOperand(MCInst &Inst, uint64_t Imm,
259 uint64_t Address,
260 const MCDisassembler *Decoder) {
261 return decodeSImmOperand<20>(Inst, Imm);
262}
263
264static DecodeStatus decodeS32ImmOperand(MCInst &Inst, uint64_t Imm,
265 uint64_t Address,
266 const MCDisassembler *Decoder) {
267 return decodeSImmOperand<32>(Inst, Imm);
268}
269
270template <unsigned N>
271static 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(Op: MCOperand::createImm(Val: Imm + 1));
277 return MCDisassembler::Success;
278}
279
280template <unsigned N>
281static 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: Value + Address, IsBranch: isBranch, Address, Offset: 2, Width: N / 8,
288 MI&: Inst, Decoder))
289 Inst.addOperand(Op: MCOperand::createImm(Val: Value));
290
291 return MCDisassembler::Success;
292}
293
294static DecodeStatus decodePC12DBLBranchOperand(MCInst &Inst, uint64_t Imm,
295 uint64_t Address,
296 const MCDisassembler *Decoder) {
297 return decodePCDBLOperand<12>(Inst, Imm, Address, isBranch: true, Decoder);
298}
299
300static DecodeStatus decodePC16DBLBranchOperand(MCInst &Inst, uint64_t Imm,
301 uint64_t Address,
302 const MCDisassembler *Decoder) {
303 return decodePCDBLOperand<16>(Inst, Imm, Address, isBranch: true, Decoder);
304}
305
306static DecodeStatus decodePC24DBLBranchOperand(MCInst &Inst, uint64_t Imm,
307 uint64_t Address,
308 const MCDisassembler *Decoder) {
309 return decodePCDBLOperand<24>(Inst, Imm, Address, isBranch: true, Decoder);
310}
311
312static DecodeStatus decodePC32DBLBranchOperand(MCInst &Inst, uint64_t Imm,
313 uint64_t Address,
314 const MCDisassembler *Decoder) {
315 return decodePCDBLOperand<32>(Inst, Imm, Address, isBranch: true, Decoder);
316}
317
318static DecodeStatus decodePC32DBLOperand(MCInst &Inst, uint64_t Imm,
319 uint64_t Address,
320 const MCDisassembler *Decoder) {
321 return decodePCDBLOperand<32>(Inst, Imm, Address, isBranch: false, Decoder);
322}
323
324#include "SystemZGenDisassemblerTables.inc"
325
326DecodeStatus SystemZDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
327 ArrayRef<uint8_t> Bytes,
328 uint64_t Address,
329 raw_ostream &CS) const {
330 // Get the first two bytes of the instruction.
331 Size = 0;
332 if (Bytes.size() < 2)
333 return MCDisassembler::Fail;
334
335 // The top 2 bits of the first byte specify the size.
336 const uint8_t *Table;
337 if (Bytes[0] < 0x40) {
338 Size = 2;
339 Table = DecoderTable16;
340 } else if (Bytes[0] < 0xc0) {
341 Size = 4;
342 Table = DecoderTable32;
343 } else {
344 Size = 6;
345 Table = DecoderTable48;
346 }
347
348 // Read any remaining bytes.
349 if (Bytes.size() < Size) {
350 Size = Bytes.size();
351 return MCDisassembler::Fail;
352 }
353
354 // Construct the instruction.
355 uint64_t Inst = 0;
356 for (uint64_t I = 0; I < Size; ++I)
357 Inst = (Inst << 8) | Bytes[I];
358
359 return decodeInstruction(DecodeTable: Table, MI, insn: Inst, Address, DisAsm: this, STI);
360}
361