blob: fc3c38d2f3430d6fe15b3fcc09d45f3d26e0e931 [file] [log] [blame]
Richard Sandifordeb9af292013-05-14 10:17:52 +00001//===-- 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,
Richard Sandiford09de0912013-11-13 16:57:53 +000051 const unsigned *Regs) {
Richard Sandifordeb9af292013-05-14 10:17:52 +000052 assert(RegNo < 16 && "Invalid register");
Richard Sandiford09de0912013-11-13 16:57:53 +000053 RegNo = Regs[RegNo];
54 if (RegNo == 0)
55 return MCDisassembler::Fail;
Richard Sandifordeb9af292013-05-14 10:17:52 +000056 Inst.addOperand(MCOperand::CreateReg(RegNo));
57 return MCDisassembler::Success;
58}
59
60static DecodeStatus DecodeGR32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
61 uint64_t Address,
62 const void *Decoder) {
63 return decodeRegisterClass(Inst, RegNo, SystemZMC::GR32Regs);
64}
65
Richard Sandifordf9496062013-09-30 10:45:16 +000066static DecodeStatus DecodeGRH32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
67 uint64_t Address,
68 const void *Decoder) {
69 return decodeRegisterClass(Inst, RegNo, SystemZMC::GRH32Regs);
70}
71
Richard Sandifordeb9af292013-05-14 10:17:52 +000072static DecodeStatus DecodeGR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
73 uint64_t Address,
74 const void *Decoder) {
75 return decodeRegisterClass(Inst, RegNo, SystemZMC::GR64Regs);
76}
77
78static DecodeStatus DecodeGR128BitRegisterClass(MCInst &Inst, uint64_t RegNo,
79 uint64_t Address,
80 const void *Decoder) {
81 return decodeRegisterClass(Inst, RegNo, SystemZMC::GR128Regs);
82}
83
84static DecodeStatus DecodeADDR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
85 uint64_t Address,
86 const void *Decoder) {
Richard Sandiford09de0912013-11-13 16:57:53 +000087 return decodeRegisterClass(Inst, RegNo, SystemZMC::GR64Regs);
Richard Sandifordeb9af292013-05-14 10:17:52 +000088}
89
90static DecodeStatus DecodeFP32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
91 uint64_t Address,
92 const void *Decoder) {
93 return decodeRegisterClass(Inst, RegNo, SystemZMC::FP32Regs);
94}
95
96static DecodeStatus DecodeFP64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
97 uint64_t Address,
98 const void *Decoder) {
99 return decodeRegisterClass(Inst, RegNo, SystemZMC::FP64Regs);
100}
101
102static DecodeStatus DecodeFP128BitRegisterClass(MCInst &Inst, uint64_t RegNo,
103 uint64_t Address,
104 const void *Decoder) {
105 return decodeRegisterClass(Inst, RegNo, SystemZMC::FP128Regs);
106}
107
108template<unsigned N>
109static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm) {
110 assert(isUInt<N>(Imm) && "Invalid immediate");
111 Inst.addOperand(MCOperand::CreateImm(Imm));
112 return MCDisassembler::Success;
113}
114
115template<unsigned N>
116static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm) {
117 assert(isUInt<N>(Imm) && "Invalid immediate");
118 Inst.addOperand(MCOperand::CreateImm(SignExtend64<N>(Imm)));
119 return MCDisassembler::Success;
120}
121
122static DecodeStatus decodeAccessRegOperand(MCInst &Inst, uint64_t Imm,
123 uint64_t Address,
124 const void *Decoder) {
125 return decodeUImmOperand<4>(Inst, Imm);
126}
127
128static DecodeStatus decodeU4ImmOperand(MCInst &Inst, uint64_t Imm,
129 uint64_t Address, const void *Decoder) {
130 return decodeUImmOperand<4>(Inst, Imm);
131}
132
133static DecodeStatus decodeU6ImmOperand(MCInst &Inst, uint64_t Imm,
134 uint64_t Address, const void *Decoder) {
135 return decodeUImmOperand<6>(Inst, Imm);
136}
137
138static DecodeStatus decodeU8ImmOperand(MCInst &Inst, uint64_t Imm,
139 uint64_t Address, const void *Decoder) {
140 return decodeUImmOperand<8>(Inst, Imm);
141}
142
143static DecodeStatus decodeU16ImmOperand(MCInst &Inst, uint64_t Imm,
144 uint64_t Address, const void *Decoder) {
145 return decodeUImmOperand<16>(Inst, Imm);
146}
147
148static DecodeStatus decodeU32ImmOperand(MCInst &Inst, uint64_t Imm,
149 uint64_t Address, const void *Decoder) {
150 return decodeUImmOperand<32>(Inst, Imm);
151}
152
153static DecodeStatus decodeS8ImmOperand(MCInst &Inst, uint64_t Imm,
154 uint64_t Address, const void *Decoder) {
155 return decodeSImmOperand<8>(Inst, Imm);
156}
157
158static DecodeStatus decodeS16ImmOperand(MCInst &Inst, uint64_t Imm,
159 uint64_t Address, const void *Decoder) {
160 return decodeSImmOperand<16>(Inst, Imm);
161}
162
163static DecodeStatus decodeS32ImmOperand(MCInst &Inst, uint64_t Imm,
164 uint64_t Address, const void *Decoder) {
165 return decodeSImmOperand<32>(Inst, Imm);
166}
167
168template<unsigned N>
169static DecodeStatus decodePCDBLOperand(MCInst &Inst, uint64_t Imm,
170 uint64_t Address) {
171 assert(isUInt<N>(Imm) && "Invalid PC-relative offset");
172 Inst.addOperand(MCOperand::CreateImm(SignExtend64<N>(Imm) * 2 + Address));
173 return MCDisassembler::Success;
174}
175
176static DecodeStatus decodePC16DBLOperand(MCInst &Inst, uint64_t Imm,
177 uint64_t Address,
178 const void *Decoder) {
179 return decodePCDBLOperand<16>(Inst, Imm, Address);
180}
181
182static DecodeStatus decodePC32DBLOperand(MCInst &Inst, uint64_t Imm,
183 uint64_t Address,
184 const void *Decoder) {
185 return decodePCDBLOperand<32>(Inst, Imm, Address);
186}
187
188static DecodeStatus decodeBDAddr12Operand(MCInst &Inst, uint64_t Field,
189 const unsigned *Regs) {
190 uint64_t Base = Field >> 12;
191 uint64_t Disp = Field & 0xfff;
192 assert(Base < 16 && "Invalid BDAddr12");
193 Inst.addOperand(MCOperand::CreateReg(Base == 0 ? 0 : Regs[Base]));
194 Inst.addOperand(MCOperand::CreateImm(Disp));
195 return MCDisassembler::Success;
196}
197
198static DecodeStatus decodeBDAddr20Operand(MCInst &Inst, uint64_t Field,
199 const unsigned *Regs) {
200 uint64_t Base = Field >> 20;
201 uint64_t Disp = ((Field << 12) & 0xff000) | ((Field >> 8) & 0xfff);
202 assert(Base < 16 && "Invalid BDAddr20");
203 Inst.addOperand(MCOperand::CreateReg(Base == 0 ? 0 : Regs[Base]));
204 Inst.addOperand(MCOperand::CreateImm(SignExtend64<20>(Disp)));
205 return MCDisassembler::Success;
206}
207
208static DecodeStatus decodeBDXAddr12Operand(MCInst &Inst, uint64_t Field,
209 const unsigned *Regs) {
210 uint64_t Index = Field >> 16;
211 uint64_t Base = (Field >> 12) & 0xf;
212 uint64_t Disp = Field & 0xfff;
213 assert(Index < 16 && "Invalid BDXAddr12");
214 Inst.addOperand(MCOperand::CreateReg(Base == 0 ? 0 : Regs[Base]));
215 Inst.addOperand(MCOperand::CreateImm(Disp));
216 Inst.addOperand(MCOperand::CreateReg(Index == 0 ? 0 : Regs[Index]));
217 return MCDisassembler::Success;
218}
219
220static DecodeStatus decodeBDXAddr20Operand(MCInst &Inst, uint64_t Field,
221 const unsigned *Regs) {
222 uint64_t Index = Field >> 24;
223 uint64_t Base = (Field >> 20) & 0xf;
224 uint64_t Disp = ((Field & 0xfff00) >> 8) | ((Field & 0xff) << 12);
225 assert(Index < 16 && "Invalid BDXAddr20");
226 Inst.addOperand(MCOperand::CreateReg(Base == 0 ? 0 : Regs[Base]));
227 Inst.addOperand(MCOperand::CreateImm(SignExtend64<20>(Disp)));
228 Inst.addOperand(MCOperand::CreateReg(Index == 0 ? 0 : Regs[Index]));
229 return MCDisassembler::Success;
230}
231
Richard Sandiford1d959002013-07-02 14:56:45 +0000232static DecodeStatus decodeBDLAddr12Len8Operand(MCInst &Inst, uint64_t Field,
233 const unsigned *Regs) {
234 uint64_t Length = Field >> 16;
235 uint64_t Base = (Field >> 12) & 0xf;
236 uint64_t Disp = Field & 0xfff;
237 assert(Length < 256 && "Invalid BDLAddr12Len8");
238 Inst.addOperand(MCOperand::CreateReg(Base == 0 ? 0 : Regs[Base]));
239 Inst.addOperand(MCOperand::CreateImm(Disp));
240 Inst.addOperand(MCOperand::CreateImm(Length + 1));
241 return MCDisassembler::Success;
242}
243
Richard Sandifordeb9af292013-05-14 10:17:52 +0000244static DecodeStatus decodeBDAddr32Disp12Operand(MCInst &Inst, uint64_t Field,
245 uint64_t Address,
246 const void *Decoder) {
247 return decodeBDAddr12Operand(Inst, Field, SystemZMC::GR32Regs);
248}
249
250static DecodeStatus decodeBDAddr32Disp20Operand(MCInst &Inst, uint64_t Field,
251 uint64_t Address,
252 const void *Decoder) {
253 return decodeBDAddr20Operand(Inst, Field, SystemZMC::GR32Regs);
254}
255
256static DecodeStatus decodeBDAddr64Disp12Operand(MCInst &Inst, uint64_t Field,
257 uint64_t Address,
258 const void *Decoder) {
259 return decodeBDAddr12Operand(Inst, Field, SystemZMC::GR64Regs);
260}
261
262static DecodeStatus decodeBDAddr64Disp20Operand(MCInst &Inst, uint64_t Field,
263 uint64_t Address,
264 const void *Decoder) {
265 return decodeBDAddr20Operand(Inst, Field, SystemZMC::GR64Regs);
266}
267
268static DecodeStatus decodeBDXAddr64Disp12Operand(MCInst &Inst, uint64_t Field,
269 uint64_t Address,
270 const void *Decoder) {
271 return decodeBDXAddr12Operand(Inst, Field, SystemZMC::GR64Regs);
272}
273
274static DecodeStatus decodeBDXAddr64Disp20Operand(MCInst &Inst, uint64_t Field,
275 uint64_t Address,
276 const void *Decoder) {
277 return decodeBDXAddr20Operand(Inst, Field, SystemZMC::GR64Regs);
278}
279
Richard Sandiford1d959002013-07-02 14:56:45 +0000280static DecodeStatus decodeBDLAddr64Disp12Len8Operand(MCInst &Inst,
281 uint64_t Field,
282 uint64_t Address,
283 const void *Decoder) {
284 return decodeBDLAddr12Len8Operand(Inst, Field, SystemZMC::GR64Regs);
285}
286
Richard Sandifordeb9af292013-05-14 10:17:52 +0000287#include "SystemZGenDisassemblerTables.inc"
288
289DecodeStatus SystemZDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
290 const MemoryObject &Region,
291 uint64_t Address,
292 raw_ostream &os,
293 raw_ostream &cs) const {
294 // Get the first two bytes of the instruction.
295 uint8_t Bytes[6];
296 Size = 0;
Benjamin Kramer534d3a42013-05-24 10:54:58 +0000297 if (Region.readBytes(Address, 2, Bytes) == -1)
Richard Sandifordeb9af292013-05-14 10:17:52 +0000298 return MCDisassembler::Fail;
299
300 // The top 2 bits of the first byte specify the size.
301 const uint8_t *Table;
302 if (Bytes[0] < 0x40) {
303 Size = 2;
304 Table = DecoderTable16;
305 } else if (Bytes[0] < 0xc0) {
306 Size = 4;
307 Table = DecoderTable32;
308 } else {
309 Size = 6;
310 Table = DecoderTable48;
311 }
312
313 // Read any remaining bytes.
Benjamin Kramer534d3a42013-05-24 10:54:58 +0000314 if (Size > 2 && Region.readBytes(Address + 2, Size - 2, Bytes + 2) == -1)
Richard Sandifordeb9af292013-05-14 10:17:52 +0000315 return MCDisassembler::Fail;
316
317 // Construct the instruction.
318 uint64_t Inst = 0;
319 for (uint64_t I = 0; I < Size; ++I)
320 Inst = (Inst << 8) | Bytes[I];
321
322 return decodeInstruction(Table, MI, Inst, Address, this, STI);
323}