]> git.proxmox.com Git - rustc.git/blob - src/llvm/lib/MC/MCDisassembler/EDOperand.cpp
Imported Upstream version 0.6
[rustc.git] / src / llvm / lib / MC / MCDisassembler / EDOperand.cpp
1 //===-- EDOperand.cpp - LLVM Enhanced Disassembler ------------------------===//
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 // This file implements the Enhanced Disassembly library's operand class. The
11 // operand is responsible for allowing evaluation given a particular register
12 // context.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #include "EDOperand.h"
17 #include "EDDisassembler.h"
18 #include "EDInst.h"
19 #include "llvm/MC/EDInstInfo.h"
20 #include "llvm/MC/MCInst.h"
21 using namespace llvm;
22
23 EDOperand::EDOperand(const EDDisassembler &disassembler,
24 const EDInst &inst,
25 unsigned int opIndex,
26 unsigned int &mcOpIndex) :
27 Disassembler(disassembler),
28 Inst(inst),
29 OpIndex(opIndex),
30 MCOpIndex(mcOpIndex) {
31 unsigned int numMCOperands = 0;
32
33 Triple::ArchType arch = Disassembler.TgtTriple.getArch();
34
35 if (arch == Triple::x86 ||
36 arch == Triple::x86_64) {
37 uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
38
39 switch (operandType) {
40 default:
41 break;
42 case kOperandTypeImmediate:
43 numMCOperands = 1;
44 break;
45 case kOperandTypeRegister:
46 numMCOperands = 1;
47 break;
48 case kOperandTypeX86Memory:
49 numMCOperands = 5;
50 break;
51 case kOperandTypeX86EffectiveAddress:
52 numMCOperands = 4;
53 break;
54 case kOperandTypeX86PCRelative:
55 numMCOperands = 1;
56 break;
57 }
58 }
59 else if (arch == Triple::arm ||
60 arch == Triple::thumb) {
61 uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
62
63 switch (operandType) {
64 default:
65 case kOperandTypeARMRegisterList:
66 case kOperandTypeARMDPRRegisterList:
67 case kOperandTypeARMSPRRegisterList:
68 break;
69 case kOperandTypeImmediate:
70 case kOperandTypeRegister:
71 case kOperandTypeARMBranchTarget:
72 case kOperandTypeARMSoImm:
73 case kOperandTypeARMRotImm:
74 case kOperandTypeThumb2SoImm:
75 case kOperandTypeARMSoImm2Part:
76 case kOperandTypeARMPredicate:
77 case kOperandTypeThumbITMask:
78 case kOperandTypeThumb2AddrModeImm8Offset:
79 case kOperandTypeARMTBAddrMode:
80 case kOperandTypeThumb2AddrModeImm8s4Offset:
81 case kOperandTypeARMAddrMode7:
82 case kOperandTypeThumb2AddrModeReg:
83 numMCOperands = 1;
84 break;
85 case kOperandTypeThumb2SoReg:
86 case kOperandTypeAddrModeImm12:
87 case kOperandTypeARMAddrMode2Offset:
88 case kOperandTypeARMAddrMode3Offset:
89 case kOperandTypeARMAddrMode4:
90 case kOperandTypeARMAddrMode5:
91 case kOperandTypeARMAddrModePC:
92 case kOperandTypeThumb2AddrModeImm8:
93 case kOperandTypeThumb2AddrModeImm12:
94 case kOperandTypeThumb2AddrModeImm8s4:
95 case kOperandTypeThumbAddrModeImmS1:
96 case kOperandTypeThumbAddrModeImmS2:
97 case kOperandTypeThumbAddrModeImmS4:
98 case kOperandTypeThumbAddrModeRR:
99 case kOperandTypeThumbAddrModeSP:
100 case kOperandTypeThumbAddrModePC:
101 numMCOperands = 2;
102 break;
103 case kOperandTypeARMSoReg:
104 case kOperandTypeLdStSOReg:
105 case kOperandTypeARMAddrMode2:
106 case kOperandTypeARMAddrMode3:
107 case kOperandTypeThumb2AddrModeSoReg:
108 case kOperandTypeThumbAddrModeRegS1:
109 case kOperandTypeThumbAddrModeRegS2:
110 case kOperandTypeThumbAddrModeRegS4:
111 case kOperandTypeARMAddrMode6Offset:
112 numMCOperands = 3;
113 break;
114 case kOperandTypeARMAddrMode6:
115 numMCOperands = 4;
116 break;
117 }
118 }
119
120 mcOpIndex += numMCOperands;
121 }
122
123 EDOperand::~EDOperand() {
124 }
125
126 int EDOperand::evaluate(uint64_t &result,
127 EDRegisterReaderCallback callback,
128 void *arg) {
129 uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
130
131 Triple::ArchType arch = Disassembler.TgtTriple.getArch();
132
133 switch (arch) {
134 default:
135 return -1;
136 case Triple::x86:
137 case Triple::x86_64:
138 switch (operandType) {
139 default:
140 return -1;
141 case kOperandTypeImmediate:
142 result = Inst.Inst->getOperand(MCOpIndex).getImm();
143 return 0;
144 case kOperandTypeRegister:
145 {
146 unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
147 return callback(&result, reg, arg);
148 }
149 case kOperandTypeX86PCRelative:
150 {
151 int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
152
153 uint64_t ripVal;
154
155 // TODO fix how we do this
156
157 if (callback(&ripVal, Disassembler.registerIDWithName("RIP"), arg))
158 return -1;
159
160 result = ripVal + displacement;
161 return 0;
162 }
163 case kOperandTypeX86Memory:
164 case kOperandTypeX86EffectiveAddress:
165 {
166 unsigned baseReg = Inst.Inst->getOperand(MCOpIndex).getReg();
167 uint64_t scaleAmount = Inst.Inst->getOperand(MCOpIndex+1).getImm();
168 unsigned indexReg = Inst.Inst->getOperand(MCOpIndex+2).getReg();
169 int64_t displacement = Inst.Inst->getOperand(MCOpIndex+3).getImm();
170
171 uint64_t addr = 0;
172
173 unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg();
174
175 if (segmentReg != 0 && arch == Triple::x86_64) {
176 unsigned fsID = Disassembler.registerIDWithName("FS");
177 unsigned gsID = Disassembler.registerIDWithName("GS");
178
179 if (segmentReg == fsID ||
180 segmentReg == gsID) {
181 uint64_t segmentBase;
182 if (!callback(&segmentBase, segmentReg, arg))
183 addr += segmentBase;
184 }
185 }
186
187 if (baseReg) {
188 uint64_t baseVal;
189 if (callback(&baseVal, baseReg, arg))
190 return -1;
191 addr += baseVal;
192 }
193
194 if (indexReg) {
195 uint64_t indexVal;
196 if (callback(&indexVal, indexReg, arg))
197 return -1;
198 addr += (scaleAmount * indexVal);
199 }
200
201 addr += displacement;
202
203 result = addr;
204 return 0;
205 }
206 } // switch (operandType)
207 case Triple::arm:
208 case Triple::thumb:
209 switch (operandType) {
210 default:
211 return -1;
212 case kOperandTypeImmediate:
213 if (!Inst.Inst->getOperand(MCOpIndex).isImm())
214 return -1;
215
216 result = Inst.Inst->getOperand(MCOpIndex).getImm();
217 return 0;
218 case kOperandTypeRegister:
219 {
220 if (!Inst.Inst->getOperand(MCOpIndex).isReg())
221 return -1;
222
223 unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
224 return callback(&result, reg, arg);
225 }
226 case kOperandTypeARMBranchTarget:
227 {
228 if (!Inst.Inst->getOperand(MCOpIndex).isImm())
229 return -1;
230
231 int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
232
233 uint64_t pcVal;
234
235 if (callback(&pcVal, Disassembler.registerIDWithName("PC"), arg))
236 return -1;
237
238 result = pcVal + displacement;
239 return 0;
240 }
241 }
242 }
243 }
244
245 int EDOperand::isRegister() {
246 return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeRegister);
247 }
248
249 unsigned EDOperand::regVal() {
250 return Inst.Inst->getOperand(MCOpIndex).getReg();
251 }
252
253 int EDOperand::isImmediate() {
254 return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeImmediate);
255 }
256
257 uint64_t EDOperand::immediateVal() {
258 return Inst.Inst->getOperand(MCOpIndex).getImm();
259 }
260
261 int EDOperand::isMemory() {
262 uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
263
264 switch (operandType) {
265 default:
266 return 0;
267 case kOperandTypeX86Memory:
268 case kOperandTypeX86PCRelative:
269 case kOperandTypeX86EffectiveAddress:
270 case kOperandTypeARMSoReg:
271 case kOperandTypeARMSoImm:
272 case kOperandTypeARMAddrMode2:
273 case kOperandTypeARMAddrMode2Offset:
274 case kOperandTypeARMAddrMode3:
275 case kOperandTypeARMAddrMode3Offset:
276 case kOperandTypeARMAddrMode4:
277 case kOperandTypeARMAddrMode5:
278 case kOperandTypeARMAddrMode6:
279 case kOperandTypeARMAddrMode7:
280 case kOperandTypeARMAddrModePC:
281 case kOperandTypeARMBranchTarget:
282 case kOperandTypeThumbAddrModeRegS1:
283 case kOperandTypeThumbAddrModeRegS2:
284 case kOperandTypeThumbAddrModeRegS4:
285 case kOperandTypeThumbAddrModeRR:
286 case kOperandTypeThumbAddrModeSP:
287 case kOperandTypeThumb2SoImm:
288 case kOperandTypeThumb2AddrModeImm8:
289 case kOperandTypeThumb2AddrModeImm8Offset:
290 case kOperandTypeThumb2AddrModeImm12:
291 case kOperandTypeThumb2AddrModeSoReg:
292 case kOperandTypeThumb2AddrModeImm8s4:
293 case kOperandTypeThumb2AddrModeReg:
294 return 1;
295 }
296 }
297
298 #ifdef __BLOCKS__
299 namespace {
300 struct RegisterReaderWrapper {
301 EDOperand::EDRegisterBlock_t regBlock;
302 };
303 }
304
305 static int readerWrapperCallback(uint64_t *value, unsigned regID, void *arg) {
306 RegisterReaderWrapper *wrapper = (RegisterReaderWrapper *)arg;
307 return wrapper->regBlock(value, regID);
308 }
309
310 int EDOperand::evaluate(uint64_t &result, EDRegisterBlock_t regBlock) {
311 RegisterReaderWrapper wrapper;
312 wrapper.regBlock = regBlock;
313 return evaluate(result, readerWrapperCallback, (void*)&wrapper);
314 }
315 #endif