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