More dead code removal (using -Wunreachable-code)
[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     case kOperandTypeARMDPRRegisterList:
65     case kOperandTypeARMSPRRegisterList:
66       break;
67     case kOperandTypeImmediate:
68     case kOperandTypeRegister:
69     case kOperandTypeARMBranchTarget:
70     case kOperandTypeARMSoImm:
71     case kOperandTypeARMRotImm:
72     case kOperandTypeThumb2SoImm:
73     case kOperandTypeARMSoImm2Part:
74     case kOperandTypeARMPredicate:
75     case kOperandTypeThumbITMask:
76     case kOperandTypeThumb2AddrModeImm8Offset:
77     case kOperandTypeARMTBAddrMode:
78     case kOperandTypeThumb2AddrModeImm8s4Offset:
79     case kOperandTypeARMAddrMode7:
80     case kOperandTypeThumb2AddrModeReg:
81       numMCOperands = 1;
82       break;
83     case kOperandTypeThumb2SoReg:
84     case kOperandTypeAddrModeImm12:
85     case kOperandTypeARMAddrMode2Offset:
86     case kOperandTypeARMAddrMode3Offset:
87     case kOperandTypeARMAddrMode4:
88     case kOperandTypeARMAddrMode5:
89     case kOperandTypeARMAddrModePC:
90     case kOperandTypeThumb2AddrModeImm8:
91     case kOperandTypeThumb2AddrModeImm12:
92     case kOperandTypeThumb2AddrModeImm8s4:
93     case kOperandTypeThumbAddrModeImmS1:
94     case kOperandTypeThumbAddrModeImmS2:
95     case kOperandTypeThumbAddrModeImmS4:
96     case kOperandTypeThumbAddrModeRR:
97     case kOperandTypeThumbAddrModeSP:
98     case kOperandTypeThumbAddrModePC:
99       numMCOperands = 2;
100       break;
101     case kOperandTypeARMSoReg:
102     case kOperandTypeLdStSOReg:
103     case kOperandTypeARMAddrMode2:
104     case kOperandTypeARMAddrMode3:
105     case kOperandTypeThumb2AddrModeSoReg:
106     case kOperandTypeThumbAddrModeRegS1:
107     case kOperandTypeThumbAddrModeRegS2:
108     case kOperandTypeThumbAddrModeRegS4:
109     case kOperandTypeARMAddrMode6Offset:
110       numMCOperands = 3;
111       break;
112     case kOperandTypeARMAddrMode6:
113       numMCOperands = 4;
114       break;
115     }
116   }
117     
118   mcOpIndex += numMCOperands;
119 }
120
121 EDOperand::~EDOperand() {
122 }
123
124 int EDOperand::evaluate(uint64_t &result,
125                         EDRegisterReaderCallback callback,
126                         void *arg) {
127   uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
128   
129   switch (Disassembler.Key.Arch) {
130   default:
131     return -1;  
132   case Triple::x86:
133   case Triple::x86_64:    
134     switch (operandType) {
135     default:
136       return -1;
137     case kOperandTypeImmediate:
138       result = Inst.Inst->getOperand(MCOpIndex).getImm();
139       return 0;
140     case kOperandTypeRegister:
141     {
142       unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
143       return callback(&result, reg, arg);
144     }
145     case kOperandTypeX86PCRelative:
146     {
147       int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
148         
149       uint64_t ripVal;
150         
151       // TODO fix how we do this
152         
153       if (callback(&ripVal, Disassembler.registerIDWithName("RIP"), arg))
154         return -1;
155         
156       result = ripVal + displacement;
157       return 0;
158     }
159     case kOperandTypeX86Memory:
160     case kOperandTypeX86EffectiveAddress:  
161     {
162       unsigned baseReg = Inst.Inst->getOperand(MCOpIndex).getReg();
163       uint64_t scaleAmount = Inst.Inst->getOperand(MCOpIndex+1).getImm();
164       unsigned indexReg = Inst.Inst->getOperand(MCOpIndex+2).getReg();
165       int64_t displacement = Inst.Inst->getOperand(MCOpIndex+3).getImm();
166     
167       uint64_t addr = 0;
168         
169       unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg();
170         
171       if (segmentReg != 0 && Disassembler.Key.Arch == Triple::x86_64) {
172         unsigned fsID = Disassembler.registerIDWithName("FS");
173         unsigned gsID = Disassembler.registerIDWithName("GS");
174         
175         if (segmentReg == fsID ||
176             segmentReg == gsID) {
177           uint64_t segmentBase;
178           if (!callback(&segmentBase, segmentReg, arg))
179             addr += segmentBase;        
180         }
181       }
182         
183       if (baseReg) {
184         uint64_t baseVal;
185         if (callback(&baseVal, baseReg, arg))
186           return -1;
187         addr += baseVal;
188       }
189         
190       if (indexReg) {
191         uint64_t indexVal;
192         if (callback(&indexVal, indexReg, arg))
193           return -1;
194         addr += (scaleAmount * indexVal);
195       }
196        
197       addr += displacement;
198        
199       result = addr;
200       return 0;
201     }
202     } // switch (operandType)
203   case Triple::arm:
204   case Triple::thumb:
205     switch (operandType) {
206     default:
207       return -1;
208     case kOperandTypeImmediate:
209       if (!Inst.Inst->getOperand(MCOpIndex).isImm())
210         return -1;
211             
212       result = Inst.Inst->getOperand(MCOpIndex).getImm();
213       return 0;
214     case kOperandTypeRegister:
215     {
216       if (!Inst.Inst->getOperand(MCOpIndex).isReg())
217         return -1;
218         
219       unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
220       return callback(&result, reg, arg);
221     }
222     case kOperandTypeARMBranchTarget:
223     {
224       if (!Inst.Inst->getOperand(MCOpIndex).isImm())
225         return -1;
226         
227       int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
228       
229       uint64_t pcVal;
230       
231       if (callback(&pcVal, Disassembler.registerIDWithName("PC"), arg))
232         return -1;
233       
234       result = pcVal + displacement;
235       return 0;
236     }
237     }
238   }
239 }
240
241 int EDOperand::isRegister() {
242   return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeRegister);
243 }
244
245 unsigned EDOperand::regVal() {
246   return Inst.Inst->getOperand(MCOpIndex).getReg(); 
247 }
248
249 int EDOperand::isImmediate() {
250   return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeImmediate);
251 }
252
253 uint64_t EDOperand::immediateVal() {
254   return Inst.Inst->getOperand(MCOpIndex).getImm();
255 }
256
257 int EDOperand::isMemory() {
258   uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
259     
260   switch (operandType) {
261   default:
262     return 0;
263   case kOperandTypeX86Memory:
264   case kOperandTypeX86PCRelative:
265   case kOperandTypeX86EffectiveAddress:
266   case kOperandTypeARMSoReg:
267   case kOperandTypeARMSoImm:
268   case kOperandTypeARMAddrMode2:
269   case kOperandTypeARMAddrMode2Offset:
270   case kOperandTypeARMAddrMode3:
271   case kOperandTypeARMAddrMode3Offset:
272   case kOperandTypeARMAddrMode4:
273   case kOperandTypeARMAddrMode5:
274   case kOperandTypeARMAddrMode6:
275   case kOperandTypeARMAddrMode7:
276   case kOperandTypeARMAddrModePC:
277   case kOperandTypeARMBranchTarget:
278   case kOperandTypeThumbAddrModeRegS1:
279   case kOperandTypeThumbAddrModeRegS2:
280   case kOperandTypeThumbAddrModeRegS4:
281   case kOperandTypeThumbAddrModeRR:
282   case kOperandTypeThumbAddrModeSP:
283   case kOperandTypeThumb2SoImm:
284   case kOperandTypeThumb2AddrModeImm8:
285   case kOperandTypeThumb2AddrModeImm8Offset:
286   case kOperandTypeThumb2AddrModeImm12:
287   case kOperandTypeThumb2AddrModeSoReg:
288   case kOperandTypeThumb2AddrModeImm8s4:
289   case kOperandTypeThumb2AddrModeReg:
290     return 1;
291   }
292 }
293
294 #ifdef __BLOCKS__
295 namespace {
296   struct RegisterReaderWrapper {
297     EDOperand::EDRegisterBlock_t regBlock;
298   };
299 }
300
301 static int readerWrapperCallback(uint64_t *value, unsigned regID, void *arg) {
302   RegisterReaderWrapper *wrapper = (RegisterReaderWrapper *)arg;
303   return wrapper->regBlock(value, regID);
304 }
305
306 int EDOperand::evaluate(uint64_t &result, EDRegisterBlock_t regBlock) {
307   RegisterReaderWrapper wrapper;
308   wrapper.regBlock = regBlock;
309   return evaluate(result, readerWrapperCallback, (void*)&wrapper);
310 }
311 #endif