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"
21using namespace llvm;
22
23EDOperand::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
123EDOperand::~EDOperand() {
124}
125
126int 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
245int EDOperand::isRegister() {
246  return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeRegister);
247}
248
249unsigned EDOperand::regVal() {
250  return Inst.Inst->getOperand(MCOpIndex).getReg();
251}
252
253int EDOperand::isImmediate() {
254  return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeImmediate);
255}
256
257uint64_t EDOperand::immediateVal() {
258  return Inst.Inst->getOperand(MCOpIndex).getImm();
259}
260
261int 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__
299namespace {
300  struct RegisterReaderWrapper {
301    EDOperand::EDRegisterBlock_t regBlock;
302  };
303}
304
305static int readerWrapperCallback(uint64_t *value, unsigned regID, void *arg) {
306  RegisterReaderWrapper *wrapper = (RegisterReaderWrapper *)arg;
307  return wrapper->regBlock(value, regID);
308}
309
310int 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
316