Coverage Report

Created: 2025-10-10 06:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/capstonenext/arch/SystemZ/SystemZMapping.c
Line
Count
Source
1
/* Capstone Disassembly Engine */
2
/* By Rot127 <unisono@quyllur.org> 2022-2023 */
3
4
#ifdef CAPSTONE_HAS_SYSTEMZ
5
6
#include <stdio.h> // debug
7
#include <string.h>
8
9
#include "../../Mapping.h"
10
#include "../../utils.h"
11
#include "../../cs_simple_types.h"
12
#include <capstone/cs_operand.h>
13
14
#include "SystemZMCTargetDesc.h"
15
#include "SystemZMapping.h"
16
#include "SystemZLinkage.h"
17
18
#ifndef CAPSTONE_DIET
19
20
static const char *const insn_name_maps[] = {
21
#include "SystemZGenCSMappingInsnName.inc"
22
};
23
24
static const name_map insn_alias_mnem_map[] = {
25
#include "SystemZGenCSAliasMnemMap.inc"
26
  { SYSTEMZ_INS_ALIAS_END, NULL },
27
};
28
29
static const map_insn_ops insn_operands[] = {
30
#include "SystemZGenCSMappingInsnOp.inc"
31
};
32
33
#endif
34
35
#define GET_REGINFO_MC_DESC
36
#include "SystemZGenRegisterInfo.inc"
37
38
const insn_map systemz_insns[] = {
39
#include "SystemZGenCSMappingInsn.inc"
40
};
41
42
void SystemZ_set_instr_map_data(MCInst *MI, const uint8_t *Bytes,
43
        size_t BytesLen)
44
58.8k
{
45
58.8k
  map_cs_id(MI, systemz_insns, ARR_SIZE(systemz_insns));
46
58.8k
  map_implicit_reads(MI, systemz_insns);
47
58.8k
  map_implicit_writes(MI, systemz_insns);
48
58.8k
  map_groups(MI, systemz_insns);
49
58.8k
  const systemz_suppl_info *suppl_info =
50
58.8k
    map_get_suppl_info(MI, systemz_insns);
51
58.8k
  if (suppl_info) {
52
58.8k
    SystemZ_get_detail(MI)->format = suppl_info->form;
53
58.8k
  }
54
58.8k
}
55
56
void SystemZ_init_mri(MCRegisterInfo *MRI)
57
1.64k
{
58
1.64k
  MCRegisterInfo_InitMCRegisterInfo(
59
1.64k
    MRI, SystemZRegDesc, AARCH64_REG_ENDING, 0, 0,
60
1.64k
    SystemZMCRegisterClasses, ARR_SIZE(SystemZMCRegisterClasses), 0,
61
1.64k
    0, SystemZRegDiffLists, 0, SystemZSubRegIdxLists,
62
1.64k
    ARR_SIZE(SystemZSubRegIdxLists), 0);
63
1.64k
}
64
65
const char *SystemZ_reg_name(csh handle, unsigned int reg)
66
35.9k
{
67
35.9k
  return SystemZ_LLVM_getRegisterName(reg);
68
35.9k
}
69
70
void SystemZ_printer(MCInst *MI, SStream *O, void * /* MCRegisterInfo* */ info)
71
57.9k
{
72
57.9k
  MI->MRI = (MCRegisterInfo *)info;
73
57.9k
  MI->fillDetailOps = detail_is_set(MI);
74
57.9k
  SystemZ_LLVM_printInstruction(MI, "", O);
75
57.9k
#ifndef CAPSTONE_DIET
76
57.9k
  map_set_alias_id(MI, O, insn_alias_mnem_map,
77
57.9k
       ARR_SIZE(insn_alias_mnem_map));
78
57.9k
#endif
79
57.9k
}
80
81
void SystemZ_init_cs_detail(MCInst *MI)
82
58.8k
{
83
58.8k
  if (!detail_is_set(MI)) {
84
0
    return;
85
0
  }
86
58.8k
  memset(get_detail(MI), 0, sizeof(cs_detail));
87
58.8k
  if (detail_is_set(MI)) {
88
58.8k
    SystemZ_get_detail(MI)->cc = SYSTEMZ_CC_INVALID;
89
58.8k
  }
90
58.8k
}
91
92
bool SystemZ_getInstruction(csh handle, const uint8_t *bytes, size_t bytes_len,
93
          MCInst *MI, uint16_t *size, uint64_t address,
94
          void *info)
