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:
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:
78 case kOperandTypeThumb2SoReg:
79 case kOperandTypeARMAddrMode2Offset:
80 case kOperandTypeARMAddrMode3Offset:
81 case kOperandTypeARMAddrMode4:
82 case kOperandTypeARMAddrMode5:
83 case kOperandTypeARMAddrModePC:
84 case kOperandTypeThumb2AddrModeImm8:
85 case kOperandTypeThumb2AddrModeImm12:
86 case kOperandTypeThumb2AddrModeImm8s4:
87 case kOperandTypeThumbAddrModeRR:
88 case kOperandTypeThumbAddrModeSP:
91 case kOperandTypeARMSoReg:
92 case kOperandTypeARMAddrMode2:
93 case kOperandTypeARMAddrMode3:
94 case kOperandTypeThumb2AddrModeSoReg:
95 case kOperandTypeThumbAddrModeS1:
96 case kOperandTypeThumbAddrModeS2:
97 case kOperandTypeThumbAddrModeS4:
98 case kOperandTypeARMAddrMode6Offset:
101 case kOperandTypeARMAddrMode6:
107 mcOpIndex += numMCOperands;
110 EDOperand::~EDOperand() {
113 int EDOperand::evaluate(uint64_t &result,
114 EDRegisterReaderCallback callback,
116 uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
118 switch (Disassembler.Key.Arch) {
123 switch (operandType) {
126 case kOperandTypeImmediate:
127 result = Inst.Inst->getOperand(MCOpIndex).getImm();
129 case kOperandTypeRegister:
131 unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
132 return callback(&result, reg, arg);
134 case kOperandTypeX86PCRelative:
136 int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
140 // TODO fix how we do this
142 if (callback(&ripVal, Disassembler.registerIDWithName("RIP"), arg))
145 result = ripVal + displacement;
148 case kOperandTypeX86Memory:
149 case kOperandTypeX86EffectiveAddress:
151 unsigned baseReg = Inst.Inst->getOperand(MCOpIndex).getReg();
152 uint64_t scaleAmount = Inst.Inst->getOperand(MCOpIndex+1).getImm();
153 unsigned indexReg = Inst.Inst->getOperand(MCOpIndex+2).getReg();
154 int64_t displacement = Inst.Inst->getOperand(MCOpIndex+3).getImm();
158 unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg();
160 if (segmentReg != 0 && Disassembler.Key.Arch == Triple::x86_64) {
161 unsigned fsID = Disassembler.registerIDWithName("FS");
162 unsigned gsID = Disassembler.registerIDWithName("GS");
164 if (segmentReg == fsID ||
165 segmentReg == gsID) {
166 uint64_t segmentBase;
167 if (!callback(&segmentBase, segmentReg, arg))
174 if (callback(&baseVal, baseReg, arg))
181 if (callback(&indexVal, indexReg, arg))
183 addr += (scaleAmount * indexVal);
186 addr += displacement;
191 } // switch (operandType)
195 switch (operandType) {
198 case kOperandTypeImmediate:
199 result = Inst.Inst->getOperand(MCOpIndex).getImm();
201 case kOperandTypeRegister:
203 unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
204 return callback(&result, reg, arg);
206 case kOperandTypeARMBranchTarget:
208 int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
212 if (callback(&pcVal, Disassembler.registerIDWithName("PC"), arg))
215 result = pcVal + displacement;
225 int EDOperand::isRegister() {
226 return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeRegister);
229 unsigned EDOperand::regVal() {
230 return Inst.Inst->getOperand(MCOpIndex).getReg();
233 int EDOperand::isImmediate() {
234 return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeImmediate);
237 uint64_t EDOperand::immediateVal() {
238 return Inst.Inst->getOperand(MCOpIndex).getImm();
241 int EDOperand::isMemory() {
242 uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
244 switch (operandType) {
247 case kOperandTypeX86Memory:
248 case kOperandTypeX86PCRelative:
249 case kOperandTypeX86EffectiveAddress:
250 case kOperandTypeARMSoReg:
251 case kOperandTypeARMSoImm:
252 case kOperandTypeARMAddrMode2:
253 case kOperandTypeARMAddrMode2Offset:
254 case kOperandTypeARMAddrMode3:
255 case kOperandTypeARMAddrMode3Offset:
256 case kOperandTypeARMAddrMode4:
257 case kOperandTypeARMAddrMode5:
258 case kOperandTypeARMAddrMode6:
259 case kOperandTypeARMAddrModePC:
260 case kOperandTypeARMBranchTarget:
261 case kOperandTypeThumbAddrModeS1:
262 case kOperandTypeThumbAddrModeS2:
263 case kOperandTypeThumbAddrModeS4:
264 case kOperandTypeThumbAddrModeRR:
265 case kOperandTypeThumbAddrModeSP:
266 case kOperandTypeThumb2SoImm:
267 case kOperandTypeThumb2AddrModeImm8:
268 case kOperandTypeThumb2AddrModeImm8Offset:
269 case kOperandTypeThumb2AddrModeImm12:
270 case kOperandTypeThumb2AddrModeSoReg:
271 case kOperandTypeThumb2AddrModeImm8s4:
278 struct RegisterReaderWrapper {
279 EDOperand::EDRegisterBlock_t regBlock;
283 static int readerWrapperCallback(uint64_t *value, unsigned regID, void *arg) {
284 RegisterReaderWrapper *wrapper = (RegisterReaderWrapper *)arg;
285 return wrapper->regBlock(value, regID);
288 int EDOperand::evaluate(uint64_t &result, EDRegisterBlock_t regBlock) {
289 RegisterReaderWrapper wrapper;
290 wrapper.regBlock = regBlock;
291 return evaluate(result, readerWrapperCallback, (void*)&wrapper);