Coverage Report

Created: 2026-08-31 06:58

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.97M
#define MCINST_CACHE (ARR_SIZE(mcInst->Operands) - 1)
18
19
void MCInst_Init(MCInst *inst)
20
3.63M
{
21
3.63M
  memset(inst, 0, sizeof(MCInst));
22
177M
  for (int i = 0; i < MAX_MC_OPS; ++i) {
23
174M
    inst->tied_op_idx[i] = -1;
24
174M
  }
25
3.63M
}
26
27
void MCInst_clear(MCInst *inst)
28
8.43M
{
29
8.43M
  inst->size = 0;
30
8.43M
}
31
32
// does not free @Op
33
void MCInst_insert0(MCInst *inst, int index, MCOperand *Op)
34
1.44M
{
35
1.44M
  assert(index < MAX_MC_OPS);
36
1.44M
  int i;
37
38
2.35M
  for(i = inst->size; i > index; i--)
39
    //memcpy(&(inst->Operands[i]), &(inst->Operands[i-1]), sizeof(MCOperand));
40
911k
    inst->Operands[i] = inst->Operands[i-1];
41
42
1.44M
  inst->Operands[index] = *Op;
43
1.44M
  inst->size++;
44
1.44M
}
45
46
void MCInst_setOpcode(MCInst *inst, unsigned Op)
47
8.11M
{
48
8.11M
  inst->Opcode = Op;
49
8.11M
}
50
51
void MCInst_setOpcodePub(MCInst *inst, unsigned Op)
52
211k
{
53
211k
  inst->OpcodePub = Op;
54
211k
}
55
56
unsigned MCInst_getOpcode(const MCInst *inst)
57
60.8M
{
58
60.8M
  return inst->Opcode;
59
60.8M
}
60
61
unsigned MCInst_getOpcodePub(const MCInst *inst)
62
8.28M
{
63
8.28M
  return inst->OpcodePub;
64
8.28M
}
65
66
MCOperand *MCInst_getOperand(MCInst *inst, unsigned i)
67
40.1M
{
68
40.1M
  assert(i < MAX_MC_OPS);
69
40.1M
  return &inst->Operands[i];
70
40.1M
}
71
72
unsigned MCInst_getNumOperands(const MCInst *inst)
73
15.7M
{
74
15.7M
  return inst->size;
75
15.7M
}
76
77
// This addOperand2 function doesnt free Op
78
void MCInst_addOperand2(MCInst *inst, MCOperand *Op)
79
2.23k
{
80
2.23k
  assert(inst->size < MAX_MC_OPS);
81
2.23k
  inst->Operands[inst->size] = *Op;
82
83
2.23k
  inst->size++;
84
2.23k
}
85
86
bool MCOperand_isValid(const MCOperand *op)
87
0
{
88
0
  return op->Kind != kInvalid;
89
0
}
90
91
bool MCOperand_isReg(const MCOperand *op)
92
6.10M
{
93
6.10M
  return op->Kind == kRegister;
94
6.10M
}
95
96
bool MCOperand_isImm(const MCOperand *op)
97
2.43M
{
98
2.43M
  return op->Kind == kImmediate;
99
2.43M
}
100
101
bool MCOperand_isFPImm(const MCOperand *op)
102
1.28k
{
103
1.28k
  return op->Kind == kFPImmediate;
104
1.28k
}
105
106
bool MCOperand_isDFPImm(const MCOperand *op)
107
2.54k
{
108
2.54k
  return op->Kind == kDFPImmediate;
109
2.54k
}
110
111
bool MCOperand_isExpr(const MCOperand *op)
112
212k
{
113
212k
  return op->Kind == kExpr;
114
212k
}
115
116
bool MCOperand_isInst(const MCOperand *op)
117
0
{
118
0
  return op->Kind == kInst;
119
0
}
120
121
/// getReg - Returns the register number.
122
unsigned MCOperand_getReg(const MCOperand *op)
123
27.0M
{
124
27.0M
  return op->RegVal;
125
27.0M
}
126
127
/// setReg - Set the register number.
128
void MCOperand_setReg(MCOperand *op, unsigned Reg)
129
29.9k
{
130
29.9k
  op->RegVal = Reg;
131
29.9k
}
132
133
int64_t MCOperand_getImm(MCOperand *op)
134
13.7M
{
135
13.7M
  return op->ImmVal;
136
13.7M
}
137
138
void MCOperand_setImm(MCOperand *op, int64_t Val)
139
41.0k
{
140
41.0k
  op->ImmVal = Val;
141
41.0k
}
142
143
double MCOperand_getFPImm(const MCOperand *op)
144
0
{
145
0
  return op->FPImmVal;
146
0
}
147
148
void MCOperand_setFPImm(MCOperand *op, double Val)
149
0
{
150
0
  op->FPImmVal = Val;
151
0
}
152
153
MCOperand *MCOperand_CreateReg1(MCInst *mcInst, unsigned Reg)
154
2.27M
{
155
2.27M
  MCOperand *op = &(mcInst->Operands[MCINST_CACHE]);
156
157
2.27M
  op->MachineOperandType = kRegister;
158
2.27M
  op->Kind = kRegister;
159
2.27M
  op->RegVal = Reg;
160
161
2.27M
  return op;
162
2.27M
}
163
164
void MCOperand_CreateReg0(MCInst *mcInst, unsigned Reg)
165
6.87M
{
166
6.87M
  MCOperand *op = &(mcInst->Operands[mcInst->size]);
167
6.87M
  mcInst->size++;
168
169
6.87M
  op->MachineOperandType = kRegister;
170
6.87M
  op->Kind = kRegister;
171
6.87M
  op->RegVal = Reg;
172
6.87M
}
173
174
MCOperand *MCOperand_CreateImm1(MCInst *mcInst, int64_t Val)
175
1.69M
{
176
1.69M
  MCOperand *op = &(mcInst->Operands[MCINST_CACHE]);
177
178
1.69M
  op->MachineOperandType = kImmediate;
179
1.69M
  op->Kind = kImmediate;
180
1.69M
  op->ImmVal = Val;
181
182
1.69M
  return op;
183
1.69M
}
184
185
void MCOperand_CreateImm0(MCInst *mcInst, int64_t Val)
186
3.18M
{
187
3.18M
  assert(mcInst->size < MAX_MC_OPS);
188
3.18M
  MCOperand *op = &(mcInst->Operands[mcInst->size]);
189
3.18M
  mcInst->size++;
190
191
3.18M
  op->MachineOperandType = kImmediate;
192
3.18M
  op->Kind = kImmediate;
193
3.18M
  op->ImmVal = Val;
194
3.18M
}
195
196
/// Check if any operand of the MCInstrDesc is predicable
197
bool MCInst_isPredicable(const MCInstrDesc *MIDesc)
198
1.27M
{
199
1.27M
  const MCOperandInfo *OpInfo = MIDesc->OpInfo;
200
1.27M
  unsigned NumOps = MIDesc->NumOperands;
201
5.56M
  for (unsigned i = 0; i < NumOps; ++i) {
202
5.48M
    if (MCOperandInfo_isPredicate(&OpInfo[i])) {
203
1.19M
      return true;
204
1.19M
    }
205
5.48M
  }
206
75.1k
  return false;
207
1.27M
}
208
209
/// Checks if tied operands exist in the instruction and sets
210
/// - The writeback flag in detail
211
/// - Saves the indices of the tied destination operands.
212
void MCInst_handleWriteback(MCInst *MI, const MCInstrDesc *InstDesc)
213
1.85M
{
214
1.85M
  const MCOperandInfo *OpInfo = InstDesc[MCInst_getOpcode(MI)].OpInfo;
215
1.85M
  unsigned short NumOps = InstDesc[MCInst_getOpcode(MI)].NumOperands;
216
217
1.85M
  unsigned i;
218
10.5M
  for (i = 0; i < NumOps; ++i) {
219
8.65M
    if (MCOperandInfo_isTiedToOp(&OpInfo[i])) {
220
399k
      int idx = MCOperandInfo_getOperandConstraint(
221
399k
        &InstDesc[MCInst_getOpcode(MI)], i,
222
399k
        MCOI_TIED_TO);
223
224
399k
      if (idx == -1)
225
0
        continue;
226
227
399k
      if (i >= MAX_MC_OPS) {
228
0
        assert(0 &&
229
0
               "Maximum number of MC operands reached.");
230
0
      }
231
399k
      MI->tied_op_idx[i] = idx;
232
233
399k
      if (MI->flat_insn->detail)
234
399k
        MI->flat_insn->detail->writeback = true;
235
399k
    }
236
8.65M
  }
237
1.85M
}
238
239
/// Check if operand with OpNum is tied by another operand
240
/// (operand is tying destination).
241
bool MCInst_opIsTied(const MCInst *MI, unsigned OpNum)
242
7.13M
{
243
7.13M
  assert(OpNum < MAX_MC_OPS && "Maximum number of MC operands exceeded.");
244
337M
  for (int i = 0; i < MAX_MC_OPS; ++i) {
245
331M
    if (MI->tied_op_idx[i] == OpNum)
246
258k
      return true;
247
331M
  }
248
6.87M
  return false;
249
7.13M
}
250
251
/// Check if operand with OpNum is tying another operand
252
/// (operand is tying src).
253
bool MCInst_opIsTying(const MCInst *MI, unsigned OpNum)
254
7.13M
{
255
7.13M
  assert(OpNum < MAX_MC_OPS && "Maximum number of MC operands exceeded.");
256
7.13M
  return MI->tied_op_idx[OpNum] != -1;
257
7.13M
}