95
58.8k
{
96
58.8k
  SystemZ_init_cs_detail(MI);
97
58.8k
  MI->MRI = (MCRegisterInfo *)info;
98
58.8k
  DecodeStatus Result = SystemZ_LLVM_getInstruction(
99
58.8k
    handle, bytes, bytes_len, MI, size, address, info);
100
58.8k
  SystemZ_set_instr_map_data(MI, bytes, bytes_len);
101
58.8k
  if (Result == MCDisassembler_SoftFail) {
102
0
    MCInst_setSoftFail(MI);
103
0
  }
104
58.8k
  return Result != MCDisassembler_Fail;
105
58.8k
}
106
107
// given internal insn id, return public instruction info
108
void SystemZ_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
109
57.9k
{
110
  // We do this after Instruction disassembly.
111
57.9k
}
112
113
const char *SystemZ_insn_name(csh handle, unsigned int id)
114
57.9k
{
115
57.9k
#ifndef CAPSTONE_DIET
116
57.9k
  if (id < SYSTEMZ_INS_ALIAS_END && id > SYSTEMZ_INS_ALIAS_BEGIN) {
117
0
    if (id - SYSTEMZ_INS_ALIAS_BEGIN >=
118
0
        ARR_SIZE(insn_alias_mnem_map))
119
0
      return NULL;
120
121
0
    return insn_alias_mnem_map[id - SYSTEMZ_INS_ALIAS_BEGIN - 1]
122
0
      .name;
123
0
  }
124
57.9k
  if (id >= SYSTEMZ_INS_ENDING)
125
0
    return NULL;
126
127
57.9k
  if (id < ARR_SIZE(insn_name_maps))
128
57.9k
    return insn_name_maps[id];
129
130
  // not found
131
0
  return NULL;
132
#else
133
  return NULL;
134
#endif
135
57.9k
}
136
137
#ifndef CAPSTONE_DIET
138
static const name_map group_name_maps[] = {
139
  // generic groups
140
  { SYSTEMZ_GRP_INVALID, NULL },
141
  { SYSTEMZ_GRP_JUMP, "jump" },
142
  { SYSTEMZ_GRP_CALL, "call" },
143
  { SYSTEMZ_GRP_RET, "return" },
144
  { SYSTEMZ_GRP_INT, "int" },
145
  { SYSTEMZ_GRP_IRET, "iret" },
146
  { SYSTEMZ_GRP_PRIVILEGE, "privilege" },
147
  { SYSTEMZ_GRP_BRANCH_RELATIVE, "branch_relative" },
148
149
#include "SystemZGenCSFeatureName.inc"
150
};
151
#endif
152
153
const char *SystemZ_group_name(csh handle, unsigned int id)
154
23.2k
{
155
23.2k
#ifndef CAPSTONE_DIET
156
23.2k
  return id2name(group_name_maps, ARR_SIZE(group_name_maps), id);
157
#else
158
  return NULL;
159
#endif
160
23.2k
}
161
162
void SystemZ_add_cs_detail(MCInst *MI, int /* aarch64_op_group */ op_group,
163
         va_list args)
