1f8af5cf6SDimitry Andric //===-- SystemZDisassembler.cpp - Disassembler for SystemZ ------*- C++ -*-===//
2f8af5cf6SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f8af5cf6SDimitry Andric //
7f8af5cf6SDimitry Andric //===----------------------------------------------------------------------===//
8f8af5cf6SDimitry Andric
971d5a254SDimitry Andric #include "MCTargetDesc/SystemZMCTargetDesc.h"
10f8af5cf6SDimitry Andric #include "SystemZ.h"
11e6d15924SDimitry Andric #include "TargetInfo/SystemZTargetInfo.h"
12145449b1SDimitry Andric #include "llvm/MC/MCDecoderOps.h"
1301095a5dSDimitry Andric #include "llvm/MC/MCDisassembler/MCDisassembler.h"
14f8af5cf6SDimitry Andric #include "llvm/MC/MCInst.h"
15f8af5cf6SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
16c0981da4SDimitry Andric #include "llvm/MC/TargetRegistry.h"
1771d5a254SDimitry Andric #include "llvm/Support/MathExtras.h"
1871d5a254SDimitry Andric #include <cassert>
1971d5a254SDimitry Andric #include <cstdint>
20f8af5cf6SDimitry Andric
21f8af5cf6SDimitry Andric using namespace llvm;
22f8af5cf6SDimitry Andric
235ca98fd9SDimitry Andric #define DEBUG_TYPE "systemz-disassembler"
245ca98fd9SDimitry Andric
25f8af5cf6SDimitry Andric typedef MCDisassembler::DecodeStatus DecodeStatus;
26f8af5cf6SDimitry Andric
27f8af5cf6SDimitry Andric namespace {
2871d5a254SDimitry Andric
29f8af5cf6SDimitry Andric class SystemZDisassembler : public MCDisassembler {
30f8af5cf6SDimitry Andric public:
SystemZDisassembler(const MCSubtargetInfo & STI,MCContext & Ctx)315ca98fd9SDimitry Andric SystemZDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
325ca98fd9SDimitry Andric : MCDisassembler(STI, Ctx) {}
3371d5a254SDimitry Andric ~SystemZDisassembler() override = default;
34f8af5cf6SDimitry Andric
35b1c73532SDimitry Andric DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
3667c32a98SDimitry Andric ArrayRef<uint8_t> Bytes, uint64_t Address,
3767c32a98SDimitry Andric raw_ostream &CStream) const override;
38f8af5cf6SDimitry Andric };
3971d5a254SDimitry Andric
40f8af5cf6SDimitry Andric } // end anonymous namespace
41f8af5cf6SDimitry Andric
createSystemZDisassembler(const Target & T,const MCSubtargetInfo & STI,MCContext & Ctx)42f8af5cf6SDimitry Andric static MCDisassembler *createSystemZDisassembler(const Target &T,
435ca98fd9SDimitry Andric const MCSubtargetInfo &STI,
445ca98fd9SDimitry Andric MCContext &Ctx) {
455ca98fd9SDimitry Andric return new SystemZDisassembler(STI, Ctx);
46f8af5cf6SDimitry Andric }
47f8af5cf6SDimitry Andric
48b1c73532SDimitry Andric // NOLINTNEXTLINE(readability-identifier-naming)
LLVMInitializeSystemZDisassembler()49706b4fc4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZDisassembler() {
50f8af5cf6SDimitry Andric // Register the disassembler.
51b915e9e0SDimitry Andric TargetRegistry::RegisterMCDisassembler(getTheSystemZTarget(),
52f8af5cf6SDimitry Andric createSystemZDisassembler);
53f8af5cf6SDimitry Andric }
54f8af5cf6SDimitry Andric
5501095a5dSDimitry Andric /// tryAddingSymbolicOperand - trys to add a symbolic operand in place of the
5601095a5dSDimitry Andric /// immediate Value in the MCInst.
5701095a5dSDimitry Andric ///
5801095a5dSDimitry Andric /// @param Value - The immediate Value, has had any PC adjustment made by
5901095a5dSDimitry Andric /// the caller.
6001095a5dSDimitry Andric /// @param isBranch - If the instruction is a branch instruction
6101095a5dSDimitry Andric /// @param Address - The starting address of the instruction
6201095a5dSDimitry Andric /// @param Offset - The byte offset to this immediate in the instruction
6301095a5dSDimitry Andric /// @param Width - The byte width of this immediate in the instruction
6401095a5dSDimitry Andric ///
6501095a5dSDimitry Andric /// If the getOpInfo() function was set when setupForSymbolicDisassembly() was
6601095a5dSDimitry Andric /// called then that function is called to get any symbolic information for the
6701095a5dSDimitry Andric /// immediate in the instruction using the Address, Offset and Width. If that
6801095a5dSDimitry Andric /// returns non-zero then the symbolic information it returns is used to create
6901095a5dSDimitry Andric /// an MCExpr and that is added as an operand to the MCInst. If getOpInfo()
7001095a5dSDimitry Andric /// returns zero and isBranch is true then a symbol look up for immediate Value
7101095a5dSDimitry Andric /// is done and if a symbol is found an MCExpr is created with that, else
7201095a5dSDimitry Andric /// an MCExpr with the immediate Value is created. This function returns true
7301095a5dSDimitry Andric /// 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)74b1c73532SDimitry Andric static bool tryAddingSymbolicOperand(int64_t Value, bool IsBranch,
7501095a5dSDimitry Andric uint64_t Address, uint64_t Offset,
7601095a5dSDimitry Andric uint64_t Width, MCInst &MI,
77145449b1SDimitry Andric const MCDisassembler *Decoder) {
78b1c73532SDimitry Andric return Decoder->tryAddingSymbolicOperand(MI, Value, Address, IsBranch, Offset,
79145449b1SDimitry Andric Width, /*InstSize=*/0);
8001095a5dSDimitry Andric }
8101095a5dSDimitry Andric
decodeRegisterClass(MCInst & Inst,uint64_t RegNo,const unsigned * Regs,unsigned Size,bool IsAddr=false)82f8af5cf6SDimitry Andric static DecodeStatus decodeRegisterClass(MCInst &Inst, uint64_t RegNo,
837fa27ce4SDimitry Andric const unsigned *Regs, unsigned Size,
847fa27ce4SDimitry Andric bool IsAddr = false) {
855a5ac124SDimitry Andric assert(RegNo < Size && "Invalid register");
867fa27ce4SDimitry Andric if (IsAddr && RegNo == 0) {
877fa27ce4SDimitry Andric RegNo = SystemZ::NoRegister;
887fa27ce4SDimitry Andric } else {
89f8af5cf6SDimitry Andric RegNo = Regs[RegNo];
90f8af5cf6SDimitry Andric if (RegNo == 0)
91f8af5cf6SDimitry Andric return MCDisassembler::Fail;
927fa27ce4SDimitry Andric }
935a5ac124SDimitry Andric Inst.addOperand(MCOperand::createReg(RegNo));
94f8af5cf6SDimitry Andric return MCDisassembler::Success;
95f8af5cf6SDimitry Andric }
96f8af5cf6SDimitry Andric
DecodeGR32BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)97f8af5cf6SDimitry Andric static DecodeStatus DecodeGR32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
98f8af5cf6SDimitry Andric uint64_t Address,
99145449b1SDimitry Andric const MCDisassembler *Decoder) {
1005a5ac124SDimitry Andric return decodeRegisterClass(Inst, RegNo, SystemZMC::GR32Regs, 16);
101f8af5cf6SDimitry Andric }
102f8af5cf6SDimitry Andric
DecodeGRH32BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)103f8af5cf6SDimitry Andric static DecodeStatus DecodeGRH32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
104f8af5cf6SDimitry Andric uint64_t Address,
105145449b1SDimitry Andric const MCDisassembler *Decoder) {
1065a5ac124SDimitry Andric return decodeRegisterClass(Inst, RegNo, SystemZMC::GRH32Regs, 16);
107f8af5cf6SDimitry Andric }
108f8af5cf6SDimitry Andric
DecodeGR64BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)109f8af5cf6SDimitry Andric static DecodeStatus DecodeGR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
110f8af5cf6SDimitry Andric uint64_t Address,
111145449b1SDimitry Andric const MCDisassembler *Decoder) {
1125a5ac124SDimitry Andric return decodeRegisterClass(Inst, RegNo, SystemZMC::GR64Regs, 16);
113f8af5cf6SDimitry Andric }
114f8af5cf6SDimitry Andric
DecodeGR128BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)115f8af5cf6SDimitry Andric static DecodeStatus DecodeGR128BitRegisterClass(MCInst &Inst, uint64_t RegNo,
116f8af5cf6SDimitry Andric uint64_t Address,
117145449b1SDimitry Andric const MCDisassembler *Decoder) {
1185a5ac124SDimitry Andric return decodeRegisterClass(Inst, RegNo, SystemZMC::GR128Regs, 16);
119f8af5cf6SDimitry Andric }
120f8af5cf6SDimitry Andric
121145449b1SDimitry Andric static DecodeStatus
DecodeADDR32BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1227fa27ce4SDimitry Andric DecodeADDR32BitRegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address,
1237fa27ce4SDimitry Andric const MCDisassembler *Decoder) {
1247fa27ce4SDimitry Andric return decodeRegisterClass(Inst, RegNo, SystemZMC::GR32Regs, 16, true);
1257fa27ce4SDimitry Andric }
1267fa27ce4SDimitry Andric
1277fa27ce4SDimitry Andric static DecodeStatus
DecodeADDR64BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)128145449b1SDimitry Andric DecodeADDR64BitRegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address,
129145449b1SDimitry Andric const MCDisassembler *Decoder) {
1307fa27ce4SDimitry Andric return decodeRegisterClass(Inst, RegNo, SystemZMC::GR64Regs, 16, true);
131f8af5cf6SDimitry Andric }
132f8af5cf6SDimitry Andric
DecodeFP32BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)133f8af5cf6SDimitry Andric static DecodeStatus DecodeFP32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
134f8af5cf6SDimitry Andric uint64_t Address,
135145449b1SDimitry Andric const MCDisassembler *Decoder) {
1365a5ac124SDimitry Andric return decodeRegisterClass(Inst, RegNo, SystemZMC::FP32Regs, 16);
137f8af5cf6SDimitry Andric }
138f8af5cf6SDimitry Andric
DecodeFP64BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)139f8af5cf6SDimitry Andric static DecodeStatus DecodeFP64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
140f8af5cf6SDimitry Andric uint64_t Address,
141145449b1SDimitry Andric const MCDisassembler *Decoder) {
1425a5ac124SDimitry Andric return decodeRegisterClass(Inst, RegNo, SystemZMC::FP64Regs, 16);
143f8af5cf6SDimitry Andric }
144f8af5cf6SDimitry Andric
DecodeFP128BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)145f8af5cf6SDimitry Andric static DecodeStatus DecodeFP128BitRegisterClass(MCInst &Inst, uint64_t RegNo,
146f8af5cf6SDimitry Andric uint64_t Address,
147145449b1SDimitry Andric const MCDisassembler *Decoder) {
1485a5ac124SDimitry Andric return decodeRegisterClass(Inst, RegNo, SystemZMC::FP128Regs, 16);
1495a5ac124SDimitry Andric }
1505a5ac124SDimitry Andric
DecodeVR32BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1515a5ac124SDimitry Andric static DecodeStatus DecodeVR32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
1525a5ac124SDimitry Andric uint64_t Address,
153145449b1SDimitry Andric const MCDisassembler *Decoder) {
1545a5ac124SDimitry Andric return decodeRegisterClass(Inst, RegNo, SystemZMC::VR32Regs, 32);
1555a5ac124SDimitry Andric }
1565a5ac124SDimitry Andric
DecodeVR64BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1575a5ac124SDimitry Andric static DecodeStatus DecodeVR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
1585a5ac124SDimitry Andric uint64_t Address,
159145449b1SDimitry Andric const MCDisassembler *Decoder) {
1605a5ac124SDimitry Andric return decodeRegisterClass(Inst, RegNo, SystemZMC::VR64Regs, 32);
1615a5ac124SDimitry Andric }
1625a5ac124SDimitry Andric
DecodeVR128BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1635a5ac124SDimitry Andric static DecodeStatus DecodeVR128BitRegisterClass(MCInst &Inst, uint64_t RegNo,
1645a5ac124SDimitry Andric uint64_t Address,
165145449b1SDimitry Andric const MCDisassembler *Decoder) {
1665a5ac124SDimitry Andric return decodeRegisterClass(Inst, RegNo, SystemZMC::VR128Regs, 32);
167f8af5cf6SDimitry Andric }
168f8af5cf6SDimitry Andric
DecodeAR32BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)169b915e9e0SDimitry Andric static DecodeStatus DecodeAR32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
170b915e9e0SDimitry Andric uint64_t Address,
171145449b1SDimitry Andric const MCDisassembler *Decoder) {
172b915e9e0SDimitry Andric return decodeRegisterClass(Inst, RegNo, SystemZMC::AR32Regs, 16);
173b915e9e0SDimitry Andric }
174b915e9e0SDimitry Andric
DecodeCR64BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1759df3605dSDimitry Andric static DecodeStatus DecodeCR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
1769df3605dSDimitry Andric uint64_t Address,
177145449b1SDimitry Andric const MCDisassembler *Decoder) {
1789df3605dSDimitry Andric return decodeRegisterClass(Inst, RegNo, SystemZMC::CR64Regs, 16);
1799df3605dSDimitry Andric }
1809df3605dSDimitry Andric
181f8af5cf6SDimitry Andric template<unsigned N>
decodeUImmOperand(MCInst & Inst,uint64_t Imm)182f8af5cf6SDimitry Andric static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm) {
1835a5ac124SDimitry Andric if (!isUInt<N>(Imm))
1845a5ac124SDimitry Andric return MCDisassembler::Fail;
1855a5ac124SDimitry Andric Inst.addOperand(MCOperand::createImm(Imm));
186f8af5cf6SDimitry Andric return MCDisassembler::Success;
187f8af5cf6SDimitry Andric }
188f8af5cf6SDimitry Andric
189f8af5cf6SDimitry Andric template<unsigned N>
decodeSImmOperand(MCInst & Inst,uint64_t Imm)190f8af5cf6SDimitry Andric static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm) {
1915a5ac124SDimitry Andric if (!isUInt<N>(Imm))
1925a5ac124SDimitry Andric return MCDisassembler::Fail;
1935a5ac124SDimitry Andric Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm)));
194f8af5cf6SDimitry Andric return MCDisassembler::Success;
195f8af5cf6SDimitry Andric }
196f8af5cf6SDimitry Andric
decodeU1ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)1975a5ac124SDimitry Andric static DecodeStatus decodeU1ImmOperand(MCInst &Inst, uint64_t Imm,
198145449b1SDimitry Andric uint64_t Address,
199145449b1SDimitry Andric const MCDisassembler *Decoder) {
2005a5ac124SDimitry Andric return decodeUImmOperand<1>(Inst, Imm);
2015a5ac124SDimitry Andric }
2025a5ac124SDimitry Andric
decodeU2ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)2035a5ac124SDimitry Andric static DecodeStatus decodeU2ImmOperand(MCInst &Inst, uint64_t Imm,
204145449b1SDimitry Andric uint64_t Address,
205145449b1SDimitry Andric const MCDisassembler *Decoder) {
2065a5ac124SDimitry Andric return decodeUImmOperand<2>(Inst, Imm);
2075a5ac124SDimitry Andric }
2085a5ac124SDimitry Andric
decodeU3ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)2095a5ac124SDimitry Andric static DecodeStatus decodeU3ImmOperand(MCInst &Inst, uint64_t Imm,
210145449b1SDimitry Andric uint64_t Address,
211145449b1SDimitry Andric const MCDisassembler *Decoder) {
2125a5ac124SDimitry Andric return decodeUImmOperand<3>(Inst, Imm);
2135a5ac124SDimitry Andric }
2145a5ac124SDimitry Andric
decodeU4ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)215f8af5cf6SDimitry Andric static DecodeStatus decodeU4ImmOperand(MCInst &Inst, uint64_t Imm,
216145449b1SDimitry Andric uint64_t Address,
217145449b1SDimitry Andric const MCDisassembler *Decoder) {
218f8af5cf6SDimitry Andric return decodeUImmOperand<4>(Inst, Imm);
219f8af5cf6SDimitry Andric }
220f8af5cf6SDimitry Andric
decodeU8ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)221f8af5cf6SDimitry Andric static DecodeStatus decodeU8ImmOperand(MCInst &Inst, uint64_t Imm,
222145449b1SDimitry Andric uint64_t Address,
223145449b1SDimitry Andric const MCDisassembler *Decoder) {
224f8af5cf6SDimitry Andric return decodeUImmOperand<8>(Inst, Imm);
225f8af5cf6SDimitry Andric }
226f8af5cf6SDimitry Andric
decodeU12ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)2275a5ac124SDimitry Andric static DecodeStatus decodeU12ImmOperand(MCInst &Inst, uint64_t Imm,
228145449b1SDimitry Andric uint64_t Address,
229145449b1SDimitry Andric const MCDisassembler *Decoder) {
2305a5ac124SDimitry Andric return decodeUImmOperand<12>(Inst, Imm);
2315a5ac124SDimitry Andric }
2325a5ac124SDimitry Andric
decodeU16ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)233f8af5cf6SDimitry Andric static DecodeStatus decodeU16ImmOperand(MCInst &Inst, uint64_t Imm,
234145449b1SDimitry Andric uint64_t Address,
235145449b1SDimitry Andric const MCDisassembler *Decoder) {
236f8af5cf6SDimitry Andric return decodeUImmOperand<16>(Inst, Imm);
237f8af5cf6SDimitry Andric }
238f8af5cf6SDimitry Andric
decodeU32ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)239f8af5cf6SDimitry Andric static DecodeStatus decodeU32ImmOperand(MCInst &Inst, uint64_t Imm,
240145449b1SDimitry Andric uint64_t Address,
241145449b1SDimitry Andric const MCDisassembler *Decoder) {
242f8af5cf6SDimitry Andric return decodeUImmOperand<32>(Inst, Imm);
243f8af5cf6SDimitry Andric }
244f8af5cf6SDimitry Andric
decodeS8ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)245f8af5cf6SDimitry Andric static DecodeStatus decodeS8ImmOperand(MCInst &Inst, uint64_t Imm,
246145449b1SDimitry Andric uint64_t Address,
247145449b1SDimitry Andric const MCDisassembler *Decoder) {
248f8af5cf6SDimitry Andric return decodeSImmOperand<8>(Inst, Imm);
249f8af5cf6SDimitry Andric }
250f8af5cf6SDimitry Andric
decodeS16ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)251f8af5cf6SDimitry Andric static DecodeStatus decodeS16ImmOperand(MCInst &Inst, uint64_t Imm,
252145449b1SDimitry Andric uint64_t Address,
253145449b1SDimitry Andric const MCDisassembler *Decoder) {
254f8af5cf6SDimitry Andric return decodeSImmOperand<16>(Inst, Imm);
255f8af5cf6SDimitry Andric }
256f8af5cf6SDimitry Andric
decodeS20ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)2577fa27ce4SDimitry Andric static DecodeStatus decodeS20ImmOperand(MCInst &Inst, uint64_t Imm,
2587fa27ce4SDimitry Andric uint64_t Address,
2597fa27ce4SDimitry Andric const MCDisassembler *Decoder) {
2607fa27ce4SDimitry Andric return decodeSImmOperand<20>(Inst, Imm);
2617fa27ce4SDimitry Andric }
2627fa27ce4SDimitry Andric
decodeS32ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)263f8af5cf6SDimitry Andric static DecodeStatus decodeS32ImmOperand(MCInst &Inst, uint64_t Imm,
264145449b1SDimitry Andric uint64_t Address,
265145449b1SDimitry Andric const MCDisassembler *Decoder) {
266f8af5cf6SDimitry Andric return decodeSImmOperand<32>(Inst, Imm);
267f8af5cf6SDimitry Andric }
268f8af5cf6SDimitry Andric
269f8af5cf6SDimitry Andric template <unsigned N>
decodeLenOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)2707fa27ce4SDimitry Andric static DecodeStatus decodeLenOperand(MCInst &Inst, uint64_t Imm,
2717fa27ce4SDimitry Andric uint64_t Address,
2727fa27ce4SDimitry Andric const MCDisassembler *Decoder) {
2737fa27ce4SDimitry Andric if (!isUInt<N>(Imm))
2747fa27ce4SDimitry Andric return MCDisassembler::Fail;
2757fa27ce4SDimitry Andric Inst.addOperand(MCOperand::createImm(Imm + 1));
2767fa27ce4SDimitry Andric return MCDisassembler::Success;
2777fa27ce4SDimitry Andric }
2787fa27ce4SDimitry Andric
2797fa27ce4SDimitry Andric template <unsigned N>
decodePCDBLOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,bool isBranch,const MCDisassembler * Decoder)280f8af5cf6SDimitry Andric static DecodeStatus decodePCDBLOperand(MCInst &Inst, uint64_t Imm,
281145449b1SDimitry Andric uint64_t Address, bool isBranch,
282145449b1SDimitry Andric const MCDisassembler *Decoder) {
283f8af5cf6SDimitry Andric assert(isUInt<N>(Imm) && "Invalid PC-relative offset");
28401095a5dSDimitry Andric uint64_t Value = SignExtend64<N>(Imm) * 2 + Address;
28501095a5dSDimitry Andric
28601095a5dSDimitry Andric if (!tryAddingSymbolicOperand(Value, isBranch, Address, 2, N / 8,
28701095a5dSDimitry Andric Inst, Decoder))
28801095a5dSDimitry Andric Inst.addOperand(MCOperand::createImm(Value));
28901095a5dSDimitry Andric
290f8af5cf6SDimitry Andric return MCDisassembler::Success;
291f8af5cf6SDimitry Andric }
292f8af5cf6SDimitry Andric
decodePC12DBLBranchOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)293b915e9e0SDimitry Andric static DecodeStatus decodePC12DBLBranchOperand(MCInst &Inst, uint64_t Imm,
294b915e9e0SDimitry Andric uint64_t Address,
295145449b1SDimitry Andric const MCDisassembler *Decoder) {
296b915e9e0SDimitry Andric return decodePCDBLOperand<12>(Inst, Imm, Address, true, Decoder);
297b915e9e0SDimitry Andric }
298b915e9e0SDimitry Andric
decodePC16DBLBranchOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)29901095a5dSDimitry Andric static DecodeStatus decodePC16DBLBranchOperand(MCInst &Inst, uint64_t Imm,
300f8af5cf6SDimitry Andric uint64_t Address,
301145449b1SDimitry Andric const MCDisassembler *Decoder) {
30201095a5dSDimitry Andric return decodePCDBLOperand<16>(Inst, Imm, Address, true, Decoder);
30301095a5dSDimitry Andric }
30401095a5dSDimitry Andric
decodePC24DBLBranchOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)305b915e9e0SDimitry Andric static DecodeStatus decodePC24DBLBranchOperand(MCInst &Inst, uint64_t Imm,
306b915e9e0SDimitry Andric uint64_t Address,
307145449b1SDimitry Andric const MCDisassembler *Decoder) {
308b915e9e0SDimitry Andric return decodePCDBLOperand<24>(Inst, Imm, Address, true, Decoder);
309b915e9e0SDimitry Andric }
310b915e9e0SDimitry Andric
decodePC32DBLBranchOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)31101095a5dSDimitry Andric static DecodeStatus decodePC32DBLBranchOperand(MCInst &Inst, uint64_t Imm,
31201095a5dSDimitry Andric uint64_t Address,
313145449b1SDimitry Andric const MCDisassembler *Decoder) {
31401095a5dSDimitry Andric return decodePCDBLOperand<32>(Inst, Imm, Address, true, Decoder);
315f8af5cf6SDimitry Andric }
316f8af5cf6SDimitry Andric
decodePC32DBLOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const MCDisassembler * Decoder)317f8af5cf6SDimitry Andric static DecodeStatus decodePC32DBLOperand(MCInst &Inst, uint64_t Imm,
318f8af5cf6SDimitry Andric uint64_t Address,
319145449b1SDimitry Andric const MCDisassembler *Decoder) {
32001095a5dSDimitry Andric return decodePCDBLOperand<32>(Inst, Imm, Address, false, Decoder);
321f8af5cf6SDimitry Andric }
322f8af5cf6SDimitry Andric
323f8af5cf6SDimitry Andric #include "SystemZGenDisassemblerTables.inc"
324f8af5cf6SDimitry Andric
getInstruction(MCInst & MI,uint64_t & Size,ArrayRef<uint8_t> Bytes,uint64_t Address,raw_ostream & CS) const325f8af5cf6SDimitry Andric DecodeStatus SystemZDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
32667c32a98SDimitry Andric ArrayRef<uint8_t> Bytes,
327f8af5cf6SDimitry Andric uint64_t Address,
32867c32a98SDimitry Andric raw_ostream &CS) const {
329f8af5cf6SDimitry Andric // Get the first two bytes of the instruction.
330f8af5cf6SDimitry Andric Size = 0;
33167c32a98SDimitry Andric if (Bytes.size() < 2)
332f8af5cf6SDimitry Andric return MCDisassembler::Fail;
333f8af5cf6SDimitry Andric
334f8af5cf6SDimitry Andric // The top 2 bits of the first byte specify the size.
335f8af5cf6SDimitry Andric const uint8_t *Table;
336f8af5cf6SDimitry Andric if (Bytes[0] < 0x40) {
337f8af5cf6SDimitry Andric Size = 2;
338f8af5cf6SDimitry Andric Table = DecoderTable16;
339f8af5cf6SDimitry Andric } else if (Bytes[0] < 0xc0) {
340f8af5cf6SDimitry Andric Size = 4;
341f8af5cf6SDimitry Andric Table = DecoderTable32;
342f8af5cf6SDimitry Andric } else {
343f8af5cf6SDimitry Andric Size = 6;
344f8af5cf6SDimitry Andric Table = DecoderTable48;
345f8af5cf6SDimitry Andric }
346f8af5cf6SDimitry Andric
347f8af5cf6SDimitry Andric // Read any remaining bytes.
348b60736ecSDimitry Andric if (Bytes.size() < Size) {
349b60736ecSDimitry Andric Size = Bytes.size();
350f8af5cf6SDimitry Andric return MCDisassembler::Fail;
351b60736ecSDimitry Andric }
352f8af5cf6SDimitry Andric
353f8af5cf6SDimitry Andric // Construct the instruction.
354f8af5cf6SDimitry Andric uint64_t Inst = 0;
355f8af5cf6SDimitry Andric for (uint64_t I = 0; I < Size; ++I)
356f8af5cf6SDimitry Andric Inst = (Inst << 8) | Bytes[I];
357f8af5cf6SDimitry Andric
358f8af5cf6SDimitry Andric return decodeInstruction(Table, MI, Inst, Address, this, STI);
359f8af5cf6SDimitry Andric }
360