blob: 2b0c73e805939d949fef4b360855a1a53ae3a9ec [file] [log] [blame]
Chris Lattner847da552010-07-20 18:25:19 +00001//===-- EDOperand.cpp - LLVM Enhanced Disassembler ------------------------===//
Sean Callananee5dfd42010-02-01 08:49:35 +00002//
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
Chris Lattner847da552010-07-20 18:25:19 +000016#include "EDOperand.h"
Sean Callananee5dfd42010-02-01 08:49:35 +000017#include "EDDisassembler.h"
18#include "EDInst.h"
Sean Callanan9899f702010-04-13 21:21:57 +000019#include "llvm/MC/EDInstInfo.h"
Sean Callananee5dfd42010-02-01 08:49:35 +000020#include "llvm/MC/MCInst.h"
Sean Callananee5dfd42010-02-01 08:49:35 +000021using namespace llvm;
22
23EDOperand::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
Sean Callanan8f993b82010-04-08 00:48:21 +000033 if (Disassembler.Key.Arch == Triple::x86 ||
34 Disassembler.Key.Arch == Triple::x86_64) {
35 uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
Sean Callananee5dfd42010-02-01 08:49:35 +000036
Sean Callanan8f993b82010-04-08 00:48:21 +000037 switch (operandType) {
38 default:
39 break;
40 case kOperandTypeImmediate:
Sean Callananee5dfd42010-02-01 08:49:35 +000041 numMCOperands = 1;
Sean Callanan8f993b82010-04-08 00:48:21 +000042 break;
43 case kOperandTypeRegister:
Sean Callananee5dfd42010-02-01 08:49:35 +000044 numMCOperands = 1;
Sean Callanan8f993b82010-04-08 00:48:21 +000045 break;
46 case kOperandTypeX86Memory:
47 numMCOperands = 5;
48 break;
49 case kOperandTypeX86EffectiveAddress:
Sean Callananee5dfd42010-02-01 08:49:35 +000050 numMCOperands = 4;
Sean Callanan8f993b82010-04-08 00:48:21 +000051 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 break;
65 case kOperandTypeImmediate:
66 case kOperandTypeRegister:
67 case kOperandTypeARMBranchTarget:
68 case kOperandTypeARMSoImm:
69 case kOperandTypeThumb2SoImm:
70 case kOperandTypeARMSoImm2Part:
71 case kOperandTypeARMPredicate:
72 case kOperandTypeThumbITMask:
73 case kOperandTypeThumb2AddrModeImm8Offset:
74 case kOperandTypeARMTBAddrMode:
75 case kOperandTypeThumb2AddrModeImm8s4Offset:
76 numMCOperands = 1;
77 break;
78 case kOperandTypeThumb2SoReg:
79 case kOperandTypeARMAddrMode2Offset:
80 case kOperandTypeARMAddrMode3Offset:
81 case kOperandTypeARMAddrMode4:
82 case kOperandTypeARMAddrMode5:
83 case kOperandTypeARMAddrModePC:
84 case kOperandTypeThumb2AddrModeImm8:
85 case kOperandTypeThumb2AddrModeImm12:
86 case kOperandTypeThumb2AddrModeImm8s4:
87 case kOperandTypeThumbAddrModeRR:
88 case kOperandTypeThumbAddrModeSP:
89 numMCOperands = 2;
90 break;
91 case kOperandTypeARMSoReg:
92 case kOperandTypeARMAddrMode2:
93 case kOperandTypeARMAddrMode3:
94 case kOperandTypeThumb2AddrModeSoReg:
95 case kOperandTypeThumbAddrModeS1:
96 case kOperandTypeThumbAddrModeS2:
97 case kOperandTypeThumbAddrModeS4:
98 case kOperandTypeARMAddrMode6Offset:
99 numMCOperands = 3;
100 break;
101 case kOperandTypeARMAddrMode6:
102 numMCOperands = 4;
103 break;
Sean Callananee5dfd42010-02-01 08:49:35 +0000104 }
105 }
106
107 mcOpIndex += numMCOperands;
108}
109
110EDOperand::~EDOperand() {
111}
112
113int EDOperand::evaluate(uint64_t &result,
114 EDRegisterReaderCallback callback,
115 void *arg) {
Sean Callanan8f993b82010-04-08 00:48:21 +0000116 uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
117
118 switch (Disassembler.Key.Arch) {
119 default:
120 return -1;
121 case Triple::x86:
122 case Triple::x86_64:
123 switch (operandType) {
124 default:
125 return -1;
126 case kOperandTypeImmediate:
Sean Callananee5dfd42010-02-01 08:49:35 +0000127 result = Inst.Inst->getOperand(MCOpIndex).getImm();
128 return 0;
Sean Callanan8f993b82010-04-08 00:48:21 +0000129 case kOperandTypeRegister:
130 {
Sean Callananee5dfd42010-02-01 08:49:35 +0000131 unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
132 return callback(&result, reg, arg);
133 }
Sean Callanan8f993b82010-04-08 00:48:21 +0000134 case kOperandTypeX86PCRelative:
135 {
136 int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
Sean Callananee5dfd42010-02-01 08:49:35 +0000137
Sean Callanan8f993b82010-04-08 00:48:21 +0000138 uint64_t ripVal;
Sean Callananee5dfd42010-02-01 08:49:35 +0000139
Sean Callanan8f993b82010-04-08 00:48:21 +0000140 // TODO fix how we do this
Sean Callananee5dfd42010-02-01 08:49:35 +0000141
Sean Callanan8f993b82010-04-08 00:48:21 +0000142 if (callback(&ripVal, Disassembler.registerIDWithName("RIP"), arg))
143 return -1;
Sean Callananee5dfd42010-02-01 08:49:35 +0000144
Sean Callanan8f993b82010-04-08 00:48:21 +0000145 result = ripVal + displacement;
146 return 0;
Sean Callananee5dfd42010-02-01 08:49:35 +0000147 }
Sean Callanan8f993b82010-04-08 00:48:21 +0000148 case kOperandTypeX86Memory:
149 case kOperandTypeX86EffectiveAddress:
150 {
151 unsigned baseReg = Inst.Inst->getOperand(MCOpIndex).getReg();
152 uint64_t scaleAmount = Inst.Inst->getOperand(MCOpIndex+1).getImm();
153 unsigned indexReg = Inst.Inst->getOperand(MCOpIndex+2).getReg();
154 int64_t displacement = Inst.Inst->getOperand(MCOpIndex+3).getImm();
Sean Callanan8fbc00b2011-02-23 03:31:28 +0000155
Sean Callanan8f993b82010-04-08 00:48:21 +0000156 uint64_t addr = 0;
157
Sean Callanan8fbc00b2011-02-23 03:31:28 +0000158 unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg();
159
160 if (segmentReg != 0 && Disassembler.Key.Arch == Triple::x86_64) {
161 unsigned fsID = Disassembler.registerIDWithName("FS");
162 unsigned gsID = Disassembler.registerIDWithName("GS");
163
164 if (segmentReg == fsID ||
165 segmentReg == gsID) {
166 uint64_t segmentBase;
167 if (!callback(&segmentBase, segmentReg, arg))
168 addr += segmentBase;
169 }
170 }
171
Sean Callanan8f993b82010-04-08 00:48:21 +0000172 if (baseReg) {
173 uint64_t baseVal;
174 if (callback(&baseVal, baseReg, arg))
175 return -1;
176 addr += baseVal;
177 }
178
179 if (indexReg) {
180 uint64_t indexVal;
181 if (callback(&indexVal, indexReg, arg))
182 return -1;
183 addr += (scaleAmount * indexVal);
184 }
185
186 addr += displacement;
187
188 result = addr;
189 return 0;
190 }
Sean Callanan8fbc00b2011-02-23 03:31:28 +0000191 } // switch (operandType)
Sean Callanan8f993b82010-04-08 00:48:21 +0000192 break;
193 case Triple::arm:
194 case Triple::thumb:
195 switch (operandType) {
196 default:
197 return -1;
198 case kOperandTypeImmediate:
199 result = Inst.Inst->getOperand(MCOpIndex).getImm();
200 return 0;
201 case kOperandTypeRegister:
202 {
203 unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
204 return callback(&result, reg, arg);
205 }
206 case kOperandTypeARMBranchTarget:
207 {
208 int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
209
210 uint64_t pcVal;
211
212 if (callback(&pcVal, Disassembler.registerIDWithName("PC"), arg))
213 return -1;
214
215 result = pcVal + displacement;
216 return 0;
217 }
218 }
Sean Callanan8fbc00b2011-02-23 03:31:28 +0000219 break;
Sean Callananee5dfd42010-02-01 08:49:35 +0000220 }
221
222 return -1;
223}
224
Sean Callanan76706582010-02-04 01:43:08 +0000225int EDOperand::isRegister() {
Sean Callanan8f993b82010-04-08 00:48:21 +0000226 return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeRegister);
Sean Callanan76706582010-02-04 01:43:08 +0000227}
228
229unsigned EDOperand::regVal() {
230 return Inst.Inst->getOperand(MCOpIndex).getReg();
231}
232
233int EDOperand::isImmediate() {
Sean Callanan8f993b82010-04-08 00:48:21 +0000234 return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeImmediate);
Sean Callanan76706582010-02-04 01:43:08 +0000235}
236
237uint64_t EDOperand::immediateVal() {
238 return Inst.Inst->getOperand(MCOpIndex).getImm();
239}
240
241int EDOperand::isMemory() {
Sean Callanand8993a32010-04-23 01:56:36 +0000242 uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
243
244 switch (operandType) {
Sean Callanan8f993b82010-04-08 00:48:21 +0000245 default:
246 return 0;
247 case kOperandTypeX86Memory:
Sean Callanana0f914b2010-04-23 22:17:17 +0000248 case kOperandTypeX86PCRelative:
249 case kOperandTypeX86EffectiveAddress:
Sean Callanan8f993b82010-04-08 00:48:21 +0000250 case kOperandTypeARMSoReg:
251 case kOperandTypeARMSoImm:
252 case kOperandTypeARMAddrMode2:
253 case kOperandTypeARMAddrMode2Offset:
254 case kOperandTypeARMAddrMode3:
255 case kOperandTypeARMAddrMode3Offset:
256 case kOperandTypeARMAddrMode4:
257 case kOperandTypeARMAddrMode5:
258 case kOperandTypeARMAddrMode6:
259 case kOperandTypeARMAddrModePC:
Sean Callanana0f914b2010-04-23 22:17:17 +0000260 case kOperandTypeARMBranchTarget:
Sean Callanan8f993b82010-04-08 00:48:21 +0000261 case kOperandTypeThumbAddrModeS1:
262 case kOperandTypeThumbAddrModeS2:
263 case kOperandTypeThumbAddrModeS4:
264 case kOperandTypeThumbAddrModeRR:
265 case kOperandTypeThumbAddrModeSP:
266 case kOperandTypeThumb2SoImm:
267 case kOperandTypeThumb2AddrModeImm8:
268 case kOperandTypeThumb2AddrModeImm8Offset:
269 case kOperandTypeThumb2AddrModeImm12:
270 case kOperandTypeThumb2AddrModeSoReg:
271 case kOperandTypeThumb2AddrModeImm8s4:
272 return 1;
273 }
Sean Callanan76706582010-02-04 01:43:08 +0000274}
275
Sean Callananee5dfd42010-02-01 08:49:35 +0000276#ifdef __BLOCKS__
Benjamin Kramera3ac4272010-10-22 17:35:07 +0000277namespace {
278 struct RegisterReaderWrapper {
279 EDOperand::EDRegisterBlock_t regBlock;
280 };
281}
Sean Callananee5dfd42010-02-01 08:49:35 +0000282
Benjamin Kramera3ac4272010-10-22 17:35:07 +0000283static int readerWrapperCallback(uint64_t *value, unsigned regID, void *arg) {
284 RegisterReaderWrapper *wrapper = (RegisterReaderWrapper *)arg;
Sean Callananee5dfd42010-02-01 08:49:35 +0000285 return wrapper->regBlock(value, regID);
286}
287
Benjamin Kramera3ac4272010-10-22 17:35:07 +0000288int EDOperand::evaluate(uint64_t &result, EDRegisterBlock_t regBlock) {
289 RegisterReaderWrapper wrapper;
Sean Callananee5dfd42010-02-01 08:49:35 +0000290 wrapper.regBlock = regBlock;
Benjamin Kramera3ac4272010-10-22 17:35:07 +0000291 return evaluate(result, readerWrapperCallback, (void*)&wrapper);
Sean Callananee5dfd42010-02-01 08:49:35 +0000292}
293#endif