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