blob: 04b21cb35926dff8b58b0230b4610b66ff55a5ba [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:
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +000076 case kOperandTypeARMAddrMode7:
77 case kOperandTypeThumb2AddrModeReg:
Sean Callanan8f993b82010-04-08 00:48:21 +000078 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();
Sean Callanan8fbc00b2011-02-23 03:31:28 +0000157
Sean Callanan8f993b82010-04-08 00:48:21 +0000158 uint64_t addr = 0;
159
Sean Callanan8fbc00b2011-02-23 03:31:28 +0000160 unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg();
161
162 if (segmentReg != 0 && Disassembler.Key.Arch == Triple::x86_64) {
163 unsigned fsID = Disassembler.registerIDWithName("FS");
164 unsigned gsID = Disassembler.registerIDWithName("GS");
165
166 if (segmentReg == fsID ||
167 segmentReg == gsID) {
168 uint64_t segmentBase;
169 if (!callback(&segmentBase, segmentReg, arg))
170 addr += segmentBase;
171 }
172 }
173
Sean Callanan8f993b82010-04-08 00:48:21 +0000174 if (baseReg) {
175 uint64_t baseVal;
176 if (callback(&baseVal, baseReg, arg))
177 return -1;
178 addr += baseVal;
179 }
180
181 if (indexReg) {
182 uint64_t indexVal;
183 if (callback(&indexVal, indexReg, arg))
184 return -1;
185 addr += (scaleAmount * indexVal);
186 }
187
188 addr += displacement;
189
190 result = addr;
191 return 0;
192 }
Sean Callanan8fbc00b2011-02-23 03:31:28 +0000193 } // switch (operandType)
Sean Callanan8f993b82010-04-08 00:48:21 +0000194 break;
195 case Triple::arm:
196 case Triple::thumb:
197 switch (operandType) {
198 default:
199 return -1;
200 case kOperandTypeImmediate:
201 result = Inst.Inst->getOperand(MCOpIndex).getImm();
202 return 0;
203 case kOperandTypeRegister:
204 {
205 unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
206 return callback(&result, reg, arg);
207 }
208 case kOperandTypeARMBranchTarget:
209 {
210 int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
211
212 uint64_t pcVal;
213
214 if (callback(&pcVal, Disassembler.registerIDWithName("PC"), arg))
215 return -1;
216
217 result = pcVal + displacement;
218 return 0;
219 }
220 }
Sean Callanan8fbc00b2011-02-23 03:31:28 +0000221 break;
Sean Callananee5dfd42010-02-01 08:49:35 +0000222 }
223
224 return -1;
225}
226
Sean Callanan76706582010-02-04 01:43:08 +0000227int EDOperand::isRegister() {
Sean Callanan8f993b82010-04-08 00:48:21 +0000228 return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeRegister);
Sean Callanan76706582010-02-04 01:43:08 +0000229}
230
231unsigned EDOperand::regVal() {
232 return Inst.Inst->getOperand(MCOpIndex).getReg();
233}
234
235int EDOperand::isImmediate() {
Sean Callanan8f993b82010-04-08 00:48:21 +0000236 return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeImmediate);
Sean Callanan76706582010-02-04 01:43:08 +0000237}
238
239uint64_t EDOperand::immediateVal() {
240 return Inst.Inst->getOperand(MCOpIndex).getImm();
241}
242
243int EDOperand::isMemory() {
Sean Callanand8993a32010-04-23 01:56:36 +0000244 uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
245
246 switch (operandType) {
Sean Callanan8f993b82010-04-08 00:48:21 +0000247 default:
248 return 0;
249 case kOperandTypeX86Memory:
Sean Callanana0f914b2010-04-23 22:17:17 +0000250 case kOperandTypeX86PCRelative:
251 case kOperandTypeX86EffectiveAddress:
Sean Callanan8f993b82010-04-08 00:48:21 +0000252 case kOperandTypeARMSoReg:
253 case kOperandTypeARMSoImm:
254 case kOperandTypeARMAddrMode2:
255 case kOperandTypeARMAddrMode2Offset:
256 case kOperandTypeARMAddrMode3:
257 case kOperandTypeARMAddrMode3Offset:
258 case kOperandTypeARMAddrMode4:
259 case kOperandTypeARMAddrMode5:
260 case kOperandTypeARMAddrMode6:
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +0000261 case kOperandTypeARMAddrMode7:
Sean Callanan8f993b82010-04-08 00:48:21 +0000262 case kOperandTypeARMAddrModePC:
Sean Callanana0f914b2010-04-23 22:17:17 +0000263 case kOperandTypeARMBranchTarget:
Sean Callanan8f993b82010-04-08 00:48:21 +0000264 case kOperandTypeThumbAddrModeS1:
265 case kOperandTypeThumbAddrModeS2:
266 case kOperandTypeThumbAddrModeS4:
267 case kOperandTypeThumbAddrModeRR:
268 case kOperandTypeThumbAddrModeSP:
269 case kOperandTypeThumb2SoImm:
270 case kOperandTypeThumb2AddrModeImm8:
271 case kOperandTypeThumb2AddrModeImm8Offset:
272 case kOperandTypeThumb2AddrModeImm12:
273 case kOperandTypeThumb2AddrModeSoReg:
274 case kOperandTypeThumb2AddrModeImm8s4:
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +0000275 case kOperandTypeThumb2AddrModeReg:
Sean Callanan8f993b82010-04-08 00:48:21 +0000276 return 1;
277 }
Sean Callanan76706582010-02-04 01:43:08 +0000278}
279
Sean Callananee5dfd42010-02-01 08:49:35 +0000280#ifdef __BLOCKS__
Benjamin Kramera3ac4272010-10-22 17:35:07 +0000281namespace {
282 struct RegisterReaderWrapper {
283 EDOperand::EDRegisterBlock_t regBlock;
284 };
285}
Sean Callananee5dfd42010-02-01 08:49:35 +0000286
Benjamin Kramera3ac4272010-10-22 17:35:07 +0000287static int readerWrapperCallback(uint64_t *value, unsigned regID, void *arg) {
288 RegisterReaderWrapper *wrapper = (RegisterReaderWrapper *)arg;
Sean Callananee5dfd42010-02-01 08:49:35 +0000289 return wrapper->regBlock(value, regID);
290}
291
Benjamin Kramera3ac4272010-10-22 17:35:07 +0000292int EDOperand::evaluate(uint64_t &result, EDRegisterBlock_t regBlock) {
293 RegisterReaderWrapper wrapper;
Sean Callananee5dfd42010-02-01 08:49:35 +0000294 wrapper.regBlock = regBlock;
Benjamin Kramera3ac4272010-10-22 17:35:07 +0000295 return evaluate(result, readerWrapperCallback, (void*)&wrapper);
Sean Callananee5dfd42010-02-01 08:49:35 +0000296}
297#endif