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 "EDDisassembler.h"
18 #include "EDOperand.h"
20 #include "llvm/MC/EDInstInfo.h"
21 #include "llvm/MC/MCInst.h"
25 EDOperand::EDOperand(const EDDisassembler &disassembler,
28 unsigned int &mcOpIndex) :
29 Disassembler(disassembler),
32 MCOpIndex(mcOpIndex) {
33 unsigned int numMCOperands = 0;
35 if (Disassembler.Key.Arch == Triple::x86 ||
36 Disassembler.Key.Arch == Triple::x86_64) {
37 uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
39 switch (operandType) {
42 case kOperandTypeImmediate:
45 case kOperandTypeRegister:
48 case kOperandTypeX86Memory:
51 case kOperandTypeX86EffectiveAddress:
54 case kOperandTypeX86PCRelative:
59 else if (Disassembler.Key.Arch == Triple::arm ||
60 Disassembler.Key.Arch == Triple::thumb) {
61 uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
63 switch (operandType) {
65 case kOperandTypeARMRegisterList:
67 case kOperandTypeImmediate:
68 case kOperandTypeRegister:
69 case kOperandTypeARMBranchTarget:
70 case kOperandTypeARMSoImm:
71 case kOperandTypeThumb2SoImm:
72 case kOperandTypeARMSoImm2Part:
73 case kOperandTypeARMPredicate:
74 case kOperandTypeThumbITMask:
75 case kOperandTypeThumb2AddrModeImm8Offset:
76 case kOperandTypeARMTBAddrMode:
77 case kOperandTypeThumb2AddrModeImm8s4Offset:
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:
93 case kOperandTypeARMSoReg:
94 case kOperandTypeARMAddrMode2:
95 case kOperandTypeARMAddrMode3:
96 case kOperandTypeThumb2AddrModeSoReg:
97 case kOperandTypeThumbAddrModeS1:
98 case kOperandTypeThumbAddrModeS2:
99 case kOperandTypeThumbAddrModeS4:
100 case kOperandTypeARMAddrMode6Offset:
103 case kOperandTypeARMAddrMode6:
109 mcOpIndex += numMCOperands;
112 EDOperand::~EDOperand() {
115 int EDOperand::evaluate(uint64_t &result,
116 EDRegisterReaderCallback callback,
118 uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
120 switch (Disassembler.Key.Arch) {
125 switch (operandType) {
128 case kOperandTypeImmediate:
129 result = Inst.Inst->getOperand(MCOpIndex).getImm();
131 case kOperandTypeRegister:
133 unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
134 return callback(&result, reg, arg);
136 case kOperandTypeX86PCRelative:
138 int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
142 // TODO fix how we do this
144 if (callback(&ripVal, Disassembler.registerIDWithName("RIP"), arg))
147 result = ripVal + displacement;
150 case kOperandTypeX86Memory:
151 case kOperandTypeX86EffectiveAddress:
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();
157 //unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg();
163 if (callback(&baseVal, baseReg, arg))
170 if (callback(&indexVal, indexReg, arg))
172 addr += (scaleAmount * indexVal);
175 addr += displacement;
184 switch (operandType) {
187 case kOperandTypeImmediate:
188 result = Inst.Inst->getOperand(MCOpIndex).getImm();
190 case kOperandTypeRegister:
192 unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
193 return callback(&result, reg, arg);
195 case kOperandTypeARMBranchTarget:
197 int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
201 if (callback(&pcVal, Disassembler.registerIDWithName("PC"), arg))
204 result = pcVal + displacement;
213 int EDOperand::isRegister() {
214 return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeRegister);
217 unsigned EDOperand::regVal() {
218 return Inst.Inst->getOperand(MCOpIndex).getReg();
221 int EDOperand::isImmediate() {
222 return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeImmediate);
225 uint64_t EDOperand::immediateVal() {
226 return Inst.Inst->getOperand(MCOpIndex).getImm();
229 int EDOperand::isMemory() {
230 uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
232 switch (operandType) {
235 case kOperandTypeX86Memory:
236 case kOperandTypeX86PCRelative:
237 case kOperandTypeX86EffectiveAddress:
238 case kOperandTypeARMSoReg:
239 case kOperandTypeARMSoImm:
240 case kOperandTypeARMAddrMode2:
241 case kOperandTypeARMAddrMode2Offset:
242 case kOperandTypeARMAddrMode3:
243 case kOperandTypeARMAddrMode3Offset:
244 case kOperandTypeARMAddrMode4:
245 case kOperandTypeARMAddrMode5:
246 case kOperandTypeARMAddrMode6:
247 case kOperandTypeARMAddrModePC:
248 case kOperandTypeARMBranchTarget:
249 case kOperandTypeThumbAddrModeS1:
250 case kOperandTypeThumbAddrModeS2:
251 case kOperandTypeThumbAddrModeS4:
252 case kOperandTypeThumbAddrModeRR:
253 case kOperandTypeThumbAddrModeSP:
254 case kOperandTypeThumb2SoImm:
255 case kOperandTypeThumb2AddrModeImm8:
256 case kOperandTypeThumb2AddrModeImm8Offset:
257 case kOperandTypeThumb2AddrModeImm12:
258 case kOperandTypeThumb2AddrModeSoReg:
259 case kOperandTypeThumb2AddrModeImm8s4:
265 struct RegisterReaderWrapper {
266 EDRegisterBlock_t regBlock;
269 int readerWrapperCallback(uint64_t *value,
272 struct RegisterReaderWrapper *wrapper = (struct RegisterReaderWrapper *)arg;
273 return wrapper->regBlock(value, regID);
276 int EDOperand::evaluate(uint64_t &result,
277 EDRegisterBlock_t regBlock) {
278 struct RegisterReaderWrapper wrapper;
279 wrapper.regBlock = regBlock;
280 return evaluate(result,
281 readerWrapperCallback,