164
139k
{
165
139k
#ifndef CAPSTONE_DIET
166
139k
  if (!detail_is_set(MI) || !map_fill_detail_ops(MI))
167
0
    return;
168
169
139k
  unsigned op_num = va_arg(args, unsigned);
170
171
139k
  switch (op_group) {
172
0
  default:
173
0
    printf("Operand group %d not handled\n", op_group);
174
0
    break;
175
79.4k
  case SystemZ_OP_GROUP_Operand: {
176
79.4k
    cs_op_type secondary_op_type = map_get_op_type(MI, op_num) &
177
79.4k
                 ~(CS_OP_MEM | CS_OP_BOUND);
178
79.4k
    if (secondary_op_type == CS_OP_IMM) {
179
0
      SystemZ_set_detail_op_imm(
180
0
        MI, op_num, MCInst_getOpVal(MI, op_num), 0);
181
79.4k
    } else if (secondary_op_type == CS_OP_REG) {
182
79.4k
      SystemZ_set_detail_op_reg(MI, op_num,
183
79.4k
              MCInst_getOpVal(MI, op_num));
184
79.4k
    } else {
185
0
      CS_ASSERT_RET(0 && "Op type not handled.");
186
0
    }
187
79.4k
    break;
188
0
  }
189
0
  case SystemZ_OP_GROUP_Cond4Operand: {
190
0
    systemz_cc cc = MCInst_getOpVal(MI, op_num);
191
0
    SystemZ_get_detail(MI)->cc = cc;
192
0
    break;
193
0
  }
194
16.9k
  case SystemZ_OP_GROUP_BDAddrOperand:
195
16.9k
    CS_ASSERT_RET(map_get_op_type(MI, (op_num)) & CS_OP_MEM);
196
16.9k
    CS_ASSERT_RET(map_get_op_type(MI, (op_num + 1)) & CS_OP_MEM);
197
16.9k
    CS_ASSERT_RET(MCOperand_isReg(MCInst_getOperand(MI, (op_num))));
198
16.9k
    CS_ASSERT_RET(
199
16.9k
      MCOperand_isImm(MCInst_getOperand(MI, (op_num + 1))));
200
16.9k
    SystemZ_set_detail_op_mem(MI, op_num,
201
16.9k
            MCInst_getOpVal(MI, (op_num)),
202
16.9k
            MCInst_getOpVal(MI, (op_num + 1)), 0,
203
16.9k
            0, SYSTEMZ_AM_BD);
204
16.9k
    break;
205
900
  case SystemZ_OP_GROUP_BDVAddrOperand:
206
14.5k
  case SystemZ_OP_GROUP_BDXAddrOperand: {
207
14.5k
    CS_ASSERT(map_get_op_type(MI, (op_num)) & CS_OP_MEM);
208
14.5k
    CS_ASSERT(map_get_op_type(MI, (op_num + 1)) & CS_OP_MEM);
209
14.5k
    CS_ASSERT(map_get_op_type(MI, (op_num + 2)) & CS_OP_MEM);
210
14.5k
    CS_ASSERT(MCOperand_isReg(MCInst_getOperand(MI, (op_num))));
211
14.5k
    CS_ASSERT(MCOperand_isImm(MCInst_getOperand(MI, (op_num + 1))));
212
14.5k
    CS_ASSERT(MCOperand_isReg(MCInst_getOperand(MI, (op_num + 2))));
213
14.5k
    SystemZ_set_detail_op_mem(
214
14.5k
      MI, op_num, MCInst_getOpVal(MI, (op_num)),
215
14.5k
      MCInst_getOpVal(MI, (op_num + 1)), 0,
216
14.5k
      MCInst_getOpVal(MI, (op_num + 2)),
217
14.5k
      (op_group == SystemZ_OP_GROUP_BDXAddrOperand ?
218
13.6k
         SYSTEMZ_AM_BDX :
219
14.5k
         SYSTEMZ_AM_BDV));
220
14.5k
    break;
221
900
  }
222
4.06k
  case SystemZ_OP_GROUP_BDLAddrOperand:
223
4.06k
    CS_ASSERT(map_get_op_type(MI, (op_num)) & CS_OP_MEM);
224
4.06k
    CS_ASSERT(map_get_op_type(MI, (op_num + 1)) & CS_OP_MEM);
225
4.06k
    CS_ASSERT(map_get_op_type(MI, (op_num + 2)) & CS_OP_MEM);
226
4.06k
    CS_ASSERT(MCOperand_isReg(MCInst_getOperand(MI, (op_num))));
227
4.06k
    CS_ASSERT(MCOperand_isImm(MCInst_getOperand(MI, (op_num + 1))));
228
4.06k
    CS_ASSERT(MCOperand_isImm(MCInst_getOperand(MI, (op_num + 2))));
229
4.06k
    SystemZ_set_detail_op_mem(MI, op_num,
230
4.06k
            MCInst_getOpVal(MI, (op_num)),
231
4.06k
            MCInst_getOpVal(MI, (op_num + 1)),
232
4.06k
            MCInst_getOpVal(MI, (op_num + 2)), 0,
233
4.06k
            SYSTEMZ_AM_BDL);
234
4.06k
    break;
235
221
  case SystemZ_OP_GROUP_BDRAddrOperand:
236
221
    CS_ASSERT(map_get_op_type(MI, (op_num)) & CS_OP_MEM);
237
221
    CS_ASSERT(map_get_op_type(MI, (op_num + 1)) & CS_OP_MEM);
238
221
    CS_ASSERT(map_get_op_type(MI, (op_num + 2)) & CS_OP_MEM);
239
221
    CS_ASSERT(MCOperand_isReg(MCInst_getOperand(MI, (op_num))));
240
221
    CS_ASSERT(MCOperand_isImm(MCInst_getOperand(MI, (op_num + 1))));
241
221
    CS_ASSERT(MCOperand_isReg(MCInst_getOperand(MI, (op_num + 2))));
242
221
    SystemZ_set_detail_op_mem(MI, op_num,
243
221
            MCInst_getOpVal(MI, (op_num)),
244
221
            MCInst_getOpVal(MI, (op_num + 1)),
245
221
            MCInst_getOpVal(MI, (op_num + 2)), 0,
246
221
            SYSTEMZ_AM_BDL);
247
221
    break;
248
2.43k
  case SystemZ_OP_GROUP_PCRelOperand:
249
2.43k
    SystemZ_set_detail_op_imm(MI, op_num,
250
2.43k
            MCInst_getOpVal(MI, op_num), 0);
251
2.43k
    break;
252
1.22k
  case SystemZ_OP_GROUP_U1ImmOperand:
253
1.22k
    SystemZ_set_detail_op_imm(MI, op_num,
254
1.22k
            MCInst_getOpVal(MI, op_num), 1);
255
1.22k
    break;
256
638
  case SystemZ_OP_GROUP_U2ImmOperand:
257
638
    SystemZ_set_detail_op_imm(MI, op_num,
258
638
            MCInst_getOpVal(MI, op_num), 2);
259
638
    break;
260
467
  case SystemZ_OP_GROUP_U3ImmOperand:
261
467
    SystemZ_set_detail_op_imm(MI, op_num,
262
467
            MCInst_getOpVal(MI, op_num), 3);
263
467
    break;
264
10.0k
  case SystemZ_OP_GROUP_U4ImmOperand:
265
10.0k
    SystemZ_set_detail_op_imm(MI, op_num,
266
10.0k
            MCInst_getOpVal(MI, op_num), 4);
267
10.0k
    break;
268
4.97k
  case SystemZ_OP_GROUP_U8ImmOperand:
269
5.84k
  case SystemZ_OP_GROUP_S8ImmOperand:
270
5.84k
    SystemZ_set_detail_op_imm(MI, op_num,
271
5.84k
            MCInst_getOpVal(MI, op_num), 8);
272
5.84k
    break;
273
229
  case SystemZ_OP_GROUP_U12ImmOperand:
274
229
    SystemZ_set_detail_op_imm(MI, op_num,
275
229
            MCInst_getOpVal(MI, op_num), 12);
276
229
    break;
277
616
  case SystemZ_OP_GROUP_U16ImmOperand:
278
1.76k
  case SystemZ_OP_GROUP_S16ImmOperand:
279
1.76k
    SystemZ_set_detail_op_imm(MI, op_num,
280
1.76k
            MCInst_getOpVal(MI, op_num), 16);
281
1.76k
    break;
282
467
  case SystemZ_OP_GROUP_U32ImmOperand:
283
1.52k
  case SystemZ_OP_GROUP_S32ImmOperand:
284
1.52k
    SystemZ_set_detail_op_imm(MI, op_num,
285
1.52k
            MCInst_getOpVal(MI, op_num), 32);
286
1.52k
    break;
287
0
  case SystemZ_OP_GROUP_U48ImmOperand:
288
0
    SystemZ_set_detail_op_imm(MI, op_num,
289
0
            MCInst_getOpVal(MI, op_num), 48);
290
0
    break;
291
139k
  }
292
139k
#endif
293
139k
}
294
295
#ifndef CAPSTONE_DIET
296
297
void SystemZ_set_detail_op_imm(MCInst *MI, unsigned op_num, int64_t Imm,
298
             size_t width)
