blob: 48b374659d5ec2e4ea06896beac8b495d2a802fd [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 Callanan3f4f34c2012-02-04 07:45:35 +000033 Triple::ArchType arch = Disassembler.TgtTriple.getArch();
34
35 if (arch == Triple::x86 ||
36 arch == Triple::x86_64) {
Sean Callanan8f993b82010-04-08 00:48:21 +000037 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 }
Sean Callanan3f4f34c2012-02-04 07:45:35 +000059 else if (arch == Triple::arm ||
60 arch == Triple::thumb) {
Sean Callanan8f993b82010-04-08 00:48:21 +000061 uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
62
63 switch (operandType) {
64 default:
65 case kOperandTypeARMRegisterList:
Shantonu Sen7ae0df42011-07-11 17:57:30 +000066 case kOperandTypeARMDPRRegisterList:
67 case kOperandTypeARMSPRRegisterList:
Sean Callanan8f993b82010-04-08 00:48:21 +000068 break;
69 case kOperandTypeImmediate:
70 case kOperandTypeRegister:
71 case kOperandTypeARMBranchTarget:
72 case kOperandTypeARMSoImm:
Shantonu Sen7ae0df42011-07-11 17:57:30 +000073 case kOperandTypeARMRotImm:
Sean Callanan8f993b82010-04-08 00:48:21 +000074 case kOperandTypeThumb2SoImm:
75 case kOperandTypeARMSoImm2Part:
76 case kOperandTypeARMPredicate:
77 case kOperandTypeThumbITMask:
78 case kOperandTypeThumb2AddrModeImm8Offset:
79 case kOperandTypeARMTBAddrMode:
80 case kOperandTypeThumb2AddrModeImm8s4Offset:
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +000081 case kOperandTypeARMAddrMode7:
82 case kOperandTypeThumb2AddrModeReg:
Sean Callanan8f993b82010-04-08 00:48:21 +000083 numMCOperands = 1;
84 break;
85 case kOperandTypeThumb2SoReg:
Shantonu Sen7ae0df42011-07-11 17:57:30 +000086 case kOperandTypeAddrModeImm12:
Sean Callanan8f993b82010-04-08 00:48:21 +000087 case kOperandTypeARMAddrMode2Offset:
88 case kOperandTypeARMAddrMode3Offset:
89 case kOperandTypeARMAddrMode4:
90 case kOperandTypeARMAddrMode5:
91 case kOperandTypeARMAddrModePC:
92 case kOperandTypeThumb2AddrModeImm8:
93 case kOperandTypeThumb2AddrModeImm12:
94 case kOperandTypeThumb2AddrModeImm8s4:
Shantonu Sen7ae0df42011-07-11 17:57:30 +000095 case kOperandTypeThumbAddrModeImmS1:
96 case kOperandTypeThumbAddrModeImmS2:
97 case kOperandTypeThumbAddrModeImmS4:
Sean Callanan8f993b82010-04-08 00:48:21 +000098 case kOperandTypeThumbAddrModeRR:
99 case kOperandTypeThumbAddrModeSP:
Shantonu Sen7ae0df42011-07-11 17:57:30 +0000100 case kOperandTypeThumbAddrModePC:
Sean Callanan8f993b82010-04-08 00:48:21 +0000101 numMCOperands = 2;
102 break;
103 case kOperandTypeARMSoReg:
Shantonu Sen7ae0df42011-07-11 17:57:30 +0000104 case kOperandTypeLdStSOReg:
Sean Callanan8f993b82010-04-08 00:48:21 +0000105 case kOperandTypeARMAddrMode2:
106 case kOperandTypeARMAddrMode3:
107 case kOperandTypeThumb2AddrModeSoReg:
Shantonu Sen7ae0df42011-07-11 17:57:30 +0000108 case kOperandTypeThumbAddrModeRegS1:
109 case kOperandTypeThumbAddrModeRegS2:
110 case kOperandTypeThumbAddrModeRegS4:
Sean Callanan8f993b82010-04-08 00:48:21 +0000111 case kOperandTypeARMAddrMode6Offset:
112 numMCOperands = 3;
113 break;
114 case kOperandTypeARMAddrMode6:
115 numMCOperands = 4;
116 break;
Sean Callananee5dfd42010-02-01 08:49:35 +0000117 }
118 }
119
120 mcOpIndex += numMCOperands;
121}
122
123EDOperand::~EDOperand() {
124}
125
126int EDOperand::evaluate(uint64_t &result,
127 EDRegisterReaderCallback callback,
128 void *arg) {
Sean Callanan8f993b82010-04-08 00:48:21 +0000129 uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
130
Sean Callanan3f4f34c2012-02-04 07:45:35 +0000131 Triple::ArchType arch = Disassembler.TgtTriple.getArch();
132
133 switch (arch) {
Sean Callanan8f993b82010-04-08 00:48:21 +0000134 default:
135 return -1;
136 case Triple::x86:
137 case Triple::x86_64:
138 switch (operandType) {
139 default:
140 return -1;
141 case kOperandTypeImmediate:
Sean Callananee5dfd42010-02-01 08:49:35 +0000142 result = Inst.Inst->getOperand(MCOpIndex).getImm();
143 return 0;
Sean Callanan8f993b82010-04-08 00:48:21 +0000144 case kOperandTypeRegister:
145 {
Sean Callananee5dfd42010-02-01 08:49:35 +0000146 unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
147 return callback(&result, reg, arg);
148 }
Sean Callanan8f993b82010-04-08 00:48:21 +0000149 case kOperandTypeX86PCRelative:
150 {
151 int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
Sean Callananee5dfd42010-02-01 08:49:35 +0000152
Sean Callanan8f993b82010-04-08 00:48:21 +0000153 uint64_t ripVal;
Sean Callananee5dfd42010-02-01 08:49:35 +0000154
Sean Callanan8f993b82010-04-08 00:48:21 +0000155 // TODO fix how we do this
Sean Callananee5dfd42010-02-01 08:49:35 +0000156
Sean Callanan8f993b82010-04-08 00:48:21 +0000157 if (callback(&ripVal, Disassembler.registerIDWithName("RIP"), arg))
158 return -1;
Sean Callananee5dfd42010-02-01 08:49:35 +0000159
Sean Callanan8f993b82010-04-08 00:48:21 +0000160 result = ripVal + displacement;
161 return 0;
Sean Callananee5dfd42010-02-01 08:49:35 +0000162 }
Sean Callanan8f993b82010-04-08 00:48:21 +0000163 case kOperandTypeX86Memory:
164 case kOperandTypeX86EffectiveAddress:
165 {
166 unsigned baseReg = Inst.Inst->getOperand(MCOpIndex).getReg();
167 uint64_t scaleAmount = Inst.Inst->getOperand(MCOpIndex+1).getImm();
168 unsigned indexReg = Inst.Inst->getOperand(MCOpIndex+2).getReg();
169 int64_t displacement = Inst.Inst->getOperand(MCOpIndex+3).getImm();
Sean Callanan8fbc00b2011-02-23 03:31:28 +0000170
Sean Callanan8f993b82010-04-08 00:48:21 +0000171 uint64_t addr = 0;
172
Sean Callanan8fbc00b2011-02-23 03:31:28 +0000173 unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg();
174
Sean Callanan3f4f34c2012-02-04 07:45:35 +0000175 if (segmentReg != 0 && arch == Triple::x86_64) {
Sean Callanan8fbc00b2011-02-23 03:31:28 +0000176 unsigned fsID = Disassembler.registerIDWithName("FS");
177 unsigned gsID = Disassembler.registerIDWithName("GS");
178
179 if (segmentReg == fsID ||
180 segmentReg == gsID) {
181 uint64_t segmentBase;
182 if (!callback(&segmentBase, segmentReg, arg))
183 addr += segmentBase;
184 }
185 }
186
Sean Callanan8f993b82010-04-08 00:48:21 +0000187 if (baseReg) {
188 uint64_t baseVal;
189 if (callback(&baseVal, baseReg, arg))
190 return -1;
191 addr += baseVal;
192 }
193
194 if (indexReg) {
195 uint64_t indexVal;
196 if (callback(&indexVal, indexReg, arg))
197 return -1;
198 addr += (scaleAmount * indexVal);
199 }
200
201 addr += displacement;
202
203 result = addr;
204 return 0;
205 }
Sean Callanan8fbc00b2011-02-23 03:31:28 +0000206 } // switch (operandType)
Sean Callanan8f993b82010-04-08 00:48:21 +0000207 case Triple::arm:
208 case Triple::thumb:
209 switch (operandType) {
210 default:
211 return -1;
212 case kOperandTypeImmediate:
Sean Callanan863f8462011-04-20 00:43:34 +0000213 if (!Inst.Inst->getOperand(MCOpIndex).isImm())
214 return -1;
215
Sean Callanan8f993b82010-04-08 00:48:21 +0000216 result = Inst.Inst->getOperand(MCOpIndex).getImm();
217 return 0;
218 case kOperandTypeRegister:
219 {
Sean Callanan863f8462011-04-20 00:43:34 +0000220 if (!Inst.Inst->getOperand(MCOpIndex).isReg())
221 return -1;
222
Sean Callanan8f993b82010-04-08 00:48:21 +0000223 unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
224 return callback(&result, reg, arg);
225 }
226 case kOperandTypeARMBranchTarget:
227 {
Sean Callanan863f8462011-04-20 00:43:34 +0000228 if (!Inst.Inst->getOperand(MCOpIndex).isImm())
229 return -1;
230
Sean Callanan8f993b82010-04-08 00:48:21 +0000231 int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
232
233 uint64_t pcVal;
234
235 if (callback(&pcVal, Disassembler.registerIDWithName("PC"), arg))
236 return -1;
237
238 result = pcVal + displacement;
239 return 0;
240 }
241 }
Sean Callananee5dfd42010-02-01 08:49:35 +0000242 }
Sean Callananee5dfd42010-02-01 08:49:35 +0000243}
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