Filled in a few new APIs for the enhanced
[oota-llvm.git] / tools / edis / EDOperand.cpp
1 //===-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
22 using namespace llvm;
23
24 EDOperand::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
60 EDOperand::~EDOperand() {
61 }
62
63 int 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 int EDOperand::isRegister() {
129   return(Inst.ThisInstInfo->operandFlags[OpIndex] & kOperandFlagRegister);
130 }
131
132 unsigned EDOperand::regVal() {
133   return Inst.Inst->getOperand(MCOpIndex).getReg(); 
134 }
135
136 int EDOperand::isImmediate() {
137   return(Inst.ThisInstInfo->operandFlags[OpIndex] & kOperandFlagImmediate);
138 }
139
140 uint64_t EDOperand::immediateVal() {
141   return Inst.Inst->getOperand(MCOpIndex).getImm();
142 }
143
144 int EDOperand::isMemory() {
145   return(Inst.ThisInstInfo->operandFlags[OpIndex] & kOperandFlagMemory);
146 }
147
148 #ifdef __BLOCKS__
149 struct RegisterReaderWrapper {
150   EDRegisterBlock_t regBlock;
151 };
152
153 int readerWrapperCallback(uint64_t *value, 
154                           unsigned regID, 
155                           void *arg) {
156   struct RegisterReaderWrapper *wrapper = (struct RegisterReaderWrapper *)arg;
157   return wrapper->regBlock(value, regID);
158 }
159
160 int EDOperand::evaluate(uint64_t &result,
161                         EDRegisterBlock_t regBlock) {
162   struct RegisterReaderWrapper wrapper;
163   wrapper.regBlock = regBlock;
164   return evaluate(result, 
165                   readerWrapperCallback, 
166                   (void*)&wrapper);
167 }
168 #endif