299
24.1k
{
300
24.1k
  if (!detail_is_set(MI))
301
0
    return;
302
24.1k
  CS_ASSERT((map_get_op_type(MI, op_num) & ~CS_OP_MEM) == CS_OP_IMM);
303
304
24.1k
  SystemZ_get_detail_op(MI, 0)->type = SYSTEMZ_OP_IMM;
305
24.1k
  SystemZ_get_detail_op(MI, 0)->imm = Imm;
306
24.1k
  SystemZ_get_detail_op(MI, 0)->access = map_get_op_access(MI, op_num);
307
24.1k
  SystemZ_get_detail_op(MI, 0)->imm_width = width;
308
24.1k
  SystemZ_inc_op_count(MI);
309
24.1k
}
310
311
void SystemZ_set_detail_op_reg(MCInst *MI, unsigned op_num, systemz_reg Reg)
312
79.4k
{
313
79.4k
  if (!detail_is_set(MI))
314
0
    return;
315
79.4k
  CS_ASSERT((map_get_op_type(MI, op_num) & ~CS_OP_MEM) == CS_OP_REG);
316
79.4k
  if (Reg == SYSTEMZ_REG_INVALID) {
317
    // This case is legal. The ISA says:
318
    // "
319
    // When the R1 field is not zero, bits 8-15 of the instruction designated
320
    // by the second-operand address are ORed with bits 56-63 of
321
    // general register R1. [...] When the R1 field is zero, no ORing takes place
322
    // "
323
    // This means we just save the neutral element for ORing, so 0.
324
688
    SystemZ_get_detail_op(MI, 0)->type = SYSTEMZ_OP_IMM;
325
688
    SystemZ_get_detail_op(MI, 0)->imm = 0;
326
688
    SystemZ_get_detail_op(MI, 0)->access =
327
688
      map_get_op_access(MI, op_num);
328
688
    SystemZ_get_detail_op(MI, 0)->imm_width = 0;
329
688
    SystemZ_inc_op_count(MI);
330
688
    return;
331
688
  }
332
333
78.8k
  SystemZ_get_detail_op(MI, 0)->type = SYSTEMZ_OP_REG;
334
78.8k
  SystemZ_get_detail_op(MI, 0)->reg = Reg;
335
78.8k
  SystemZ_get_detail_op(MI, 0)->access = map_get_op_access(MI, op_num);
336
78.8k
  SystemZ_inc_op_count(MI);
337
78.8k
}
338
339
void SystemZ_set_detail_op_mem(MCInst *MI, unsigned op_num, systemz_reg base,
340
             int64_t disp, uint64_t length, systemz_reg index,
341
             systemz_addr_mode am)
