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