blob: d63c1c6bfbf938d18a7367fb9d8e846c3200b6de [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
Sean Callanan9899f702010-04-13 21:21:57 +000020#include "llvm/MC/EDInstInfo.h"
Sean Callananee5dfd42010-02-01 08:49:35 +000021#include "llvm/MC/MCInst.h"
22
23using namespace llvm;
24
25EDOperand::EDOperand(const EDDisassembler &disassembler,
26 const EDInst &inst,
27 unsigned int opIndex,
28 unsigned int &mcOpIndex) :
29 Disassembler(disassembler),
30 Inst(inst),
31 OpIndex(opIndex),
32 MCOpIndex(mcOpIndex) {
33 unsigned int numMCOperands = 0;
34
Sean Callanan8f993b82010-04-08 00:48:21 +000035 if (Disassembler.Key.Arch == Triple::x86 ||
36 Disassembler.Key.Arch == Triple::x86_64) {
37 uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
Sean Callananee5dfd42010-02-01 08:49:35 +000038
Sean Callanan8f993b82010-04-08 00:48:21 +000039 switch (operandType) {
40 default:
41 break;
42 case kOperandTypeImmediate:
Sean Callananee5dfd42010-02-01 08:49:35 +000043 numMCOperands = 1;
Sean Callanan8f993b82010-04-08 00:48:21 +000044 break;
45 case kOperandTypeRegister:
Sean Callananee5dfd42010-02-01 08:49:35 +000046 numMCOperands = 1;
Sean Callanan8f993b82010-04-08 00:48:21 +000047 break;
48 case kOperandTypeX86Memory:
49 numMCOperands = 5;
50 break;
51 case kOperandTypeX86EffectiveAddress:
Sean Callananee5dfd42010-02-01 08:49:35 +000052 numMCOperands = 4;
Sean Callanan8f993b82010-04-08 00:48:21 +000053 break;
54 case kOperandTypeX86PCRelative:
55 numMCOperands = 1;
56 break;
57 }
58 }
59 else if (Disassembler.Key.Arch == Triple::arm ||
60 Disassembler.Key.Arch == Triple::thumb) {
61 uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
62
63 switch (operandType) {
64 default:
65 case kOperandTypeARMRegisterList:
66 break;
67 case kOperandTypeImmediate:
68 case kOperandTypeRegister:
69 case kOperandTypeARMBranchTarget:
70 case kOperandTypeARMSoImm:
71 case kOperandTypeThumb2SoImm:
72 case kOperandTypeARMSoImm2Part:
73 case kOperandTypeARMPredicate:
74 case kOperandTypeThumbITMask:
75 case kOperandTypeThumb2AddrModeImm8Offset:
76 case kOperandTypeARMTBAddrMode:
77 case kOperandTypeThumb2AddrModeImm8s4Offset:
78 numMCOperands = 1;
79 break;
80 case kOperandTypeThumb2SoReg:
81 case kOperandTypeARMAddrMode2Offset:
82 case kOperandTypeARMAddrMode3Offset:
83 case kOperandTypeARMAddrMode4:
84 case kOperandTypeARMAddrMode5:
85 case kOperandTypeARMAddrModePC:
86 case kOperandTypeThumb2AddrModeImm8:
87 case kOperandTypeThumb2AddrModeImm12:
88 case kOperandTypeThumb2AddrModeImm8s4:
89 case kOperandTypeThumbAddrModeRR:
90 case kOperandTypeThumbAddrModeSP:
91 numMCOperands = 2;
92 break;
93 case kOperandTypeARMSoReg:
94 case kOperandTypeARMAddrMode2:
95 case kOperandTypeARMAddrMode3:
96 case kOperandTypeThumb2AddrModeSoReg:
97 case kOperandTypeThumbAddrModeS1:
98 case kOperandTypeThumbAddrModeS2:
99 case kOperandTypeThumbAddrModeS4:
100 case kOperandTypeARMAddrMode6Offset:
101 numMCOperands = 3;
102 break;
103 case kOperandTypeARMAddrMode6:
104 numMCOperands = 4;
105 break;
Sean Callananee5dfd42010-02-01 08:49:35 +0000106 }
107 }
108
109 mcOpIndex += numMCOperands;
110}
111
112EDOperand::~EDOperand() {
113}
114
115int EDOperand::evaluate(uint64_t &result,
116 EDRegisterReaderCallback callback,
117 void *arg) {
Sean Callanan8f993b82010-04-08 00:48:21 +0000118 uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
119
120 switch (Disassembler.Key.Arch) {
121 default:
122 return -1;
123 case Triple::x86:
124 case Triple::x86_64:
125 switch (operandType) {
126 default:
127 return -1;
128 case kOperandTypeImmediate:
Sean Callananee5dfd42010-02-01 08:49:35 +0000129 result = Inst.Inst->getOperand(MCOpIndex).getImm();
130 return 0;
Sean Callanan8f993b82010-04-08 00:48:21 +0000131 case kOperandTypeRegister:
132 {
Sean Callananee5dfd42010-02-01 08:49:35 +0000133 unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
134 return callback(&result, reg, arg);
135 }
Sean Callanan8f993b82010-04-08 00:48:21 +0000136 case kOperandTypeX86PCRelative:
137 {
138 int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
Sean Callananee5dfd42010-02-01 08:49:35 +0000139
Sean Callanan8f993b82010-04-08 00:48:21 +0000140 uint64_t ripVal;
Sean Callananee5dfd42010-02-01 08:49:35 +0000141
Sean Callanan8f993b82010-04-08 00:48:21 +0000142 // TODO fix how we do this
Sean Callananee5dfd42010-02-01 08:49:35 +0000143
Sean Callanan8f993b82010-04-08 00:48:21 +0000144 if (callback(&ripVal, Disassembler.registerIDWithName("RIP"), arg))
145 return -1;
Sean Callananee5dfd42010-02-01 08:49:35 +0000146
Sean Callanan8f993b82010-04-08 00:48:21 +0000147 result = ripVal + displacement;
148 return 0;
Sean Callananee5dfd42010-02-01 08:49:35 +0000149 }
Sean Callanan8f993b82010-04-08 00:48:21 +0000150 case kOperandTypeX86Memory:
151 case kOperandTypeX86EffectiveAddress:
152 {
153 unsigned baseReg = Inst.Inst->getOperand(MCOpIndex).getReg();
154 uint64_t scaleAmount = Inst.Inst->getOperand(MCOpIndex+1).getImm();
155 unsigned indexReg = Inst.Inst->getOperand(MCOpIndex+2).getReg();
156 int64_t displacement = Inst.Inst->getOperand(MCOpIndex+3).getImm();
157 //unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg();
158
159 uint64_t addr = 0;
160
161 if (baseReg) {
162 uint64_t baseVal;
163 if (callback(&baseVal, baseReg, arg))
164 return -1;
165 addr += baseVal;
166 }
167
168 if (indexReg) {
169 uint64_t indexVal;
170 if (callback(&indexVal, indexReg, arg))
171 return -1;
172 addr += (scaleAmount * indexVal);
173 }
174
175 addr += displacement;
176
177 result = addr;
178 return 0;
179 }
180 }
181 break;
182 case Triple::arm:
183 case Triple::thumb:
184 switch (operandType) {
185 default:
186 return -1;
187 case kOperandTypeImmediate:
188 result = Inst.Inst->getOperand(MCOpIndex).getImm();
189 return 0;
190 case kOperandTypeRegister:
191 {
192 unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
193 return callback(&result, reg, arg);
194 }
195 case kOperandTypeARMBranchTarget:
196 {
197 int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
198
199 uint64_t pcVal;
200
201 if (callback(&pcVal, Disassembler.registerIDWithName("PC"), arg))
202 return -1;
203
204 result = pcVal + displacement;
205 return 0;
206 }
207 }
Sean Callananee5dfd42010-02-01 08:49:35 +0000208 }
209
210 return -1;
211}
212
Sean Callanan76706582010-02-04 01:43:08 +0000213int EDOperand::isRegister() {
Sean Callanan8f993b82010-04-08 00:48:21 +0000214 return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeRegister);
Sean Callanan76706582010-02-04 01:43:08 +0000215}
216
217unsigned EDOperand::regVal() {
218 return Inst.Inst->getOperand(MCOpIndex).getReg();
219}
220
221int EDOperand::isImmediate() {
Sean Callanan8f993b82010-04-08 00:48:21 +0000222 return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeImmediate);
Sean Callanan76706582010-02-04 01:43:08 +0000223}
224
225uint64_t EDOperand::immediateVal() {
226 return Inst.Inst->getOperand(MCOpIndex).getImm();
227}
228
229int EDOperand::isMemory() {
Sean Callanand8993a32010-04-23 01:56:36 +0000230 uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
231
232 switch (operandType) {
Sean Callanan8f993b82010-04-08 00:48:21 +0000233 default:
234 return 0;
235 case kOperandTypeX86Memory:
Sean Callanana0f914b2010-04-23 22:17:17 +0000236 case kOperandTypeX86PCRelative:
237 case kOperandTypeX86EffectiveAddress:
Sean Callanan8f993b82010-04-08 00:48:21 +0000238 case kOperandTypeARMSoReg:
239 case kOperandTypeARMSoImm:
240 case kOperandTypeARMAddrMode2:
241 case kOperandTypeARMAddrMode2Offset:
242 case kOperandTypeARMAddrMode3:
243 case kOperandTypeARMAddrMode3Offset:
244 case kOperandTypeARMAddrMode4:
245 case kOperandTypeARMAddrMode5:
246 case kOperandTypeARMAddrMode6:
247 case kOperandTypeARMAddrModePC:
Sean Callanana0f914b2010-04-23 22:17:17 +0000248 case kOperandTypeARMBranchTarget:
Sean Callanan8f993b82010-04-08 00:48:21 +0000249 case kOperandTypeThumbAddrModeS1:
250 case kOperandTypeThumbAddrModeS2:
251 case kOperandTypeThumbAddrModeS4:
252 case kOperandTypeThumbAddrModeRR:
253 case kOperandTypeThumbAddrModeSP:
254 case kOperandTypeThumb2SoImm:
255 case kOperandTypeThumb2AddrModeImm8:
256 case kOperandTypeThumb2AddrModeImm8Offset:
257 case kOperandTypeThumb2AddrModeImm12:
258 case kOperandTypeThumb2AddrModeSoReg:
259 case kOperandTypeThumb2AddrModeImm8s4:
260 return 1;
261 }
Sean Callanan76706582010-02-04 01:43:08 +0000262}
263
Sean Callananee5dfd42010-02-01 08:49:35 +0000264#ifdef __BLOCKS__
265struct RegisterReaderWrapper {
266 EDRegisterBlock_t regBlock;
267};
268
269int readerWrapperCallback(uint64_t *value,
270 unsigned regID,
271 void *arg) {
272 struct RegisterReaderWrapper *wrapper = (struct RegisterReaderWrapper *)arg;
273 return wrapper->regBlock(value, regID);
274}
275
276int EDOperand::evaluate(uint64_t &result,
277 EDRegisterBlock_t regBlock) {
278 struct RegisterReaderWrapper wrapper;
279 wrapper.regBlock = regBlock;
280 return evaluate(result,
281 readerWrapperCallback,
282 (void*)&wrapper);
283}
284#endif