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