blob: 9aededb676e4acfc628ee0ccd01c237630f174ba [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 case Triple::arm:
204 case Triple::thumb:
205 switch (operandType) {
206 default:
207 return -1;
208 case kOperandTypeImmediate:
Sean Callanan863f8462011-04-20 00:43:34 +0000209 if (!Inst.Inst->getOperand(MCOpIndex).isImm())
210 return -1;
211
Sean Callanan8f993b82010-04-08 00:48:21 +0000212 result = Inst.Inst->getOperand(MCOpIndex).getImm();
213 return 0;
214 case kOperandTypeRegister:
215 {
Sean Callanan863f8462011-04-20 00:43:34 +0000216 if (!Inst.Inst->getOperand(MCOpIndex).isReg())
217 return -1;
218
Sean Callanan8f993b82010-04-08 00:48:21 +0000219 unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
220 return callback(&result, reg, arg);
221 }
222 case kOperandTypeARMBranchTarget:
223 {
Sean Callanan863f8462011-04-20 00:43:34 +0000224 if (!Inst.Inst->getOperand(MCOpIndex).isImm())
225 return -1;
226
Sean Callanan8f993b82010-04-08 00:48:21 +0000227 int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
228
229 uint64_t pcVal;
230
231 if (callback(&pcVal, Disassembler.registerIDWithName("PC"), arg))
232 return -1;
233
234 result = pcVal + displacement;
235 return 0;
236 }
237 }
Sean Callananee5dfd42010-02-01 08:49:35 +0000238 }
Sean Callananee5dfd42010-02-01 08:49:35 +0000239}
240
Sean Callanan76706582010-02-04 01:43:08 +0000241int EDOperand::isRegister() {
Sean Callanan8f993b82010-04-08 00:48:21 +0000242 return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeRegister);
Sean Callanan76706582010-02-04 01:43:08 +0000243}
244
245unsigned EDOperand::regVal() {
246 return Inst.Inst->getOperand(MCOpIndex).getReg();
247}
248
249int EDOperand::isImmediate() {
Sean Callanan8f993b82010-04-08 00:48:21 +0000250 return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeImmediate);
Sean Callanan76706582010-02-04 01:43:08 +0000251}
252
253uint64_t EDOperand::immediateVal() {
254 return Inst.Inst->getOperand(MCOpIndex).getImm();
255}
256
257int EDOperand::isMemory() {
Sean Callanand8993a32010-04-23 01:56:36 +0000258 uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
259
260 switch (operandType) {
Sean Callanan8f993b82010-04-08 00:48:21 +0000261 default:
262 return 0;
263 case kOperandTypeX86Memory:
Sean Callanana0f914b2010-04-23 22:17:17 +0000264 case kOperandTypeX86PCRelative:
265 case kOperandTypeX86EffectiveAddress:
Sean Callanan8f993b82010-04-08 00:48:21 +0000266 case kOperandTypeARMSoReg:
267 case kOperandTypeARMSoImm:
268 case kOperandTypeARMAddrMode2:
269 case kOperandTypeARMAddrMode2Offset:
270 case kOperandTypeARMAddrMode3:
271 case kOperandTypeARMAddrMode3Offset:
272 case kOperandTypeARMAddrMode4:
273 case kOperandTypeARMAddrMode5:
274 case kOperandTypeARMAddrMode6:
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +0000275 case kOperandTypeARMAddrMode7:
Sean Callanan8f993b82010-04-08 00:48:21 +0000276 case kOperandTypeARMAddrModePC:
Sean Callanana0f914b2010-04-23 22:17:17 +0000277 case kOperandTypeARMBranchTarget:
Shantonu Sen7ae0df42011-07-11 17:57:30 +0000278 case kOperandTypeThumbAddrModeRegS1:
279 case kOperandTypeThumbAddrModeRegS2:
280 case kOperandTypeThumbAddrModeRegS4:
Sean Callanan8f993b82010-04-08 00:48:21 +0000281 case kOperandTypeThumbAddrModeRR:
282 case kOperandTypeThumbAddrModeSP:
283 case kOperandTypeThumb2SoImm:
284 case kOperandTypeThumb2AddrModeImm8:
285 case kOperandTypeThumb2AddrModeImm8Offset:
286 case kOperandTypeThumb2AddrModeImm12:
287 case kOperandTypeThumb2AddrModeSoReg:
288 case kOperandTypeThumb2AddrModeImm8s4:
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +0000289 case kOperandTypeThumb2AddrModeReg:
Sean Callanan8f993b82010-04-08 00:48:21 +0000290 return 1;
291 }
Sean Callanan76706582010-02-04 01:43:08 +0000292}
293
Sean Callananee5dfd42010-02-01 08:49:35 +0000294#ifdef __BLOCKS__
Benjamin Kramera3ac4272010-10-22 17:35:07 +0000295namespace {
296 struct RegisterReaderWrapper {
297 EDOperand::EDRegisterBlock_t regBlock;
298 };
299}
Sean Callananee5dfd42010-02-01 08:49:35 +0000300
Benjamin Kramera3ac4272010-10-22 17:35:07 +0000301static int readerWrapperCallback(uint64_t *value, unsigned regID, void *arg) {
302 RegisterReaderWrapper *wrapper = (RegisterReaderWrapper *)arg;
Sean Callananee5dfd42010-02-01 08:49:35 +0000303 return wrapper->regBlock(value, regID);
304}
305
Benjamin Kramera3ac4272010-10-22 17:35:07 +0000306int EDOperand::evaluate(uint64_t &result, EDRegisterBlock_t regBlock) {
307 RegisterReaderWrapper wrapper;
Sean Callananee5dfd42010-02-01 08:49:35 +0000308 wrapper.regBlock = regBlock;
Benjamin Kramera3ac4272010-10-22 17:35:07 +0000309 return evaluate(result, readerWrapperCallback, (void*)&wrapper);
Sean Callananee5dfd42010-02-01 08:49:35 +0000310}
311#endif