1*9880d681SAndroid Build Coastguard Worker //===-- SystemZDisassembler.cpp - Disassembler for SystemZ ------*- C++ -*-===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker
10*9880d681SAndroid Build Coastguard Worker #include "SystemZ.h"
11*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCDisassembler/MCDisassembler.h"
12*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCFixedLenDisassembler.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInst.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSubtargetInfo.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/TargetRegistry.h"
16*9880d681SAndroid Build Coastguard Worker
17*9880d681SAndroid Build Coastguard Worker using namespace llvm;
18*9880d681SAndroid Build Coastguard Worker
19*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "systemz-disassembler"
20*9880d681SAndroid Build Coastguard Worker
21*9880d681SAndroid Build Coastguard Worker typedef MCDisassembler::DecodeStatus DecodeStatus;
22*9880d681SAndroid Build Coastguard Worker
23*9880d681SAndroid Build Coastguard Worker namespace {
24*9880d681SAndroid Build Coastguard Worker class SystemZDisassembler : public MCDisassembler {
25*9880d681SAndroid Build Coastguard Worker public:
SystemZDisassembler(const MCSubtargetInfo & STI,MCContext & Ctx)26*9880d681SAndroid Build Coastguard Worker SystemZDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
27*9880d681SAndroid Build Coastguard Worker : MCDisassembler(STI, Ctx) {}
~SystemZDisassembler()28*9880d681SAndroid Build Coastguard Worker ~SystemZDisassembler() override {}
29*9880d681SAndroid Build Coastguard Worker
30*9880d681SAndroid Build Coastguard Worker DecodeStatus getInstruction(MCInst &instr, uint64_t &Size,
31*9880d681SAndroid Build Coastguard Worker ArrayRef<uint8_t> Bytes, uint64_t Address,
32*9880d681SAndroid Build Coastguard Worker raw_ostream &VStream,
33*9880d681SAndroid Build Coastguard Worker raw_ostream &CStream) const override;
34*9880d681SAndroid Build Coastguard Worker };
35*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
36*9880d681SAndroid Build Coastguard Worker
createSystemZDisassembler(const Target & T,const MCSubtargetInfo & STI,MCContext & Ctx)37*9880d681SAndroid Build Coastguard Worker static MCDisassembler *createSystemZDisassembler(const Target &T,
38*9880d681SAndroid Build Coastguard Worker const MCSubtargetInfo &STI,
39*9880d681SAndroid Build Coastguard Worker MCContext &Ctx) {
40*9880d681SAndroid Build Coastguard Worker return new SystemZDisassembler(STI, Ctx);
41*9880d681SAndroid Build Coastguard Worker }
42*9880d681SAndroid Build Coastguard Worker
LLVMInitializeSystemZDisassembler()43*9880d681SAndroid Build Coastguard Worker extern "C" void LLVMInitializeSystemZDisassembler() {
44*9880d681SAndroid Build Coastguard Worker // Register the disassembler.
45*9880d681SAndroid Build Coastguard Worker TargetRegistry::RegisterMCDisassembler(TheSystemZTarget,
46*9880d681SAndroid Build Coastguard Worker createSystemZDisassembler);
47*9880d681SAndroid Build Coastguard Worker }
48*9880d681SAndroid Build Coastguard Worker
49*9880d681SAndroid Build Coastguard Worker /// tryAddingSymbolicOperand - trys to add a symbolic operand in place of the
50*9880d681SAndroid Build Coastguard Worker /// immediate Value in the MCInst.
51*9880d681SAndroid Build Coastguard Worker ///
52*9880d681SAndroid Build Coastguard Worker /// @param Value - The immediate Value, has had any PC adjustment made by
53*9880d681SAndroid Build Coastguard Worker /// the caller.
54*9880d681SAndroid Build Coastguard Worker /// @param isBranch - If the instruction is a branch instruction
55*9880d681SAndroid Build Coastguard Worker /// @param Address - The starting address of the instruction
56*9880d681SAndroid Build Coastguard Worker /// @param Offset - The byte offset to this immediate in the instruction
57*9880d681SAndroid Build Coastguard Worker /// @param Width - The byte width of this immediate in the instruction
58*9880d681SAndroid Build Coastguard Worker ///
59*9880d681SAndroid Build Coastguard Worker /// If the getOpInfo() function was set when setupForSymbolicDisassembly() was
60*9880d681SAndroid Build Coastguard Worker /// called then that function is called to get any symbolic information for the
61*9880d681SAndroid Build Coastguard Worker /// immediate in the instruction using the Address, Offset and Width. If that
62*9880d681SAndroid Build Coastguard Worker /// returns non-zero then the symbolic information it returns is used to create
63*9880d681SAndroid Build Coastguard Worker /// an MCExpr and that is added as an operand to the MCInst. If getOpInfo()
64*9880d681SAndroid Build Coastguard Worker /// returns zero and isBranch is true then a symbol look up for immediate Value
65*9880d681SAndroid Build Coastguard Worker /// is done and if a symbol is found an MCExpr is created with that, else
66*9880d681SAndroid Build Coastguard Worker /// an MCExpr with the immediate Value is created. This function returns true
67*9880d681SAndroid Build Coastguard Worker /// 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)68*9880d681SAndroid Build Coastguard Worker static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch,
69*9880d681SAndroid Build Coastguard Worker uint64_t Address, uint64_t Offset,
70*9880d681SAndroid Build Coastguard Worker uint64_t Width, MCInst &MI,
71*9880d681SAndroid Build Coastguard Worker const void *Decoder) {
72*9880d681SAndroid Build Coastguard Worker const MCDisassembler *Dis = static_cast<const MCDisassembler*>(Decoder);
73*9880d681SAndroid Build Coastguard Worker return Dis->tryAddingSymbolicOperand(MI, Value, Address, isBranch,
74*9880d681SAndroid Build Coastguard Worker Offset, Width);
75*9880d681SAndroid Build Coastguard Worker }
76*9880d681SAndroid Build Coastguard Worker
decodeRegisterClass(MCInst & Inst,uint64_t RegNo,const unsigned * Regs,unsigned Size)77*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeRegisterClass(MCInst &Inst, uint64_t RegNo,
78*9880d681SAndroid Build Coastguard Worker const unsigned *Regs, unsigned Size) {
79*9880d681SAndroid Build Coastguard Worker assert(RegNo < Size && "Invalid register");
80*9880d681SAndroid Build Coastguard Worker RegNo = Regs[RegNo];
81*9880d681SAndroid Build Coastguard Worker if (RegNo == 0)
82*9880d681SAndroid Build Coastguard Worker return MCDisassembler::Fail;
83*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(RegNo));
84*9880d681SAndroid Build Coastguard Worker return MCDisassembler::Success;
85*9880d681SAndroid Build Coastguard Worker }
86*9880d681SAndroid Build Coastguard Worker
DecodeGR32BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)87*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeGR32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
88*9880d681SAndroid Build Coastguard Worker uint64_t Address,
89*9880d681SAndroid Build Coastguard Worker const void *Decoder) {
90*9880d681SAndroid Build Coastguard Worker return decodeRegisterClass(Inst, RegNo, SystemZMC::GR32Regs, 16);
91*9880d681SAndroid Build Coastguard Worker }
92*9880d681SAndroid Build Coastguard Worker
DecodeGRH32BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)93*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeGRH32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
94*9880d681SAndroid Build Coastguard Worker uint64_t Address,
95*9880d681SAndroid Build Coastguard Worker const void *Decoder) {
96*9880d681SAndroid Build Coastguard Worker return decodeRegisterClass(Inst, RegNo, SystemZMC::GRH32Regs, 16);
97*9880d681SAndroid Build Coastguard Worker }
98*9880d681SAndroid Build Coastguard Worker
DecodeGR64BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)99*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeGR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
100*9880d681SAndroid Build Coastguard Worker uint64_t Address,
101*9880d681SAndroid Build Coastguard Worker const void *Decoder) {
102*9880d681SAndroid Build Coastguard Worker return decodeRegisterClass(Inst, RegNo, SystemZMC::GR64Regs, 16);
103*9880d681SAndroid Build Coastguard Worker }
104*9880d681SAndroid Build Coastguard Worker
DecodeGR128BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)105*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeGR128BitRegisterClass(MCInst &Inst, uint64_t RegNo,
106*9880d681SAndroid Build Coastguard Worker uint64_t Address,
107*9880d681SAndroid Build Coastguard Worker const void *Decoder) {
108*9880d681SAndroid Build Coastguard Worker return decodeRegisterClass(Inst, RegNo, SystemZMC::GR128Regs, 16);
109*9880d681SAndroid Build Coastguard Worker }
110*9880d681SAndroid Build Coastguard Worker
DecodeADDR64BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)111*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeADDR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
112*9880d681SAndroid Build Coastguard Worker uint64_t Address,
113*9880d681SAndroid Build Coastguard Worker const void *Decoder) {
114*9880d681SAndroid Build Coastguard Worker return decodeRegisterClass(Inst, RegNo, SystemZMC::GR64Regs, 16);
115*9880d681SAndroid Build Coastguard Worker }
116*9880d681SAndroid Build Coastguard Worker
DecodeFP32BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)117*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeFP32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
118*9880d681SAndroid Build Coastguard Worker uint64_t Address,
119*9880d681SAndroid Build Coastguard Worker const void *Decoder) {
120*9880d681SAndroid Build Coastguard Worker return decodeRegisterClass(Inst, RegNo, SystemZMC::FP32Regs, 16);
121*9880d681SAndroid Build Coastguard Worker }
122*9880d681SAndroid Build Coastguard Worker
DecodeFP64BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)123*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeFP64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
124*9880d681SAndroid Build Coastguard Worker uint64_t Address,
125*9880d681SAndroid Build Coastguard Worker const void *Decoder) {
126*9880d681SAndroid Build Coastguard Worker return decodeRegisterClass(Inst, RegNo, SystemZMC::FP64Regs, 16);
127*9880d681SAndroid Build Coastguard Worker }
128*9880d681SAndroid Build Coastguard Worker
DecodeFP128BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)129*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeFP128BitRegisterClass(MCInst &Inst, uint64_t RegNo,
130*9880d681SAndroid Build Coastguard Worker uint64_t Address,
131*9880d681SAndroid Build Coastguard Worker const void *Decoder) {
132*9880d681SAndroid Build Coastguard Worker return decodeRegisterClass(Inst, RegNo, SystemZMC::FP128Regs, 16);
133*9880d681SAndroid Build Coastguard Worker }
134*9880d681SAndroid Build Coastguard Worker
DecodeVR32BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)135*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVR32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
136*9880d681SAndroid Build Coastguard Worker uint64_t Address,
137*9880d681SAndroid Build Coastguard Worker const void *Decoder) {
138*9880d681SAndroid Build Coastguard Worker return decodeRegisterClass(Inst, RegNo, SystemZMC::VR32Regs, 32);
139*9880d681SAndroid Build Coastguard Worker }
140*9880d681SAndroid Build Coastguard Worker
DecodeVR64BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)141*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
142*9880d681SAndroid Build Coastguard Worker uint64_t Address,
143*9880d681SAndroid Build Coastguard Worker const void *Decoder) {
144*9880d681SAndroid Build Coastguard Worker return decodeRegisterClass(Inst, RegNo, SystemZMC::VR64Regs, 32);
145*9880d681SAndroid Build Coastguard Worker }
146*9880d681SAndroid Build Coastguard Worker
DecodeVR128BitRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)147*9880d681SAndroid Build Coastguard Worker static DecodeStatus DecodeVR128BitRegisterClass(MCInst &Inst, uint64_t RegNo,
148*9880d681SAndroid Build Coastguard Worker uint64_t Address,
149*9880d681SAndroid Build Coastguard Worker const void *Decoder) {
150*9880d681SAndroid Build Coastguard Worker return decodeRegisterClass(Inst, RegNo, SystemZMC::VR128Regs, 32);
151*9880d681SAndroid Build Coastguard Worker }
152*9880d681SAndroid Build Coastguard Worker
153*9880d681SAndroid Build Coastguard Worker template<unsigned N>
decodeUImmOperand(MCInst & Inst,uint64_t Imm)154*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm) {
155*9880d681SAndroid Build Coastguard Worker if (!isUInt<N>(Imm))
156*9880d681SAndroid Build Coastguard Worker return MCDisassembler::Fail;
157*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Imm));
158*9880d681SAndroid Build Coastguard Worker return MCDisassembler::Success;
159*9880d681SAndroid Build Coastguard Worker }
160*9880d681SAndroid Build Coastguard Worker
161*9880d681SAndroid Build Coastguard Worker template<unsigned N>
decodeSImmOperand(MCInst & Inst,uint64_t Imm)162*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm) {
163*9880d681SAndroid Build Coastguard Worker if (!isUInt<N>(Imm))
164*9880d681SAndroid Build Coastguard Worker return MCDisassembler::Fail;
165*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm)));
166*9880d681SAndroid Build Coastguard Worker return MCDisassembler::Success;
167*9880d681SAndroid Build Coastguard Worker }
168*9880d681SAndroid Build Coastguard Worker
decodeAccessRegOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)169*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeAccessRegOperand(MCInst &Inst, uint64_t Imm,
170*9880d681SAndroid Build Coastguard Worker uint64_t Address,
171*9880d681SAndroid Build Coastguard Worker const void *Decoder) {
172*9880d681SAndroid Build Coastguard Worker return decodeUImmOperand<4>(Inst, Imm);
173*9880d681SAndroid Build Coastguard Worker }
174*9880d681SAndroid Build Coastguard Worker
decodeU1ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)175*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeU1ImmOperand(MCInst &Inst, uint64_t Imm,
176*9880d681SAndroid Build Coastguard Worker uint64_t Address, const void *Decoder) {
177*9880d681SAndroid Build Coastguard Worker return decodeUImmOperand<1>(Inst, Imm);
178*9880d681SAndroid Build Coastguard Worker }
179*9880d681SAndroid Build Coastguard Worker
decodeU2ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)180*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeU2ImmOperand(MCInst &Inst, uint64_t Imm,
181*9880d681SAndroid Build Coastguard Worker uint64_t Address, const void *Decoder) {
182*9880d681SAndroid Build Coastguard Worker return decodeUImmOperand<2>(Inst, Imm);
183*9880d681SAndroid Build Coastguard Worker }
184*9880d681SAndroid Build Coastguard Worker
decodeU3ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)185*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeU3ImmOperand(MCInst &Inst, uint64_t Imm,
186*9880d681SAndroid Build Coastguard Worker uint64_t Address, const void *Decoder) {
187*9880d681SAndroid Build Coastguard Worker return decodeUImmOperand<3>(Inst, Imm);
188*9880d681SAndroid Build Coastguard Worker }
189*9880d681SAndroid Build Coastguard Worker
decodeU4ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)190*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeU4ImmOperand(MCInst &Inst, uint64_t Imm,
191*9880d681SAndroid Build Coastguard Worker uint64_t Address, const void *Decoder) {
192*9880d681SAndroid Build Coastguard Worker return decodeUImmOperand<4>(Inst, Imm);
193*9880d681SAndroid Build Coastguard Worker }
194*9880d681SAndroid Build Coastguard Worker
decodeU6ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)195*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeU6ImmOperand(MCInst &Inst, uint64_t Imm,
196*9880d681SAndroid Build Coastguard Worker uint64_t Address, const void *Decoder) {
197*9880d681SAndroid Build Coastguard Worker return decodeUImmOperand<6>(Inst, Imm);
198*9880d681SAndroid Build Coastguard Worker }
199*9880d681SAndroid Build Coastguard Worker
decodeU8ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)200*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeU8ImmOperand(MCInst &Inst, uint64_t Imm,
201*9880d681SAndroid Build Coastguard Worker uint64_t Address, const void *Decoder) {
202*9880d681SAndroid Build Coastguard Worker return decodeUImmOperand<8>(Inst, Imm);
203*9880d681SAndroid Build Coastguard Worker }
204*9880d681SAndroid Build Coastguard Worker
decodeU12ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)205*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeU12ImmOperand(MCInst &Inst, uint64_t Imm,
206*9880d681SAndroid Build Coastguard Worker uint64_t Address, const void *Decoder) {
207*9880d681SAndroid Build Coastguard Worker return decodeUImmOperand<12>(Inst, Imm);
208*9880d681SAndroid Build Coastguard Worker }
209*9880d681SAndroid Build Coastguard Worker
decodeU16ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)210*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeU16ImmOperand(MCInst &Inst, uint64_t Imm,
211*9880d681SAndroid Build Coastguard Worker uint64_t Address, const void *Decoder) {
212*9880d681SAndroid Build Coastguard Worker return decodeUImmOperand<16>(Inst, Imm);
213*9880d681SAndroid Build Coastguard Worker }
214*9880d681SAndroid Build Coastguard Worker
decodeU32ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)215*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeU32ImmOperand(MCInst &Inst, uint64_t Imm,
216*9880d681SAndroid Build Coastguard Worker uint64_t Address, const void *Decoder) {
217*9880d681SAndroid Build Coastguard Worker return decodeUImmOperand<32>(Inst, Imm);
218*9880d681SAndroid Build Coastguard Worker }
219*9880d681SAndroid Build Coastguard Worker
decodeS8ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)220*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeS8ImmOperand(MCInst &Inst, uint64_t Imm,
221*9880d681SAndroid Build Coastguard Worker uint64_t Address, const void *Decoder) {
222*9880d681SAndroid Build Coastguard Worker return decodeSImmOperand<8>(Inst, Imm);
223*9880d681SAndroid Build Coastguard Worker }
224*9880d681SAndroid Build Coastguard Worker
decodeS16ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)225*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeS16ImmOperand(MCInst &Inst, uint64_t Imm,
226*9880d681SAndroid Build Coastguard Worker uint64_t Address, const void *Decoder) {
227*9880d681SAndroid Build Coastguard Worker return decodeSImmOperand<16>(Inst, Imm);
228*9880d681SAndroid Build Coastguard Worker }
229*9880d681SAndroid Build Coastguard Worker
decodeS32ImmOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)230*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeS32ImmOperand(MCInst &Inst, uint64_t Imm,
231*9880d681SAndroid Build Coastguard Worker uint64_t Address, const void *Decoder) {
232*9880d681SAndroid Build Coastguard Worker return decodeSImmOperand<32>(Inst, Imm);
233*9880d681SAndroid Build Coastguard Worker }
234*9880d681SAndroid Build Coastguard Worker
235*9880d681SAndroid Build Coastguard Worker template<unsigned N>
decodePCDBLOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,bool isBranch,const void * Decoder)236*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodePCDBLOperand(MCInst &Inst, uint64_t Imm,
237*9880d681SAndroid Build Coastguard Worker uint64_t Address,
238*9880d681SAndroid Build Coastguard Worker bool isBranch,
239*9880d681SAndroid Build Coastguard Worker const void *Decoder) {
240*9880d681SAndroid Build Coastguard Worker assert(isUInt<N>(Imm) && "Invalid PC-relative offset");
241*9880d681SAndroid Build Coastguard Worker uint64_t Value = SignExtend64<N>(Imm) * 2 + Address;
242*9880d681SAndroid Build Coastguard Worker
243*9880d681SAndroid Build Coastguard Worker if (!tryAddingSymbolicOperand(Value, isBranch, Address, 2, N / 8,
244*9880d681SAndroid Build Coastguard Worker Inst, Decoder))
245*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Value));
246*9880d681SAndroid Build Coastguard Worker
247*9880d681SAndroid Build Coastguard Worker return MCDisassembler::Success;
248*9880d681SAndroid Build Coastguard Worker }
249*9880d681SAndroid Build Coastguard Worker
decodePC16DBLBranchOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)250*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodePC16DBLBranchOperand(MCInst &Inst, uint64_t Imm,
251*9880d681SAndroid Build Coastguard Worker uint64_t Address,
252*9880d681SAndroid Build Coastguard Worker const void *Decoder) {
253*9880d681SAndroid Build Coastguard Worker return decodePCDBLOperand<16>(Inst, Imm, Address, true, Decoder);
254*9880d681SAndroid Build Coastguard Worker }
255*9880d681SAndroid Build Coastguard Worker
decodePC32DBLBranchOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)256*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodePC32DBLBranchOperand(MCInst &Inst, uint64_t Imm,
257*9880d681SAndroid Build Coastguard Worker uint64_t Address,
258*9880d681SAndroid Build Coastguard Worker const void *Decoder) {
259*9880d681SAndroid Build Coastguard Worker return decodePCDBLOperand<32>(Inst, Imm, Address, true, Decoder);
260*9880d681SAndroid Build Coastguard Worker }
261*9880d681SAndroid Build Coastguard Worker
decodePC32DBLOperand(MCInst & Inst,uint64_t Imm,uint64_t Address,const void * Decoder)262*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodePC32DBLOperand(MCInst &Inst, uint64_t Imm,
263*9880d681SAndroid Build Coastguard Worker uint64_t Address,
264*9880d681SAndroid Build Coastguard Worker const void *Decoder) {
265*9880d681SAndroid Build Coastguard Worker return decodePCDBLOperand<32>(Inst, Imm, Address, false, Decoder);
266*9880d681SAndroid Build Coastguard Worker }
267*9880d681SAndroid Build Coastguard Worker
decodeBDAddr12Operand(MCInst & Inst,uint64_t Field,const unsigned * Regs)268*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeBDAddr12Operand(MCInst &Inst, uint64_t Field,
269*9880d681SAndroid Build Coastguard Worker const unsigned *Regs) {
270*9880d681SAndroid Build Coastguard Worker uint64_t Base = Field >> 12;
271*9880d681SAndroid Build Coastguard Worker uint64_t Disp = Field & 0xfff;
272*9880d681SAndroid Build Coastguard Worker assert(Base < 16 && "Invalid BDAddr12");
273*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Base == 0 ? 0 : Regs[Base]));
274*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Disp));
275*9880d681SAndroid Build Coastguard Worker return MCDisassembler::Success;
276*9880d681SAndroid Build Coastguard Worker }
277*9880d681SAndroid Build Coastguard Worker
decodeBDAddr20Operand(MCInst & Inst,uint64_t Field,const unsigned * Regs)278*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeBDAddr20Operand(MCInst &Inst, uint64_t Field,
279*9880d681SAndroid Build Coastguard Worker const unsigned *Regs) {
280*9880d681SAndroid Build Coastguard Worker uint64_t Base = Field >> 20;
281*9880d681SAndroid Build Coastguard Worker uint64_t Disp = ((Field << 12) & 0xff000) | ((Field >> 8) & 0xfff);
282*9880d681SAndroid Build Coastguard Worker assert(Base < 16 && "Invalid BDAddr20");
283*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Base == 0 ? 0 : Regs[Base]));
284*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(SignExtend64<20>(Disp)));
285*9880d681SAndroid Build Coastguard Worker return MCDisassembler::Success;
286*9880d681SAndroid Build Coastguard Worker }
287*9880d681SAndroid Build Coastguard Worker
decodeBDXAddr12Operand(MCInst & Inst,uint64_t Field,const unsigned * Regs)288*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeBDXAddr12Operand(MCInst &Inst, uint64_t Field,
289*9880d681SAndroid Build Coastguard Worker const unsigned *Regs) {
290*9880d681SAndroid Build Coastguard Worker uint64_t Index = Field >> 16;
291*9880d681SAndroid Build Coastguard Worker uint64_t Base = (Field >> 12) & 0xf;
292*9880d681SAndroid Build Coastguard Worker uint64_t Disp = Field & 0xfff;
293*9880d681SAndroid Build Coastguard Worker assert(Index < 16 && "Invalid BDXAddr12");
294*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Base == 0 ? 0 : Regs[Base]));
295*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Disp));
296*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Index == 0 ? 0 : Regs[Index]));
297*9880d681SAndroid Build Coastguard Worker return MCDisassembler::Success;
298*9880d681SAndroid Build Coastguard Worker }
299*9880d681SAndroid Build Coastguard Worker
decodeBDXAddr20Operand(MCInst & Inst,uint64_t Field,const unsigned * Regs)300*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeBDXAddr20Operand(MCInst &Inst, uint64_t Field,
301*9880d681SAndroid Build Coastguard Worker const unsigned *Regs) {
302*9880d681SAndroid Build Coastguard Worker uint64_t Index = Field >> 24;
303*9880d681SAndroid Build Coastguard Worker uint64_t Base = (Field >> 20) & 0xf;
304*9880d681SAndroid Build Coastguard Worker uint64_t Disp = ((Field & 0xfff00) >> 8) | ((Field & 0xff) << 12);
305*9880d681SAndroid Build Coastguard Worker assert(Index < 16 && "Invalid BDXAddr20");
306*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Base == 0 ? 0 : Regs[Base]));
307*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(SignExtend64<20>(Disp)));
308*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Index == 0 ? 0 : Regs[Index]));
309*9880d681SAndroid Build Coastguard Worker return MCDisassembler::Success;
310*9880d681SAndroid Build Coastguard Worker }
311*9880d681SAndroid Build Coastguard Worker
decodeBDLAddr12Len8Operand(MCInst & Inst,uint64_t Field,const unsigned * Regs)312*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeBDLAddr12Len8Operand(MCInst &Inst, uint64_t Field,
313*9880d681SAndroid Build Coastguard Worker const unsigned *Regs) {
314*9880d681SAndroid Build Coastguard Worker uint64_t Length = Field >> 16;
315*9880d681SAndroid Build Coastguard Worker uint64_t Base = (Field >> 12) & 0xf;
316*9880d681SAndroid Build Coastguard Worker uint64_t Disp = Field & 0xfff;
317*9880d681SAndroid Build Coastguard Worker assert(Length < 256 && "Invalid BDLAddr12Len8");
318*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Base == 0 ? 0 : Regs[Base]));
319*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Disp));
320*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Length + 1));
321*9880d681SAndroid Build Coastguard Worker return MCDisassembler::Success;
322*9880d681SAndroid Build Coastguard Worker }
323*9880d681SAndroid Build Coastguard Worker
decodeBDVAddr12Operand(MCInst & Inst,uint64_t Field,const unsigned * Regs)324*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeBDVAddr12Operand(MCInst &Inst, uint64_t Field,
325*9880d681SAndroid Build Coastguard Worker const unsigned *Regs) {
326*9880d681SAndroid Build Coastguard Worker uint64_t Index = Field >> 16;
327*9880d681SAndroid Build Coastguard Worker uint64_t Base = (Field >> 12) & 0xf;
328*9880d681SAndroid Build Coastguard Worker uint64_t Disp = Field & 0xfff;
329*9880d681SAndroid Build Coastguard Worker assert(Index < 32 && "Invalid BDVAddr12");
330*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(Base == 0 ? 0 : Regs[Base]));
331*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(Disp));
332*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(SystemZMC::VR128Regs[Index]));
333*9880d681SAndroid Build Coastguard Worker return MCDisassembler::Success;
334*9880d681SAndroid Build Coastguard Worker }
335*9880d681SAndroid Build Coastguard Worker
decodeBDAddr32Disp12Operand(MCInst & Inst,uint64_t Field,uint64_t Address,const void * Decoder)336*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeBDAddr32Disp12Operand(MCInst &Inst, uint64_t Field,
337*9880d681SAndroid Build Coastguard Worker uint64_t Address,
338*9880d681SAndroid Build Coastguard Worker const void *Decoder) {
339*9880d681SAndroid Build Coastguard Worker return decodeBDAddr12Operand(Inst, Field, SystemZMC::GR32Regs);
340*9880d681SAndroid Build Coastguard Worker }
341*9880d681SAndroid Build Coastguard Worker
decodeBDAddr32Disp20Operand(MCInst & Inst,uint64_t Field,uint64_t Address,const void * Decoder)342*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeBDAddr32Disp20Operand(MCInst &Inst, uint64_t Field,
343*9880d681SAndroid Build Coastguard Worker uint64_t Address,
344*9880d681SAndroid Build Coastguard Worker const void *Decoder) {
345*9880d681SAndroid Build Coastguard Worker return decodeBDAddr20Operand(Inst, Field, SystemZMC::GR32Regs);
346*9880d681SAndroid Build Coastguard Worker }
347*9880d681SAndroid Build Coastguard Worker
decodeBDAddr64Disp12Operand(MCInst & Inst,uint64_t Field,uint64_t Address,const void * Decoder)348*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeBDAddr64Disp12Operand(MCInst &Inst, uint64_t Field,
349*9880d681SAndroid Build Coastguard Worker uint64_t Address,
350*9880d681SAndroid Build Coastguard Worker const void *Decoder) {
351*9880d681SAndroid Build Coastguard Worker return decodeBDAddr12Operand(Inst, Field, SystemZMC::GR64Regs);
352*9880d681SAndroid Build Coastguard Worker }
353*9880d681SAndroid Build Coastguard Worker
decodeBDAddr64Disp20Operand(MCInst & Inst,uint64_t Field,uint64_t Address,const void * Decoder)354*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeBDAddr64Disp20Operand(MCInst &Inst, uint64_t Field,
355*9880d681SAndroid Build Coastguard Worker uint64_t Address,
356*9880d681SAndroid Build Coastguard Worker const void *Decoder) {
357*9880d681SAndroid Build Coastguard Worker return decodeBDAddr20Operand(Inst, Field, SystemZMC::GR64Regs);
358*9880d681SAndroid Build Coastguard Worker }
359*9880d681SAndroid Build Coastguard Worker
decodeBDXAddr64Disp12Operand(MCInst & Inst,uint64_t Field,uint64_t Address,const void * Decoder)360*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeBDXAddr64Disp12Operand(MCInst &Inst, uint64_t Field,
361*9880d681SAndroid Build Coastguard Worker uint64_t Address,
362*9880d681SAndroid Build Coastguard Worker const void *Decoder) {
363*9880d681SAndroid Build Coastguard Worker return decodeBDXAddr12Operand(Inst, Field, SystemZMC::GR64Regs);
364*9880d681SAndroid Build Coastguard Worker }
365*9880d681SAndroid Build Coastguard Worker
decodeBDXAddr64Disp20Operand(MCInst & Inst,uint64_t Field,uint64_t Address,const void * Decoder)366*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeBDXAddr64Disp20Operand(MCInst &Inst, uint64_t Field,
367*9880d681SAndroid Build Coastguard Worker uint64_t Address,
368*9880d681SAndroid Build Coastguard Worker const void *Decoder) {
369*9880d681SAndroid Build Coastguard Worker return decodeBDXAddr20Operand(Inst, Field, SystemZMC::GR64Regs);
370*9880d681SAndroid Build Coastguard Worker }
371*9880d681SAndroid Build Coastguard Worker
decodeBDLAddr64Disp12Len8Operand(MCInst & Inst,uint64_t Field,uint64_t Address,const void * Decoder)372*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeBDLAddr64Disp12Len8Operand(MCInst &Inst,
373*9880d681SAndroid Build Coastguard Worker uint64_t Field,
374*9880d681SAndroid Build Coastguard Worker uint64_t Address,
375*9880d681SAndroid Build Coastguard Worker const void *Decoder) {
376*9880d681SAndroid Build Coastguard Worker return decodeBDLAddr12Len8Operand(Inst, Field, SystemZMC::GR64Regs);
377*9880d681SAndroid Build Coastguard Worker }
378*9880d681SAndroid Build Coastguard Worker
decodeBDVAddr64Disp12Operand(MCInst & Inst,uint64_t Field,uint64_t Address,const void * Decoder)379*9880d681SAndroid Build Coastguard Worker static DecodeStatus decodeBDVAddr64Disp12Operand(MCInst &Inst, uint64_t Field,
380*9880d681SAndroid Build Coastguard Worker uint64_t Address,
381*9880d681SAndroid Build Coastguard Worker const void *Decoder) {
382*9880d681SAndroid Build Coastguard Worker return decodeBDVAddr12Operand(Inst, Field, SystemZMC::GR64Regs);
383*9880d681SAndroid Build Coastguard Worker }
384*9880d681SAndroid Build Coastguard Worker
385*9880d681SAndroid Build Coastguard Worker #include "SystemZGenDisassemblerTables.inc"
386*9880d681SAndroid Build Coastguard Worker
getInstruction(MCInst & MI,uint64_t & Size,ArrayRef<uint8_t> Bytes,uint64_t Address,raw_ostream & OS,raw_ostream & CS) const387*9880d681SAndroid Build Coastguard Worker DecodeStatus SystemZDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
388*9880d681SAndroid Build Coastguard Worker ArrayRef<uint8_t> Bytes,
389*9880d681SAndroid Build Coastguard Worker uint64_t Address,
390*9880d681SAndroid Build Coastguard Worker raw_ostream &OS,
391*9880d681SAndroid Build Coastguard Worker raw_ostream &CS) const {
392*9880d681SAndroid Build Coastguard Worker // Get the first two bytes of the instruction.
393*9880d681SAndroid Build Coastguard Worker Size = 0;
394*9880d681SAndroid Build Coastguard Worker if (Bytes.size() < 2)
395*9880d681SAndroid Build Coastguard Worker return MCDisassembler::Fail;
396*9880d681SAndroid Build Coastguard Worker
397*9880d681SAndroid Build Coastguard Worker // The top 2 bits of the first byte specify the size.
398*9880d681SAndroid Build Coastguard Worker const uint8_t *Table;
399*9880d681SAndroid Build Coastguard Worker if (Bytes[0] < 0x40) {
400*9880d681SAndroid Build Coastguard Worker Size = 2;
401*9880d681SAndroid Build Coastguard Worker Table = DecoderTable16;
402*9880d681SAndroid Build Coastguard Worker } else if (Bytes[0] < 0xc0) {
403*9880d681SAndroid Build Coastguard Worker Size = 4;
404*9880d681SAndroid Build Coastguard Worker Table = DecoderTable32;
405*9880d681SAndroid Build Coastguard Worker } else {
406*9880d681SAndroid Build Coastguard Worker Size = 6;
407*9880d681SAndroid Build Coastguard Worker Table = DecoderTable48;
408*9880d681SAndroid Build Coastguard Worker }
409*9880d681SAndroid Build Coastguard Worker
410*9880d681SAndroid Build Coastguard Worker // Read any remaining bytes.
411*9880d681SAndroid Build Coastguard Worker if (Bytes.size() < Size)
412*9880d681SAndroid Build Coastguard Worker return MCDisassembler::Fail;
413*9880d681SAndroid Build Coastguard Worker
414*9880d681SAndroid Build Coastguard Worker // Construct the instruction.
415*9880d681SAndroid Build Coastguard Worker uint64_t Inst = 0;
416*9880d681SAndroid Build Coastguard Worker for (uint64_t I = 0; I < Size; ++I)
417*9880d681SAndroid Build Coastguard Worker Inst = (Inst << 8) | Bytes[I];
418*9880d681SAndroid Build Coastguard Worker
419*9880d681SAndroid Build Coastguard Worker return decodeInstruction(Table, MI, Inst, Address, this, STI);
420*9880d681SAndroid Build Coastguard Worker }
421