Fixed a bug in the enhanced disassembler that caused
[oota-llvm.git] / lib / MC / MCDisassembler / 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 "EDOperand.h"
17 #include "EDDisassembler.h"
18 #include "EDInst.h"
19 #include "llvm/MC/EDInstInfo.h"
20 #include "llvm/MC/MCInst.h"
21 using namespace llvm;
22
23 EDOperand::EDOperand(const EDDisassembler &disassembler,
24                      const EDInst &inst,
25                      unsigned int opIndex,
26                      unsigned int &mcOpIndex) :
27   Disassembler(disassembler),
28   Inst(inst),
29   OpIndex(opIndex),
30   MCOpIndex(mcOpIndex) {
31   unsigned int numMCOperands = 0;
32     
33   if (Disassembler.Key.Arch == Triple::x86 ||
34       Disassembler.Key.Arch == Triple::x86_64) {
35     uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
36     
37     switch (operandType) {
38     default:
39       break;
40     case kOperandTypeImmediate:
41       numMCOperands = 1;
42       break;
43     case kOperandTypeRegister:
44       numMCOperands = 1;
45       break;
46     case kOperandTypeX86Memory:
47       numMCOperands = 5;
48       break;
49     case kOperandTypeX86EffectiveAddress:
50       numMCOperands = 4;
51       break;
52     case kOperandTypeX86PCRelative:
53       numMCOperands = 1;
54       break;
55     }
56   }
57   else if (Disassembler.Key.Arch == Triple::arm ||
58            Disassembler.Key.Arch == Triple::thumb) {
59     uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
60     
61     switch (operandType) {
62     default:
63     case kOperandTypeARMRegisterList:
64       break;
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:
76       numMCOperands = 1;
77       break;
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:
89       numMCOperands = 2;
90       break;
91     case kOperandTypeARMSoReg:
92     case kOperandTypeARMAddrMode2:
93     case kOperandTypeARMAddrMode3:
94     case kOperandTypeThumb2AddrModeSoReg:
95     case kOperandTypeThumbAddrModeS1:
96     case kOperandTypeThumbAddrModeS2:
97     case kOperandTypeThumbAddrModeS4:
98     case kOperandTypeARMAddrMode6Offset:
99       numMCOperands = 3;
100       break;
101     case kOperandTypeARMAddrMode6:
102       numMCOperands = 4;
103       break;
104     }
105   }
106     
107   mcOpIndex += numMCOperands;
108 }
109
110 EDOperand::~EDOperand() {
111 }
112
113 int EDOperand::evaluate(uint64_t &result,
114                         EDRegisterReaderCallback callback,
115                         void *arg) {
116   uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
117   
118   switch (Disassembler.Key.Arch) {
119   default:
120     return -1;  
121   case Triple::x86:
122   case Triple::x86_64:    
123     switch (operandType) {
124     default:
125       return -1;
126     case kOperandTypeImmediate:
127       result = Inst.Inst->getOperand(MCOpIndex).getImm();
128       return 0;
129     case kOperandTypeRegister:
130     {
131       unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
132       return callback(&result, reg, arg);
133     }
134     case kOperandTypeX86PCRelative:
135     {
136       int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
137         
138       uint64_t ripVal;
139         
140       // TODO fix how we do this
141         
142       if (callback(&ripVal, Disassembler.registerIDWithName("RIP"), arg))
143         return -1;
144         
145       result = ripVal + displacement;
146       return 0;
147     }
148     case kOperandTypeX86Memory:
149     case kOperandTypeX86EffectiveAddress:  
150     {
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();
155     
156       uint64_t addr = 0;
157         
158       unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg();
159         
160       if (segmentReg != 0 && Disassembler.Key.Arch == Triple::x86_64) {
161         unsigned fsID = Disassembler.registerIDWithName("FS");
162         unsigned gsID = Disassembler.registerIDWithName("GS");
163         
164         if (segmentReg == fsID ||
165             segmentReg == gsID) {
166           uint64_t segmentBase;
167           if (!callback(&segmentBase, segmentReg, arg))
168             addr += segmentBase;        
169         }
170       }
171         
172       if (baseReg) {
173         uint64_t baseVal;
174         if (callback(&baseVal, baseReg, arg))
175           return -1;
176         addr += baseVal;
177       }
178         
179       if (indexReg) {
180         uint64_t indexVal;
181         if (callback(&indexVal, indexReg, arg))
182           return -1;
183         addr += (scaleAmount * indexVal);
184       }
185        
186       addr += displacement;
187        
188       result = addr;
189       return 0;
190     }
191     } // switch (operandType)
192     break;
193   case Triple::arm:
194   case Triple::thumb:
195     switch (operandType) {
196     default:
197       return -1;
198     case kOperandTypeImmediate:
199       result = Inst.Inst->getOperand(MCOpIndex).getImm();
200       return 0;
201     case kOperandTypeRegister:
202     {
203       unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
204       return callback(&result, reg, arg);
205     }
206     case kOperandTypeARMBranchTarget:
207     {
208       int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
209       
210       uint64_t pcVal;
211       
212       if (callback(&pcVal, Disassembler.registerIDWithName("PC"), arg))
213         return -1;
214       
215       result = pcVal + displacement;
216       return 0;
217     }
218     }
219     break;
220   }
221   
222   return -1;
223 }
224
225 int EDOperand::isRegister() {
226   return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeRegister);
227 }
228
229 unsigned EDOperand::regVal() {
230   return Inst.Inst->getOperand(MCOpIndex).getReg(); 
231 }
232
233 int EDOperand::isImmediate() {
234   return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeImmediate);
235 }
236
237 uint64_t EDOperand::immediateVal() {
238   return Inst.Inst->getOperand(MCOpIndex).getImm();
239 }
240
241 int EDOperand::isMemory() {
242   uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
243     
244   switch (operandType) {
245   default:
246     return 0;
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:
272     return 1;
273   }
274 }
275
276 #ifdef __BLOCKS__
277 namespace {
278   struct RegisterReaderWrapper {
279     EDOperand::EDRegisterBlock_t regBlock;
280   };
281 }
282
283 static int readerWrapperCallback(uint64_t *value, unsigned regID, void *arg) {
284   RegisterReaderWrapper *wrapper = (RegisterReaderWrapper *)arg;
285   return wrapper->regBlock(value, regID);
286 }
287
288 int EDOperand::evaluate(uint64_t &result, EDRegisterBlock_t regBlock) {
289   RegisterReaderWrapper wrapper;
290   wrapper.regBlock = regBlock;
291   return evaluate(result, readerWrapperCallback, (void*)&wrapper);
292 }
293 #endif