blob: 93efd47094473694ad75a3d6214a1cb2f62c513a [file] [log] [blame]
Sean Callananee5dfd42010-02-01 08:49:35 +00001//===-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 "EDDisassembler.h"
17#include "EDInst.h"
18#include "EDOperand.h"
19
20#include "llvm/MC/MCInst.h"
21
22using namespace llvm;
23
24EDOperand::EDOperand(const EDDisassembler &disassembler,
25 const EDInst &inst,
26 unsigned int opIndex,
27 unsigned int &mcOpIndex) :
28 Disassembler(disassembler),
29 Inst(inst),
30 OpIndex(opIndex),
31 MCOpIndex(mcOpIndex) {
32 unsigned int numMCOperands = 0;
33
Sean Callanan8f993b82010-04-08 00:48:21 +000034 if (Disassembler.Key.Arch == Triple::x86 ||
35 Disassembler.Key.Arch == Triple::x86_64) {
36 uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
Sean Callananee5dfd42010-02-01 08:49:35 +000037
Sean Callanan8f993b82010-04-08 00:48:21 +000038 switch (operandType) {
39 default:
40 break;
41 case kOperandTypeImmediate:
Sean Callananee5dfd42010-02-01 08:49:35 +000042 numMCOperands = 1;
Sean Callanan8f993b82010-04-08 00:48:21 +000043 break;
44 case kOperandTypeRegister:
Sean Callananee5dfd42010-02-01 08:49:35 +000045 numMCOperands = 1;
Sean Callanan8f993b82010-04-08 00:48:21 +000046 break;
47 case kOperandTypeX86Memory:
48 numMCOperands = 5;
49 break;
50 case kOperandTypeX86EffectiveAddress:
Sean Callananee5dfd42010-02-01 08:49:35 +000051 numMCOperands = 4;
Sean Callanan8f993b82010-04-08 00:48:21 +000052 break;
53 case kOperandTypeX86PCRelative:
54 numMCOperands = 1;
55 break;
56 }
57 }
58 else if (Disassembler.Key.Arch == Triple::arm ||
59 Disassembler.Key.Arch == Triple::thumb) {
60 uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
61
62 switch (operandType) {
63 default:
64 case kOperandTypeARMRegisterList:
65 break;
66 case kOperandTypeImmediate:
67 case kOperandTypeRegister:
68 case kOperandTypeARMBranchTarget:
69 case kOperandTypeARMSoImm:
70 case kOperandTypeThumb2SoImm:
71 case kOperandTypeARMSoImm2Part:
72 case kOperandTypeARMPredicate:
73 case kOperandTypeThumbITMask:
74 case kOperandTypeThumb2AddrModeImm8Offset:
75 case kOperandTypeARMTBAddrMode:
76 case kOperandTypeThumb2AddrModeImm8s4Offset:
77 numMCOperands = 1;
78 break;
79 case kOperandTypeThumb2SoReg:
80 case kOperandTypeARMAddrMode2Offset:
81 case kOperandTypeARMAddrMode3Offset:
82 case kOperandTypeARMAddrMode4:
83 case kOperandTypeARMAddrMode5:
84 case kOperandTypeARMAddrModePC:
85 case kOperandTypeThumb2AddrModeImm8:
86 case kOperandTypeThumb2AddrModeImm12:
87 case kOperandTypeThumb2AddrModeImm8s4:
88 case kOperandTypeThumbAddrModeRR:
89 case kOperandTypeThumbAddrModeSP:
90 numMCOperands = 2;
91 break;
92 case kOperandTypeARMSoReg:
93 case kOperandTypeARMAddrMode2:
94 case kOperandTypeARMAddrMode3:
95 case kOperandTypeThumb2AddrModeSoReg:
96 case kOperandTypeThumbAddrModeS1:
97 case kOperandTypeThumbAddrModeS2:
98 case kOperandTypeThumbAddrModeS4:
99 case kOperandTypeARMAddrMode6Offset:
100 numMCOperands = 3;
101 break;
102 case kOperandTypeARMAddrMode6:
103 numMCOperands = 4;
104 break;
Sean Callananee5dfd42010-02-01 08:49:35 +0000105 }
106 }
107
108 mcOpIndex += numMCOperands;
109}
110
111EDOperand::~EDOperand() {
112}
113
114int EDOperand::evaluate(uint64_t &result,
115 EDRegisterReaderCallback callback,
116 void *arg) {
Sean Callanan8f993b82010-04-08 00:48:21 +0000117 uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
118
119 switch (Disassembler.Key.Arch) {
120 default:
121 return -1;
122 case Triple::x86:
123 case Triple::x86_64:
124 switch (operandType) {
125 default:
126 return -1;
127 case kOperandTypeImmediate:
Sean Callananee5dfd42010-02-01 08:49:35 +0000128 result = Inst.Inst->getOperand(MCOpIndex).getImm();
129 return 0;
Sean Callanan8f993b82010-04-08 00:48:21 +0000130 case kOperandTypeRegister:
131 {
Sean Callananee5dfd42010-02-01 08:49:35 +0000132 unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
133 return callback(&result, reg, arg);
134 }
Sean Callanan8f993b82010-04-08 00:48:21 +0000135 case kOperandTypeX86PCRelative:
136 {
137 int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
Sean Callananee5dfd42010-02-01 08:49:35 +0000138
Sean Callanan8f993b82010-04-08 00:48:21 +0000139 uint64_t ripVal;
Sean Callananee5dfd42010-02-01 08:49:35 +0000140
Sean Callanan8f993b82010-04-08 00:48:21 +0000141 // TODO fix how we do this
Sean Callananee5dfd42010-02-01 08:49:35 +0000142
Sean Callanan8f993b82010-04-08 00:48:21 +0000143 if (callback(&ripVal, Disassembler.registerIDWithName("RIP"), arg))
144 return -1;
Sean Callananee5dfd42010-02-01 08:49:35 +0000145
Sean Callanan8f993b82010-04-08 00:48:21 +0000146 result = ripVal + displacement;
147 return 0;
Sean Callananee5dfd42010-02-01 08:49:35 +0000148 }
Sean Callanan8f993b82010-04-08 00:48:21 +0000149 case kOperandTypeX86Memory:
150 case kOperandTypeX86EffectiveAddress:
151 {
152 unsigned baseReg = Inst.Inst->getOperand(MCOpIndex).getReg();
153 uint64_t scaleAmount = Inst.Inst->getOperand(MCOpIndex+1).getImm();
154 unsigned indexReg = Inst.Inst->getOperand(MCOpIndex+2).getReg();
155 int64_t displacement = Inst.Inst->getOperand(MCOpIndex+3).getImm();
156 //unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg();
157
158 uint64_t addr = 0;
159
160 if (baseReg) {
161 uint64_t baseVal;
162 if (callback(&baseVal, baseReg, arg))
163 return -1;
164 addr += baseVal;
165 }
166
167 if (indexReg) {
168 uint64_t indexVal;
169 if (callback(&indexVal, indexReg, arg))
170 return -1;
171 addr += (scaleAmount * indexVal);
172 }
173
174 addr += displacement;
175
176 result = addr;
177 return 0;
178 }
179 }
180 break;
181 case Triple::arm:
182 case Triple::thumb:
183 switch (operandType) {
184 default:
185 return -1;
186 case kOperandTypeImmediate:
187 result = Inst.Inst->getOperand(MCOpIndex).getImm();
188 return 0;
189 case kOperandTypeRegister:
190 {
191 unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
192 return callback(&result, reg, arg);
193 }
194 case kOperandTypeARMBranchTarget:
195 {
196 int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
197
198 uint64_t pcVal;
199
200 if (callback(&pcVal, Disassembler.registerIDWithName("PC"), arg))
201 return -1;
202
203 result = pcVal + displacement;
204 return 0;
205 }
206 }
Sean Callananee5dfd42010-02-01 08:49:35 +0000207 }
208
209 return -1;
210}
211
Sean Callanan76706582010-02-04 01:43:08 +0000212int EDOperand::isRegister() {
Sean Callanan8f993b82010-04-08 00:48:21 +0000213 return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeRegister);
Sean Callanan76706582010-02-04 01:43:08 +0000214}
215
216unsigned EDOperand::regVal() {
217 return Inst.Inst->getOperand(MCOpIndex).getReg();
218}
219
220int EDOperand::isImmediate() {
Sean Callanan8f993b82010-04-08 00:48:21 +0000221 return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeImmediate);
Sean Callanan76706582010-02-04 01:43:08 +0000222}
223
224uint64_t EDOperand::immediateVal() {
225 return Inst.Inst->getOperand(MCOpIndex).getImm();
226}
227
228int EDOperand::isMemory() {
Sean Callanan8f993b82010-04-08 00:48:21 +0000229 switch (Inst.ThisInstInfo->operandFlags[OpIndex]) {
230 default:
231 return 0;
232 case kOperandTypeX86Memory:
233 case kOperandTypeARMSoReg:
234 case kOperandTypeARMSoImm:
235 case kOperandTypeARMAddrMode2:
236 case kOperandTypeARMAddrMode2Offset:
237 case kOperandTypeARMAddrMode3:
238 case kOperandTypeARMAddrMode3Offset:
239 case kOperandTypeARMAddrMode4:
240 case kOperandTypeARMAddrMode5:
241 case kOperandTypeARMAddrMode6:
242 case kOperandTypeARMAddrModePC:
243 case kOperandTypeThumbAddrModeS1:
244 case kOperandTypeThumbAddrModeS2:
245 case kOperandTypeThumbAddrModeS4:
246 case kOperandTypeThumbAddrModeRR:
247 case kOperandTypeThumbAddrModeSP:
248 case kOperandTypeThumb2SoImm:
249 case kOperandTypeThumb2AddrModeImm8:
250 case kOperandTypeThumb2AddrModeImm8Offset:
251 case kOperandTypeThumb2AddrModeImm12:
252 case kOperandTypeThumb2AddrModeSoReg:
253 case kOperandTypeThumb2AddrModeImm8s4:
254 return 1;
255 }
Sean Callanan76706582010-02-04 01:43:08 +0000256}
257
Sean Callananee5dfd42010-02-01 08:49:35 +0000258#ifdef __BLOCKS__
259struct RegisterReaderWrapper {
260 EDRegisterBlock_t regBlock;
261};
262
263int readerWrapperCallback(uint64_t *value,
264 unsigned regID,
265 void *arg) {
266 struct RegisterReaderWrapper *wrapper = (struct RegisterReaderWrapper *)arg;
267 return wrapper->regBlock(value, regID);
268}
269
270int EDOperand::evaluate(uint64_t &result,
271 EDRegisterBlock_t regBlock) {
272 struct RegisterReaderWrapper wrapper;
273 wrapper.regBlock = regBlock;
274 return evaluate(result,
275 readerWrapperCallback,
276 (void*)&wrapper);
277}
278#endif