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