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
EDOperand(const EDDisassembler & disassembler,const EDInst & inst,unsigned int opIndex,unsigned int & mcOpIndex)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 if (Disassembler.Key.Arch == Triple::x86 ||
34 Disassembler.Key.Arch == Triple::x86_64) {
35 uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
36
37 switch (operandType) {
38 default:
39 break;
40 case kOperandTypeImmediate:
41 numMCOperands = 1;
42 break;
43 case kOperandTypeRegister:
44 numMCOperands = 1;
45 break;
46 case kOperandTypeX86Memory:
47 numMCOperands = 5;
48 break;
49 case kOperandTypeX86EffectiveAddress:
50 numMCOperands = 4;
51 break;
52 case kOperandTypeX86PCRelative:
53 numMCOperands = 1;
54 break;
55 }
56 }
57 else if (Disassembler.Key.Arch == Triple::arm ||
58 Disassembler.Key.Arch == Triple::thumb) {
59 uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
60
61 switch (operandType) {
62 default:
63 case kOperandTypeARMRegisterList:
64 case kOperandTypeARMDPRRegisterList:
65 case kOperandTypeARMSPRRegisterList:
66 break;
67 case kOperandTypeImmediate:
68 case kOperandTypeRegister:
69 case kOperandTypeARMBranchTarget:
70 case kOperandTypeARMSoImm:
71 case kOperandTypeARMRotImm:
72 case kOperandTypeThumb2SoImm:
73 case kOperandTypeARMSoImm2Part:
74 case kOperandTypeARMPredicate:
75 case kOperandTypeThumbITMask:
76 case kOperandTypeThumb2AddrModeImm8Offset:
77 case kOperandTypeARMTBAddrMode:
78 case kOperandTypeThumb2AddrModeImm8s4Offset:
79 case kOperandTypeARMAddrMode7:
80 case kOperandTypeThumb2AddrModeReg:
81 numMCOperands = 1;
82 break;
83 case kOperandTypeThumb2SoReg:
84 case kOperandTypeAddrModeImm12:
85 case kOperandTypeARMAddrMode2Offset:
86 case kOperandTypeARMAddrMode3Offset:
87 case kOperandTypeARMAddrMode4:
88 case kOperandTypeARMAddrMode5:
89 case kOperandTypeARMAddrModePC:
90 case kOperandTypeThumb2AddrModeImm8:
91 case kOperandTypeThumb2AddrModeImm12:
92 case kOperandTypeThumb2AddrModeImm8s4:
93 case kOperandTypeThumbAddrModeImmS1:
94 case kOperandTypeThumbAddrModeImmS2:
95 case kOperandTypeThumbAddrModeImmS4:
96 case kOperandTypeThumbAddrModeRR:
97 case kOperandTypeThumbAddrModeSP:
98 case kOperandTypeThumbAddrModePC:
99 numMCOperands = 2;
100 break;
101 case kOperandTypeARMSoReg:
102 case kOperandTypeLdStSOReg:
103 case kOperandTypeARMAddrMode2:
104 case kOperandTypeARMAddrMode3:
105 case kOperandTypeThumb2AddrModeSoReg:
106 case kOperandTypeThumbAddrModeRegS1:
107 case kOperandTypeThumbAddrModeRegS2:
108 case kOperandTypeThumbAddrModeRegS4:
109 case kOperandTypeARMAddrMode6Offset:
110 numMCOperands = 3;
111 break;
112 case kOperandTypeARMAddrMode6:
113 numMCOperands = 4;
114 break;
115 }
116 }
117
118 mcOpIndex += numMCOperands;
119 }
120
~EDOperand()121 EDOperand::~EDOperand() {
122 }
123
evaluate(uint64_t & result,EDRegisterReaderCallback callback,void * arg)124 int EDOperand::evaluate(uint64_t &result,
125 EDRegisterReaderCallback callback,
126 void *arg) {
127 uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
128
129 switch (Disassembler.Key.Arch) {
130 default:
131 return -1;
132 case Triple::x86:
133 case Triple::x86_64:
134 switch (operandType) {
135 default:
136 return -1;
137 case kOperandTypeImmediate:
138 result = Inst.Inst->getOperand(MCOpIndex).getImm();
139 return 0;
140 case kOperandTypeRegister:
141 {
142 unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
143 return callback(&result, reg, arg);
144 }
145 case kOperandTypeX86PCRelative:
146 {
147 int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
148
149 uint64_t ripVal;
150
151 // TODO fix how we do this
152
153 if (callback(&ripVal, Disassembler.registerIDWithName("RIP"), arg))
154 return -1;
155
156 result = ripVal + displacement;
157 return 0;
158 }
159 case kOperandTypeX86Memory:
160 case kOperandTypeX86EffectiveAddress:
161 {
162 unsigned baseReg = Inst.Inst->getOperand(MCOpIndex).getReg();
163 uint64_t scaleAmount = Inst.Inst->getOperand(MCOpIndex+1).getImm();
164 unsigned indexReg = Inst.Inst->getOperand(MCOpIndex+2).getReg();
165 int64_t displacement = Inst.Inst->getOperand(MCOpIndex+3).getImm();
166
167 uint64_t addr = 0;
168
169 unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg();
170
171 if (segmentReg != 0 && Disassembler.Key.Arch == Triple::x86_64) {
172 unsigned fsID = Disassembler.registerIDWithName("FS");
173 unsigned gsID = Disassembler.registerIDWithName("GS");
174
175 if (segmentReg == fsID ||
176 segmentReg == gsID) {
177 uint64_t segmentBase;
178 if (!callback(&segmentBase, segmentReg, arg))
179 addr += segmentBase;
180 }
181 }
182
183 if (baseReg) {
184 uint64_t baseVal;
185 if (callback(&baseVal, baseReg, arg))
186 return -1;
187 addr += baseVal;
188 }
189
190 if (indexReg) {
191 uint64_t indexVal;
192 if (callback(&indexVal, indexReg, arg))
193 return -1;
194 addr += (scaleAmount * indexVal);
195 }
196
197 addr += displacement;
198
199 result = addr;
200 return 0;
201 }
202 } // switch (operandType)
203 break;
204 case Triple::arm:
205 case Triple::thumb:
206 switch (operandType) {
207 default:
208 return -1;
209 case kOperandTypeImmediate:
210 if (!Inst.Inst->getOperand(MCOpIndex).isImm())
211 return -1;
212
213 result = Inst.Inst->getOperand(MCOpIndex).getImm();
214 return 0;
215 case kOperandTypeRegister:
216 {
217 if (!Inst.Inst->getOperand(MCOpIndex).isReg())
218 return -1;
219
220 unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
221 return callback(&result, reg, arg);
222 }
223 case kOperandTypeARMBranchTarget:
224 {
225 if (!Inst.Inst->getOperand(MCOpIndex).isImm())
226 return -1;
227
228 int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
229
230 uint64_t pcVal;
231
232 if (callback(&pcVal, Disassembler.registerIDWithName("PC"), arg))
233 return -1;
234
235 result = pcVal + displacement;
236 return 0;
237 }
238 }
239 break;
240 }
241
242 return -1;
243 }
244
isRegister()245 int EDOperand::isRegister() {
246 return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeRegister);
247 }
248
regVal()249 unsigned EDOperand::regVal() {
250 return Inst.Inst->getOperand(MCOpIndex).getReg();
251 }
252
isImmediate()253 int EDOperand::isImmediate() {
254 return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeImmediate);
255 }
256
immediateVal()257 uint64_t EDOperand::immediateVal() {
258 return Inst.Inst->getOperand(MCOpIndex).getImm();
259 }
260
isMemory()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
readerWrapperCallback(uint64_t * value,unsigned regID,void * arg)305 static int readerWrapperCallback(uint64_t *value, unsigned regID, void *arg) {
306 RegisterReaderWrapper *wrapper = (RegisterReaderWrapper *)arg;
307 return wrapper->regBlock(value, regID);
308 }
309
evaluate(uint64_t & result,EDRegisterBlock_t regBlock)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
316