1 //===-- EDOperand.cpp - LLVM Enhanced Disassembler ------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the Enhanced Disassembly library's operand class. The
11 // operand is responsible for allowing evaluation given a particular register
14 //===----------------------------------------------------------------------===//
16 #include "EDOperand.h"
17 #include "EDDisassembler.h"
19 #include "llvm/MC/EDInstInfo.h"
20 #include "llvm/MC/MCInst.h"
23 EDOperand::EDOperand(const EDDisassembler &disassembler,
26 unsigned int &mcOpIndex) :
27 Disassembler(disassembler),
30 MCOpIndex(mcOpIndex) {
31 unsigned int numMCOperands = 0;
33 if (Disassembler.Key.Arch == Triple::x86 ||
34 Disassembler.Key.Arch == Triple::x86_64) {
35 uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
37 switch (operandType) {
40 case kOperandTypeImmediate:
43 case kOperandTypeRegister:
46 case kOperandTypeX86Memory:
49 case kOperandTypeX86EffectiveAddress:
52 case kOperandTypeX86PCRelative:
57 else if (Disassembler.Key.Arch == Triple::arm ||
58 Disassembler.Key.Arch == Triple::thumb) {
59 uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
61 switch (operandType) {
63 case kOperandTypeARMRegisterList:
64 case kOperandTypeARMDPRRegisterList:
65 case kOperandTypeARMSPRRegisterList:
67 case kOperandTypeImmediate:
68 case kOperandTypeRegister:
69 case kOperandTypeARMBranchTarget:
70 case kOperandTypeARMSoImm:
71 case kOperandTypeARMRotImm:
72 case kOperandTypeThumb2SoImm:
73 case kOperandTypeARMSoImm2Part:
74 case kOperandTypeARMPredicate:
75 case kOperandTypeThumbITMask:
76 case kOperandTypeThumb2AddrModeImm8Offset:
77 case kOperandTypeARMTBAddrMode:
78 case kOperandTypeThumb2AddrModeImm8s4Offset:
79 case kOperandTypeARMAddrMode7:
80 case kOperandTypeThumb2AddrModeReg:
83 case kOperandTypeThumb2SoReg:
84 case kOperandTypeAddrModeImm12:
85 case kOperandTypeARMAddrMode2Offset:
86 case kOperandTypeARMAddrMode3Offset:
87 case kOperandTypeARMAddrMode4:
88 case kOperandTypeARMAddrMode5:
89 case kOperandTypeARMAddrModePC:
90 case kOperandTypeThumb2AddrModeImm8:
91 case kOperandTypeThumb2AddrModeImm12:
92 case kOperandTypeThumb2AddrModeImm8s4:
93 case kOperandTypeThumbAddrModeImmS1:
94 case kOperandTypeThumbAddrModeImmS2:
95 case kOperandTypeThumbAddrModeImmS4:
96 case kOperandTypeThumbAddrModeRR:
97 case kOperandTypeThumbAddrModeSP:
98 case kOperandTypeThumbAddrModePC:
101 case kOperandTypeARMSoReg:
102 case kOperandTypeLdStSOReg:
103 case kOperandTypeARMAddrMode2:
104 case kOperandTypeARMAddrMode3:
105 case kOperandTypeThumb2AddrModeSoReg:
106 case kOperandTypeThumbAddrModeRegS1:
107 case kOperandTypeThumbAddrModeRegS2:
108 case kOperandTypeThumbAddrModeRegS4:
109 case kOperandTypeARMAddrMode6Offset:
112 case kOperandTypeARMAddrMode6:
118 mcOpIndex += numMCOperands;
121 EDOperand::~EDOperand() {
124 int EDOperand::evaluate(uint64_t &result,
125 EDRegisterReaderCallback callback,
127 uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
129 switch (Disassembler.Key.Arch) {
134 switch (operandType) {
137 case kOperandTypeImmediate:
138 result = Inst.Inst->getOperand(MCOpIndex).getImm();
140 case kOperandTypeRegister:
142 unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
143 return callback(&result, reg, arg);
145 case kOperandTypeX86PCRelative:
147 int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
151 // TODO fix how we do this
153 if (callback(&ripVal, Disassembler.registerIDWithName("RIP"), arg))
156 result = ripVal + displacement;
159 case kOperandTypeX86Memory:
160 case kOperandTypeX86EffectiveAddress:
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();
169 unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg();
171 if (segmentReg != 0 && Disassembler.Key.Arch == Triple::x86_64) {
172 unsigned fsID = Disassembler.registerIDWithName("FS");
173 unsigned gsID = Disassembler.registerIDWithName("GS");
175 if (segmentReg == fsID ||
176 segmentReg == gsID) {
177 uint64_t segmentBase;
178 if (!callback(&segmentBase, segmentReg, arg))
185 if (callback(&baseVal, baseReg, arg))
192 if (callback(&indexVal, indexReg, arg))
194 addr += (scaleAmount * indexVal);
197 addr += displacement;
202 } // switch (operandType)
205 switch (operandType) {
208 case kOperandTypeImmediate:
209 if (!Inst.Inst->getOperand(MCOpIndex).isImm())
212 result = Inst.Inst->getOperand(MCOpIndex).getImm();
214 case kOperandTypeRegister:
216 if (!Inst.Inst->getOperand(MCOpIndex).isReg())
219 unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
220 return callback(&result, reg, arg);
222 case kOperandTypeARMBranchTarget:
224 if (!Inst.Inst->getOperand(MCOpIndex).isImm())
227 int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
231 if (callback(&pcVal, Disassembler.registerIDWithName("PC"), arg))
234 result = pcVal + displacement;
241 int EDOperand::isRegister() {
242 return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeRegister);
245 unsigned EDOperand::regVal() {
246 return Inst.Inst->getOperand(MCOpIndex).getReg();
249 int EDOperand::isImmediate() {
250 return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeImmediate);
253 uint64_t EDOperand::immediateVal() {
254 return Inst.Inst->getOperand(MCOpIndex).getImm();
257 int EDOperand::isMemory() {
258 uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
260 switch (operandType) {
263 case kOperandTypeX86Memory:
264 case kOperandTypeX86PCRelative:
265 case kOperandTypeX86EffectiveAddress:
266 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:
275 case kOperandTypeARMAddrMode7:
276 case kOperandTypeARMAddrModePC:
277 case kOperandTypeARMBranchTarget:
278 case kOperandTypeThumbAddrModeRegS1:
279 case kOperandTypeThumbAddrModeRegS2:
280 case kOperandTypeThumbAddrModeRegS4:
281 case kOperandTypeThumbAddrModeRR:
282 case kOperandTypeThumbAddrModeSP:
283 case kOperandTypeThumb2SoImm:
284 case kOperandTypeThumb2AddrModeImm8:
285 case kOperandTypeThumb2AddrModeImm8Offset:
286 case kOperandTypeThumb2AddrModeImm12:
287 case kOperandTypeThumb2AddrModeSoReg:
288 case kOperandTypeThumb2AddrModeImm8s4:
289 case kOperandTypeThumb2AddrModeReg:
296 struct RegisterReaderWrapper {
297 EDOperand::EDRegisterBlock_t regBlock;
301 static int readerWrapperCallback(uint64_t *value, unsigned regID, void *arg) {
302 RegisterReaderWrapper *wrapper = (RegisterReaderWrapper *)arg;
303 return wrapper->regBlock(value, regID);
306 int EDOperand::evaluate(uint64_t &result, EDRegisterBlock_t regBlock) {
307 RegisterReaderWrapper wrapper;
308 wrapper.regBlock = regBlock;
309 return evaluate(result, readerWrapperCallback, (void*)&wrapper);