SubRegIndex'ize Mips
[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/EDInstInfo.h"
21 #include "llvm/MC/MCInst.h"
22
23 using namespace llvm;
24
25 EDOperand::EDOperand(const EDDisassembler &disassembler,
26                      const EDInst &inst,
27                      unsigned int opIndex,
28                      unsigned int &mcOpIndex) :
29   Disassembler(disassembler),
30   Inst(inst),
31   OpIndex(opIndex),
32   MCOpIndex(mcOpIndex) {
33   unsigned int numMCOperands = 0;
34     
35   if (Disassembler.Key.Arch == Triple::x86 ||
36       Disassembler.Key.Arch == Triple::x86_64) {
37     uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
38     
39     switch (operandType) {
40     default:
41       break;
42     case kOperandTypeImmediate:
43       numMCOperands = 1;
44       break;
45     case kOperandTypeRegister:
46       numMCOperands = 1;
47       break;
48     case kOperandTypeX86Memory:
49       numMCOperands = 5;
50       break;
51     case kOperandTypeX86EffectiveAddress:
52       numMCOperands = 4;
53       break;
54     case kOperandTypeX86PCRelative:
55       numMCOperands = 1;
56       break;
57     }
58   }
59   else if (Disassembler.Key.Arch == Triple::arm ||
60            Disassembler.Key.Arch == Triple::thumb) {
61     uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
62     
63     switch (operandType) {
64     default:
65     case kOperandTypeARMRegisterList:
66       break;
67     case kOperandTypeImmediate:
68     case kOperandTypeRegister:
69     case kOperandTypeARMBranchTarget:
70     case kOperandTypeARMSoImm:
71     case kOperandTypeThumb2SoImm:
72     case kOperandTypeARMSoImm2Part:
73     case kOperandTypeARMPredicate:
74     case kOperandTypeThumbITMask:
75     case kOperandTypeThumb2AddrModeImm8Offset:
76     case kOperandTypeARMTBAddrMode:
77     case kOperandTypeThumb2AddrModeImm8s4Offset:
78       numMCOperands = 1;
79       break;
80     case kOperandTypeThumb2SoReg:
81     case kOperandTypeARMAddrMode2Offset:
82     case kOperandTypeARMAddrMode3Offset:
83     case kOperandTypeARMAddrMode4:
84     case kOperandTypeARMAddrMode5:
85     case kOperandTypeARMAddrModePC:
86     case kOperandTypeThumb2AddrModeImm8:
87     case kOperandTypeThumb2AddrModeImm12:
88     case kOperandTypeThumb2AddrModeImm8s4:
89     case kOperandTypeThumbAddrModeRR:
90     case kOperandTypeThumbAddrModeSP:
91       numMCOperands = 2;
92       break;
93     case kOperandTypeARMSoReg:
94     case kOperandTypeARMAddrMode2:
95     case kOperandTypeARMAddrMode3:
96     case kOperandTypeThumb2AddrModeSoReg:
97     case kOperandTypeThumbAddrModeS1:
98     case kOperandTypeThumbAddrModeS2:
99     case kOperandTypeThumbAddrModeS4:
100     case kOperandTypeARMAddrMode6Offset:
101       numMCOperands = 3;
102       break;
103     case kOperandTypeARMAddrMode6:
104       numMCOperands = 4;
105       break;
106     }
107   }
108     
109   mcOpIndex += numMCOperands;
110 }
111
112 EDOperand::~EDOperand() {
113 }
114
115 int EDOperand::evaluate(uint64_t &result,
116                         EDRegisterReaderCallback callback,
117                         void *arg) {
118   uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
119   
120   switch (Disassembler.Key.Arch) {
121   default:
122     return -1;  
123   case Triple::x86:
124   case Triple::x86_64:    
125     switch (operandType) {
126     default:
127       return -1;
128     case kOperandTypeImmediate:
129       result = Inst.Inst->getOperand(MCOpIndex).getImm();
130       return 0;
131     case kOperandTypeRegister:
132     {
133       unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
134       return callback(&result, reg, arg);
135     }
136     case kOperandTypeX86PCRelative:
137     {
138       int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
139         
140       uint64_t ripVal;
141         
142       // TODO fix how we do this
143         
144       if (callback(&ripVal, Disassembler.registerIDWithName("RIP"), arg))
145         return -1;
146         
147       result = ripVal + displacement;
148       return 0;
149     }
150     case kOperandTypeX86Memory:
151     case kOperandTypeX86EffectiveAddress:  
152     {
153       unsigned baseReg = Inst.Inst->getOperand(MCOpIndex).getReg();
154       uint64_t scaleAmount = Inst.Inst->getOperand(MCOpIndex+1).getImm();
155       unsigned indexReg = Inst.Inst->getOperand(MCOpIndex+2).getReg();
156       int64_t displacement = Inst.Inst->getOperand(MCOpIndex+3).getImm();
157       //unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg();
158       
159       uint64_t addr = 0;
160         
161       if (baseReg) {
162         uint64_t baseVal;
163         if (callback(&baseVal, baseReg, arg))
164           return -1;
165         addr += baseVal;
166       }
167         
168       if (indexReg) {
169         uint64_t indexVal;
170         if (callback(&indexVal, indexReg, arg))
171           return -1;
172         addr += (scaleAmount * indexVal);
173       }
174        
175       addr += displacement;
176        
177       result = addr;
178       return 0;
179     }
180     }
181     break;
182   case Triple::arm:
183   case Triple::thumb:
184     switch (operandType) {
185     default:
186       return -1;
187     case kOperandTypeImmediate:
188       result = Inst.Inst->getOperand(MCOpIndex).getImm();
189       return 0;
190     case kOperandTypeRegister:
191     {
192       unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
193       return callback(&result, reg, arg);
194     }
195     case kOperandTypeARMBranchTarget:
196     {
197       int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
198       
199       uint64_t pcVal;
200       
201       if (callback(&pcVal, Disassembler.registerIDWithName("PC"), arg))
202         return -1;
203       
204       result = pcVal + displacement;
205       return 0;
206     }
207     }
208   }
209   
210   return -1;
211 }
212
213 int EDOperand::isRegister() {
214   return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeRegister);
215 }
216
217 unsigned EDOperand::regVal() {
218   return Inst.Inst->getOperand(MCOpIndex).getReg(); 
219 }
220
221 int EDOperand::isImmediate() {
222   return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeImmediate);
223 }
224
225 uint64_t EDOperand::immediateVal() {
226   return Inst.Inst->getOperand(MCOpIndex).getImm();
227 }
228
229 int EDOperand::isMemory() {
230   uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
231     
232   switch (operandType) {
233   default:
234     return 0;
235   case kOperandTypeX86Memory:
236   case kOperandTypeX86PCRelative:
237   case kOperandTypeX86EffectiveAddress:
238   case kOperandTypeARMSoReg:
239   case kOperandTypeARMSoImm:
240   case kOperandTypeARMAddrMode2:
241   case kOperandTypeARMAddrMode2Offset:
242   case kOperandTypeARMAddrMode3:
243   case kOperandTypeARMAddrMode3Offset:
244   case kOperandTypeARMAddrMode4:
245   case kOperandTypeARMAddrMode5:
246   case kOperandTypeARMAddrMode6:
247   case kOperandTypeARMAddrModePC:
248   case kOperandTypeARMBranchTarget:
249   case kOperandTypeThumbAddrModeS1:
250   case kOperandTypeThumbAddrModeS2:
251   case kOperandTypeThumbAddrModeS4:
252   case kOperandTypeThumbAddrModeRR:
253   case kOperandTypeThumbAddrModeSP:
254   case kOperandTypeThumb2SoImm:
255   case kOperandTypeThumb2AddrModeImm8:
256   case kOperandTypeThumb2AddrModeImm8Offset:
257   case kOperandTypeThumb2AddrModeImm12:
258   case kOperandTypeThumb2AddrModeSoReg:
259   case kOperandTypeThumb2AddrModeImm8s4:
260     return 1;
261   }
262 }
263
264 #ifdef __BLOCKS__
265 struct RegisterReaderWrapper {
266   EDRegisterBlock_t regBlock;
267 };
268
269 int readerWrapperCallback(uint64_t *value, 
270                           unsigned regID, 
271                           void *arg) {
272   struct RegisterReaderWrapper *wrapper = (struct RegisterReaderWrapper *)arg;
273   return wrapper->regBlock(value, regID);
274 }
275
276 int EDOperand::evaluate(uint64_t &result,
277                         EDRegisterBlock_t regBlock) {
278   struct RegisterReaderWrapper wrapper;
279   wrapper.regBlock = regBlock;
280   return evaluate(result, 
281                   readerWrapperCallback, 
282                   (void*)&wrapper);
283 }
284 #endif