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"
11 #include "TargetInfo/SystemZTargetInfo.h"
12 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
13 #include "llvm/MC/MCFixedLenDisassembler.h"
14 #include "llvm/MC/MCInst.h"
15 #include "llvm/MC/MCSubtargetInfo.h"
16 #include "llvm/Support/MathExtras.h"
17 #include "llvm/Support/TargetRegistry.h"
23 #define DEBUG_TYPE "systemz-disassembler"
25 typedef MCDisassembler::DecodeStatus DecodeStatus
;
29 class SystemZDisassembler
: public MCDisassembler
{
31 SystemZDisassembler(const MCSubtargetInfo
&STI
, MCContext
&Ctx
)
32 : MCDisassembler(STI
, Ctx
) {}
33 ~SystemZDisassembler() override
= default;
35 DecodeStatus
getInstruction(MCInst
&instr
, uint64_t &Size
,
36 ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
38 raw_ostream
&CStream
) const override
;
41 } // end anonymous namespace
43 static MCDisassembler
*createSystemZDisassembler(const Target
&T
,
44 const MCSubtargetInfo
&STI
,
46 return new SystemZDisassembler(STI
, Ctx
);
49 extern "C" void LLVMInitializeSystemZDisassembler() {
50 // Register the disassembler.
51 TargetRegistry::RegisterMCDisassembler(getTheSystemZTarget(),
52 createSystemZDisassembler
);
55 /// tryAddingSymbolicOperand - trys to add a symbolic operand in place of the
56 /// immediate Value in the MCInst.
58 /// @param Value - The immediate Value, has had any PC adjustment made by
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
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.
74 static bool tryAddingSymbolicOperand(int64_t Value
, bool isBranch
,
75 uint64_t Address
, uint64_t Offset
,
76 uint64_t Width
, MCInst
&MI
,
77 const void *Decoder
) {
78 const MCDisassembler
*Dis
= static_cast<const MCDisassembler
*>(Decoder
);
79 return Dis
->tryAddingSymbolicOperand(MI
, Value
, Address
, isBranch
,
83 static DecodeStatus
decodeRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
84 const unsigned *Regs
, unsigned Size
) {
85 assert(RegNo
< Size
&& "Invalid register");
88 return MCDisassembler::Fail
;
89 Inst
.addOperand(MCOperand::createReg(RegNo
));
90 return MCDisassembler::Success
;
93 static DecodeStatus
DecodeGR32BitRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
95 const void *Decoder
) {
96 return decodeRegisterClass(Inst
, RegNo
, SystemZMC::GR32Regs
, 16);
99 static DecodeStatus
DecodeGRH32BitRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
101 const void *Decoder
) {
102 return decodeRegisterClass(Inst
, RegNo
, SystemZMC::GRH32Regs
, 16);
105 static DecodeStatus
DecodeGR64BitRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
107 const void *Decoder
) {
108 return decodeRegisterClass(Inst
, RegNo
, SystemZMC::GR64Regs
, 16);
111 static DecodeStatus
DecodeGR128BitRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
113 const void *Decoder
) {
114 return decodeRegisterClass(Inst
, RegNo
, SystemZMC::GR128Regs
, 16);
117 static DecodeStatus
DecodeADDR64BitRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
119 const void *Decoder
) {
120 return decodeRegisterClass(Inst
, RegNo
, SystemZMC::GR64Regs
, 16);
123 static DecodeStatus
DecodeFP32BitRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
125 const void *Decoder
) {
126 return decodeRegisterClass(Inst
, RegNo
, SystemZMC::FP32Regs
, 16);
129 static DecodeStatus
DecodeFP64BitRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
131 const void *Decoder
) {
132 return decodeRegisterClass(Inst
, RegNo
, SystemZMC::FP64Regs
, 16);
135 static DecodeStatus
DecodeFP128BitRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
137 const void *Decoder
) {
138 return decodeRegisterClass(Inst
, RegNo
, SystemZMC::FP128Regs
, 16);
141 static DecodeStatus
DecodeVR32BitRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
143 const void *Decoder
) {
144 return decodeRegisterClass(Inst
, RegNo
, SystemZMC::VR32Regs
, 32);
147 static DecodeStatus
DecodeVR64BitRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
149 const void *Decoder
) {
150 return decodeRegisterClass(Inst
, RegNo
, SystemZMC::VR64Regs
, 32);
153 static DecodeStatus
DecodeVR128BitRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
155 const void *Decoder
) {
156 return decodeRegisterClass(Inst
, RegNo
, SystemZMC::VR128Regs
, 32);
159 static DecodeStatus
DecodeAR32BitRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
161 const void *Decoder
) {
162 return decodeRegisterClass(Inst
, RegNo
, SystemZMC::AR32Regs
, 16);
165 static DecodeStatus
DecodeCR64BitRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
167 const void *Decoder
) {
168 return decodeRegisterClass(Inst
, RegNo
, SystemZMC::CR64Regs
, 16);
172 static DecodeStatus
decodeUImmOperand(MCInst
&Inst
, uint64_t Imm
) {
174 return MCDisassembler::Fail
;
175 Inst
.addOperand(MCOperand::createImm(Imm
));
176 return MCDisassembler::Success
;
180 static DecodeStatus
decodeSImmOperand(MCInst
&Inst
, uint64_t Imm
) {
182 return MCDisassembler::Fail
;
183 Inst
.addOperand(MCOperand::createImm(SignExtend64
<N
>(Imm
)));
184 return MCDisassembler::Success
;
187 static DecodeStatus
decodeU1ImmOperand(MCInst
&Inst
, uint64_t Imm
,
188 uint64_t Address
, const void *Decoder
) {
189 return decodeUImmOperand
<1>(Inst
, Imm
);
192 static DecodeStatus
decodeU2ImmOperand(MCInst
&Inst
, uint64_t Imm
,
193 uint64_t Address
, const void *Decoder
) {
194 return decodeUImmOperand
<2>(Inst
, Imm
);
197 static DecodeStatus
decodeU3ImmOperand(MCInst
&Inst
, uint64_t Imm
,
198 uint64_t Address
, const void *Decoder
) {
199 return decodeUImmOperand
<3>(Inst
, Imm
);
202 static DecodeStatus
decodeU4ImmOperand(MCInst
&Inst
, uint64_t Imm
,
203 uint64_t Address
, const void *Decoder
) {
204 return decodeUImmOperand
<4>(Inst
, Imm
);
207 static DecodeStatus
decodeU6ImmOperand(MCInst
&Inst
, uint64_t Imm
,
208 uint64_t Address
, const void *Decoder
) {
209 return decodeUImmOperand
<6>(Inst
, Imm
);
212 static DecodeStatus
decodeU8ImmOperand(MCInst
&Inst
, uint64_t Imm
,
213 uint64_t Address
, const void *Decoder
) {
214 return decodeUImmOperand
<8>(Inst
, Imm
);
217 static DecodeStatus
decodeU12ImmOperand(MCInst
&Inst
, uint64_t Imm
,
218 uint64_t Address
, const void *Decoder
) {
219 return decodeUImmOperand
<12>(Inst
, Imm
);
222 static DecodeStatus
decodeU16ImmOperand(MCInst
&Inst
, uint64_t Imm
,
223 uint64_t Address
, const void *Decoder
) {
224 return decodeUImmOperand
<16>(Inst
, Imm
);
227 static DecodeStatus
decodeU32ImmOperand(MCInst
&Inst
, uint64_t Imm
,
228 uint64_t Address
, const void *Decoder
) {
229 return decodeUImmOperand
<32>(Inst
, Imm
);
232 static DecodeStatus
decodeS8ImmOperand(MCInst
&Inst
, uint64_t Imm
,
233 uint64_t Address
, const void *Decoder
) {
234 return decodeSImmOperand
<8>(Inst
, Imm
);
237 static DecodeStatus
decodeS16ImmOperand(MCInst
&Inst
, uint64_t Imm
,
238 uint64_t Address
, const void *Decoder
) {
239 return decodeSImmOperand
<16>(Inst
, Imm
);
242 static DecodeStatus
decodeS32ImmOperand(MCInst
&Inst
, uint64_t Imm
,
243 uint64_t Address
, const void *Decoder
) {
244 return decodeSImmOperand
<32>(Inst
, Imm
);
248 static DecodeStatus
decodePCDBLOperand(MCInst
&Inst
, uint64_t Imm
,
251 const void *Decoder
) {
252 assert(isUInt
<N
>(Imm
) && "Invalid PC-relative offset");
253 uint64_t Value
= SignExtend64
<N
>(Imm
) * 2 + Address
;
255 if (!tryAddingSymbolicOperand(Value
, isBranch
, Address
, 2, N
/ 8,
257 Inst
.addOperand(MCOperand::createImm(Value
));
259 return MCDisassembler::Success
;
262 static DecodeStatus
decodePC12DBLBranchOperand(MCInst
&Inst
, uint64_t Imm
,
264 const void *Decoder
) {
265 return decodePCDBLOperand
<12>(Inst
, Imm
, Address
, true, Decoder
);
268 static DecodeStatus
decodePC16DBLBranchOperand(MCInst
&Inst
, uint64_t Imm
,
270 const void *Decoder
) {
271 return decodePCDBLOperand
<16>(Inst
, Imm
, Address
, true, Decoder
);
274 static DecodeStatus
decodePC24DBLBranchOperand(MCInst
&Inst
, uint64_t Imm
,
276 const void *Decoder
) {
277 return decodePCDBLOperand
<24>(Inst
, Imm
, Address
, true, Decoder
);
280 static DecodeStatus
decodePC32DBLBranchOperand(MCInst
&Inst
, uint64_t Imm
,
282 const void *Decoder
) {
283 return decodePCDBLOperand
<32>(Inst
, Imm
, Address
, true, Decoder
);
286 static DecodeStatus
decodePC32DBLOperand(MCInst
&Inst
, uint64_t Imm
,
288 const void *Decoder
) {
289 return decodePCDBLOperand
<32>(Inst
, Imm
, Address
, false, Decoder
);
292 static DecodeStatus
decodeBDAddr12Operand(MCInst
&Inst
, uint64_t Field
,
293 const unsigned *Regs
) {
294 uint64_t Base
= Field
>> 12;
295 uint64_t Disp
= Field
& 0xfff;
296 assert(Base
< 16 && "Invalid BDAddr12");
297 Inst
.addOperand(MCOperand::createReg(Base
== 0 ? 0 : Regs
[Base
]));
298 Inst
.addOperand(MCOperand::createImm(Disp
));
299 return MCDisassembler::Success
;
302 static DecodeStatus
decodeBDAddr20Operand(MCInst
&Inst
, uint64_t Field
,
303 const unsigned *Regs
) {
304 uint64_t Base
= Field
>> 20;
305 uint64_t Disp
= ((Field
<< 12) & 0xff000) | ((Field
>> 8) & 0xfff);
306 assert(Base
< 16 && "Invalid BDAddr20");
307 Inst
.addOperand(MCOperand::createReg(Base
== 0 ? 0 : Regs
[Base
]));
308 Inst
.addOperand(MCOperand::createImm(SignExtend64
<20>(Disp
)));
309 return MCDisassembler::Success
;
312 static DecodeStatus
decodeBDXAddr12Operand(MCInst
&Inst
, uint64_t Field
,
313 const unsigned *Regs
) {
314 uint64_t Index
= Field
>> 16;
315 uint64_t Base
= (Field
>> 12) & 0xf;
316 uint64_t Disp
= Field
& 0xfff;
317 assert(Index
< 16 && "Invalid BDXAddr12");
318 Inst
.addOperand(MCOperand::createReg(Base
== 0 ? 0 : Regs
[Base
]));
319 Inst
.addOperand(MCOperand::createImm(Disp
));
320 Inst
.addOperand(MCOperand::createReg(Index
== 0 ? 0 : Regs
[Index
]));
321 return MCDisassembler::Success
;
324 static DecodeStatus
decodeBDXAddr20Operand(MCInst
&Inst
, uint64_t Field
,
325 const unsigned *Regs
) {
326 uint64_t Index
= Field
>> 24;
327 uint64_t Base
= (Field
>> 20) & 0xf;
328 uint64_t Disp
= ((Field
& 0xfff00) >> 8) | ((Field
& 0xff) << 12);
329 assert(Index
< 16 && "Invalid BDXAddr20");
330 Inst
.addOperand(MCOperand::createReg(Base
== 0 ? 0 : Regs
[Base
]));
331 Inst
.addOperand(MCOperand::createImm(SignExtend64
<20>(Disp
)));
332 Inst
.addOperand(MCOperand::createReg(Index
== 0 ? 0 : Regs
[Index
]));
333 return MCDisassembler::Success
;
336 static DecodeStatus
decodeBDLAddr12Len4Operand(MCInst
&Inst
, uint64_t Field
,
337 const unsigned *Regs
) {
338 uint64_t Length
= Field
>> 16;
339 uint64_t Base
= (Field
>> 12) & 0xf;
340 uint64_t Disp
= Field
& 0xfff;
341 assert(Length
< 16 && "Invalid BDLAddr12Len4");
342 Inst
.addOperand(MCOperand::createReg(Base
== 0 ? 0 : Regs
[Base
]));
343 Inst
.addOperand(MCOperand::createImm(Disp
));
344 Inst
.addOperand(MCOperand::createImm(Length
+ 1));
345 return MCDisassembler::Success
;
348 static DecodeStatus
decodeBDLAddr12Len8Operand(MCInst
&Inst
, uint64_t Field
,
349 const unsigned *Regs
) {
350 uint64_t Length
= Field
>> 16;
351 uint64_t Base
= (Field
>> 12) & 0xf;
352 uint64_t Disp
= Field
& 0xfff;
353 assert(Length
< 256 && "Invalid BDLAddr12Len8");
354 Inst
.addOperand(MCOperand::createReg(Base
== 0 ? 0 : Regs
[Base
]));
355 Inst
.addOperand(MCOperand::createImm(Disp
));
356 Inst
.addOperand(MCOperand::createImm(Length
+ 1));
357 return MCDisassembler::Success
;
360 static DecodeStatus
decodeBDRAddr12Operand(MCInst
&Inst
, uint64_t Field
,
361 const unsigned *Regs
) {
362 uint64_t Length
= Field
>> 16;
363 uint64_t Base
= (Field
>> 12) & 0xf;
364 uint64_t Disp
= Field
& 0xfff;
365 assert(Length
< 16 && "Invalid BDRAddr12");
366 Inst
.addOperand(MCOperand::createReg(Base
== 0 ? 0 : Regs
[Base
]));
367 Inst
.addOperand(MCOperand::createImm(Disp
));
368 Inst
.addOperand(MCOperand::createReg(Regs
[Length
]));
369 return MCDisassembler::Success
;
372 static DecodeStatus
decodeBDVAddr12Operand(MCInst
&Inst
, uint64_t Field
,
373 const unsigned *Regs
) {
374 uint64_t Index
= Field
>> 16;
375 uint64_t Base
= (Field
>> 12) & 0xf;
376 uint64_t Disp
= Field
& 0xfff;
377 assert(Index
< 32 && "Invalid BDVAddr12");
378 Inst
.addOperand(MCOperand::createReg(Base
== 0 ? 0 : Regs
[Base
]));
379 Inst
.addOperand(MCOperand::createImm(Disp
));
380 Inst
.addOperand(MCOperand::createReg(SystemZMC::VR128Regs
[Index
]));
381 return MCDisassembler::Success
;
384 static DecodeStatus
decodeBDAddr32Disp12Operand(MCInst
&Inst
, uint64_t Field
,
386 const void *Decoder
) {
387 return decodeBDAddr12Operand(Inst
, Field
, SystemZMC::GR32Regs
);
390 static DecodeStatus
decodeBDAddr32Disp20Operand(MCInst
&Inst
, uint64_t Field
,
392 const void *Decoder
) {
393 return decodeBDAddr20Operand(Inst
, Field
, SystemZMC::GR32Regs
);
396 static DecodeStatus
decodeBDAddr64Disp12Operand(MCInst
&Inst
, uint64_t Field
,
398 const void *Decoder
) {
399 return decodeBDAddr12Operand(Inst
, Field
, SystemZMC::GR64Regs
);
402 static DecodeStatus
decodeBDAddr64Disp20Operand(MCInst
&Inst
, uint64_t Field
,
404 const void *Decoder
) {
405 return decodeBDAddr20Operand(Inst
, Field
, SystemZMC::GR64Regs
);
408 static DecodeStatus
decodeBDXAddr64Disp12Operand(MCInst
&Inst
, uint64_t Field
,
410 const void *Decoder
) {
411 return decodeBDXAddr12Operand(Inst
, Field
, SystemZMC::GR64Regs
);
414 static DecodeStatus
decodeBDXAddr64Disp20Operand(MCInst
&Inst
, uint64_t Field
,
416 const void *Decoder
) {
417 return decodeBDXAddr20Operand(Inst
, Field
, SystemZMC::GR64Regs
);
420 static DecodeStatus
decodeBDLAddr64Disp12Len4Operand(MCInst
&Inst
,
423 const void *Decoder
) {
424 return decodeBDLAddr12Len4Operand(Inst
, Field
, SystemZMC::GR64Regs
);
427 static DecodeStatus
decodeBDLAddr64Disp12Len8Operand(MCInst
&Inst
,
430 const void *Decoder
) {
431 return decodeBDLAddr12Len8Operand(Inst
, Field
, SystemZMC::GR64Regs
);
434 static DecodeStatus
decodeBDRAddr64Disp12Operand(MCInst
&Inst
,
437 const void *Decoder
) {
438 return decodeBDRAddr12Operand(Inst
, Field
, SystemZMC::GR64Regs
);
441 static DecodeStatus
decodeBDVAddr64Disp12Operand(MCInst
&Inst
, uint64_t Field
,
443 const void *Decoder
) {
444 return decodeBDVAddr12Operand(Inst
, Field
, SystemZMC::GR64Regs
);
447 #include "SystemZGenDisassemblerTables.inc"
449 DecodeStatus
SystemZDisassembler::getInstruction(MCInst
&MI
, uint64_t &Size
,
450 ArrayRef
<uint8_t> Bytes
,
453 raw_ostream
&CS
) const {
454 // Get the first two bytes of the instruction.
456 if (Bytes
.size() < 2)
457 return MCDisassembler::Fail
;
459 // The top 2 bits of the first byte specify the size.
460 const uint8_t *Table
;
461 if (Bytes
[0] < 0x40) {
463 Table
= DecoderTable16
;
464 } else if (Bytes
[0] < 0xc0) {
466 Table
= DecoderTable32
;
469 Table
= DecoderTable48
;
472 // Read any remaining bytes.
473 if (Bytes
.size() < Size
)
474 return MCDisassembler::Fail
;
476 // Construct the instruction.
478 for (uint64_t I
= 0; I
< Size
; ++I
)
479 Inst
= (Inst
<< 8) | Bytes
[I
];
481 return decodeInstruction(Table
, MI
, Inst
, Address
, this, STI
);