Coverage Report

Created: 2025-10-14 06:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/capstonev5/MCInst.c
Line
Count
Source
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
3.29M
#define MCINST_CACHE (ARR_SIZE(mcInst->Operands) - 1)
18
19
void MCInst_Init(MCInst *inst)
20
3.11M
{
21
  // unnecessary to initialize in loop . its expensive and inst->size shuold be honored
22
3.11M
  inst->Operands[0].Kind = kInvalid;
23
3.11M
  inst->Operands[0].ImmVal = 0;
24
25
3.11M
  inst->Opcode = 0;
26
3.11M
  inst->OpcodePub = 0;
27
3.11M
  inst->size = 0;
28
3.11M
  inst->has_imm = false;
29
3.11M
  inst->op1_size = 0;
30
3.11M
  inst->writeback = false;
31
3.11M
  inst->ac_idx = 0;
32
3.11M
  inst->popcode_adjust = 0;
33
3.11M
  inst->assembly[0] = '\0';
34
3.11M
  inst->wasm_data.type = WASM_OP_INVALID;
35
3.11M
  inst->xAcquireRelease = 0;
36
152M
  for (int i = 0; i < MAX_MC_OPS; ++i)
37
149M
    inst->tied_op_idx[i] = -1;
38
3.11M
}
39
40
void MCInst_clear(MCInst *inst)
41
7.18M
{
42
7.18M
  inst->size = 0;
43
7.18M
}
44
45
// does not free @Op
46
void MCInst_insert0(MCInst *inst, int index, MCOperand *Op)
47
1.24M
{
48
1.24M
  assert(index < MAX_MC_OPS);
49
1.24M
  int i;
50
51
2.07M
  for(i = inst->size; i > index; i--)
52
    //memcpy(&(inst->Operands[i]), &(inst->Operands[i-1]), sizeof(MCOperand));
53
832k
    inst->Operands[i] = inst->Operands[i-1];
54
55
1.24M
  inst->Operands[index] = *Op;
56
1.24M
  inst->size++;
57
1.24M
}
58
59
void MCInst_setOpcode(MCInst *inst, unsigned Op)
60
6.69M
{
61
6.69M
  inst->Opcode = Op;
62
6.69M
}
63
64
void MCInst_setOpcodePub(MCInst *inst, unsigned Op)
65
219k
{
66
219k
  inst->OpcodePub = Op;
67
219k
}
68
69
unsigned MCInst_getOpcode(const MCInst *inst)
70
51.0M
{
71
51.0M
  return inst->Opcode;
72
51.0M
}
73
74
unsigned MCInst_getOpcodePub(const MCInst *inst)
75
6.93M
{
76
6.93M
  return inst->OpcodePub;
77
6.93M
}
78
79
MCOperand *MCInst_getOperand(MCInst *inst, unsigned i)
80
35.8M
{
81
35.8M
  assert(i < MAX_MC_OPS);
82
35.8M
  return &inst->Operands[i];
83
35.8M
}
84
85
unsigned MCInst_getNumOperands(const MCInst *inst)
86
13.6M
{
87
13.6M
  return inst->size;
88
13.6M
}
89
90
// This addOperand2 function doesnt free Op
91
void MCInst_addOperand2(MCInst *inst, MCOperand *Op)
92
5.05k
{
93
5.05k
  assert(inst->size < MAX_MC_OPS);
94
5.05k
  inst->Operands[inst->size] = *Op;
95
96
5.05k
  inst->size++;
97
5.05k
}
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
5.46M
{
106
5.46M
  return op->Kind == kRegister;
107
5.46M
}
108
109
bool MCOperand_isImm(const MCOperand *op)
110
2.34M
{
111
2.34M
  return op->Kind == kImmediate;
112
2.34M
}
113
114
bool MCOperand_isFPImm(const MCOperand *op)
115
2.06k
{
116
2.06k
  return op->Kind == kFPImmediate;
117
2.06k
}
118
119
bool MCOperand_isDFPImm(const MCOperand *op)
120
1.41k
{
121
1.41k
  return op->Kind == kDFPImmediate;
122
1.41k
}
123
124
bool MCOperand_isExpr(const MCOperand *op)
125
170k
{
126
170k
  return op->Kind == kExpr;
127
170k
}
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
23.2M
{
137
23.2M
  return op->RegVal;
138
23.2M
}
139
140
/// setReg - Set the register number.
141
void MCOperand_setReg(MCOperand *op, unsigned Reg)
142
21.9k
{
143
21.9k
  op->RegVal = Reg;
144
21.9k
}
145
146
int64_t MCOperand_getImm(MCOperand *op)
147
12.0M
{
148
12.0M
  return op->ImmVal;
149
12.0M
}
150
151
void MCOperand_setImm(MCOperand *op, int64_t Val)
152
33.7k
{
153
33.7k
  op->ImmVal = Val;
154
33.7k
}
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
1.88M
{
168
1.88M
  MCOperand *op = &(mcInst->Operands[MCINST_CACHE]);
169
170
1.88M
  op->MachineOperandType = kRegister;
171
1.88M
  op->Kind = kRegister;
172
1.88M
  op->RegVal = Reg;
173
174
1.88M
  return op;
175
1.88M
}
176
177
void MCOperand_CreateReg0(MCInst *mcInst, unsigned Reg)
178
12.7M
{
179
12.7M
  MCOperand *op = &(mcInst->Operands[mcInst->size]);
180
12.7M
  mcInst->size++;
181
182
12.7M
  op->MachineOperandType = kRegister;
183
12.7M
  op->Kind = kRegister;
184
12.7M
  op->RegVal = Reg;
185
12.7M
}
186
187
MCOperand *MCOperand_CreateImm1(MCInst *mcInst, int64_t Val)
188
1.40M
{
189
1.40M
  MCOperand *op = &(mcInst->Operands[MCINST_CACHE]);
190
191
1.40M
  op->MachineOperandType = kImmediate;
192
1.40M
  op->Kind = kImmediate;
193
1.40M
  op->ImmVal = Val;
194
195
1.40M
  return op;
196
1.40M
}
197
198
void MCOperand_CreateImm0(MCInst *mcInst, int64_t Val)
199
5.85M
{
200
5.85M
  assert(mcInst->size < MAX_MC_OPS);
201
5.85M
  MCOperand *op = &(mcInst->Operands[mcInst->size]);
202
5.85M
  mcInst->size++;
203
204
5.85M
  op->MachineOperandType = kImmediate;
205
5.85M
  op->Kind = kImmediate;
206
5.85M
  op->ImmVal = Val;
207
5.85M
}
208
209
/// Check if any operand of the MCInstrDesc is predicable
210
bool MCInst_isPredicable(const MCInstrDesc *MIDesc)
211
1.03M
{
212
1.03M
  const MCOperandInfo *OpInfo = MIDesc->OpInfo;
213
1.03M
  unsigned NumOps = MIDesc->NumOperands;
214
4.57M
  for (unsigned i = 0; i < NumOps; ++i) {
215
4.50M
    if (MCOperandInfo_isPredicate(&OpInfo[i])) {
216
963k
      return true;
217
963k
    }
218
4.50M
  }
219
67.9k
  return false;
220
1.03M
}
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
1.49M
{
227
1.49M
  const MCOperandInfo *OpInfo = InstDesc[MCInst_getOpcode(MI)].OpInfo;
228
1.49M
  unsigned short NumOps = InstDesc[MCInst_getOpcode(MI)].NumOperands;
229
230
1.49M
  unsigned i;
231
8.56M
  for (i = 0; i < NumOps; ++i) {
232
7.07M
    if (MCOperandInfo_isTiedToOp(&OpInfo[i])) {
233
334k
      int idx = MCOperandInfo_getOperandConstraint(
234
334k
        &InstDesc[MCInst_getOpcode(MI)], i,
235
334k
        MCOI_TIED_TO);
236
237
334k
      if (idx == -1)
238
0
        continue;
239
240
334k
      if (i >= MAX_MC_OPS) {
241
0
        assert(0 &&
242
0
               "Maximum number of MC operands reached.");
243
0
      }
244
334k
      MI->tied_op_idx[i] = idx;
245
246
334k
      if (MI->flat_insn->detail)
247
334k
        MI->flat_insn->detail->writeback = true;
248
334k
    }
249
7.07M
  }
250
1.49M
}
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
6.13M
{
256
6.13M
  assert(OpNum < MAX_MC_OPS && "Maximum number of MC operands exceeded.");
257
290M
  for (int i = 0; i < MAX_MC_OPS; ++i) {
258
284M
    if (MI->tied_op_idx[i] == OpNum)
259
228k
      return true;
260
284M
  }
261
5.90M
  return false;
262
6.13M
}
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
6.13M
{
268
6.13M
  assert(OpNum < MAX_MC_OPS && "Maximum number of MC operands exceeded.");
269
6.13M
  return MI->tied_op_idx[OpNum] != -1;
270
6.13M
}