Coverage Report

Created: 2026-09-01 07:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/capstonenext/arch/Xtensa/XtensaMapping.c
Line
Count
Source
1
/* Capstone Disassembly Engine */
2
/* By billow <billow.fun@gmail.com>, 2024 */
3
4
#include <capstone/xtensa.h>
5
6
#include "../../MCRegisterInfo.h"
7
#include "../../MCInst.h"
8
#include "../../SStream.h"
9
#include "../../Mapping.h"
10
#include "../../utils.h"
11
#include "../../cs_simple_types.h"
12
#include "XtensaDisassembler.h"
13
#include "XtensaInstPrinter.h"
14
#include "priv.h"
15
#include "XtensaMapping.h"
16
17
#ifndef CAPSTONE_DIET
18
19
static const char *const insn_name_maps[] = {
20
#include "XtensaGenCSMappingInsnName.inc"
21
};
22
23
static const name_map group_name_maps[] = {
24
#include "XtensaGenCSFeatureName.inc"
25
};
26
27
static const insn_map mapping_insns[] = {
28
#include "XtensaGenCSMappingInsn.inc"
29
};
30
31
static const map_insn_ops insn_operands[] = {
32
#include "XtensaGenCSMappingInsnOp.inc"
33
};
34
35
#endif
36
37
#define GET_REGINFO_MC_DESC
38
#include "XtensaGenRegisterInfo.inc"
39
#include "../../MathExtras.h"
40
41
void Xtensa_init_mri(MCRegisterInfo *mri)
42
1.03k
{
43
1.03k
  MCRegisterInfo_InitMCRegisterInfo(
44
1.03k
    mri, XtensaRegDesc, ARR_SIZE(XtensaRegDesc), 0, 0,
45
1.03k
    XtensaMCRegisterClasses, ARR_SIZE(XtensaMCRegisterClasses), 0,
46
1.03k
    0, XtensaRegDiffLists, NULL, XtensaSubRegIdxLists,
47
1.03k
    ARR_SIZE(XtensaSubRegIdxLists), XtensaRegEncodingTable);
48
1.03k
}
49
50
void Xtensa_printer(MCInst *MI, SStream *OS, void *info)
51
47.0k
{
52
47.0k
  Xtensa_LLVM_printInstruction(MI, MI->address, OS);
53
47.0k
}
54
55
static void set_instr_map_data(MCInst *MI)
56
47.0k
{
57
47.0k
#ifndef CAPSTONE_DIET
58
47.0k
  map_cs_id(MI, mapping_insns, ARR_SIZE(mapping_insns));
59
47.0k
  map_implicit_reads(MI, mapping_insns);
60
47.0k
  map_implicit_writes(MI, mapping_insns);
61
47.0k
  map_groups(MI, mapping_insns);
62
63
47.0k
  const xtensa_suppl_info *suppl_info =
64
47.0k
    map_get_suppl_info(MI, mapping_insns);
65
47.0k
  if (suppl_info) {
66
47.0k
    Xtensa_get_detail(MI)->format = suppl_info->form;
67
47.0k
  }
68
47.0k
#endif
69
47.0k
}
70
71
void Xtensa_init_cs_detail(MCInst *MI)
72
47.7k
{
73
47.7k
  if (detail_is_set(MI)) {
74
47.7k
    memset(get_detail(MI), 0,
75
47.7k
           offsetof(cs_detail, xtensa) + sizeof(cs_xtensa));
76
47.7k
  }
77
47.7k
}
78
79
bool Xtensa_disasm(csh handle, const uint8_t *code, size_t code_len,
80
       MCInst *instr, uint16_t *size, uint64_t address, void *info)
81
47.7k
{
82
47.7k
  if (detail_is_set(instr)) {
83
47.7k
    Xtensa_init_cs_detail(instr);
84
47.7k
  }
85
47.7k
  DecodeStatus res = Xtensa_LLVM_getInstruction(instr, size, code,
86
47.7k
                  code_len, address);
87
47.7k
  if (res != MCDisassembler_Fail) {
88
47.0k
    set_instr_map_data(instr);
89
47.0k
  }
90
47.7k
  if (res == MCDisassembler_SoftFail) {
91
0
    MCInst_setSoftFail(instr);
92
0
  }
93
47.7k
  return res != MCDisassembler_Fail;
94
47.7k
}
95
96
const char *Xtensa_reg_name(csh handle, unsigned int id)
97
6.05k
{
98
6.05k
  return Xtensa_LLVM_getRegisterName(id);
99
6.05k
}
100
101
void Xtensa_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
102
47.0k
{
103
  // Done in Xtensa_disasm
104
47.0k
}
105
106
const char *Xtensa_insn_name(csh handle, unsigned int id)
107
47.0k
{
108
47.0k
#ifndef CAPSTONE_DIET
109
47.0k
  if (id >= ARR_SIZE(insn_name_maps)) {
110
0
    return NULL;
111
0
  }
112
47.0k
  return insn_name_maps[id];
113
#else
114
  return NULL;
115
#endif
116
47.0k
}
117
118
const char *Xtensa_group_name(csh handle, unsigned int id)
119
34.5k
{
120
34.5k
#ifndef CAPSTONE_DIET
121
34.5k
  return id2name(group_name_maps, ARR_SIZE(group_name_maps), id);
122
#else
123
  return NULL;
124
#endif
125
34.5k
}
126
127
#ifndef CAPSTONE_DIET
128
void Xtensa_reg_access(const cs_insn *insn, cs_regs regs_read,
129
           uint8_t *regs_read_count, cs_regs regs_write,
130
           uint8_t *regs_write_count)
