Coverage Report

Created: 2025-08-26 06:30

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