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 Triple::ArchType arch
= Disassembler
.TgtTriple
.getArch();
35 if (arch
== Triple::x86
||
36 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 (arch
== Triple::arm
||
60 arch
== Triple::thumb
) {
61 uint8_t operandType
= inst
.ThisInstInfo
->operandTypes
[opIndex
];
63 switch (operandType
) {
65 case kOperandTypeARMRegisterList
:
66 case kOperandTypeARMDPRRegisterList
:
67 case kOperandTypeARMSPRRegisterList
:
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
:
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
:
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
:
114 case kOperandTypeARMAddrMode6
:
120 mcOpIndex
+= numMCOperands
;
123 EDOperand::~EDOperand() {
126 int EDOperand::evaluate(uint64_t &result
,
127 EDRegisterReaderCallback callback
,
129 uint8_t operandType
= Inst
.ThisInstInfo
->operandTypes
[OpIndex
];
131 Triple::ArchType arch
= Disassembler
.TgtTriple
.getArch();
138 switch (operandType
) {
141 case kOperandTypeImmediate
:
142 result
= Inst
.Inst
->getOperand(MCOpIndex
).getImm();
144 case kOperandTypeRegister
:
146 unsigned reg
= Inst
.Inst
->getOperand(MCOpIndex
).getReg();
147 return callback(&result
, reg
, arg
);
149 case kOperandTypeX86PCRelative
:
151 int64_t displacement
= Inst
.Inst
->getOperand(MCOpIndex
).getImm();
155 // TODO fix how we do this
157 if (callback(&ripVal
, Disassembler
.registerIDWithName("RIP"), arg
))
160 result
= ripVal
+ displacement
;
163 case kOperandTypeX86Memory
:
164 case kOperandTypeX86EffectiveAddress
:
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();
173 unsigned segmentReg
= Inst
.Inst
->getOperand(MCOpIndex
+4).getReg();
175 if (segmentReg
!= 0 && arch
== Triple::x86_64
) {
176 unsigned fsID
= Disassembler
.registerIDWithName("FS");
177 unsigned gsID
= Disassembler
.registerIDWithName("GS");
179 if (segmentReg
== fsID
||
180 segmentReg
== gsID
) {
181 uint64_t segmentBase
;
182 if (!callback(&segmentBase
, segmentReg
, arg
))
189 if (callback(&baseVal
, baseReg
, arg
))
196 if (callback(&indexVal
, indexReg
, arg
))
198 addr
+= (scaleAmount
* indexVal
);
201 addr
+= displacement
;
206 } // switch (operandType)
209 switch (operandType
) {
212 case kOperandTypeImmediate
:
213 if (!Inst
.Inst
->getOperand(MCOpIndex
).isImm())
216 result
= Inst
.Inst
->getOperand(MCOpIndex
).getImm();
218 case kOperandTypeRegister
:
220 if (!Inst
.Inst
->getOperand(MCOpIndex
).isReg())
223 unsigned reg
= Inst
.Inst
->getOperand(MCOpIndex
).getReg();
224 return callback(&result
, reg
, arg
);
226 case kOperandTypeARMBranchTarget
:
228 if (!Inst
.Inst
->getOperand(MCOpIndex
).isImm())
231 int64_t displacement
= Inst
.Inst
->getOperand(MCOpIndex
).getImm();
235 if (callback(&pcVal
, Disassembler
.registerIDWithName("PC"), arg
))
238 result
= pcVal
+ displacement
;
245 int EDOperand::isRegister() {
246 return(Inst
.ThisInstInfo
->operandFlags
[OpIndex
] == kOperandTypeRegister
);
249 unsigned EDOperand::regVal() {
250 return Inst
.Inst
->getOperand(MCOpIndex
).getReg();
253 int EDOperand::isImmediate() {
254 return(Inst
.ThisInstInfo
->operandFlags
[OpIndex
] == kOperandTypeImmediate
);
257 uint64_t EDOperand::immediateVal() {
258 return Inst
.Inst
->getOperand(MCOpIndex
).getImm();
261 int EDOperand::isMemory() {
262 uint8_t operandType
= Inst
.ThisInstInfo
->operandTypes
[OpIndex
];
264 switch (operandType
) {
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
:
300 struct RegisterReaderWrapper
{
301 EDOperand::EDRegisterBlock_t regBlock
;
305 static int readerWrapperCallback(uint64_t *value
, unsigned regID
, void *arg
) {
306 RegisterReaderWrapper
*wrapper
= (RegisterReaderWrapper
*)arg
;
307 return wrapper
->regBlock(value
, regID
);
310 int EDOperand::evaluate(uint64_t &result
, EDRegisterBlock_t regBlock
) {
311 RegisterReaderWrapper wrapper
;
312 wrapper
.regBlock
= regBlock
;
313 return evaluate(result
, readerWrapperCallback
, (void*)&wrapper
);