blob: c15860affda526ac74bafded0fa49daba66381bf [file] [log] [blame]
Sean Callananee5dfd42010-02-01 08:49:35 +00001//===-EDOperand.cpp - LLVM Enhanced Disassembler --------------------------===//
2//
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
16#include "EDDisassembler.h"
17#include "EDInst.h"
18#include "EDOperand.h"
19
20#include "llvm/MC/MCInst.h"
21
22using namespace llvm;
23
24EDOperand::EDOperand(const EDDisassembler &disassembler,
25 const EDInst &inst,
26 unsigned int opIndex,
27 unsigned int &mcOpIndex) :
28 Disassembler(disassembler),
29 Inst(inst),
30 OpIndex(opIndex),
31 MCOpIndex(mcOpIndex) {
32 unsigned int numMCOperands = 0;
33
34 if(Disassembler.Key.Arch == Triple::x86 ||
35 Disassembler.Key.Arch == Triple::x86_64) {
36 uint8_t operandFlags = inst.ThisInstInfo->operandFlags[opIndex];
37
38 if (operandFlags & kOperandFlagImmediate) {
39 numMCOperands = 1;
40 }
41 else if (operandFlags & kOperandFlagRegister) {
42 numMCOperands = 1;
43 }
44 else if (operandFlags & kOperandFlagMemory) {
45 if (operandFlags & kOperandFlagPCRelative) {
46 numMCOperands = 1;
47 }
48 else {
49 numMCOperands = 5;
50 }
51 }
52 else if (operandFlags & kOperandFlagEffectiveAddress) {
53 numMCOperands = 4;
54 }
55 }
56
57 mcOpIndex += numMCOperands;
58}
59
60EDOperand::~EDOperand() {
61}
62
63int EDOperand::evaluate(uint64_t &result,
64 EDRegisterReaderCallback callback,
65 void *arg) {
66 if (Disassembler.Key.Arch == Triple::x86 ||
67 Disassembler.Key.Arch == Triple::x86_64) {
68 uint8_t operandFlags = Inst.ThisInstInfo->operandFlags[OpIndex];
69
70 if (operandFlags & kOperandFlagImmediate) {
71 result = Inst.Inst->getOperand(MCOpIndex).getImm();
72 return 0;
73 }
74 if (operandFlags & kOperandFlagRegister) {
75 unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
76 return callback(&result, reg, arg);
77 }
78 if (operandFlags & kOperandFlagMemory ||
79 operandFlags & kOperandFlagEffectiveAddress){
80 if(operandFlags & kOperandFlagPCRelative) {
81 int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
82
83 uint64_t ripVal;
84
85 // TODO fix how we do this
86
87 if (callback(&ripVal, Disassembler.registerIDWithName("RIP"), arg))
88 return -1;
89
90 result = ripVal + displacement;
91 return 0;
92 }
93 else {
94 unsigned baseReg = Inst.Inst->getOperand(MCOpIndex).getReg();
95 uint64_t scaleAmount = Inst.Inst->getOperand(MCOpIndex+1).getImm();
96 unsigned indexReg = Inst.Inst->getOperand(MCOpIndex+2).getReg();
97 int64_t displacement = Inst.Inst->getOperand(MCOpIndex+3).getImm();
98 //unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg();
99
100 uint64_t addr = 0;
101
102 if(baseReg) {
103 uint64_t baseVal;
104 if (callback(&baseVal, baseReg, arg))
105 return -1;
106 addr += baseVal;
107 }
108
109 if(indexReg) {
110 uint64_t indexVal;
111 if (callback(&indexVal, indexReg, arg))
112 return -1;
113 addr += (scaleAmount * indexVal);
114 }
115
116 addr += displacement;
117
118 result = addr;
119 return 0;
120 }
121 }
122 return -1;
123 }
124
125 return -1;
126}
127
128#ifdef __BLOCKS__
129struct RegisterReaderWrapper {
130 EDRegisterBlock_t regBlock;
131};
132
133int readerWrapperCallback(uint64_t *value,
134 unsigned regID,
135 void *arg) {
136 struct RegisterReaderWrapper *wrapper = (struct RegisterReaderWrapper *)arg;
137 return wrapper->regBlock(value, regID);
138}
139
140int EDOperand::evaluate(uint64_t &result,
141 EDRegisterBlock_t regBlock) {
142 struct RegisterReaderWrapper wrapper;
143 wrapper.regBlock = regBlock;
144 return evaluate(result,
145 readerWrapperCallback,
146 (void*)&wrapper);
147}
148#endif