1*eb9af294SRichard Sandiford //===-- SystemZDisassembler.cpp - Disassembler for SystemZ ------*- C++ -*-===//
2*eb9af294SRichard Sandiford //
3*eb9af294SRichard Sandiford //                     The LLVM Compiler Infrastructure
4*eb9af294SRichard Sandiford //
5*eb9af294SRichard Sandiford // This file is distributed under the University of Illinois Open Source
6*eb9af294SRichard Sandiford // License. See LICENSE.TXT for details.
7*eb9af294SRichard Sandiford //
8*eb9af294SRichard Sandiford //===----------------------------------------------------------------------===//
9*eb9af294SRichard Sandiford 
10*eb9af294SRichard Sandiford #include "SystemZ.h"
11*eb9af294SRichard Sandiford #include "llvm/MC/MCDisassembler.h"
12*eb9af294SRichard Sandiford #include "llvm/MC/MCFixedLenDisassembler.h"
13*eb9af294SRichard Sandiford #include "llvm/MC/MCInst.h"
14*eb9af294SRichard Sandiford #include "llvm/MC/MCSubtargetInfo.h"
15*eb9af294SRichard Sandiford #include "llvm/Support/MemoryObject.h"
16*eb9af294SRichard Sandiford #include "llvm/Support/TargetRegistry.h"
17*eb9af294SRichard Sandiford 
18*eb9af294SRichard Sandiford using namespace llvm;
19*eb9af294SRichard Sandiford 
20*eb9af294SRichard Sandiford typedef MCDisassembler::DecodeStatus DecodeStatus;
21*eb9af294SRichard Sandiford 
22*eb9af294SRichard Sandiford namespace {
23*eb9af294SRichard Sandiford class SystemZDisassembler : public MCDisassembler {
24*eb9af294SRichard Sandiford public:
25*eb9af294SRichard Sandiford   SystemZDisassembler(const MCSubtargetInfo &STI)
26*eb9af294SRichard Sandiford     : MCDisassembler(STI) {}
27*eb9af294SRichard Sandiford   virtual ~SystemZDisassembler() {}
28*eb9af294SRichard Sandiford 
29*eb9af294SRichard Sandiford   // Override MCDisassembler.
30*eb9af294SRichard Sandiford   virtual DecodeStatus getInstruction(MCInst &instr,
31*eb9af294SRichard Sandiford                                       uint64_t &size,
32*eb9af294SRichard Sandiford                                       const MemoryObject &region,
33*eb9af294SRichard Sandiford                                       uint64_t address,
34*eb9af294SRichard Sandiford                                       raw_ostream &vStream,
35*eb9af294SRichard Sandiford                                       raw_ostream &cStream) const LLVM_OVERRIDE;
36*eb9af294SRichard Sandiford };
37*eb9af294SRichard Sandiford } // end anonymous namespace
38*eb9af294SRichard Sandiford 
39*eb9af294SRichard Sandiford static MCDisassembler *createSystemZDisassembler(const Target &T,
40*eb9af294SRichard Sandiford                                                  const MCSubtargetInfo &STI) {
41*eb9af294SRichard Sandiford   return new SystemZDisassembler(STI);
42*eb9af294SRichard Sandiford }
43*eb9af294SRichard Sandiford 
44*eb9af294SRichard Sandiford extern "C" void LLVMInitializeSystemZDisassembler() {
45*eb9af294SRichard Sandiford   // Register the disassembler.
46*eb9af294SRichard Sandiford   TargetRegistry::RegisterMCDisassembler(TheSystemZTarget,
47*eb9af294SRichard Sandiford                                          createSystemZDisassembler);
48*eb9af294SRichard Sandiford }
49*eb9af294SRichard Sandiford 
50*eb9af294SRichard Sandiford static DecodeStatus decodeRegisterClass(MCInst &Inst, uint64_t RegNo,
51*eb9af294SRichard Sandiford                                         const unsigned *Regs,
52*eb9af294SRichard Sandiford                                         bool isAddress = false) {
53*eb9af294SRichard Sandiford   assert(RegNo < 16 && "Invalid register");
54*eb9af294SRichard Sandiford   if (!isAddress || RegNo) {
55*eb9af294SRichard Sandiford     RegNo = Regs[RegNo];
56*eb9af294SRichard Sandiford     if (RegNo == 0)
57*eb9af294SRichard Sandiford       return MCDisassembler::Fail;
58*eb9af294SRichard Sandiford   }
59*eb9af294SRichard Sandiford   Inst.addOperand(MCOperand::CreateReg(RegNo));
60*eb9af294SRichard Sandiford   return MCDisassembler::Success;
61*eb9af294SRichard Sandiford }
62*eb9af294SRichard Sandiford 
63*eb9af294SRichard Sandiford static DecodeStatus DecodeGR32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
64*eb9af294SRichard Sandiford                                                uint64_t Address,
65*eb9af294SRichard Sandiford                                                const void *Decoder) {
66*eb9af294SRichard Sandiford   return decodeRegisterClass(Inst, RegNo, SystemZMC::GR32Regs);
67*eb9af294SRichard Sandiford }
68*eb9af294SRichard Sandiford 
69*eb9af294SRichard Sandiford static DecodeStatus DecodeGR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
70*eb9af294SRichard Sandiford                                                uint64_t Address,
71*eb9af294SRichard Sandiford                                                const void *Decoder) {
72*eb9af294SRichard Sandiford   return decodeRegisterClass(Inst, RegNo, SystemZMC::GR64Regs);
73*eb9af294SRichard Sandiford }
74*eb9af294SRichard Sandiford 
75*eb9af294SRichard Sandiford static DecodeStatus DecodeGR128BitRegisterClass(MCInst &Inst, uint64_t RegNo,
76*eb9af294SRichard Sandiford                                                 uint64_t Address,
77*eb9af294SRichard Sandiford                                                 const void *Decoder) {
78*eb9af294SRichard Sandiford   return decodeRegisterClass(Inst, RegNo, SystemZMC::GR128Regs);
79*eb9af294SRichard Sandiford }
80*eb9af294SRichard Sandiford 
81*eb9af294SRichard Sandiford static DecodeStatus DecodeADDR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
82*eb9af294SRichard Sandiford                                                  uint64_t Address,
83*eb9af294SRichard Sandiford                                                  const void *Decoder) {
84*eb9af294SRichard Sandiford   return decodeRegisterClass(Inst, RegNo, SystemZMC::GR64Regs, true);
85*eb9af294SRichard Sandiford }
86*eb9af294SRichard Sandiford 
87*eb9af294SRichard Sandiford static DecodeStatus DecodeFP32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
88*eb9af294SRichard Sandiford                                                uint64_t Address,
89*eb9af294SRichard Sandiford                                                const void *Decoder) {
90*eb9af294SRichard Sandiford   return decodeRegisterClass(Inst, RegNo, SystemZMC::FP32Regs);
91*eb9af294SRichard Sandiford }
92*eb9af294SRichard Sandiford 
93*eb9af294SRichard Sandiford static DecodeStatus DecodeFP64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
94*eb9af294SRichard Sandiford                                                uint64_t Address,
95*eb9af294SRichard Sandiford                                                const void *Decoder) {
96*eb9af294SRichard Sandiford   return decodeRegisterClass(Inst, RegNo, SystemZMC::FP64Regs);
97*eb9af294SRichard Sandiford }
98*eb9af294SRichard Sandiford 
99*eb9af294SRichard Sandiford static DecodeStatus DecodeFP128BitRegisterClass(MCInst &Inst, uint64_t RegNo,
100*eb9af294SRichard Sandiford                                                 uint64_t Address,
101*eb9af294SRichard Sandiford                                                 const void *Decoder) {
102*eb9af294SRichard Sandiford   return decodeRegisterClass(Inst, RegNo, SystemZMC::FP128Regs);
103*eb9af294SRichard Sandiford }
104*eb9af294SRichard Sandiford 
105*eb9af294SRichard Sandiford template<unsigned N>
106*eb9af294SRichard Sandiford static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm) {
107*eb9af294SRichard Sandiford   assert(isUInt<N>(Imm) && "Invalid immediate");
108*eb9af294SRichard Sandiford   Inst.addOperand(MCOperand::CreateImm(Imm));
109*eb9af294SRichard Sandiford   return MCDisassembler::Success;
110*eb9af294SRichard Sandiford }
111*eb9af294SRichard Sandiford 
112*eb9af294SRichard Sandiford template<unsigned N>
113*eb9af294SRichard Sandiford static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm) {
114*eb9af294SRichard Sandiford   assert(isUInt<N>(Imm) && "Invalid immediate");
115*eb9af294SRichard Sandiford   Inst.addOperand(MCOperand::CreateImm(SignExtend64<N>(Imm)));
116*eb9af294SRichard Sandiford   return MCDisassembler::Success;
117*eb9af294SRichard Sandiford }
118*eb9af294SRichard Sandiford 
119*eb9af294SRichard Sandiford static DecodeStatus decodeAccessRegOperand(MCInst &Inst, uint64_t Imm,
120*eb9af294SRichard Sandiford                                            uint64_t Address,
121*eb9af294SRichard Sandiford                                            const void *Decoder) {
122*eb9af294SRichard Sandiford   return decodeUImmOperand<4>(Inst, Imm);
123*eb9af294SRichard Sandiford }
124*eb9af294SRichard Sandiford 
125*eb9af294SRichard Sandiford static DecodeStatus decodeU4ImmOperand(MCInst &Inst, uint64_t Imm,
126*eb9af294SRichard Sandiford                                        uint64_t Address, const void *Decoder) {
127*eb9af294SRichard Sandiford   return decodeUImmOperand<4>(Inst, Imm);
128*eb9af294SRichard Sandiford }
129*eb9af294SRichard Sandiford 
130*eb9af294SRichard Sandiford static DecodeStatus decodeU6ImmOperand(MCInst &Inst, uint64_t Imm,
131*eb9af294SRichard Sandiford                                        uint64_t Address, const void *Decoder) {
132*eb9af294SRichard Sandiford   return decodeUImmOperand<6>(Inst, Imm);
133*eb9af294SRichard Sandiford }
134*eb9af294SRichard Sandiford 
135*eb9af294SRichard Sandiford static DecodeStatus decodeU8ImmOperand(MCInst &Inst, uint64_t Imm,
136*eb9af294SRichard Sandiford                                        uint64_t Address, const void *Decoder) {
137*eb9af294SRichard Sandiford   return decodeUImmOperand<8>(Inst, Imm);
138*eb9af294SRichard Sandiford }
139*eb9af294SRichard Sandiford 
140*eb9af294SRichard Sandiford static DecodeStatus decodeU16ImmOperand(MCInst &Inst, uint64_t Imm,
141*eb9af294SRichard Sandiford                                         uint64_t Address, const void *Decoder) {
142*eb9af294SRichard Sandiford   return decodeUImmOperand<16>(Inst, Imm);
143*eb9af294SRichard Sandiford }
144*eb9af294SRichard Sandiford 
145*eb9af294SRichard Sandiford static DecodeStatus decodeU32ImmOperand(MCInst &Inst, uint64_t Imm,
146*eb9af294SRichard Sandiford                                         uint64_t Address, const void *Decoder) {
147*eb9af294SRichard Sandiford   return decodeUImmOperand<32>(Inst, Imm);
148*eb9af294SRichard Sandiford }
149*eb9af294SRichard Sandiford 
150*eb9af294SRichard Sandiford static DecodeStatus decodeS8ImmOperand(MCInst &Inst, uint64_t Imm,
151*eb9af294SRichard Sandiford                                        uint64_t Address, const void *Decoder) {
152*eb9af294SRichard Sandiford   return decodeSImmOperand<8>(Inst, Imm);
153*eb9af294SRichard Sandiford }
154*eb9af294SRichard Sandiford 
155*eb9af294SRichard Sandiford static DecodeStatus decodeS16ImmOperand(MCInst &Inst, uint64_t Imm,
156*eb9af294SRichard Sandiford                                         uint64_t Address, const void *Decoder) {
157*eb9af294SRichard Sandiford   return decodeSImmOperand<16>(Inst, Imm);
158*eb9af294SRichard Sandiford }
159*eb9af294SRichard Sandiford 
160*eb9af294SRichard Sandiford static DecodeStatus decodeS32ImmOperand(MCInst &Inst, uint64_t Imm,
161*eb9af294SRichard Sandiford                                         uint64_t Address, const void *Decoder) {
162*eb9af294SRichard Sandiford   return decodeSImmOperand<32>(Inst, Imm);
163*eb9af294SRichard Sandiford }
164*eb9af294SRichard Sandiford 
165*eb9af294SRichard Sandiford template<unsigned N>
166*eb9af294SRichard Sandiford static DecodeStatus decodePCDBLOperand(MCInst &Inst, uint64_t Imm,
167*eb9af294SRichard Sandiford                                        uint64_t Address) {
168*eb9af294SRichard Sandiford   assert(isUInt<N>(Imm) && "Invalid PC-relative offset");
169*eb9af294SRichard Sandiford   Inst.addOperand(MCOperand::CreateImm(SignExtend64<N>(Imm) * 2 + Address));
170*eb9af294SRichard Sandiford   return MCDisassembler::Success;
171*eb9af294SRichard Sandiford }
172*eb9af294SRichard Sandiford 
173*eb9af294SRichard Sandiford static DecodeStatus decodePC16DBLOperand(MCInst &Inst, uint64_t Imm,
174*eb9af294SRichard Sandiford                                          uint64_t Address,
175*eb9af294SRichard Sandiford                                          const void *Decoder) {
176*eb9af294SRichard Sandiford   return decodePCDBLOperand<16>(Inst, Imm, Address);
177*eb9af294SRichard Sandiford }
178*eb9af294SRichard Sandiford 
179*eb9af294SRichard Sandiford static DecodeStatus decodePC32DBLOperand(MCInst &Inst, uint64_t Imm,
180*eb9af294SRichard Sandiford                                          uint64_t Address,
181*eb9af294SRichard Sandiford                                          const void *Decoder) {
182*eb9af294SRichard Sandiford   return decodePCDBLOperand<32>(Inst, Imm, Address);
183*eb9af294SRichard Sandiford }
184*eb9af294SRichard Sandiford 
185*eb9af294SRichard Sandiford static DecodeStatus decodeBDAddr12Operand(MCInst &Inst, uint64_t Field,
186*eb9af294SRichard Sandiford                                           const unsigned *Regs) {
187*eb9af294SRichard Sandiford   uint64_t Base = Field >> 12;
188*eb9af294SRichard Sandiford   uint64_t Disp = Field & 0xfff;
189*eb9af294SRichard Sandiford   assert(Base < 16 && "Invalid BDAddr12");
190*eb9af294SRichard Sandiford   Inst.addOperand(MCOperand::CreateReg(Base == 0 ? 0 : Regs[Base]));
191*eb9af294SRichard Sandiford   Inst.addOperand(MCOperand::CreateImm(Disp));
192*eb9af294SRichard Sandiford   return MCDisassembler::Success;
193*eb9af294SRichard Sandiford }
194*eb9af294SRichard Sandiford 
195*eb9af294SRichard Sandiford static DecodeStatus decodeBDAddr20Operand(MCInst &Inst, uint64_t Field,
196*eb9af294SRichard Sandiford                                           const unsigned *Regs) {
197*eb9af294SRichard Sandiford   uint64_t Base = Field >> 20;
198*eb9af294SRichard Sandiford   uint64_t Disp = ((Field << 12) & 0xff000) | ((Field >> 8) & 0xfff);
199*eb9af294SRichard Sandiford   assert(Base < 16 && "Invalid BDAddr20");
200*eb9af294SRichard Sandiford   Inst.addOperand(MCOperand::CreateReg(Base == 0 ? 0 : Regs[Base]));
201*eb9af294SRichard Sandiford   Inst.addOperand(MCOperand::CreateImm(SignExtend64<20>(Disp)));
202*eb9af294SRichard Sandiford   return MCDisassembler::Success;
203*eb9af294SRichard Sandiford }
204*eb9af294SRichard Sandiford 
205*eb9af294SRichard Sandiford static DecodeStatus decodeBDXAddr12Operand(MCInst &Inst, uint64_t Field,
206*eb9af294SRichard Sandiford                                            const unsigned *Regs) {
207*eb9af294SRichard Sandiford   uint64_t Index = Field >> 16;
208*eb9af294SRichard Sandiford   uint64_t Base = (Field >> 12) & 0xf;
209*eb9af294SRichard Sandiford   uint64_t Disp = Field & 0xfff;
210*eb9af294SRichard Sandiford   assert(Index < 16 && "Invalid BDXAddr12");
211*eb9af294SRichard Sandiford   Inst.addOperand(MCOperand::CreateReg(Base == 0 ? 0 : Regs[Base]));
212*eb9af294SRichard Sandiford   Inst.addOperand(MCOperand::CreateImm(Disp));
213*eb9af294SRichard Sandiford   Inst.addOperand(MCOperand::CreateReg(Index == 0 ? 0 : Regs[Index]));
214*eb9af294SRichard Sandiford   return MCDisassembler::Success;
215*eb9af294SRichard Sandiford }
216*eb9af294SRichard Sandiford 
217*eb9af294SRichard Sandiford static DecodeStatus decodeBDXAddr20Operand(MCInst &Inst, uint64_t Field,
218*eb9af294SRichard Sandiford                                            const unsigned *Regs) {
219*eb9af294SRichard Sandiford   uint64_t Index = Field >> 24;
220*eb9af294SRichard Sandiford   uint64_t Base = (Field >> 20) & 0xf;
221*eb9af294SRichard Sandiford   uint64_t Disp = ((Field & 0xfff00) >> 8) | ((Field & 0xff) << 12);
222*eb9af294SRichard Sandiford   assert(Index < 16 && "Invalid BDXAddr20");
223*eb9af294SRichard Sandiford   Inst.addOperand(MCOperand::CreateReg(Base == 0 ? 0 : Regs[Base]));
224*eb9af294SRichard Sandiford   Inst.addOperand(MCOperand::CreateImm(SignExtend64<20>(Disp)));
225*eb9af294SRichard Sandiford   Inst.addOperand(MCOperand::CreateReg(Index == 0 ? 0 : Regs[Index]));
226*eb9af294SRichard Sandiford   return MCDisassembler::Success;
227*eb9af294SRichard Sandiford }
228*eb9af294SRichard Sandiford 
229*eb9af294SRichard Sandiford static DecodeStatus decodeBDAddr32Disp12Operand(MCInst &Inst, uint64_t Field,
230*eb9af294SRichard Sandiford                                                 uint64_t Address,
231*eb9af294SRichard Sandiford                                                 const void *Decoder) {
232*eb9af294SRichard Sandiford   return decodeBDAddr12Operand(Inst, Field, SystemZMC::GR32Regs);
233*eb9af294SRichard Sandiford }
234*eb9af294SRichard Sandiford 
235*eb9af294SRichard Sandiford static DecodeStatus decodeBDAddr32Disp20Operand(MCInst &Inst, uint64_t Field,
236*eb9af294SRichard Sandiford                                                 uint64_t Address,
237*eb9af294SRichard Sandiford                                                 const void *Decoder) {
238*eb9af294SRichard Sandiford   return decodeBDAddr20Operand(Inst, Field, SystemZMC::GR32Regs);
239*eb9af294SRichard Sandiford }
240*eb9af294SRichard Sandiford 
241*eb9af294SRichard Sandiford static DecodeStatus decodeBDAddr64Disp12Operand(MCInst &Inst, uint64_t Field,
242*eb9af294SRichard Sandiford                                                 uint64_t Address,
243*eb9af294SRichard Sandiford                                                 const void *Decoder) {
244*eb9af294SRichard Sandiford   return decodeBDAddr12Operand(Inst, Field, SystemZMC::GR64Regs);
245*eb9af294SRichard Sandiford }
246*eb9af294SRichard Sandiford 
247*eb9af294SRichard Sandiford static DecodeStatus decodeBDAddr64Disp20Operand(MCInst &Inst, uint64_t Field,
248*eb9af294SRichard Sandiford                                                 uint64_t Address,
249*eb9af294SRichard Sandiford                                                 const void *Decoder) {
250*eb9af294SRichard Sandiford   return decodeBDAddr20Operand(Inst, Field, SystemZMC::GR64Regs);
251*eb9af294SRichard Sandiford }
252*eb9af294SRichard Sandiford 
253*eb9af294SRichard Sandiford static DecodeStatus decodeBDXAddr64Disp12Operand(MCInst &Inst, uint64_t Field,
254*eb9af294SRichard Sandiford                                                  uint64_t Address,
255*eb9af294SRichard Sandiford                                                  const void *Decoder) {
256*eb9af294SRichard Sandiford   return decodeBDXAddr12Operand(Inst, Field, SystemZMC::GR64Regs);
257*eb9af294SRichard Sandiford }
258*eb9af294SRichard Sandiford 
259*eb9af294SRichard Sandiford static DecodeStatus decodeBDXAddr64Disp20Operand(MCInst &Inst, uint64_t Field,
260*eb9af294SRichard Sandiford                                                  uint64_t Address,
261*eb9af294SRichard Sandiford                                                  const void *Decoder) {
262*eb9af294SRichard Sandiford   return decodeBDXAddr20Operand(Inst, Field, SystemZMC::GR64Regs);
263*eb9af294SRichard Sandiford }
264*eb9af294SRichard Sandiford 
265*eb9af294SRichard Sandiford #include "SystemZGenDisassemblerTables.inc"
266*eb9af294SRichard Sandiford 
267*eb9af294SRichard Sandiford DecodeStatus SystemZDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
268*eb9af294SRichard Sandiford                                                  const MemoryObject &Region,
269*eb9af294SRichard Sandiford                                                  uint64_t Address,
270*eb9af294SRichard Sandiford                                                  raw_ostream &os,
271*eb9af294SRichard Sandiford                                                  raw_ostream &cs) const {
272*eb9af294SRichard Sandiford   // Get the first two bytes of the instruction.
273*eb9af294SRichard Sandiford   uint8_t Bytes[6];
274*eb9af294SRichard Sandiford   Size = 0;
275*eb9af294SRichard Sandiford   if (Region.readBytes(Address, 2, Bytes, 0) == -1)
276*eb9af294SRichard Sandiford     return MCDisassembler::Fail;
277*eb9af294SRichard Sandiford 
278*eb9af294SRichard Sandiford   // The top 2 bits of the first byte specify the size.
279*eb9af294SRichard Sandiford   const uint8_t *Table;
280*eb9af294SRichard Sandiford   if (Bytes[0] < 0x40) {
281*eb9af294SRichard Sandiford     Size = 2;
282*eb9af294SRichard Sandiford     Table = DecoderTable16;
283*eb9af294SRichard Sandiford   } else if (Bytes[0] < 0xc0) {
284*eb9af294SRichard Sandiford     Size = 4;
285*eb9af294SRichard Sandiford     Table = DecoderTable32;
286*eb9af294SRichard Sandiford   } else {
287*eb9af294SRichard Sandiford     Size = 6;
288*eb9af294SRichard Sandiford     Table = DecoderTable48;
289*eb9af294SRichard Sandiford   }
290*eb9af294SRichard Sandiford 
291*eb9af294SRichard Sandiford   // Read any remaining bytes.
292*eb9af294SRichard Sandiford   if (Size > 2 && Region.readBytes(Address + 2, Size - 2, Bytes + 2, 0) == -1)
293*eb9af294SRichard Sandiford     return MCDisassembler::Fail;
294*eb9af294SRichard Sandiford 
295*eb9af294SRichard Sandiford   // Construct the instruction.
296*eb9af294SRichard Sandiford   uint64_t Inst = 0;
297*eb9af294SRichard Sandiford   for (uint64_t I = 0; I < Size; ++I)
298*eb9af294SRichard Sandiford     Inst = (Inst << 8) | Bytes[I];
299*eb9af294SRichard Sandiford 
300*eb9af294SRichard Sandiford   return decodeInstruction(Table, MI, Inst, Address, this, STI);
301*eb9af294SRichard Sandiford }
302