1 //===-- EDOperand.cpp - LLVM Enhanced Disassembler ------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the Enhanced Disassembly library's operand class. The
11 // operand is responsible for allowing evaluation given a particular register
14 //===----------------------------------------------------------------------===//
16 #include "EDOperand.h"
17 #include "EDDisassembler.h"
19 #include "llvm/MC/EDInstInfo.h"
20 #include "llvm/MC/MCInst.h"
23 EDOperand::EDOperand(const EDDisassembler
&disassembler
,
26 unsigned int &mcOpIndex
) :
27 Disassembler(disassembler
),
30 MCOpIndex(mcOpIndex
) {
31 unsigned int numMCOperands
= 0;
33 if (Disassembler
.Key
.Arch
== Triple::x86
||
34 Disassembler
.Key
.Arch
== Triple::x86_64
) {
35 uint8_t operandType
= inst
.ThisInstInfo
->operandTypes
[opIndex
];
37 switch (operandType
) {
40 case kOperandTypeImmediate
:
43 case kOperandTypeRegister
:
46 case kOperandTypeX86Memory
:
49 case kOperandTypeX86EffectiveAddress
:
52 case kOperandTypeX86PCRelative
:
57 else if (Disassembler
.Key
.Arch
== Triple::arm
||
58 Disassembler
.Key
.Arch
== Triple::thumb
) {
59 uint8_t operandType
= inst
.ThisInstInfo
->operandTypes
[opIndex
];
61 switch (operandType
) {
63 case kOperandTypeARMRegisterList
:
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 case kOperandTypeARMAddrMode7
:
77 case kOperandTypeThumb2AddrModeReg
:
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
:
93 case kOperandTypeARMSoReg
:
94 case kOperandTypeARMAddrMode2
:
95 case kOperandTypeARMAddrMode3
:
96 case kOperandTypeThumb2AddrModeSoReg
:
97 case kOperandTypeThumbAddrModeS1
:
98 case kOperandTypeThumbAddrModeS2
:
99 case kOperandTypeThumbAddrModeS4
:
100 case kOperandTypeARMAddrMode6Offset
:
103 case kOperandTypeARMAddrMode6
:
109 mcOpIndex
+= numMCOperands
;
112 EDOperand::~EDOperand() {
115 int EDOperand::evaluate(uint64_t &result
,
116 EDRegisterReaderCallback callback
,
118 uint8_t operandType
= Inst
.ThisInstInfo
->operandTypes
[OpIndex
];
120 switch (Disassembler
.Key
.Arch
) {
125 switch (operandType
) {
128 case kOperandTypeImmediate
:
129 result
= Inst
.Inst
->getOperand(MCOpIndex
).getImm();
131 case kOperandTypeRegister
:
133 unsigned reg
= Inst
.Inst
->getOperand(MCOpIndex
).getReg();
134 return callback(&result
, reg
, arg
);
136 case kOperandTypeX86PCRelative
:
138 int64_t displacement
= Inst
.Inst
->getOperand(MCOpIndex
).getImm();
142 // TODO fix how we do this
144 if (callback(&ripVal
, Disassembler
.registerIDWithName("RIP"), arg
))
147 result
= ripVal
+ displacement
;
150 case kOperandTypeX86Memory
:
151 case kOperandTypeX86EffectiveAddress
:
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();
160 unsigned segmentReg
= Inst
.Inst
->getOperand(MCOpIndex
+4).getReg();
162 if (segmentReg
!= 0 && Disassembler
.Key
.Arch
== Triple::x86_64
) {
163 unsigned fsID
= Disassembler
.registerIDWithName("FS");
164 unsigned gsID
= Disassembler
.registerIDWithName("GS");
166 if (segmentReg
== fsID
||
167 segmentReg
== gsID
) {
168 uint64_t segmentBase
;
169 if (!callback(&segmentBase
, segmentReg
, arg
))
176 if (callback(&baseVal
, baseReg
, arg
))
183 if (callback(&indexVal
, indexReg
, arg
))
185 addr
+= (scaleAmount
* indexVal
);
188 addr
+= displacement
;
193 } // switch (operandType)
197 switch (operandType
) {
200 case kOperandTypeImmediate
:
201 if (!Inst
.Inst
->getOperand(MCOpIndex
).isImm())
204 result
= Inst
.Inst
->getOperand(MCOpIndex
).getImm();
206 case kOperandTypeRegister
:
208 if (!Inst
.Inst
->getOperand(MCOpIndex
).isReg())
211 unsigned reg
= Inst
.Inst
->getOperand(MCOpIndex
).getReg();
212 return callback(&result
, reg
, arg
);
214 case kOperandTypeARMBranchTarget
:
216 if (!Inst
.Inst
->getOperand(MCOpIndex
).isImm())
219 int64_t displacement
= Inst
.Inst
->getOperand(MCOpIndex
).getImm();
223 if (callback(&pcVal
, Disassembler
.registerIDWithName("PC"), arg
))
226 result
= pcVal
+ displacement
;
236 int EDOperand::isRegister() {
237 return(Inst
.ThisInstInfo
->operandFlags
[OpIndex
] == kOperandTypeRegister
);
240 unsigned EDOperand::regVal() {
241 return Inst
.Inst
->getOperand(MCOpIndex
).getReg();
244 int EDOperand::isImmediate() {
245 return(Inst
.ThisInstInfo
->operandFlags
[OpIndex
] == kOperandTypeImmediate
);
248 uint64_t EDOperand::immediateVal() {
249 return Inst
.Inst
->getOperand(MCOpIndex
).getImm();
252 int EDOperand::isMemory() {
253 uint8_t operandType
= Inst
.ThisInstInfo
->operandTypes
[OpIndex
];
255 switch (operandType
) {
258 case kOperandTypeX86Memory
:
259 case kOperandTypeX86PCRelative
:
260 case kOperandTypeX86EffectiveAddress
:
261 case kOperandTypeARMSoReg
:
262 case kOperandTypeARMSoImm
:
263 case kOperandTypeARMAddrMode2
:
264 case kOperandTypeARMAddrMode2Offset
:
265 case kOperandTypeARMAddrMode3
:
266 case kOperandTypeARMAddrMode3Offset
:
267 case kOperandTypeARMAddrMode4
:
268 case kOperandTypeARMAddrMode5
:
269 case kOperandTypeARMAddrMode6
:
270 case kOperandTypeARMAddrMode7
:
271 case kOperandTypeARMAddrModePC
:
272 case kOperandTypeARMBranchTarget
:
273 case kOperandTypeThumbAddrModeS1
:
274 case kOperandTypeThumbAddrModeS2
:
275 case kOperandTypeThumbAddrModeS4
:
276 case kOperandTypeThumbAddrModeRR
:
277 case kOperandTypeThumbAddrModeSP
:
278 case kOperandTypeThumb2SoImm
:
279 case kOperandTypeThumb2AddrModeImm8
:
280 case kOperandTypeThumb2AddrModeImm8Offset
:
281 case kOperandTypeThumb2AddrModeImm12
:
282 case kOperandTypeThumb2AddrModeSoReg
:
283 case kOperandTypeThumb2AddrModeImm8s4
:
284 case kOperandTypeThumb2AddrModeReg
:
291 struct RegisterReaderWrapper
{
292 EDOperand::EDRegisterBlock_t regBlock
;
296 static int readerWrapperCallback(uint64_t *value
, unsigned regID
, void *arg
) {
297 RegisterReaderWrapper
*wrapper
= (RegisterReaderWrapper
*)arg
;
298 return wrapper
->regBlock(value
, regID
);
301 int EDOperand::evaluate(uint64_t &result
, EDRegisterBlock_t regBlock
) {
302 RegisterReaderWrapper wrapper
;
303 wrapper
.regBlock
= regBlock
;
304 return evaluate(result
, readerWrapperCallback
, (void*)&wrapper
);