1 //===-- SystemZDisassembler.cpp - Disassembler for SystemZ ------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
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/MathExtras.h"
22 #define DEBUG_TYPE "systemz-disassembler"
24 typedef MCDisassembler::DecodeStatus DecodeStatus
;
28 class SystemZDisassembler
: public MCDisassembler
{
30 SystemZDisassembler(const MCSubtargetInfo
&STI
, MCContext
&Ctx
)
31 : MCDisassembler(STI
, Ctx
) {}
32 ~SystemZDisassembler() override
= default;
34 DecodeStatus
getInstruction(MCInst
&Instr
, uint64_t &Size
,
35 ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
36 raw_ostream
&CStream
) const override
;
39 } // end anonymous namespace
41 static MCDisassembler
*createSystemZDisassembler(const Target
&T
,
42 const MCSubtargetInfo
&STI
,
44 return new SystemZDisassembler(STI
, Ctx
);
47 // NOLINTNEXTLINE(readability-identifier-naming)
48 extern "C" LLVM_EXTERNAL_VISIBILITY
void LLVMInitializeSystemZDisassembler() {
49 // Register the disassembler.
50 TargetRegistry::RegisterMCDisassembler(getTheSystemZTarget(),
51 createSystemZDisassembler
);
54 /// tryAddingSymbolicOperand - trys to add a symbolic operand in place of the
55 /// immediate Value in the MCInst.
57 /// @param Value - The immediate Value, has had any PC adjustment made by
59 /// @param isBranch - If the instruction is a branch instruction
60 /// @param Address - The starting address of the instruction
61 /// @param Offset - The byte offset to this immediate in the instruction
62 /// @param Width - The byte width of this immediate in the instruction
64 /// If the getOpInfo() function was set when setupForSymbolicDisassembly() was
65 /// called then that function is called to get any symbolic information for the
66 /// immediate in the instruction using the Address, Offset and Width. If that
67 /// returns non-zero then the symbolic information it returns is used to create
68 /// an MCExpr and that is added as an operand to the MCInst. If getOpInfo()
69 /// returns zero and isBranch is true then a symbol look up for immediate Value
70 /// is done and if a symbol is found an MCExpr is created with that, else
71 /// an MCExpr with the immediate Value is created. This function returns true
72 /// if it adds an operand to the MCInst and false otherwise.
73 static bool tryAddingSymbolicOperand(int64_t Value
, bool IsBranch
,
74 uint64_t Address
, uint64_t Offset
,
75 uint64_t Width
, MCInst
&MI
,
76 const MCDisassembler
*Decoder
) {
77 return Decoder
->tryAddingSymbolicOperand(MI
, Value
, Address
, IsBranch
, Offset
,
78 Width
, /*InstSize=*/0);
81 static DecodeStatus
decodeRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
82 const unsigned *Regs
, unsigned Size
,
83 bool IsAddr
= false) {
84 assert(RegNo
< Size
&& "Invalid register");
85 if (IsAddr
&& RegNo
== 0) {
86 RegNo
= SystemZ::NoRegister
;
90 return MCDisassembler::Fail
;
92 Inst
.addOperand(MCOperand::createReg(RegNo
));
93 return MCDisassembler::Success
;
96 static DecodeStatus
DecodeGR32BitRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
98 const MCDisassembler
*Decoder
) {
99 return decodeRegisterClass(Inst
, RegNo
, SystemZMC::GR32Regs
, 16);
102 static DecodeStatus
DecodeGRH32BitRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
104 const MCDisassembler
*Decoder
) {
105 return decodeRegisterClass(Inst
, RegNo
, SystemZMC::GRH32Regs
, 16);
108 static DecodeStatus
DecodeGR64BitRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
110 const MCDisassembler
*Decoder
) {
111 return decodeRegisterClass(Inst
, RegNo
, SystemZMC::GR64Regs
, 16);
114 static DecodeStatus
DecodeGR128BitRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
116 const MCDisassembler
*Decoder
) {
117 return decodeRegisterClass(Inst
, RegNo
, SystemZMC::GR128Regs
, 16);
121 DecodeADDR32BitRegisterClass(MCInst
&Inst
, uint64_t RegNo
, uint64_t Address
,
122 const MCDisassembler
*Decoder
) {
123 return decodeRegisterClass(Inst
, RegNo
, SystemZMC::GR32Regs
, 16, true);
127 DecodeADDR64BitRegisterClass(MCInst
&Inst
, uint64_t RegNo
, uint64_t Address
,
128 const MCDisassembler
*Decoder
) {
129 return decodeRegisterClass(Inst
, RegNo
, SystemZMC::GR64Regs
, 16, true);
132 static DecodeStatus
DecodeFP32BitRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
134 const MCDisassembler
*Decoder
) {
135 return decodeRegisterClass(Inst
, RegNo
, SystemZMC::FP32Regs
, 16);
138 static DecodeStatus
DecodeFP64BitRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
140 const MCDisassembler
*Decoder
) {
141 return decodeRegisterClass(Inst
, RegNo
, SystemZMC::FP64Regs
, 16);
144 static DecodeStatus
DecodeFP128BitRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
146 const MCDisassembler
*Decoder
) {
147 return decodeRegisterClass(Inst
, RegNo
, SystemZMC::FP128Regs
, 16);
150 static DecodeStatus
DecodeVR32BitRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
152 const MCDisassembler
*Decoder
) {
153 return decodeRegisterClass(Inst
, RegNo
, SystemZMC::VR32Regs
, 32);
156 static DecodeStatus
DecodeVR64BitRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
158 const MCDisassembler
*Decoder
) {
159 return decodeRegisterClass(Inst
, RegNo
, SystemZMC::VR64Regs
, 32);
162 static DecodeStatus
DecodeVR128BitRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
164 const MCDisassembler
*Decoder
) {
165 return decodeRegisterClass(Inst
, RegNo
, SystemZMC::VR128Regs
, 32);
168 static DecodeStatus
DecodeAR32BitRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
170 const MCDisassembler
*Decoder
) {
171 return decodeRegisterClass(Inst
, RegNo
, SystemZMC::AR32Regs
, 16);
174 static DecodeStatus
DecodeCR64BitRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
176 const MCDisassembler
*Decoder
) {
177 return decodeRegisterClass(Inst
, RegNo
, SystemZMC::CR64Regs
, 16);
181 static DecodeStatus
decodeUImmOperand(MCInst
&Inst
, uint64_t Imm
) {
183 return MCDisassembler::Fail
;
184 Inst
.addOperand(MCOperand::createImm(Imm
));
185 return MCDisassembler::Success
;
189 static DecodeStatus
decodeSImmOperand(MCInst
&Inst
, uint64_t Imm
) {
191 return MCDisassembler::Fail
;
192 Inst
.addOperand(MCOperand::createImm(SignExtend64
<N
>(Imm
)));
193 return MCDisassembler::Success
;
196 static DecodeStatus
decodeU1ImmOperand(MCInst
&Inst
, uint64_t Imm
,
198 const MCDisassembler
*Decoder
) {
199 return decodeUImmOperand
<1>(Inst
, Imm
);
202 static DecodeStatus
decodeU2ImmOperand(MCInst
&Inst
, uint64_t Imm
,
204 const MCDisassembler
*Decoder
) {
205 return decodeUImmOperand
<2>(Inst
, Imm
);
208 static DecodeStatus
decodeU3ImmOperand(MCInst
&Inst
, uint64_t Imm
,
210 const MCDisassembler
*Decoder
) {
211 return decodeUImmOperand
<3>(Inst
, Imm
);
214 static DecodeStatus
decodeU4ImmOperand(MCInst
&Inst
, uint64_t Imm
,
216 const MCDisassembler
*Decoder
) {
217 return decodeUImmOperand
<4>(Inst
, Imm
);
220 static DecodeStatus
decodeU8ImmOperand(MCInst
&Inst
, uint64_t Imm
,
222 const MCDisassembler
*Decoder
) {
223 return decodeUImmOperand
<8>(Inst
, Imm
);
226 static DecodeStatus
decodeU12ImmOperand(MCInst
&Inst
, uint64_t Imm
,
228 const MCDisassembler
*Decoder
) {
229 return decodeUImmOperand
<12>(Inst
, Imm
);
232 static DecodeStatus
decodeU16ImmOperand(MCInst
&Inst
, uint64_t Imm
,
234 const MCDisassembler
*Decoder
) {
235 return decodeUImmOperand
<16>(Inst
, Imm
);
238 static DecodeStatus
decodeU32ImmOperand(MCInst
&Inst
, uint64_t Imm
,
240 const MCDisassembler
*Decoder
) {
241 return decodeUImmOperand
<32>(Inst
, Imm
);
244 static DecodeStatus
decodeS8ImmOperand(MCInst
&Inst
, uint64_t Imm
,
246 const MCDisassembler
*Decoder
) {
247 return decodeSImmOperand
<8>(Inst
, Imm
);
250 static DecodeStatus
decodeS16ImmOperand(MCInst
&Inst
, uint64_t Imm
,
252 const MCDisassembler
*Decoder
) {
253 return decodeSImmOperand
<16>(Inst
, Imm
);
256 static DecodeStatus
decodeS20ImmOperand(MCInst
&Inst
, uint64_t Imm
,
258 const MCDisassembler
*Decoder
) {
259 return decodeSImmOperand
<20>(Inst
, Imm
);
262 static DecodeStatus
decodeS32ImmOperand(MCInst
&Inst
, uint64_t Imm
,
264 const MCDisassembler
*Decoder
) {
265 return decodeSImmOperand
<32>(Inst
, Imm
);
268 template <unsigned N
>
269 static DecodeStatus
decodeLenOperand(MCInst
&Inst
, uint64_t Imm
,
271 const MCDisassembler
*Decoder
) {
273 return MCDisassembler::Fail
;
274 Inst
.addOperand(MCOperand::createImm(Imm
+ 1));
275 return MCDisassembler::Success
;
278 template <unsigned N
>
279 static DecodeStatus
decodePCDBLOperand(MCInst
&Inst
, uint64_t Imm
,
280 uint64_t Address
, bool isBranch
,
281 const MCDisassembler
*Decoder
) {
282 assert(isUInt
<N
>(Imm
) && "Invalid PC-relative offset");
283 uint64_t Value
= SignExtend64
<N
>(Imm
) * 2 + Address
;
285 if (!tryAddingSymbolicOperand(Value
, isBranch
, Address
, 2, N
/ 8,
287 Inst
.addOperand(MCOperand::createImm(Value
));
289 return MCDisassembler::Success
;
292 static DecodeStatus
decodePC12DBLBranchOperand(MCInst
&Inst
, uint64_t Imm
,
294 const MCDisassembler
*Decoder
) {
295 return decodePCDBLOperand
<12>(Inst
, Imm
, Address
, true, Decoder
);
298 static DecodeStatus
decodePC16DBLBranchOperand(MCInst
&Inst
, uint64_t Imm
,
300 const MCDisassembler
*Decoder
) {
301 return decodePCDBLOperand
<16>(Inst
, Imm
, Address
, true, Decoder
);
304 static DecodeStatus
decodePC24DBLBranchOperand(MCInst
&Inst
, uint64_t Imm
,
306 const MCDisassembler
*Decoder
) {
307 return decodePCDBLOperand
<24>(Inst
, Imm
, Address
, true, Decoder
);
310 static DecodeStatus
decodePC32DBLBranchOperand(MCInst
&Inst
, uint64_t Imm
,
312 const MCDisassembler
*Decoder
) {
313 return decodePCDBLOperand
<32>(Inst
, Imm
, Address
, true, Decoder
);
316 static DecodeStatus
decodePC32DBLOperand(MCInst
&Inst
, uint64_t Imm
,
318 const MCDisassembler
*Decoder
) {
319 return decodePCDBLOperand
<32>(Inst
, Imm
, Address
, false, Decoder
);
322 #include "SystemZGenDisassemblerTables.inc"
324 DecodeStatus
SystemZDisassembler::getInstruction(MCInst
&MI
, uint64_t &Size
,
325 ArrayRef
<uint8_t> Bytes
,
327 raw_ostream
&CS
) const {
328 // Get the first two bytes of the instruction.
330 if (Bytes
.size() < 2)
331 return MCDisassembler::Fail
;
333 // The top 2 bits of the first byte specify the size.
334 const uint8_t *Table
;
335 if (Bytes
[0] < 0x40) {
337 Table
= DecoderTable16
;
338 } else if (Bytes
[0] < 0xc0) {
340 Table
= DecoderTable32
;
343 Table
= DecoderTable48
;
346 // Read any remaining bytes.
347 if (Bytes
.size() < Size
) {
349 return MCDisassembler::Fail
;
352 // Construct the instruction.
354 for (uint64_t I
= 0; I
< Size
; ++I
)
355 Inst
= (Inst
<< 8) | Bytes
[I
];
357 return decodeInstruction(Table
, MI
, Inst
, Address
, this, STI
);