blob: 6a4e56ff72c46fff02834f39c77fa458f9500a08 [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:
Shantonu Sen7ae0df42011-07-11 17:57:30 +000064 case kOperandTypeARMDPRRegisterList:
65 case kOperandTypeARMSPRRegisterList:
Sean Callanan8f993b82010-04-08 00:48:21 +000066 break;
67 case kOperandTypeImmediate:
68 case kOperandTypeRegister:
69 case kOperandTypeARMBranchTarget:
70 case kOperandTypeARMSoImm:
Shantonu Sen7ae0df42011-07-11 17:57:30 +000071 case kOperandTypeARMRotImm:
Sean Callanan8f993b82010-04-08 00:48:21 +000072 case kOperandTypeThumb2SoImm:
73 case kOperandTypeARMSoImm2Part:
74 case kOperandTypeARMPredicate:
75 case kOperandTypeThumbITMask:
76 case kOperandTypeThumb2AddrModeImm8Offset:
77 case kOperandTypeARMTBAddrMode:
78 case kOperandTypeThumb2AddrModeImm8s4Offset:
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +000079 case kOperandTypeARMAddrMode7:
80 case kOperandTypeThumb2AddrModeReg:
Sean Callanan8f993b82010-04-08 00:48:21 +000081 numMCOperands = 1;
82 break;
83 case kOperandTypeThumb2SoReg:
Shantonu Sen7ae0df42011-07-11 17:57:30 +000084 case kOperandTypeAddrModeImm12:
Sean Callanan8f993b82010-04-08 00:48:21 +000085 case kOperandTypeARMAddrMode2Offset:
86 case kOperandTypeARMAddrMode3Offset:
87 case kOperandTypeARMAddrMode4:
88 case kOperandTypeARMAddrMode5:
89 case kOperandTypeARMAddrModePC:
90 case kOperandTypeThumb2AddrModeImm8:
91 case kOperandTypeThumb2AddrModeImm12:
92 case kOperandTypeThumb2AddrModeImm8s4:
Shantonu Sen7ae0df42011-07-11 17:57:30 +000093 case kOperandTypeThumbAddrModeImmS1:
94 case kOperandTypeThumbAddrModeImmS2:
95 case kOperandTypeThumbAddrModeImmS4:
Sean Callanan8f993b82010-04-08 00:48:21 +000096 case kOperandTypeThumbAddrModeRR:
97 case kOperandTypeThumbAddrModeSP:
Shantonu Sen7ae0df42011-07-11 17:57:30 +000098 case kOperandTypeThumbAddrModePC:
Sean Callanan8f993b82010-04-08 00:48:21 +000099 numMCOperands = 2;
100 break;
101 case kOperandTypeARMSoReg:
Shantonu Sen7ae0df42011-07-11 17:57:30 +0000102 case kOperandTypeLdStSOReg:
Sean Callanan8f993b82010-04-08 00:48:21 +0000103 case kOperandTypeARMAddrMode2:
104 case kOperandTypeARMAddrMode3:
105 case kOperandTypeThumb2AddrModeSoReg:
Shantonu Sen7ae0df42011-07-11 17:57:30 +0000106 case kOperandTypeThumbAddrModeRegS1:
107 case kOperandTypeThumbAddrModeRegS2:
108 case kOperandTypeThumbAddrModeRegS4:
Sean Callanan8f993b82010-04-08 00:48:21 +0000109 case kOperandTypeARMAddrMode6Offset:
110 numMCOperands = 3;
111 break;
112 case kOperandTypeARMAddrMode6:
113 numMCOperands = 4;
114 break;
Sean Callananee5dfd42010-02-01 08:49:35 +0000115 }
116 }
117
118 mcOpIndex += numMCOperands;
119}
120
121EDOperand::~EDOperand() {
122}
123
124int EDOperand::evaluate(uint64_t &result,
125 EDRegisterReaderCallback callback,
126 void *arg) {
Sean Callanan8f993b82010-04-08 00:48:21 +0000127 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:
Sean Callananee5dfd42010-02-01 08:49:35 +0000138 result = Inst.Inst->getOperand(MCOpIndex).getImm();
139 return 0;
Sean Callanan8f993b82010-04-08 00:48:21 +0000140 case kOperandTypeRegister:
141 {
Sean Callananee5dfd42010-02-01 08:49:35 +0000142 unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
143 return callback(&result, reg, arg);
144 }
Sean Callanan8f993b82010-04-08 00:48:21 +0000145 case kOperandTypeX86PCRelative:
146 {
147 int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
Sean Callananee5dfd42010-02-01 08:49:35 +0000148
Sean Callanan8f993b82010-04-08 00:48:21 +0000149 uint64_t ripVal;
Sean Callananee5dfd42010-02-01 08:49:35 +0000150
Sean Callanan8f993b82010-04-08 00:48:21 +0000151 // TODO fix how we do this
Sean Callananee5dfd42010-02-01 08:49:35 +0000152
Sean Callanan8f993b82010-04-08 00:48:21 +0000153 if (callback(&ripVal, Disassembler.registerIDWithName("RIP"), arg))
154 return -1;
Sean Callananee5dfd42010-02-01 08:49:35 +0000155
Sean Callanan8f993b82010-04-08 00:48:21 +0000156 result = ripVal + displacement;
157 return 0;
Sean Callananee5dfd42010-02-01 08:49:35 +0000158 }
Sean Callanan8f993b82010-04-08 00:48:21 +0000159 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();
Sean Callanan8fbc00b2011-02-23 03:31:28 +0000166
Sean Callanan8f993b82010-04-08 00:48:21 +0000167 uint64_t addr = 0;
168
Sean Callanan8fbc00b2011-02-23 03:31:28 +0000169 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
Sean Callanan8f993b82010-04-08 00:48:21 +0000183 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 }
Sean Callanan8fbc00b2011-02-23 03:31:28 +0000202 } // switch (operandType)
Sean Callanan8f993b82010-04-08 00:48:21 +0000203 break;
204 case Triple::arm:
205 case Triple::thumb:
206 switch (operandType) {
207 default:
208 return -1;
209 case kOperandTypeImmediate:
Sean Callanan863f8462011-04-20 00:43:34 +0000210 if (!Inst.Inst->getOperand(MCOpIndex).isImm())
211 return -1;
212
Sean Callanan8f993b82010-04-08 00:48:21 +0000213 result = Inst.Inst->getOperand(MCOpIndex).getImm();
214 return 0;
215 case kOperandTypeRegister:
216 {
Sean Callanan863f8462011-04-20 00:43:34 +0000217 if (!Inst.Inst->getOperand(MCOpIndex).isReg())
218 return -1;
219
Sean Callanan8f993b82010-04-08 00:48:21 +0000220 unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
221 return callback(&result, reg, arg);
222 }
223 case kOperandTypeARMBranchTarget:
224 {
Sean Callanan863f8462011-04-20 00:43:34 +0000225 if (!Inst.Inst->getOperand(MCOpIndex).isImm())
226 return -1;
227
Sean Callanan8f993b82010-04-08 00:48:21 +0000228 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 }
Sean Callanan8fbc00b2011-02-23 03:31:28 +0000239 break;
Sean Callananee5dfd42010-02-01 08:49:35 +0000240 }
241
242 return -1;
243}
244
Sean Callanan76706582010-02-04 01:43:08 +0000245int EDOperand::isRegister() {
Sean Callanan8f993b82010-04-08 00:48:21 +0000246 return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeRegister);
Sean Callanan76706582010-02-04 01:43:08 +0000247}
248
249unsigned EDOperand::regVal() {
250 return Inst.Inst->getOperand(MCOpIndex).getReg();
251}
252
253int EDOperand::isImmediate() {
Sean Callanan8f993b82010-04-08 00:48:21 +0000254 return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeImmediate);
Sean Callanan76706582010-02-04 01:43:08 +0000255}
256
257uint64_t EDOperand::immediateVal() {
258 return Inst.Inst->getOperand(MCOpIndex).getImm();
259}
260
261int EDOperand::isMemory() {
Sean Callanand8993a32010-04-23 01:56:36 +0000262 uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
263
264 switch (operandType) {
Sean Callanan8f993b82010-04-08 00:48:21 +0000265 default:
266 return 0;
267 case kOperandTypeX86Memory:
Sean Callanana0f914b2010-04-23 22:17:17 +0000268 case kOperandTypeX86PCRelative:
269 case kOperandTypeX86EffectiveAddress:
Sean Callanan8f993b82010-04-08 00:48:21 +0000270 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:
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +0000279 case kOperandTypeARMAddrMode7:
Sean Callanan8f993b82010-04-08 00:48:21 +0000280 case kOperandTypeARMAddrModePC:
Sean Callanana0f914b2010-04-23 22:17:17 +0000281 case kOperandTypeARMBranchTarget:
Shantonu Sen7ae0df42011-07-11 17:57:30 +0000282 case kOperandTypeThumbAddrModeRegS1:
283 case kOperandTypeThumbAddrModeRegS2:
284 case kOperandTypeThumbAddrModeRegS4:
Sean Callanan8f993b82010-04-08 00:48:21 +0000285 case kOperandTypeThumbAddrModeRR:
286 case kOperandTypeThumbAddrModeSP:
287 case kOperandTypeThumb2SoImm:
288 case kOperandTypeThumb2AddrModeImm8:
289 case kOperandTypeThumb2AddrModeImm8Offset:
290 case kOperandTypeThumb2AddrModeImm12:
291 case kOperandTypeThumb2AddrModeSoReg:
292 case kOperandTypeThumb2AddrModeImm8s4:
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +0000293 case kOperandTypeThumb2AddrModeReg:
Sean Callanan8f993b82010-04-08 00:48:21 +0000294 return 1;
295 }
Sean Callanan76706582010-02-04 01:43:08 +0000296}
297
Sean Callananee5dfd42010-02-01 08:49:35 +0000298#ifdef __BLOCKS__
Benjamin Kramera3ac4272010-10-22 17:35:07 +0000299namespace {
300 struct RegisterReaderWrapper {
301 EDOperand::EDRegisterBlock_t regBlock;
302 };
303}
Sean Callananee5dfd42010-02-01 08:49:35 +0000304
Benjamin Kramera3ac4272010-10-22 17:35:07 +0000305static int readerWrapperCallback(uint64_t *value, unsigned regID, void *arg) {
306 RegisterReaderWrapper *wrapper = (RegisterReaderWrapper *)arg;
Sean Callananee5dfd42010-02-01 08:49:35 +0000307 return wrapper->regBlock(value, regID);
308}
309
Benjamin Kramera3ac4272010-10-22 17:35:07 +0000310int EDOperand::evaluate(uint64_t &result, EDRegisterBlock_t regBlock) {
311 RegisterReaderWrapper wrapper;
Sean Callananee5dfd42010-02-01 08:49:35 +0000312 wrapper.regBlock = regBlock;
Benjamin Kramera3ac4272010-10-22 17:35:07 +0000313 return evaluate(result, readerWrapperCallback, (void*)&wrapper);
Sean Callananee5dfd42010-02-01 08:49:35 +0000314}
315#endif