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
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_EXTERNAL_VISIBILITY void LLVMInitializeSystemZDisassembler() {
50 // Register the disassembler.
51 TargetRegistry::RegisterMCDisassembler(T&: getTheSystemZTarget(),
52 Fn: 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.
74static 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(Inst&: MI, Value, Address, IsBranch, Offset,
79 OpSize: Width, /*InstSize=*/0);
80}
81
82static 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(Op: MCOperand::createReg(Reg: RegNo));
94 return MCDisassembler::Success;
95}
96
97static DecodeStatus DecodeGR32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
98 uint64_t Address,
99 const MCDisassembler *Decoder) {
100 return decodeRegisterClass(Inst, RegNo, Regs: SystemZMC::GR32Regs, Size: 16);
101}
102
103static DecodeStatus DecodeGRH32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
104 uint64_t Address,
105 const MCDisassembler *Decoder) {
106 return decodeRegisterClass(Inst, RegNo, Regs: SystemZMC::GRH32Regs, Size: 16);
107}
108
109static DecodeStatus DecodeGR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
110 uint64_t Address,
111 const MCDisassembler *Decoder) {
112 return decodeRegisterClass(Inst, RegNo, Regs: SystemZMC::GR64Regs, Size: 16);
113}
114
115static DecodeStatus DecodeGR128BitRegisterClass(MCInst &Inst, uint64_t RegNo,
116 uint64_t Address,
117 const MCDisassembler *Decoder) {
118 return decodeRegisterClass(Inst, RegNo, Regs: SystemZMC::GR128Regs, Size: 16);
119}
120
121static DecodeStatus
122DecodeADDR32BitRegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address,
123 const MCDisassembler *Decoder) {
124 return decodeRegisterClass(Inst, RegNo, Regs: SystemZMC::GR32Regs, Size: 16, IsAddr: true);
125}
126
127static DecodeStatus
128DecodeADDR64BitRegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address,
129 const MCDisassembler *Decoder) {
130 return decodeRegisterClass(Inst, RegNo, Regs: SystemZMC::GR64Regs, Size: 16, IsAddr: true);
131}
132
133static DecodeStatus DecodeFP32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
134 uint64_t Address,
135 const MCDisassembler *Decoder) {
136 return decodeRegisterClass(Inst, RegNo, Regs: SystemZMC::FP32Regs, Size: 16);
137}
138
139static DecodeStatus DecodeFP64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
140 uint64_t Address,
141 const MCDisassembler *Decoder) {
142 return decodeRegisterClass(Inst, RegNo, Regs: SystemZMC::FP64Regs, Size: 16);
143}
144
145static DecodeStatus DecodeFP128BitRegisterClass(MCInst &Inst, uint64_t RegNo,
146 uint64_t Address,
147 const MCDisassembler *Decoder) {
148 return decodeRegisterClass(Inst, RegNo, Regs: SystemZMC::FP128Regs, Size: 16);
149}
150
151static DecodeStatus DecodeVR32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
152 uint64_t Address,
153 const MCDisassembler *Decoder) {
154 return decodeRegisterClass(Inst, RegNo, Regs: SystemZMC::VR32Regs, Size: 32);
155}
156
157static DecodeStatus DecodeVR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
158 uint64_t Address,
159 const MCDisassembler *Decoder) {
160 return decodeRegisterClass(Inst, RegNo, Regs: SystemZMC::VR64Regs, Size: 32);
161}
162
163static DecodeStatus DecodeVR128BitRegisterClass(MCInst &Inst, uint64_t RegNo,
164 uint64_t Address,
165 const MCDisassembler *Decoder) {
166 return decodeRegisterClass(Inst, RegNo, Regs: SystemZMC::VR128Regs, Size: 32);
167}
168
169static DecodeStatus DecodeAR32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
170 uint64_t Address,
171 const MCDisassembler *Decoder) {
172 return decodeRegisterClass(Inst, RegNo, Regs: SystemZMC::AR32Regs, Size: 16);
173}
174
175static DecodeStatus DecodeCR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
176 uint64_t Address,
177 const MCDisassembler *Decoder) {
178 return decodeRegisterClass(Inst, RegNo, Regs: SystemZMC::CR64Regs, Size: 16);
179}
180
181template<unsigned N>
182static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm) {
183 if (!isUInt<N>(Imm))
184 return MCDisassembler::Fail;
185 Inst.addOperand(Op: MCOperand::createImm(Val: Imm));
186 return MCDisassembler::Success;
187}
188
189template<unsigned N>
190static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm) {
191 if (!isUInt<N>(Imm))
192 return MCDisassembler::Fail;
193 Inst.addOperand(Op: MCOperand::createImm(Val: SignExtend64<N>(Imm)));
194 return MCDisassembler::Success;
195}
196
197static DecodeStatus decodeU1ImmOperand(MCInst &Inst, uint64_t Imm,
198 uint64_t Address,
199 const MCDisassembler *Decoder) {
200 return decodeUImmOperand<1>(Inst, Imm);
201}
202
203static DecodeStatus decodeU2ImmOperand(MCInst &Inst, uint64_t Imm,
204 uint64_t Address,
205 const MCDisassembler *Decoder) {
206 return decodeUImmOperand<2>(Inst, Imm);
207}
208
209static DecodeStatus decodeU3ImmOperand(MCInst &Inst, uint64_t Imm,
210 uint64_t Address,
211 const MCDisassembler *Decoder) {
212 return decodeUImmOperand<3>(Inst, Imm);
213}
214
215static DecodeStatus decodeU4ImmOperand(MCInst &Inst, uint64_t Imm,
216 uint64_t Address,
217 const MCDisassembler *Decoder) {
218 return decodeUImmOperand<4>(Inst, Imm);
219}
220
221static DecodeStatus decodeU8ImmOperand(MCInst &Inst, uint64_t Imm,
222 uint64_t Address,
223 const MCDisassembler *Decoder) {
224 return decodeUImmOperand<8>(Inst, Imm);
225}
226
227static DecodeStatus decodeU12ImmOperand(MCInst &Inst, uint64_t Imm,
228 uint64_t Address,
229 const MCDisassembler *Decoder) {
230 return decodeUImmOperand<12>(Inst, Imm);
231}
232
233static DecodeStatus decodeU16ImmOperand(MCInst &Inst, uint64_t Imm,
234 uint64_t Address,
235 const MCDisassembler *Decoder) {
236 return decodeUImmOperand<16>(Inst, Imm);
237}
238
239static DecodeStatus decodeU32ImmOperand(MCInst &Inst, uint64_t Imm,
240 uint64_t Address,
241 const MCDisassembler *Decoder) {
242 return decodeUImmOperand<32>(Inst, Imm);
243}
244
245static DecodeStatus decodeS8ImmOperand(MCInst &Inst, uint64_t Imm,
246 uint64_t Address,
247 const MCDisassembler *Decoder) {
248 return decodeSImmOperand<8>(Inst, Imm);
249}
250
251static DecodeStatus decodeS16ImmOperand(MCInst &Inst, uint64_t Imm,
252 uint64_t Address,
253 const MCDisassembler *Decoder) {
254 return decodeSImmOperand<16>(Inst, Imm);
255}
256
257static DecodeStatus decodeS20ImmOperand(MCInst &Inst, uint64_t Imm,
258 uint64_t Address,
259 const MCDisassembler *Decoder) {
260 return decodeSImmOperand<20>(Inst, Imm);
261}
262
263static DecodeStatus decodeS32ImmOperand(MCInst &Inst, uint64_t Imm,
264 uint64_t Address,
265 const MCDisassembler *Decoder) {
266 return decodeSImmOperand<32>(Inst, Imm);
267}
268
269template <unsigned N>
270static 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(Op: MCOperand::createImm(Val: Imm + 1));
276 return MCDisassembler::Success;
277}
278
279template <unsigned N>
280static 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: isBranch, Address, Offset: 2, Width: N / 8,
287 MI&: Inst, Decoder))
288 Inst.addOperand(Op: MCOperand::createImm(Val: Value));
289
290 return MCDisassembler::Success;
291}
292
293static DecodeStatus decodePC12DBLBranchOperand(MCInst &Inst, uint64_t Imm,
294 uint64_t Address,
295 const MCDisassembler *Decoder) {
296 return decodePCDBLOperand<12>(Inst, Imm, Address, isBranch: true, Decoder);
297}
298
299static DecodeStatus decodePC16DBLBranchOperand(MCInst &Inst, uint64_t Imm,
300 uint64_t Address,
301 const MCDisassembler *Decoder) {
302 return decodePCDBLOperand<16>(Inst, Imm, Address, isBranch: true, Decoder);
303}
304
305static DecodeStatus decodePC24DBLBranchOperand(MCInst &Inst, uint64_t Imm,
306 uint64_t Address,
307 const MCDisassembler *Decoder) {
308 return decodePCDBLOperand<24>(Inst, Imm, Address, isBranch: true, Decoder);
309}
310
311static DecodeStatus decodePC32DBLBranchOperand(MCInst &Inst, uint64_t Imm,
312 uint64_t Address,
313 const MCDisassembler *Decoder) {
314 return decodePCDBLOperand<32>(Inst, Imm, Address, isBranch: true, Decoder);
315}
316
317static DecodeStatus decodePC32DBLOperand(MCInst &Inst, uint64_t Imm,
318 uint64_t Address,
319 const MCDisassembler *Decoder) {
320 return decodePCDBLOperand<32>(Inst, Imm, Address, isBranch: false, Decoder);
321}
322
323#include "SystemZGenDisassemblerTables.inc"
324
325DecodeStatus 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(DecodeTable: Table, MI, insn: Inst, Address, DisAsm: this, STI);
359}
360