10b57cec5SDimitry Andric //===-- SystemZDisassembler.cpp - Disassembler for SystemZ ------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "MCTargetDesc/SystemZMCTargetDesc.h"
100b57cec5SDimitry Andric #include "SystemZ.h"
110b57cec5SDimitry Andric #include "TargetInfo/SystemZTargetInfo.h"
120b57cec5SDimitry Andric #include "llvm/MC/MCDisassembler/MCDisassembler.h"
130b57cec5SDimitry Andric #include "llvm/MC/MCFixedLenDisassembler.h"
140b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
150b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
160b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
170b57cec5SDimitry Andric #include "llvm/Support/TargetRegistry.h"
180b57cec5SDimitry Andric #include <cassert>
190b57cec5SDimitry Andric #include <cstdint>
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric using namespace llvm;
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric #define DEBUG_TYPE "systemz-disassembler"
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric typedef MCDisassembler::DecodeStatus DecodeStatus;
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric namespace {
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric class SystemZDisassembler : public MCDisassembler {
300b57cec5SDimitry Andric public:
SystemZDisassembler(const MCSubtargetInfo & STI,MCContext & Ctx)310b57cec5SDimitry Andric   SystemZDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
320b57cec5SDimitry Andric     : MCDisassembler(STI, Ctx) {}
330b57cec5SDimitry Andric   ~SystemZDisassembler() override = default;
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric   DecodeStatus getInstruction(MCInst &instr, uint64_t &Size,
360b57cec5SDimitry Andric                               ArrayRef<uint8_t> Bytes, uint64_t Address,
370b57cec5SDimitry Andric                               raw_ostream &CStream) const override;
380b57cec5SDimitry Andric };
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric } // end anonymous namespace
410b57cec5SDimitry Andric 
createSystemZDisassembler(const Target & T,const MCSubtargetInfo & STI,MCContext & Ctx)420b57cec5SDimitry Andric static MCDisassembler *createSystemZDisassembler(const Target &T,
430b57cec5SDimitry Andric                                                  const MCSubtargetInfo &STI,
440b57cec5SDimitry Andric                                                  MCContext &Ctx) {
450b57cec5SDimitry Andric   return new SystemZDisassembler(STI, Ctx);
460b57cec5SDimitry Andric }
470b57cec5SDimitry Andric 
LLVMInitializeSystemZDisassembler()48480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZDisassembler() {
490b57cec5SDimitry Andric   // Register the disassembler.
500b57cec5SDimitry Andric   TargetRegistry::RegisterMCDisassembler(getTheSystemZTarget(),
510b57cec5SDimitry Andric                                          createSystemZDisassembler);
520b57cec5SDimitry Andric }
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric /// tryAddingSymbolicOperand - trys to add a symbolic operand in place of the
550b57cec5SDimitry Andric /// immediate Value in the MCInst.
560b57cec5SDimitry Andric ///
570b57cec5SDimitry Andric /// @param Value      - The immediate Value, has had any PC adjustment made by
580b57cec5SDimitry Andric ///                     the caller.
590b57cec5SDimitry Andric /// @param isBranch   - If the instruction is a branch instruction
600b57cec5SDimitry Andric /// @param Address    - The starting address of the instruction
610b57cec5SDimitry Andric /// @param Offset     - The byte offset to this immediate in the instruction
620b57cec5SDimitry Andric /// @param Width      - The byte width of this immediate in the instruction
630b57cec5SDimitry Andric ///
640b57cec5SDimitry Andric /// If the getOpInfo() function was set when setupForSymbolicDisassembly() was
650b57cec5SDimitry Andric /// called then that function is called to get any symbolic information for the
660b57cec5SDimitry Andric /// immediate in the instruction using the Address, Offset and Width.  If that
670b57cec5SDimitry Andric /// returns non-zero then the symbolic information it returns is used to create
680b57cec5SDimitry Andric /// an MCExpr and that is added as an operand to the MCInst.  If getOpInfo()
690b57cec5SDimitry Andric /// returns zero and isBranch is true then a symbol look up for immediate Value
700b57cec5SDimitry Andric /// is done and if a symbol is found an MCExpr is created with that, else
710b57cec5SDimitry Andric /// an MCExpr with the immediate Value is created.  This function returns true
720b57cec5SDimitry 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 void * Decoder)730b57cec5SDimitry Andric static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch,
740b57cec5SDimitry Andric                                      uint64_t Address, uint64_t Offset,
750b57cec5SDimitry Andric                                      uint64_t Width, MCInst &MI,
760b57cec5SDimitry Andric                                      const void *Decoder) {
770b57cec5SDimitry Andric   const MCDisassembler *Dis = static_cast<const MCDisassembler*>(Decoder);
780b57cec5SDimitry Andric   return Dis->tryAddingSymbolicOperand(MI, Value, Address, isBranch,
790b57cec5SDimitry Andric                                        Offset, Width);
800b57cec5SDimitry Andric }
810b57cec5SDimitry Andric 
decodeRegisterClass(MCInst & Inst,uint64_t RegNo,const unsigned * Regs,unsigned Size)820b57cec5SDimitry Andric static DecodeStatus decodeRegisterClass(MCInst &Inst, uint64_t RegNo,
830b57cec5SDimitry Andric                                         const unsigned *Regs, unsigned Size) {
840b57cec5SDimitry Andric   assert(RegNo < Size && "Invalid register");
850b57cec5SDimitry Andric   RegNo = Regs[RegNo];
860b57cec5SDimitry Andric   if (RegNo == 0)
870b57cec5SDimitry Andric     return MCDisassembler::Fail;
880b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createReg(RegNo));
890b57cec5SDimitry Andric   return MCDisassembler::Success;
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric 
DecodeGR32BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)920b57cec5SDimitry Andric static DecodeStatus DecodeGR32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
930b57cec5SDimitry Andric                                                uint64_t Address,
940b57cec5SDimitry Andric                                                const void *Decoder) {
950b57cec5SDimitry Andric   return decodeRegisterClass(Inst, RegNo, SystemZMC::GR32Regs, 16);
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric 
DecodeGRH32BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)980b57cec5SDimitry Andric static DecodeStatus DecodeGRH32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
990b57cec5SDimitry Andric                                                 uint64_t Address,
1000b57cec5SDimitry Andric                                                 const void *Decoder) {
1010b57cec5SDimitry Andric   return decodeRegisterClass(Inst, RegNo, SystemZMC::GRH32Regs, 16);
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric 
DecodeGR64BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)1040b57cec5SDimitry Andric static DecodeStatus DecodeGR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
1050b57cec5SDimitry Andric                                                uint64_t Address,
1060b57cec5SDimitry Andric                                                const void *Decoder) {
1070b57cec5SDimitry Andric   return decodeRegisterClass(Inst, RegNo, SystemZMC::GR64Regs, 16);
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric 
DecodeGR128BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)1100b57cec5SDimitry Andric static DecodeStatus DecodeGR128BitRegisterClass(MCInst &Inst, uint64_t RegNo,
1110b57cec5SDimitry Andric                                                 uint64_t Address,
1120b57cec5SDimitry Andric                                                 const void *Decoder) {
1130b57cec5SDimitry Andric   return decodeRegisterClass(Inst, RegNo, SystemZMC::GR128Regs, 16);
1140b57cec5SDimitry Andric }
1150b57cec5SDimitry Andric 
DecodeADDR64BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)1160b57cec5SDimitry Andric static DecodeStatus DecodeADDR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
1170b57cec5SDimitry Andric                                                  uint64_t Address,
1180b57cec5SDimitry Andric                                                  const void *Decoder) {
1190b57cec5SDimitry Andric   return decodeRegisterClass(Inst, RegNo, SystemZMC::GR64Regs, 16);
1200b57cec5SDimitry Andric }
1210b57cec5SDimitry Andric 
DecodeFP32BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)1220b57cec5SDimitry Andric static DecodeStatus DecodeFP32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
1230b57cec5SDimitry Andric                                                uint64_t Address,
1240b57cec5SDimitry Andric                                                const void *Decoder) {
1250b57cec5SDimitry Andric   return decodeRegisterClass(Inst, RegNo, SystemZMC::FP32Regs, 16);
1260b57cec5SDimitry Andric }
1270b57cec5SDimitry Andric 
DecodeFP64BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)1280b57cec5SDimitry Andric static DecodeStatus DecodeFP64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
1290b57cec5SDimitry Andric                                                uint64_t Address,
1300b57cec5SDimitry Andric                                                const void *Decoder) {
1310b57cec5SDimitry Andric   return decodeRegisterClass(Inst, RegNo, SystemZMC::FP64Regs, 16);
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric 
DecodeFP128BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)1340b57cec5SDimitry Andric static DecodeStatus DecodeFP128BitRegisterClass(MCInst &Inst, uint64_t RegNo,
1350b57cec5SDimitry Andric                                                 uint64_t Address,
1360b57cec5SDimitry Andric                                                 const void *Decoder) {
1370b57cec5SDimitry Andric   return decodeRegisterClass(Inst, RegNo, SystemZMC::FP128Regs, 16);
1380b57cec5SDimitry Andric }
1390b57cec5SDimitry Andric 
DecodeVR32BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)1400b57cec5SDimitry Andric static DecodeStatus DecodeVR32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
1410b57cec5SDimitry Andric                                                uint64_t Address,
1420b57cec5SDimitry Andric                                                const void *Decoder) {
1430b57cec5SDimitry Andric   return decodeRegisterClass(Inst, RegNo, SystemZMC::VR32Regs, 32);
1440b57cec5SDimitry Andric }
1450b57cec5SDimitry Andric 
DecodeVR64BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)1460b57cec5SDimitry Andric static DecodeStatus DecodeVR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
1470b57cec5SDimitry Andric                                                uint64_t Address,
1480b57cec5SDimitry Andric                                                const void *Decoder) {
1490b57cec5SDimitry Andric   return decodeRegisterClass(Inst, RegNo, SystemZMC::VR64Regs, 32);
1500b57cec5SDimitry Andric }
1510b57cec5SDimitry Andric 
DecodeVR128BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)1520b57cec5SDimitry Andric static DecodeStatus DecodeVR128BitRegisterClass(MCInst &Inst, uint64_t RegNo,
1530b57cec5SDimitry Andric                                                 uint64_t Address,
1540b57cec5SDimitry Andric                                                 const void *Decoder) {
1550b57cec5SDimitry Andric   return decodeRegisterClass(Inst, RegNo, SystemZMC::VR128Regs, 32);
1560b57cec5SDimitry Andric }
1570b57cec5SDimitry Andric 
DecodeAR32BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)1580b57cec5SDimitry Andric static DecodeStatus DecodeAR32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
1590b57cec5SDimitry Andric                                                uint64_t Address,
1600b57cec5SDimitry Andric                                                const void *Decoder) {
1610b57cec5SDimitry Andric   return decodeRegisterClass(Inst, RegNo, SystemZMC::AR32Regs, 16);
1620b57cec5SDimitry Andric }
1630b57cec5SDimitry Andric 
DecodeCR64BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)1640b57cec5SDimitry Andric static DecodeStatus DecodeCR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
1650b57cec5SDimitry Andric                                                uint64_t Address,
1660b57cec5SDimitry Andric                                                const void *Decoder) {
1670b57cec5SDimitry Andric   return decodeRegisterClass(Inst, RegNo, SystemZMC::CR64Regs, 16);
1680b57cec5SDimitry Andric }
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric template<unsigned N>
decodeUImmOperand(MCInst & Inst,uint64_t Imm)1710b57cec5SDimitry Andric static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm) {
1720b57cec5SDimitry Andric   if (!isUInt<N>(Imm))
1730b57cec5SDimitry Andric     return MCDisassembler::Fail;
1740b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createImm(Imm));
1750b57cec5SDimitry Andric   return MCDisassembler::Success;
1760b57cec5SDimitry Andric }
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric template<unsigned N>
decodeSImmOperand(MCInst & Inst,uint64_t Imm)1790b57cec5SDimitry Andric static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm) {
1800b57cec5SDimitry Andric   if (!isUInt<N>(Imm))
1810b57cec5SDimitry Andric     return MCDisassembler::Fail;
1820b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm)));
1830b57cec5SDimitry Andric   return MCDisassembler::Success;
1840b57cec5SDimitry Andric }
1850b57cec5SDimitry Andric 
decodeU1ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)1860b57cec5SDimitry Andric static DecodeStatus decodeU1ImmOperand(MCInst &Inst, uint64_t Imm,
1870b57cec5SDimitry Andric                                        uint64_t Address, const void *Decoder) {
1880b57cec5SDimitry Andric   return decodeUImmOperand<1>(Inst, Imm);
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric 
decodeU2ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)1910b57cec5SDimitry Andric static DecodeStatus decodeU2ImmOperand(MCInst &Inst, uint64_t Imm,
1920b57cec5SDimitry Andric                                        uint64_t Address, const void *Decoder) {
1930b57cec5SDimitry Andric   return decodeUImmOperand<2>(Inst, Imm);
1940b57cec5SDimitry Andric }
1950b57cec5SDimitry Andric 
decodeU3ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)1960b57cec5SDimitry Andric static DecodeStatus decodeU3ImmOperand(MCInst &Inst, uint64_t Imm,
1970b57cec5SDimitry Andric                                        uint64_t Address, const void *Decoder) {
1980b57cec5SDimitry Andric   return decodeUImmOperand<3>(Inst, Imm);
1990b57cec5SDimitry Andric }
2000b57cec5SDimitry Andric 
decodeU4ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)2010b57cec5SDimitry Andric static DecodeStatus decodeU4ImmOperand(MCInst &Inst, uint64_t Imm,
2020b57cec5SDimitry Andric                                        uint64_t Address, const void *Decoder) {
2030b57cec5SDimitry Andric   return decodeUImmOperand<4>(Inst, Imm);
2040b57cec5SDimitry Andric }
2050b57cec5SDimitry Andric 
decodeU6ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)2060b57cec5SDimitry Andric static DecodeStatus decodeU6ImmOperand(MCInst &Inst, uint64_t Imm,
2070b57cec5SDimitry Andric                                        uint64_t Address, const void *Decoder) {
2080b57cec5SDimitry Andric   return decodeUImmOperand<6>(Inst, Imm);
2090b57cec5SDimitry Andric }
2100b57cec5SDimitry Andric 
decodeU8ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)2110b57cec5SDimitry Andric static DecodeStatus decodeU8ImmOperand(MCInst &Inst, uint64_t Imm,
2120b57cec5SDimitry Andric                                        uint64_t Address, const void *Decoder) {
2130b57cec5SDimitry Andric   return decodeUImmOperand<8>(Inst, Imm);
2140b57cec5SDimitry Andric }
2150b57cec5SDimitry Andric 
decodeU12ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)2160b57cec5SDimitry Andric static DecodeStatus decodeU12ImmOperand(MCInst &Inst, uint64_t Imm,
2170b57cec5SDimitry Andric                                         uint64_t Address, const void *Decoder) {
2180b57cec5SDimitry Andric   return decodeUImmOperand<12>(Inst, Imm);
2190b57cec5SDimitry Andric }
2200b57cec5SDimitry Andric 
decodeU16ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)2210b57cec5SDimitry Andric static DecodeStatus decodeU16ImmOperand(MCInst &Inst, uint64_t Imm,
2220b57cec5SDimitry Andric                                         uint64_t Address, const void *Decoder) {
2230b57cec5SDimitry Andric   return decodeUImmOperand<16>(Inst, Imm);
2240b57cec5SDimitry Andric }
2250b57cec5SDimitry Andric 
decodeU32ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)2260b57cec5SDimitry Andric static DecodeStatus decodeU32ImmOperand(MCInst &Inst, uint64_t Imm,
2270b57cec5SDimitry Andric                                         uint64_t Address, const void *Decoder) {
2280b57cec5SDimitry Andric   return decodeUImmOperand<32>(Inst, Imm);
2290b57cec5SDimitry Andric }
2300b57cec5SDimitry Andric 
decodeS8ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)2310b57cec5SDimitry Andric static DecodeStatus decodeS8ImmOperand(MCInst &Inst, uint64_t Imm,
2320b57cec5SDimitry Andric                                        uint64_t Address, const void *Decoder) {
2330b57cec5SDimitry Andric   return decodeSImmOperand<8>(Inst, Imm);
2340b57cec5SDimitry Andric }
2350b57cec5SDimitry Andric 
decodeS16ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)2360b57cec5SDimitry Andric static DecodeStatus decodeS16ImmOperand(MCInst &Inst, uint64_t Imm,
2370b57cec5SDimitry Andric                                         uint64_t Address, const void *Decoder) {
2380b57cec5SDimitry Andric   return decodeSImmOperand<16>(Inst, Imm);
2390b57cec5SDimitry Andric }
2400b57cec5SDimitry Andric 
decodeS32ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)2410b57cec5SDimitry Andric static DecodeStatus decodeS32ImmOperand(MCInst &Inst, uint64_t Imm,
2420b57cec5SDimitry Andric                                         uint64_t Address, const void *Decoder) {
2430b57cec5SDimitry Andric   return decodeSImmOperand<32>(Inst, Imm);
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric template<unsigned N>
decodePCDBLOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,bool isBranch,const void * Decoder)2470b57cec5SDimitry Andric static DecodeStatus decodePCDBLOperand(MCInst &Inst, uint64_t Imm,
2480b57cec5SDimitry Andric                                        uint64_t Address,
2490b57cec5SDimitry Andric                                        bool isBranch,
2500b57cec5SDimitry Andric                                        const void *Decoder) {
2510b57cec5SDimitry Andric   assert(isUInt<N>(Imm) && "Invalid PC-relative offset");
2520b57cec5SDimitry Andric   uint64_t Value = SignExtend64<N>(Imm) * 2 + Address;
2530b57cec5SDimitry Andric 
2540b57cec5SDimitry Andric   if (!tryAddingSymbolicOperand(Value, isBranch, Address, 2, N / 8,
2550b57cec5SDimitry Andric                                 Inst, Decoder))
2560b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createImm(Value));
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric   return MCDisassembler::Success;
2590b57cec5SDimitry Andric }
2600b57cec5SDimitry Andric 
decodePC12DBLBranchOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)2610b57cec5SDimitry Andric static DecodeStatus decodePC12DBLBranchOperand(MCInst &Inst, uint64_t Imm,
2620b57cec5SDimitry Andric                                                uint64_t Address,
2630b57cec5SDimitry Andric                                                const void *Decoder) {
2640b57cec5SDimitry Andric   return decodePCDBLOperand<12>(Inst, Imm, Address, true, Decoder);
2650b57cec5SDimitry Andric }
2660b57cec5SDimitry Andric 
decodePC16DBLBranchOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)2670b57cec5SDimitry Andric static DecodeStatus decodePC16DBLBranchOperand(MCInst &Inst, uint64_t Imm,
2680b57cec5SDimitry Andric                                                uint64_t Address,
2690b57cec5SDimitry Andric                                                const void *Decoder) {
2700b57cec5SDimitry Andric   return decodePCDBLOperand<16>(Inst, Imm, Address, true, Decoder);
2710b57cec5SDimitry Andric }
2720b57cec5SDimitry Andric 
decodePC24DBLBranchOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)2730b57cec5SDimitry Andric static DecodeStatus decodePC24DBLBranchOperand(MCInst &Inst, uint64_t Imm,
2740b57cec5SDimitry Andric                                                uint64_t Address,
2750b57cec5SDimitry Andric                                                const void *Decoder) {
2760b57cec5SDimitry Andric   return decodePCDBLOperand<24>(Inst, Imm, Address, true, Decoder);
2770b57cec5SDimitry Andric }
2780b57cec5SDimitry Andric 
decodePC32DBLBranchOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)2790b57cec5SDimitry Andric static DecodeStatus decodePC32DBLBranchOperand(MCInst &Inst, uint64_t Imm,
2800b57cec5SDimitry Andric                                                uint64_t Address,
2810b57cec5SDimitry Andric                                                const void *Decoder) {
2820b57cec5SDimitry Andric   return decodePCDBLOperand<32>(Inst, Imm, Address, true, Decoder);
2830b57cec5SDimitry Andric }
2840b57cec5SDimitry Andric 
decodePC32DBLOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)2850b57cec5SDimitry Andric static DecodeStatus decodePC32DBLOperand(MCInst &Inst, uint64_t Imm,
2860b57cec5SDimitry Andric                                          uint64_t Address,
2870b57cec5SDimitry Andric                                          const void *Decoder) {
2880b57cec5SDimitry Andric   return decodePCDBLOperand<32>(Inst, Imm, Address, false, Decoder);
2890b57cec5SDimitry Andric }
2900b57cec5SDimitry Andric 
decodeBDAddr12Operand(MCInst & Inst,uint64_t Field,const unsigned * Regs)2910b57cec5SDimitry Andric static DecodeStatus decodeBDAddr12Operand(MCInst &Inst, uint64_t Field,
2920b57cec5SDimitry Andric                                           const unsigned *Regs) {
2930b57cec5SDimitry Andric   uint64_t Base = Field >> 12;
2940b57cec5SDimitry Andric   uint64_t Disp = Field & 0xfff;
2950b57cec5SDimitry Andric   assert(Base < 16 && "Invalid BDAddr12");
2960b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createReg(Base == 0 ? 0 : Regs[Base]));
2970b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createImm(Disp));
2980b57cec5SDimitry Andric   return MCDisassembler::Success;
2990b57cec5SDimitry Andric }
3000b57cec5SDimitry Andric 
decodeBDAddr20Operand(MCInst & Inst,uint64_t Field,const unsigned * Regs)3010b57cec5SDimitry Andric static DecodeStatus decodeBDAddr20Operand(MCInst &Inst, uint64_t Field,
3020b57cec5SDimitry Andric                                           const unsigned *Regs) {
3030b57cec5SDimitry Andric   uint64_t Base = Field >> 20;
3040b57cec5SDimitry Andric   uint64_t Disp = ((Field << 12) & 0xff000) | ((Field >> 8) & 0xfff);
3050b57cec5SDimitry Andric   assert(Base < 16 && "Invalid BDAddr20");
3060b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createReg(Base == 0 ? 0 : Regs[Base]));
3070b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createImm(SignExtend64<20>(Disp)));
3080b57cec5SDimitry Andric   return MCDisassembler::Success;
3090b57cec5SDimitry Andric }
3100b57cec5SDimitry Andric 
decodeBDXAddr12Operand(MCInst & Inst,uint64_t Field,const unsigned * Regs)3110b57cec5SDimitry Andric static DecodeStatus decodeBDXAddr12Operand(MCInst &Inst, uint64_t Field,
3120b57cec5SDimitry Andric                                            const unsigned *Regs) {
3130b57cec5SDimitry Andric   uint64_t Index = Field >> 16;
3140b57cec5SDimitry Andric   uint64_t Base = (Field >> 12) & 0xf;
3150b57cec5SDimitry Andric   uint64_t Disp = Field & 0xfff;
3160b57cec5SDimitry Andric   assert(Index < 16 && "Invalid BDXAddr12");
3170b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createReg(Base == 0 ? 0 : Regs[Base]));
3180b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createImm(Disp));
3190b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createReg(Index == 0 ? 0 : Regs[Index]));
3200b57cec5SDimitry Andric   return MCDisassembler::Success;
3210b57cec5SDimitry Andric }
3220b57cec5SDimitry Andric 
decodeBDXAddr20Operand(MCInst & Inst,uint64_t Field,const unsigned * Regs)3230b57cec5SDimitry Andric static DecodeStatus decodeBDXAddr20Operand(MCInst &Inst, uint64_t Field,
3240b57cec5SDimitry Andric                                            const unsigned *Regs) {
3250b57cec5SDimitry Andric   uint64_t Index = Field >> 24;
3260b57cec5SDimitry Andric   uint64_t Base = (Field >> 20) & 0xf;
3270b57cec5SDimitry Andric   uint64_t Disp = ((Field & 0xfff00) >> 8) | ((Field & 0xff) << 12);
3280b57cec5SDimitry Andric   assert(Index < 16 && "Invalid BDXAddr20");
3290b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createReg(Base == 0 ? 0 : Regs[Base]));
3300b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createImm(SignExtend64<20>(Disp)));
3310b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createReg(Index == 0 ? 0 : Regs[Index]));
3320b57cec5SDimitry Andric   return MCDisassembler::Success;
3330b57cec5SDimitry Andric }
3340b57cec5SDimitry Andric 
decodeBDLAddr12Len4Operand(MCInst & Inst,uint64_t Field,const unsigned * Regs)3350b57cec5SDimitry Andric static DecodeStatus decodeBDLAddr12Len4Operand(MCInst &Inst, uint64_t Field,
3360b57cec5SDimitry Andric                                                const unsigned *Regs) {
3370b57cec5SDimitry Andric   uint64_t Length = Field >> 16;
3380b57cec5SDimitry Andric   uint64_t Base = (Field >> 12) & 0xf;
3390b57cec5SDimitry Andric   uint64_t Disp = Field & 0xfff;
3400b57cec5SDimitry Andric   assert(Length < 16 && "Invalid BDLAddr12Len4");
3410b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createReg(Base == 0 ? 0 : Regs[Base]));
3420b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createImm(Disp));
3430b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createImm(Length + 1));
3440b57cec5SDimitry Andric   return MCDisassembler::Success;
3450b57cec5SDimitry Andric }
3460b57cec5SDimitry Andric 
decodeBDLAddr12Len8Operand(MCInst & Inst,uint64_t Field,const unsigned * Regs)3470b57cec5SDimitry Andric static DecodeStatus decodeBDLAddr12Len8Operand(MCInst &Inst, uint64_t Field,
3480b57cec5SDimitry Andric                                                const unsigned *Regs) {
3490b57cec5SDimitry Andric   uint64_t Length = Field >> 16;
3500b57cec5SDimitry Andric   uint64_t Base = (Field >> 12) & 0xf;
3510b57cec5SDimitry Andric   uint64_t Disp = Field & 0xfff;
3520b57cec5SDimitry Andric   assert(Length < 256 && "Invalid BDLAddr12Len8");
3530b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createReg(Base == 0 ? 0 : Regs[Base]));
3540b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createImm(Disp));
3550b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createImm(Length + 1));
3560b57cec5SDimitry Andric   return MCDisassembler::Success;
3570b57cec5SDimitry Andric }
3580b57cec5SDimitry Andric 
decodeBDRAddr12Operand(MCInst & Inst,uint64_t Field,const unsigned * Regs)3590b57cec5SDimitry Andric static DecodeStatus decodeBDRAddr12Operand(MCInst &Inst, uint64_t Field,
3600b57cec5SDimitry Andric                                            const unsigned *Regs) {
3610b57cec5SDimitry Andric   uint64_t Length = Field >> 16;
3620b57cec5SDimitry Andric   uint64_t Base = (Field >> 12) & 0xf;
3630b57cec5SDimitry Andric   uint64_t Disp = Field & 0xfff;
3640b57cec5SDimitry Andric   assert(Length < 16 && "Invalid BDRAddr12");
3650b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createReg(Base == 0 ? 0 : Regs[Base]));
3660b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createImm(Disp));
3670b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createReg(Regs[Length]));
3680b57cec5SDimitry Andric   return MCDisassembler::Success;
3690b57cec5SDimitry Andric }
3700b57cec5SDimitry Andric 
decodeBDVAddr12Operand(MCInst & Inst,uint64_t Field,const unsigned * Regs)3710b57cec5SDimitry Andric static DecodeStatus decodeBDVAddr12Operand(MCInst &Inst, uint64_t Field,
3720b57cec5SDimitry Andric                                            const unsigned *Regs) {
3730b57cec5SDimitry Andric   uint64_t Index = Field >> 16;
3740b57cec5SDimitry Andric   uint64_t Base = (Field >> 12) & 0xf;
3750b57cec5SDimitry Andric   uint64_t Disp = Field & 0xfff;
3760b57cec5SDimitry Andric   assert(Index < 32 && "Invalid BDVAddr12");
3770b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createReg(Base == 0 ? 0 : Regs[Base]));
3780b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createImm(Disp));
3790b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createReg(SystemZMC::VR128Regs[Index]));
3800b57cec5SDimitry Andric   return MCDisassembler::Success;
3810b57cec5SDimitry Andric }
3820b57cec5SDimitry Andric 
decodeBDAddr32Disp12Operand(MCInst & Inst,uint64_t Field,uint64_t Address,const void * Decoder)3830b57cec5SDimitry Andric static DecodeStatus decodeBDAddr32Disp12Operand(MCInst &Inst, uint64_t Field,
3840b57cec5SDimitry Andric                                                 uint64_t Address,
3850b57cec5SDimitry Andric                                                 const void *Decoder) {
3860b57cec5SDimitry Andric   return decodeBDAddr12Operand(Inst, Field, SystemZMC::GR32Regs);
3870b57cec5SDimitry Andric }
3880b57cec5SDimitry Andric 
decodeBDAddr32Disp20Operand(MCInst & Inst,uint64_t Field,uint64_t Address,const void * Decoder)3890b57cec5SDimitry Andric static DecodeStatus decodeBDAddr32Disp20Operand(MCInst &Inst, uint64_t Field,
3900b57cec5SDimitry Andric                                                 uint64_t Address,
3910b57cec5SDimitry Andric                                                 const void *Decoder) {
3920b57cec5SDimitry Andric   return decodeBDAddr20Operand(Inst, Field, SystemZMC::GR32Regs);
3930b57cec5SDimitry Andric }
3940b57cec5SDimitry Andric 
decodeBDAddr64Disp12Operand(MCInst & Inst,uint64_t Field,uint64_t Address,const void * Decoder)3950b57cec5SDimitry Andric static DecodeStatus decodeBDAddr64Disp12Operand(MCInst &Inst, uint64_t Field,
3960b57cec5SDimitry Andric                                                 uint64_t Address,
3970b57cec5SDimitry Andric                                                 const void *Decoder) {
3980b57cec5SDimitry Andric   return decodeBDAddr12Operand(Inst, Field, SystemZMC::GR64Regs);
3990b57cec5SDimitry Andric }
4000b57cec5SDimitry Andric 
decodeBDAddr64Disp20Operand(MCInst & Inst,uint64_t Field,uint64_t Address,const void * Decoder)4010b57cec5SDimitry Andric static DecodeStatus decodeBDAddr64Disp20Operand(MCInst &Inst, uint64_t Field,
4020b57cec5SDimitry Andric                                                 uint64_t Address,
4030b57cec5SDimitry Andric                                                 const void *Decoder) {
4040b57cec5SDimitry Andric   return decodeBDAddr20Operand(Inst, Field, SystemZMC::GR64Regs);
4050b57cec5SDimitry Andric }
4060b57cec5SDimitry Andric 
decodeBDXAddr64Disp12Operand(MCInst & Inst,uint64_t Field,uint64_t Address,const void * Decoder)4070b57cec5SDimitry Andric static DecodeStatus decodeBDXAddr64Disp12Operand(MCInst &Inst, uint64_t Field,
4080b57cec5SDimitry Andric                                                  uint64_t Address,
4090b57cec5SDimitry Andric                                                  const void *Decoder) {
4100b57cec5SDimitry Andric   return decodeBDXAddr12Operand(Inst, Field, SystemZMC::GR64Regs);
4110b57cec5SDimitry Andric }
4120b57cec5SDimitry Andric 
decodeBDXAddr64Disp20Operand(MCInst & Inst,uint64_t Field,uint64_t Address,const void * Decoder)4130b57cec5SDimitry Andric static DecodeStatus decodeBDXAddr64Disp20Operand(MCInst &Inst, uint64_t Field,
4140b57cec5SDimitry Andric                                                  uint64_t Address,
4150b57cec5SDimitry Andric                                                  const void *Decoder) {
4160b57cec5SDimitry Andric   return decodeBDXAddr20Operand(Inst, Field, SystemZMC::GR64Regs);
4170b57cec5SDimitry Andric }
4180b57cec5SDimitry Andric 
decodeBDLAddr64Disp12Len4Operand(MCInst & Inst,uint64_t Field,uint64_t Address,const void * Decoder)4190b57cec5SDimitry Andric static DecodeStatus decodeBDLAddr64Disp12Len4Operand(MCInst &Inst,
4200b57cec5SDimitry Andric                                                      uint64_t Field,
4210b57cec5SDimitry Andric                                                      uint64_t Address,
4220b57cec5SDimitry Andric                                                      const void *Decoder) {
4230b57cec5SDimitry Andric   return decodeBDLAddr12Len4Operand(Inst, Field, SystemZMC::GR64Regs);
4240b57cec5SDimitry Andric }
4250b57cec5SDimitry Andric 
decodeBDLAddr64Disp12Len8Operand(MCInst & Inst,uint64_t Field,uint64_t Address,const void * Decoder)4260b57cec5SDimitry Andric static DecodeStatus decodeBDLAddr64Disp12Len8Operand(MCInst &Inst,
4270b57cec5SDimitry Andric                                                      uint64_t Field,
4280b57cec5SDimitry Andric                                                      uint64_t Address,
4290b57cec5SDimitry Andric                                                      const void *Decoder) {
4300b57cec5SDimitry Andric   return decodeBDLAddr12Len8Operand(Inst, Field, SystemZMC::GR64Regs);
4310b57cec5SDimitry Andric }
4320b57cec5SDimitry Andric 
decodeBDRAddr64Disp12Operand(MCInst & Inst,uint64_t Field,uint64_t Address,const void * Decoder)4330b57cec5SDimitry Andric static DecodeStatus decodeBDRAddr64Disp12Operand(MCInst &Inst,
4340b57cec5SDimitry Andric                                                  uint64_t Field,
4350b57cec5SDimitry Andric                                                  uint64_t Address,
4360b57cec5SDimitry Andric                                                  const void *Decoder) {
4370b57cec5SDimitry Andric   return decodeBDRAddr12Operand(Inst, Field, SystemZMC::GR64Regs);
4380b57cec5SDimitry Andric }
4390b57cec5SDimitry Andric 
decodeBDVAddr64Disp12Operand(MCInst & Inst,uint64_t Field,uint64_t Address,const void * Decoder)4400b57cec5SDimitry Andric static DecodeStatus decodeBDVAddr64Disp12Operand(MCInst &Inst, uint64_t Field,
4410b57cec5SDimitry Andric                                                  uint64_t Address,
4420b57cec5SDimitry Andric                                                  const void *Decoder) {
4430b57cec5SDimitry Andric   return decodeBDVAddr12Operand(Inst, Field, SystemZMC::GR64Regs);
4440b57cec5SDimitry Andric }
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric #include "SystemZGenDisassemblerTables.inc"
4470b57cec5SDimitry Andric 
getInstruction(MCInst & MI,uint64_t & Size,ArrayRef<uint8_t> Bytes,uint64_t Address,raw_ostream & CS) const4480b57cec5SDimitry Andric DecodeStatus SystemZDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
4490b57cec5SDimitry Andric                                                  ArrayRef<uint8_t> Bytes,
4500b57cec5SDimitry Andric                                                  uint64_t Address,
4510b57cec5SDimitry Andric                                                  raw_ostream &CS) const {
4520b57cec5SDimitry Andric   // Get the first two bytes of the instruction.
4530b57cec5SDimitry Andric   Size = 0;
4540b57cec5SDimitry Andric   if (Bytes.size() < 2)
4550b57cec5SDimitry Andric     return MCDisassembler::Fail;
4560b57cec5SDimitry Andric 
4570b57cec5SDimitry Andric   // The top 2 bits of the first byte specify the size.
4580b57cec5SDimitry Andric   const uint8_t *Table;
4590b57cec5SDimitry Andric   if (Bytes[0] < 0x40) {
4600b57cec5SDimitry Andric     Size = 2;
4610b57cec5SDimitry Andric     Table = DecoderTable16;
4620b57cec5SDimitry Andric   } else if (Bytes[0] < 0xc0) {
4630b57cec5SDimitry Andric     Size = 4;
4640b57cec5SDimitry Andric     Table = DecoderTable32;
4650b57cec5SDimitry Andric   } else {
4660b57cec5SDimitry Andric     Size = 6;
4670b57cec5SDimitry Andric     Table = DecoderTable48;
4680b57cec5SDimitry Andric   }
4690b57cec5SDimitry Andric 
4700b57cec5SDimitry Andric   // Read any remaining bytes.
471*af732203SDimitry Andric   if (Bytes.size() < Size) {
472*af732203SDimitry Andric     Size = Bytes.size();
4730b57cec5SDimitry Andric     return MCDisassembler::Fail;
474*af732203SDimitry Andric   }
4750b57cec5SDimitry Andric 
4760b57cec5SDimitry Andric   // Construct the instruction.
4770b57cec5SDimitry Andric   uint64_t Inst = 0;
4780b57cec5SDimitry Andric   for (uint64_t I = 0; I < Size; ++I)
4790b57cec5SDimitry Andric     Inst = (Inst << 8) | Bytes[I];
4800b57cec5SDimitry Andric 
4810b57cec5SDimitry Andric   return decodeInstruction(Table, MI, Inst, Address, this, STI);
4820b57cec5SDimitry Andric }
483