342
35.7k
{
343
35.7k
  if (!detail_is_set(MI))
344
0
    return;
345
35.7k
  SystemZ_get_detail_op(MI, 0)->type = SYSTEMZ_OP_MEM;
346
35.7k
  SystemZ_get_detail_op(MI, 0)->access = map_get_op_access(MI, op_num);
347
35.7k
  SystemZ_get_detail_op(MI, 0)->mem.am = am;
348
35.7k
  switch (am) {
349
0
  default:
350
0
    CS_ASSERT(0 && "Address mode not handled\n");
351
0
    break;
352
16.9k
  case SYSTEMZ_AM_BD:
353
16.9k
    SystemZ_get_detail_op(MI, 0)->mem.base = base;
354
16.9k
    SystemZ_get_detail_op(MI, 0)->mem.disp = disp;
355
16.9k
    break;
356
13.6k
  case SYSTEMZ_AM_BDX:
357
14.5k
  case SYSTEMZ_AM_BDV:
358
14.5k
    SystemZ_get_detail_op(MI, 0)->mem.base = base;
359
14.5k
    SystemZ_get_detail_op(MI, 0)->mem.disp = disp;
360
14.5k
    SystemZ_get_detail_op(MI, 0)->mem.index = index;
361
14.5k
    break;
362
4.28k
  case SYSTEMZ_AM_BDL:
363
4.28k
    SystemZ_get_detail_op(MI, 0)->mem.base = base;
364
4.28k
    SystemZ_get_detail_op(MI, 0)->mem.disp = disp;
365
4.28k
    SystemZ_get_detail_op(MI, 0)->mem.length = length;
366
4.28k
    break;
367
0
  case SYSTEMZ_AM_BDR:
368
0
    SystemZ_get_detail_op(MI, 0)->mem.base = base;
369
0
    SystemZ_get_detail_op(MI, 0)->mem.disp = disp;
370
0
    SystemZ_get_detail_op(MI, 0)->mem.length = length;
371
0
    break;
372
35.7k
  }
373
35.7k
  SystemZ_inc_op_count(MI);
374
35.7k
}
375
376
#endif
377
378
#endif