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 "EDDisassembler.h"
18 #include "EDOperand.h"
20 #include "llvm/MC/EDInstInfo.h"
21 #include "llvm/MC/MCInst.h"
25 EDOperand::EDOperand(const EDDisassembler
&disassembler
,
28 unsigned int &mcOpIndex
) :
29 Disassembler(disassembler
),
32 MCOpIndex(mcOpIndex
) {
33 unsigned int numMCOperands
= 0;
35 if (Disassembler
.Key
.Arch
== Triple::x86
||
36 Disassembler
.Key
.Arch
== Triple::x86_64
) {
37 uint8_t operandType
= inst
.ThisInstInfo
->operandTypes
[opIndex
];
39 switch (operandType
) {
42 case kOperandTypeImmediate
:
45 case kOperandTypeRegister
:
48 case kOperandTypeX86Memory
:
51 case kOperandTypeX86EffectiveAddress
:
54 case kOperandTypeX86PCRelative
:
59 else if (Disassembler
.Key
.Arch
== Triple::arm
||
60 Disassembler
.Key
.Arch
== Triple::thumb
) {
61 uint8_t operandType
= inst
.ThisInstInfo
->operandTypes
[opIndex
];
63 switch (operandType
) {
65 case kOperandTypeARMRegisterList
:
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
:
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();
157 //unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg();
163 if (callback(&baseVal
, baseReg
, arg
))
170 if (callback(&indexVal
, indexReg
, arg
))
172 addr
+= (scaleAmount
* indexVal
);
175 addr
+= displacement
;
184 switch (operandType
) {
187 case kOperandTypeImmediate
:
188 result
= Inst
.Inst
->getOperand(MCOpIndex
).getImm();
190 case kOperandTypeRegister
:
192 unsigned reg
= Inst
.Inst
->getOperand(MCOpIndex
).getReg();
193 return callback(&result
, reg
, arg
);
195 case kOperandTypeARMBranchTarget
:
197 int64_t displacement
= Inst
.Inst
->getOperand(MCOpIndex
).getImm();
201 if (callback(&pcVal
, Disassembler
.registerIDWithName("PC"), arg
))
204 result
= pcVal
+ displacement
;
213 int EDOperand::isRegister() {
214 return(Inst
.ThisInstInfo
->operandFlags
[OpIndex
] == kOperandTypeRegister
);
217 unsigned EDOperand::regVal() {
218 return Inst
.Inst
->getOperand(MCOpIndex
).getReg();
221 int EDOperand::isImmediate() {
222 return(Inst
.ThisInstInfo
->operandFlags
[OpIndex
] == kOperandTypeImmediate
);
225 uint64_t EDOperand::immediateVal() {
226 return Inst
.Inst
->getOperand(MCOpIndex
).getImm();
229 int EDOperand::isMemory() {
230 uint8_t operandType
= Inst
.ThisInstInfo
->operandTypes
[OpIndex
];
232 switch (operandType
) {
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
:
265 struct RegisterReaderWrapper
{
266 EDRegisterBlock_t regBlock
;
269 int readerWrapperCallback(uint64_t *value
,
272 struct RegisterReaderWrapper
*wrapper
= (struct RegisterReaderWrapper
*)arg
;
273 return wrapper
->regBlock(value
, regID
);
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
,