Add instruction encodings / disassembly support for rus instructions.
[oota-llvm.git] / lib / Target / XCore / Disassembler / XCoreDisassembler.cpp
1 //===- XCoreDisassembler.cpp - Disassembler for XCore -----------*- 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 /// \file
11 /// \brief This file is part of the XCore Disassembler.
12 ///
13 //===----------------------------------------------------------------------===//
14
15 #include "XCore.h"
16 #include "XCoreRegisterInfo.h"
17 #include "llvm/MC/MCDisassembler.h"
18 #include "llvm/MC/MCFixedLenDisassembler.h"
19 #include "llvm/MC/MCInst.h"
20 #include "llvm/MC/MCSubtargetInfo.h"
21 #include "llvm/Support/MemoryObject.h"
22 #include "llvm/Support/TargetRegistry.h"
23
24 using namespace llvm;
25
26 typedef MCDisassembler::DecodeStatus DecodeStatus;
27
28 namespace {
29
30 /// \brief A disassembler class for XCore.
31 class XCoreDisassembler : public MCDisassembler {
32   const MCRegisterInfo *RegInfo;
33 public:
34   XCoreDisassembler(const MCSubtargetInfo &STI, const MCRegisterInfo *Info) :
35     MCDisassembler(STI), RegInfo(Info) {}
36
37   /// \brief See MCDisassembler.
38   virtual DecodeStatus getInstruction(MCInst &instr,
39                                       uint64_t &size,
40                                       const MemoryObject &region,
41                                       uint64_t address,
42                                       raw_ostream &vStream,
43                                       raw_ostream &cStream) const;
44
45   const MCRegisterInfo *getRegInfo() const { return RegInfo; }
46 };
47 }
48
49 static bool readInstruction16(const MemoryObject &region,
50                               uint64_t address,
51                               uint64_t &size,
52                               uint16_t &insn) {
53   uint8_t Bytes[4];
54
55   // We want to read exactly 2 Bytes of data.
56   if (region.readBytes(address, 2, Bytes, NULL) == -1) {
57     size = 0;
58     return false;
59   }
60   // Encoded as a little-endian 16-bit word in the stream.
61   insn = (Bytes[0] <<  0) | (Bytes[1] <<  8);
62   return true;
63 }
64
65 static unsigned getReg(const void *D, unsigned RC, unsigned RegNo) {
66   const XCoreDisassembler *Dis = static_cast<const XCoreDisassembler*>(D);
67   return *(Dis->getRegInfo()->getRegClass(RC).begin() + RegNo);
68 }
69
70 static DecodeStatus DecodeGRRegsRegisterClass(MCInst &Inst,
71                                               unsigned RegNo,
72                                               uint64_t Address,
73                                               const void *Decoder);
74
75 static DecodeStatus DecodeBitpOperand(MCInst &Inst, unsigned Val,
76                                       uint64_t Address, const void *Decoder);
77
78 static DecodeStatus Decode2RInstruction(MCInst &Inst,
79                                         unsigned RegNo,
80                                         uint64_t Address,
81                                         const void *Decoder);
82
83 static DecodeStatus DecodeR2RInstruction(MCInst &Inst,
84                                          unsigned RegNo,
85                                          uint64_t Address,
86                                          const void *Decoder);
87
88 static DecodeStatus Decode2RSrcDstInstruction(MCInst &Inst,
89                                               unsigned RegNo,
90                                               uint64_t Address,
91                                               const void *Decoder);
92
93 static DecodeStatus DecodeRUSInstruction(MCInst &Inst,
94                                          unsigned Insn,
95                                          uint64_t Address,
96                                          const void *Decoder);
97
98 static DecodeStatus DecodeRUSBitpInstruction(MCInst &Inst,
99                                              unsigned Insn,
100                                              uint64_t Address,
101                                              const void *Decoder);
102
103 static DecodeStatus DecodeRUSSrcDstBitpInstruction(MCInst &Inst,
104                                                    unsigned Insn,
105                                                    uint64_t Address,
106                                                    const void *Decoder);
107
108 #include "XCoreGenDisassemblerTables.inc"
109
110 static DecodeStatus DecodeGRRegsRegisterClass(MCInst &Inst,
111                                               unsigned RegNo,
112                                               uint64_t Address,
113                                               const void *Decoder)
114 {
115   if (RegNo > 11)
116     return MCDisassembler::Fail;
117   unsigned Reg = getReg(Decoder, XCore::GRRegsRegClassID, RegNo);
118   Inst.addOperand(MCOperand::CreateReg(Reg));
119   return MCDisassembler::Success;
120 }
121
122 static DecodeStatus DecodeBitpOperand(MCInst &Inst, unsigned Val,
123                                       uint64_t Address, const void *Decoder) {
124   if (Val > 11)
125     return MCDisassembler::Fail;
126   static unsigned Values[] = {
127     32 /*bpw*/, 1, 2, 3, 4, 5, 6, 7, 8, 16, 24, 32
128   };
129   Inst.addOperand(MCOperand::CreateImm(Values[Val]));
130   return MCDisassembler::Success;
131 }
132
133 static DecodeStatus
134 Decode2OpInstruction(unsigned Insn, unsigned &Op1, unsigned &Op2) {
135   unsigned Combined = fieldFromInstruction(Insn, 6, 5) +
136                       fieldFromInstruction(Insn, 5, 1) * 5 - 27;
137   if (Combined >= 9)
138     return MCDisassembler::Fail;
139
140   unsigned Op1High = Combined % 3;
141   unsigned Op2High = Combined / 3;
142   Op1 = (Op1High << 2) | fieldFromInstruction(Insn, 2, 2);
143   Op2 = (Op2High << 2) | fieldFromInstruction(Insn, 0, 2);
144   return MCDisassembler::Success;
145 }
146
147 static DecodeStatus
148 Decode2RInstruction(MCInst &Inst, unsigned Insn, uint64_t Address,
149                     const void *Decoder) {
150   unsigned Op1, Op2;
151   DecodeStatus S = Decode2OpInstruction(Insn, Op1, Op2);
152   if (S == MCDisassembler::Success) {
153     DecodeGRRegsRegisterClass(Inst, Op1, Address, Decoder);
154     DecodeGRRegsRegisterClass(Inst, Op2, Address, Decoder);
155   }
156   return S;
157 }
158
159 static DecodeStatus
160 DecodeR2RInstruction(MCInst &Inst, unsigned Insn, uint64_t Address,
161                      const void *Decoder) {
162   unsigned Op1, Op2;
163   DecodeStatus S = Decode2OpInstruction(Insn, Op2, Op1);
164   if (S == MCDisassembler::Success) {
165     DecodeGRRegsRegisterClass(Inst, Op1, Address, Decoder);
166     DecodeGRRegsRegisterClass(Inst, Op2, Address, Decoder);
167   }
168   return S;
169 }
170
171 static DecodeStatus
172 Decode2RSrcDstInstruction(MCInst &Inst, unsigned Insn, uint64_t Address,
173                           const void *Decoder) {
174   unsigned Op1, Op2;
175   DecodeStatus S = Decode2OpInstruction(Insn, Op1, Op2);
176   if (S == MCDisassembler::Success) {
177     DecodeGRRegsRegisterClass(Inst, Op1, Address, Decoder);
178     DecodeGRRegsRegisterClass(Inst, Op1, Address, Decoder);
179     DecodeGRRegsRegisterClass(Inst, Op2, Address, Decoder);
180   }
181   return S;
182 }
183
184 static DecodeStatus
185 DecodeRUSInstruction(MCInst &Inst, unsigned Insn, uint64_t Address,
186                      const void *Decoder) {
187   unsigned Op1, Op2;
188   DecodeStatus S = Decode2OpInstruction(Insn, Op1, Op2);
189   if (S == MCDisassembler::Success) {
190     DecodeGRRegsRegisterClass(Inst, Op1, Address, Decoder);
191     Inst.addOperand(MCOperand::CreateImm(Op2));
192   }
193   return S;
194 }
195
196 static DecodeStatus
197 DecodeRUSBitpInstruction(MCInst &Inst, unsigned Insn, uint64_t Address,
198                          const void *Decoder) {
199   unsigned Op1, Op2;
200   DecodeStatus S = Decode2OpInstruction(Insn, Op1, Op2);
201   if (S == MCDisassembler::Success) {
202     DecodeGRRegsRegisterClass(Inst, Op1, Address, Decoder);
203     DecodeBitpOperand(Inst, Op2, Address, Decoder);
204   }
205   return S;
206 }
207
208 static DecodeStatus
209 DecodeRUSSrcDstBitpInstruction(MCInst &Inst, unsigned Insn, uint64_t Address,
210                                const void *Decoder) {
211   unsigned Op1, Op2;
212   DecodeStatus S = Decode2OpInstruction(Insn, Op1, Op2);
213   if (S == MCDisassembler::Success) {
214     DecodeGRRegsRegisterClass(Inst, Op1, Address, Decoder);
215     DecodeGRRegsRegisterClass(Inst, Op1, Address, Decoder);
216     DecodeBitpOperand(Inst, Op2, Address, Decoder);
217   }
218   return S;
219 }
220
221 MCDisassembler::DecodeStatus
222 XCoreDisassembler::getInstruction(MCInst &instr,
223                                   uint64_t &Size,
224                                   const MemoryObject &Region,
225                                   uint64_t Address,
226                                   raw_ostream &vStream,
227                                   raw_ostream &cStream) const {
228   uint16_t low;
229
230   if (!readInstruction16(Region, Address, Size, low)) {
231     return Fail;
232   }
233
234   // Calling the auto-generated decoder function.
235   DecodeStatus Result = decodeInstruction(DecoderTable16, instr, low, Address,
236                              this, STI);
237   if (Result != Fail) {
238     Size = 2;
239     return Result;
240   }
241
242   return Fail;
243 }
244
245 namespace llvm {
246   extern Target TheXCoreTarget;
247 }
248
249 static MCDisassembler *createXCoreDisassembler(const Target &T,
250                                                const MCSubtargetInfo &STI) {
251   return new XCoreDisassembler(STI, T.createMCRegInfo(""));
252 }
253
254 extern "C" void LLVMInitializeXCoreDisassembler() {
255   // Register the disassembler.
256   TargetRegistry::RegisterMCDisassembler(TheXCoreTarget,
257                                          createXCoreDisassembler);
258 }