Line | Count | Source (jump to first uncovered line) |
1 | | /* Capstone Disassembly Engine */ |
2 | | /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */ |
3 | | |
4 | | #if defined(CAPSTONE_HAS_OSXKERNEL) |
5 | | #include <Availability.h> |
6 | | #include <libkern/libkern.h> |
7 | | #else |
8 | | #include <stdio.h> |
9 | | #include <stdlib.h> |
10 | | #endif |
11 | | #include <string.h> |
12 | | #include <assert.h> |
13 | | |
14 | | #include "MCInst.h" |
15 | | #include "utils.h" |
16 | | |
17 | 960k | #define MCINST_CACHE (ARR_SIZE(mcInst->Operands) - 1) |
18 | | |
19 | | void MCInst_Init(MCInst *inst) |
20 | 2.43M | { |
21 | | // unnecessary to initialize in loop . its expensive and inst->size shuold be honored |
22 | 2.43M | inst->Operands[0].Kind = kInvalid; |
23 | 2.43M | inst->Operands[0].ImmVal = 0; |
24 | | |
25 | 2.43M | inst->Opcode = 0; |
26 | 2.43M | inst->OpcodePub = 0; |
27 | 2.43M | inst->size = 0; |
28 | 2.43M | inst->has_imm = false; |
29 | 2.43M | inst->op1_size = 0; |
30 | 2.43M | inst->writeback = false; |
31 | 2.43M | inst->ac_idx = 0; |
32 | 2.43M | inst->popcode_adjust = 0; |
33 | 2.43M | inst->assembly[0] = '\0'; |
34 | 2.43M | inst->wasm_data.type = WASM_OP_INVALID; |
35 | 2.43M | inst->xAcquireRelease = 0; |
36 | 119M | for (int i = 0; i < MAX_MC_OPS; ++i) |
37 | 116M | inst->tied_op_idx[i] = -1; |
38 | 2.43M | } |
39 | | |
40 | | void MCInst_clear(MCInst *inst) |
41 | 2.80M | { |
42 | 2.80M | inst->size = 0; |
43 | 2.80M | } |
44 | | |
45 | | // does not free @Op |
46 | | void MCInst_insert0(MCInst *inst, int index, MCOperand *Op) |
47 | 962k | { |
48 | 962k | assert(index < MAX_MC_OPS); |
49 | 962k | int i; |
50 | | |
51 | 1.60M | for(i = inst->size; i > index; i--) |
52 | | //memcpy(&(inst->Operands[i]), &(inst->Operands[i-1]), sizeof(MCOperand)); |
53 | 646k | inst->Operands[i] = inst->Operands[i-1]; |
54 | | |
55 | 962k | inst->Operands[index] = *Op; |
56 | 962k | inst->size++; |
57 | 962k | } |
58 | | |
59 | | void MCInst_setOpcode(MCInst *inst, unsigned Op) |
60 | 2.39M | { |
61 | 2.39M | inst->Opcode = Op; |
62 | 2.39M | } |
63 | | |
64 | | void MCInst_setOpcodePub(MCInst *inst, unsigned Op) |
65 | 121k | { |
66 | 121k | inst->OpcodePub = Op; |
67 | 121k | } |
68 | | |
69 | | unsigned MCInst_getOpcode(const MCInst *inst) |
70 | 12.9M | { |
71 | 12.9M | return inst->Opcode; |
72 | 12.9M | } |
73 | | |
74 | | unsigned MCInst_getOpcodePub(const MCInst *inst) |
75 | 2.60M | { |
76 | 2.60M | return inst->OpcodePub; |
77 | 2.60M | } |
78 | | |
79 | | MCOperand *MCInst_getOperand(MCInst *inst, unsigned i) |
80 | 10.4M | { |
81 | 10.4M | assert(i < MAX_MC_OPS); |
82 | 10.4M | return &inst->Operands[i]; |
83 | 10.4M | } |
84 | | |
85 | | unsigned MCInst_getNumOperands(const MCInst *inst) |
86 | 3.00M | { |
87 | 3.00M | return inst->size; |
88 | 3.00M | } |
89 | | |
90 | | // This addOperand2 function doesnt free Op |
91 | | void MCInst_addOperand2(MCInst *inst, MCOperand *Op) |
92 | 2.91k | { |
93 | 2.91k | assert(inst->size < MAX_MC_OPS); |
94 | 2.91k | inst->Operands[inst->size] = *Op; |
95 | | |
96 | 2.91k | inst->size++; |
97 | 2.91k | } |
98 | | |
99 | | bool MCOperand_isValid(const MCOperand *op) |
100 | 0 | { |
101 | 0 | return op->Kind != kInvalid; |
102 | 0 | } |
103 | | |
104 | | bool MCOperand_isReg(const MCOperand *op) |
105 | 3.91M | { |
106 | 3.91M | return op->Kind == kRegister; |
107 | 3.91M | } |
108 | | |
109 | | bool MCOperand_isImm(const MCOperand *op) |
110 | 1.65M | { |
111 | 1.65M | return op->Kind == kImmediate; |
112 | 1.65M | } |
113 | | |
114 | | bool MCOperand_isFPImm(const MCOperand *op) |
115 | 1.05k | { |
116 | 1.05k | return op->Kind == kFPImmediate; |
117 | 1.05k | } |
118 | | |
119 | | bool MCOperand_isDFPImm(const MCOperand *op) |
120 | 0 | { |
121 | 0 | return op->Kind == kDFPImmediate; |
122 | 0 | } |
123 | | |
124 | | bool MCOperand_isExpr(const MCOperand *op) |
125 | 0 | { |
126 | 0 | return op->Kind == kExpr; |
127 | 0 | } |
128 | | |
129 | | bool MCOperand_isInst(const MCOperand *op) |
130 | 0 | { |
131 | 0 | return op->Kind == kInst; |
132 | 0 | } |
133 | | |
134 | | /// getReg - Returns the register number. |
135 | | unsigned MCOperand_getReg(const MCOperand *op) |
136 | 6.91M | { |
137 | 6.91M | return op->RegVal; |
138 | 6.91M | } |
139 | | |
140 | | /// setReg - Set the register number. |
141 | | void MCOperand_setReg(MCOperand *op, unsigned Reg) |
142 | 5.69k | { |
143 | 5.69k | op->RegVal = Reg; |
144 | 5.69k | } |
145 | | |
146 | | int64_t MCOperand_getImm(MCOperand *op) |
147 | 3.28M | { |
148 | 3.28M | return op->ImmVal; |
149 | 3.28M | } |
150 | | |
151 | | void MCOperand_setImm(MCOperand *op, int64_t Val) |
152 | 14.6k | { |
153 | 14.6k | op->ImmVal = Val; |
154 | 14.6k | } |
155 | | |
156 | | double MCOperand_getFPImm(const MCOperand *op) |
157 | 0 | { |
158 | 0 | return op->FPImmVal; |
159 | 0 | } |
160 | | |
161 | | void MCOperand_setFPImm(MCOperand *op, double Val) |
162 | 0 | { |
163 | 0 | op->FPImmVal = Val; |
164 | 0 | } |
165 | | |
166 | | MCOperand *MCOperand_CreateReg1(MCInst *mcInst, unsigned Reg) |
167 | 540k | { |
168 | 540k | MCOperand *op = &(mcInst->Operands[MCINST_CACHE]); |
169 | | |
170 | 540k | op->MachineOperandType = kRegister; |
171 | 540k | op->Kind = kRegister; |
172 | 540k | op->RegVal = Reg; |
173 | | |
174 | 540k | return op; |
175 | 540k | } |
176 | | |
177 | | void MCOperand_CreateReg0(MCInst *mcInst, unsigned Reg) |
178 | 4.35M | { |
179 | 4.35M | MCOperand *op = &(mcInst->Operands[mcInst->size]); |
180 | 4.35M | mcInst->size++; |
181 | | |
182 | 4.35M | op->MachineOperandType = kRegister; |
183 | 4.35M | op->Kind = kRegister; |
184 | 4.35M | op->RegVal = Reg; |
185 | 4.35M | } |
186 | | |
187 | | MCOperand *MCOperand_CreateImm1(MCInst *mcInst, int64_t Val) |
188 | 419k | { |
189 | 419k | MCOperand *op = &(mcInst->Operands[MCINST_CACHE]); |
190 | | |
191 | 419k | op->MachineOperandType = kImmediate; |
192 | 419k | op->Kind = kImmediate; |
193 | 419k | op->ImmVal = Val; |
194 | | |
195 | 419k | return op; |
196 | 419k | } |
197 | | |
198 | | void MCOperand_CreateImm0(MCInst *mcInst, int64_t Val) |
199 | 1.99M | { |
200 | 1.99M | assert(mcInst->size < MAX_MC_OPS); |
201 | 1.99M | MCOperand *op = &(mcInst->Operands[mcInst->size]); |
202 | 1.99M | mcInst->size++; |
203 | | |
204 | 1.99M | op->MachineOperandType = kImmediate; |
205 | 1.99M | op->Kind = kImmediate; |
206 | 1.99M | op->ImmVal = Val; |
207 | 1.99M | } |
208 | | |
209 | | /// Check if any operand of the MCInstrDesc is predicable |
210 | | bool MCInst_isPredicable(const MCInstrDesc *MIDesc) |
211 | 0 | { |
212 | 0 | const MCOperandInfo *OpInfo = MIDesc->OpInfo; |
213 | 0 | unsigned NumOps = MIDesc->NumOperands; |
214 | 0 | for (unsigned i = 0; i < NumOps; ++i) { |
215 | 0 | if (MCOperandInfo_isPredicate(&OpInfo[i])) { |
216 | 0 | return true; |
217 | 0 | } |
218 | 0 | } |
219 | 0 | return false; |
220 | 0 | } |
221 | | |
222 | | /// Checks if tied operands exist in the instruction and sets |
223 | | /// - The writeback flag in detail |
224 | | /// - Saves the indices of the tied destination operands. |
225 | | void MCInst_handleWriteback(MCInst *MI, const MCInstrDesc *InstDesc) |
226 | 0 | { |
227 | 0 | const MCOperandInfo *OpInfo = InstDesc[MCInst_getOpcode(MI)].OpInfo; |
228 | 0 | unsigned short NumOps = InstDesc[MCInst_getOpcode(MI)].NumOperands; |
229 | |
|
230 | 0 | unsigned i; |
231 | 0 | for (i = 0; i < NumOps; ++i) { |
232 | 0 | if (MCOperandInfo_isTiedToOp(&OpInfo[i])) { |
233 | 0 | int idx = MCOperandInfo_getOperandConstraint( |
234 | 0 | &InstDesc[MCInst_getOpcode(MI)], i, |
235 | 0 | MCOI_TIED_TO); |
236 | |
|
237 | 0 | if (idx == -1) |
238 | 0 | continue; |
239 | | |
240 | 0 | if (i >= MAX_MC_OPS) { |
241 | 0 | assert(0 && |
242 | 0 | "Maximum number of MC operands reached."); |
243 | 0 | } |
244 | 0 | MI->tied_op_idx[i] = idx; |
245 | |
|
246 | 0 | if (MI->flat_insn->detail) |
247 | 0 | MI->flat_insn->detail->writeback = true; |
248 | 0 | } |
249 | 0 | } |
250 | 0 | } |
251 | | |
252 | | /// Check if operand with OpNum is tied by another operand |
253 | | /// (operand is tying destination). |
254 | | bool MCInst_opIsTied(const MCInst *MI, unsigned OpNum) |
255 | 0 | { |
256 | 0 | assert(OpNum < MAX_MC_OPS && "Maximum number of MC operands exceeded."); |
257 | 0 | for (int i = 0; i < MAX_MC_OPS; ++i) { |
258 | 0 | if (MI->tied_op_idx[i] == OpNum) |
259 | 0 | return true; |
260 | 0 | } |
261 | 0 | return false; |
262 | 0 | } |
263 | | |
264 | | /// Check if operand with OpNum is tying another operand |
265 | | /// (operand is tying src). |
266 | | bool MCInst_opIsTying(const MCInst *MI, unsigned OpNum) |
267 | 0 | { |
268 | 0 | assert(OpNum < MAX_MC_OPS && "Maximum number of MC operands exceeded."); |
269 | 0 | return MI->tied_op_idx[OpNum] != -1; |
270 | 0 | } |