131
0
{
132
0
  uint8_t i;
133
0
  uint8_t read_count, write_count;
134
0
  cs_xtensa *detail = &(insn->detail->xtensa);
135
136
0
  read_count = insn->detail->regs_read_count;
137
0
  write_count = insn->detail->regs_write_count;
138
139
  // implicit registers
140
0
  memcpy(regs_read, insn->detail->regs_read,
141
0
         read_count * sizeof(insn->detail->regs_read[0]));
142
0
  memcpy(regs_write, insn->detail->regs_write,
143
0
         write_count * sizeof(insn->detail->regs_write[0]));
144
145
  // explicit registers
146
0
  for (i = 0; i < detail->op_count; i++) {
147
0
    cs_xtensa_op *op = &(detail->operands[i]);
148
0
    switch (op->type) {
149
0
    case XTENSA_OP_REG:
150
0
      if ((op->access & CS_AC_READ) &&
151
0
          !arr_exist(regs_read, read_count, op->reg)) {
152
0
        regs_read[read_count] = (uint16_t)op->reg;
153
0
        read_count++;
154
0
      }
155
0
      if ((op->access & CS_AC_WRITE) &&
156
0
          !arr_exist(regs_write, write_count, op->reg)) {
157
0
        regs_write[write_count] = (uint16_t)op->reg;
158
0
        write_count++;
159
0
      }
160
0
      break;
161
0
    case XTENSA_OP_MEM:
162
      // registers appeared in memory references always being read
163
0
      if ((op->mem.base != XTENSA_REG_INVALID) &&
164
0
          !arr_exist(regs_read, read_count, op->mem.base)) {
165
0
        regs_read[read_count] = (uint16_t)op->mem.base;
166
0
        read_count++;
167
0
      }
168
0
      if ((insn->detail->writeback) &&
169
0
          (op->mem.base != XTENSA_REG_INVALID) &&
170
0
          !arr_exist(regs_write, write_count, op->mem.base)) {
171
0
        regs_write[write_count] =
172
0
          (uint16_t)op->mem.base;
173
0
        write_count++;
174
0
      }
175
0
    default:
176
0
      break;
177
0
    }
178
0
  }
179
180
0
  *regs_read_count = read_count;
181
0
  *regs_write_count = write_count;
182
0
}
183
#endif
184
185
int64_t Xtensa_L32R_Value(MCInst *MI, int op_num)
186
6.21k
{
187
6.21k
  int64_t InstrOff = MCOperand_getImm(MCInst_getOperand(MI, (op_num)));
188
6.21k
  CS_ASSERT((InstrOff >= -262144 && InstrOff <= -4) &&
189
6.21k
      "Invalid argument, value must be in ranges [-262144,-4]");
190
6.21k
  int64_t Value = 0;
191
6.21k
  if (MI->csh->LITBASE & 0x1) {
192
0
    Value = (MI->csh->LITBASE & 0xfffff000) + InstrOff;
193
6.21k
  } else {
194
6.21k
    Value = (((int64_t)MI->address + 3) & ~0x3) + InstrOff;
195
6.21k
  }
196
6.21k
  return Value;
197
6.21k
}
198
199
void Xtensa_add_cs_detail_0(MCInst *MI, xtensa_op_group op_group, int op_num)
200
112k
{
201
112k
  if (!detail_is_set(MI)) {
202
0
    return;
203
0
  }
204
205
112k
  cs_xtensa_op *xop = Xtensa_get_detail_op(MI, 0);
206
112k
  if (!xop) {
207
0
    return;
208
0
  }
209
210
112k
  switch (op_group) {
211
74.6k
  case Xtensa_OP_GROUP_Operand: {
212
74.6k
    const MCOperand *MC = MCInst_getOperand(MI, op_num);
213
74.6k
    if (MCOperand_isReg(MC)) {
214
74.6k
      xop->type = XTENSA_OP_REG;
215
74.6k
      xop->reg = MC->RegVal;
216
74.6k
    } else if (MCOperand_isImm(MC)) {
217
0
      xop->type = XTENSA_OP_IMM;
218
0
      xop->imm = MC->ImmVal;
219
0
    }
220
74.6k
  } break;
221
690
  case Xtensa_OP_GROUP_Imm1_16_AsmOperand:
222
4.07k
  case Xtensa_OP_GROUP_Imm1n_15_AsmOperand:
223
4.13k
  case Xtensa_OP_GROUP_Imm7_22_AsmOperand:
224
4.46k
  case Xtensa_OP_GROUP_Imm8_AsmOperand:
225
4.95k
  case Xtensa_OP_GROUP_Imm8_sh8_AsmOperand:
226
5.03k
  case Xtensa_OP_GROUP_Imm8n_7_AsmOperand:
227
5.03k
  case Xtensa_OP_GROUP_Imm12_AsmOperand:
228
5.21k
  case Xtensa_OP_GROUP_Imm12m_AsmOperand:
229
6.24k
  case Xtensa_OP_GROUP_Imm32n_95_AsmOperand:
230
6.28k
  case Xtensa_OP_GROUP_Imm64n_4n_AsmOperand:
231
6.28k
  case Xtensa_OP_GROUP_ImmOperand_minus32_28_4:
232
8.45k
  case Xtensa_OP_GROUP_Uimm5_AsmOperand:
233
10.2k
  case Xtensa_OP_GROUP_Uimm4_AsmOperand:
234
10.5k
  case Xtensa_OP_GROUP_Shimm0_31_AsmOperand:
235
10.5k
  case Xtensa_OP_GROUP_Shimm1_31_AsmOperand:
236
13.0k
  case Xtensa_OP_GROUP_B4const_AsmOperand:
237
16.1k
  case Xtensa_OP_GROUP_B4constu_AsmOperand:
238
16.1k
  case Xtensa_OP_GROUP_ImmOperand_minus16_14_2:
239
16.1k
  case Xtensa_OP_GROUP_ImmOperand_minus64_56_8:
240
16.1k
  case Xtensa_OP_GROUP_ImmOperand_0_56_8:
241
16.1k
  case Xtensa_OP_GROUP_ImmOperand_minus16_47_1:
242
16.1k
  case Xtensa_OP_GROUP_ImmOperand_0_3_1:
243
16.1k
  case Xtensa_OP_GROUP_ImmOperand_0_63_1:
244
16.2k
  case Xtensa_OP_GROUP_Entry_Imm12_AsmOperand:
245
17.1k
  case Xtensa_OP_GROUP_Offset8m32_AsmOperand:
246
17.1k
  case Xtensa_OP_GROUP_Select_4_AsmOperand:
247
17.1k
  case Xtensa_OP_GROUP_Select_2_AsmOperand:
248
17.1k
  case Xtensa_OP_GROUP_Select_8_AsmOperand:
249
17.1k
  case Xtensa_OP_GROUP_Offset_16_16_AsmOperand:
250
17.1k
  case Xtensa_OP_GROUP_Offset_256_8_AsmOperand:
251
17.1k
  case Xtensa_OP_GROUP_Offset_256_16_AsmOperand:
252
17.1k
  case Xtensa_OP_GROUP_Offset_256_4_AsmOperand:
253
17.1k
  case Xtensa_OP_GROUP_Select_16_AsmOperand:
254
17.1k
  case Xtensa_OP_GROUP_Offset_128_2_AsmOperand:
255
17.1k
  case Xtensa_OP_GROUP_Offset_128_1_AsmOperand:
256
17.1k
  case Xtensa_OP_GROUP_Offset_64_16_AsmOperand:
257
17.2k
  case Xtensa_OP_GROUP_Select_256_AsmOperand: {
258
17.2k
    int64_t val = MCOperand_getImm(MCInst_getOperand(MI, op_num));
259
17.2k
    xop->type = XTENSA_OP_IMM;
260
17.2k
    xop->imm = (int32_t)val;
261
17.2k
  } break;
262
8.42k
  case Xtensa_OP_GROUP_BranchTarget:
263
9.25k
  case Xtensa_OP_GROUP_JumpTarget:
264
10.9k
  case Xtensa_OP_GROUP_CallOperand:
265
11.0k
  case Xtensa_OP_GROUP_LoopTarget: {
266
11.0k
    int64_t val =
267
11.0k
      MCOperand_getImm(MCInst_getOperand(MI, op_num)) + 4;
268
11.0k
    xop->type = XTENSA_OP_IMM;
269
11.0k
    xop->imm = (int32_t)val;
270
11.0k
  } break;
271
3.10k
  case Xtensa_OP_GROUP_L32RTarget: {
272
3.10k
    xop->type = XTENSA_OP_L32R;
273
3.10k
    xop->imm = (int32_t)Xtensa_L32R_Value(MI, op_num);
274
3.10k
  } break;
275
6.45k
  case Xtensa_OP_GROUP_MemOperand: {
276
6.45k
    unsigned reg =
277
6.45k
      MCOperand_getReg(MCInst_getOperand(MI, (op_num)));
278
6.45k
    int64_t imm8 =
279
6.45k
      MCOperand_getImm(MCInst_getOperand(MI, op_num + 1));
280
6.45k
    xop->type = XTENSA_OP_MEM;
281
6.45k
    xop->mem.base = reg;
282
6.45k
    xop->mem.disp = (int32_t)imm8;
283
6.45k
  } break;
284
112k
  }
285
286
112k
  xop->access = map_get_op_access(MI, op_num);
287
112k
  Xtensa_inc_op_count(MI);
288
112k
}