Added the enhanced disassembly library's implementation and
[oota-llvm.git] / tools / ed / 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 #ifdef __BLOCKS__
129 struct RegisterReaderWrapper {
130   EDRegisterBlock_t regBlock;
131 };
132
133 int 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
140 int 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