/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 | 79.7k | { |
45 | 79.7k | map_cs_id(MI, systemz_insns, ARR_SIZE(systemz_insns)); |
46 | 79.7k | map_implicit_reads(MI, systemz_insns); |
47 | 79.7k | map_implicit_writes(MI, systemz_insns); |
48 | 79.7k | map_groups(MI, systemz_insns); |
49 | 79.7k | const systemz_suppl_info *suppl_info = |
50 | 79.7k | map_get_suppl_info(MI, systemz_insns); |
51 | 79.7k | if (suppl_info) { |
52 | 79.7k | SystemZ_get_detail(MI)->format = suppl_info->form; |
53 | 79.7k | } |
54 | 79.7k | } |
55 | | |
56 | | void SystemZ_init_mri(MCRegisterInfo *MRI) |
57 | 2.81k | { |
58 | 2.81k | MCRegisterInfo_InitMCRegisterInfo( |
59 | 2.81k | MRI, SystemZRegDesc, AARCH64_REG_ENDING, 0, 0, |
60 | 2.81k | SystemZMCRegisterClasses, ARR_SIZE(SystemZMCRegisterClasses), 0, |
61 | 2.81k | 0, SystemZRegDiffLists, 0, SystemZSubRegIdxLists, |
62 | 2.81k | ARR_SIZE(SystemZSubRegIdxLists), 0); |
63 | 2.81k | } |
64 | | |
65 | | const char *SystemZ_reg_name(csh handle, unsigned int reg) |
66 | 50.9k | { |
67 | 50.9k | return SystemZ_LLVM_getRegisterName(reg); |
68 | 50.9k | } |
69 | | |
70 | | void SystemZ_printer(MCInst *MI, SStream *O, void * /* MCRegisterInfo* */ info) |
71 | 78.2k | { |
72 | 78.2k | MI->MRI = (MCRegisterInfo *)info; |
73 | 78.2k | MI->fillDetailOps = detail_is_set(MI); |
74 | 78.2k | SystemZ_LLVM_printInstruction(MI, "", O); |
75 | 78.2k | #ifndef CAPSTONE_DIET |
76 | 78.2k | map_set_alias_id(MI, O, insn_alias_mnem_map, |
77 | 78.2k | ARR_SIZE(insn_alias_mnem_map)); |
78 | 78.2k | #endif |
79 | 78.2k | } |
80 | | |
81 | 79.7k | void SystemZ_init_cs_detail(MCInst *MI) { |
82 | 79.7k | if (!detail_is_set(MI)) { |
83 | 0 | return; |
84 | 0 | } |
85 | 79.7k | memset(get_detail(MI), 0, sizeof(cs_detail)); |
86 | 79.7k | if (detail_is_set(MI)) { |
87 | 79.7k | SystemZ_get_detail(MI)->cc = SYSTEMZ_CC_INVALID; |
88 | 79.7k | } |
89 | 79.7k | } |
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 | 79.7k | { |
95 | 79.7k | SystemZ_init_cs_detail(MI); |
96 | 79.7k | MI->MRI = (MCRegisterInfo *)info; |
97 | 79.7k | DecodeStatus Result = SystemZ_LLVM_getInstruction( |
98 | 79.7k | handle, bytes, bytes_len, MI, size, address, info); |
99 | 79.7k | SystemZ_set_instr_map_data(MI, bytes, bytes_len); |
100 | 79.7k | if (Result == MCDisassembler_SoftFail) { |
101 | 0 | MCInst_setSoftFail(MI); |
102 | 0 | } |
103 | 79.7k | return Result != MCDisassembler_Fail; |
104 | 79.7k | } |
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 | 78.2k | { |
109 | | // We do this after Instruction disassembly. |
110 | 78.2k | } |
111 | | |
112 | | const char *SystemZ_insn_name(csh handle, unsigned int id) |
113 | 78.2k | { |
114 | 78.2k | #ifndef CAPSTONE_DIET |
115 | 78.2k | 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 | 78.2k | if (id >= SYSTEMZ_INS_ENDING) |
124 | 0 | return NULL; |
125 | | |
126 | 78.2k | if (id < ARR_SIZE(insn_name_maps)) |
127 | 78.2k | return insn_name_maps[id]; |
128 | | |
129 | | // not found |
130 | 0 | return NULL; |
131 | | #else |
132 | | return NULL; |
133 | | #endif |
134 | 78.2k | } |
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 | 48.7k | { |
154 | 48.7k | #ifndef CAPSTONE_DIET |
155 | 48.7k | return id2name(group_name_maps, ARR_SIZE(group_name_maps), id); |
156 | | #else |
157 | | return NULL; |
158 | | #endif |
159 | 48.7k | } |
160 | | |
161 | | void SystemZ_add_cs_detail(MCInst *MI, int /* aarch64_op_group */ op_group, |
162 | | va_list args) |
163 | 183k | { |
164 | 183k | #ifndef CAPSTONE_DIET |
165 | 183k | if (!detail_is_set(MI) || !map_fill_detail_ops(MI)) |
166 | 0 | return; |
167 | | |
168 | 183k | unsigned op_num = va_arg(args, unsigned); |
169 | | |
170 | 183k | switch (op_group) { |
171 | 0 | default: |
172 | 0 | printf("Operand group %d not handled\n", op_group); |
173 | 0 | break; |
174 | 109k | case SystemZ_OP_GROUP_Operand: { |
175 | 109k | cs_op_type secondary_op_type = map_get_op_type(MI, op_num) & |
176 | 109k | ~(CS_OP_MEM | CS_OP_BOUND); |
177 | 109k | 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 | 109k | } else if (secondary_op_type == CS_OP_REG) { |
181 | 109k | SystemZ_set_detail_op_reg(MI, op_num, |
182 | 109k | MCInst_getOpVal(MI, op_num)); |
183 | 109k | } else { |
184 | 0 | CS_ASSERT_RET(0 && "Op type not handled."); |
185 | 0 | } |
186 | 109k | 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 | 20.6k | case SystemZ_OP_GROUP_BDAddrOperand: |
194 | 20.6k | CS_ASSERT_RET(map_get_op_type(MI, (op_num)) & CS_OP_MEM); |
195 | 20.6k | CS_ASSERT_RET(map_get_op_type(MI, (op_num + 1)) & CS_OP_MEM); |
196 | 20.6k | CS_ASSERT_RET(MCOperand_isReg(MCInst_getOperand(MI, (op_num)))); |
197 | 20.6k | CS_ASSERT_RET(MCOperand_isImm(MCInst_getOperand(MI, (op_num + 1)))); |
198 | 20.6k | SystemZ_set_detail_op_mem(MI, |
199 | 20.6k | op_num, |
200 | 20.6k | MCInst_getOpVal(MI, (op_num)), |
201 | 20.6k | MCInst_getOpVal(MI, (op_num + 1)), |
202 | 20.6k | 0, |
203 | 20.6k | 0, |
204 | 20.6k | SYSTEMZ_AM_BD |
205 | 20.6k | ); |
206 | 20.6k | break; |
207 | 437 | case SystemZ_OP_GROUP_BDVAddrOperand: |
208 | 18.7k | case SystemZ_OP_GROUP_BDXAddrOperand: { |
209 | 18.7k | CS_ASSERT(map_get_op_type(MI, (op_num)) & CS_OP_MEM); |
210 | 18.7k | CS_ASSERT(map_get_op_type(MI, (op_num + 1)) & CS_OP_MEM); |
211 | 18.7k | CS_ASSERT(map_get_op_type(MI, (op_num + 2)) & CS_OP_MEM); |
212 | 18.7k | CS_ASSERT(MCOperand_isReg(MCInst_getOperand(MI, (op_num)))); |
213 | 18.7k | CS_ASSERT(MCOperand_isImm(MCInst_getOperand(MI, (op_num + 1)))); |
214 | 18.7k | CS_ASSERT(MCOperand_isReg(MCInst_getOperand(MI, (op_num + 2)))); |
215 | 18.7k | SystemZ_set_detail_op_mem(MI, |
216 | 18.7k | op_num, |
217 | 18.7k | MCInst_getOpVal(MI, (op_num)), |
218 | 18.7k | MCInst_getOpVal(MI, (op_num + 1)), |
219 | 18.7k | 0, |
220 | 18.7k | MCInst_getOpVal(MI, (op_num + 2)), |
221 | 18.7k | (op_group == SystemZ_OP_GROUP_BDXAddrOperand ? SYSTEMZ_AM_BDX : SYSTEMZ_AM_BDV) |
222 | 18.7k | ); |
223 | 18.7k | break; |
224 | 437 | } |
225 | 6.49k | case SystemZ_OP_GROUP_BDLAddrOperand: |
226 | 6.49k | CS_ASSERT(map_get_op_type(MI, (op_num)) & CS_OP_MEM); |
227 | 6.49k | CS_ASSERT(map_get_op_type(MI, (op_num + 1)) & CS_OP_MEM); |
228 | 6.49k | CS_ASSERT(map_get_op_type(MI, (op_num + 2)) & CS_OP_MEM); |
229 | 6.49k | CS_ASSERT(MCOperand_isReg(MCInst_getOperand(MI, (op_num)))); |
230 | 6.49k | CS_ASSERT(MCOperand_isImm(MCInst_getOperand(MI, (op_num + 1)))); |
231 | 6.49k | CS_ASSERT(MCOperand_isImm(MCInst_getOperand(MI, (op_num + 2)))); |
232 | 6.49k | SystemZ_set_detail_op_mem(MI, |
233 | 6.49k | op_num, |
234 | 6.49k | MCInst_getOpVal(MI, (op_num)), |
235 | 6.49k | MCInst_getOpVal(MI, (op_num + 1)), |
236 | 6.49k | MCInst_getOpVal(MI, (op_num + 2)), |
237 | 6.49k | 0, |
238 | 6.49k | SYSTEMZ_AM_BDL |
239 | 6.49k | ); |
240 | 6.49k | break; |
241 | 400 | case SystemZ_OP_GROUP_BDRAddrOperand: |
242 | 400 | CS_ASSERT(map_get_op_type(MI, (op_num)) & CS_OP_MEM); |
243 | 400 | CS_ASSERT(map_get_op_type(MI, (op_num + 1)) & CS_OP_MEM); |
244 | 400 | CS_ASSERT(map_get_op_type(MI, (op_num + 2)) & CS_OP_MEM); |
245 | 400 | CS_ASSERT(MCOperand_isReg(MCInst_getOperand(MI, (op_num)))); |
246 | 400 | CS_ASSERT(MCOperand_isImm(MCInst_getOperand(MI, (op_num + 1)))); |
247 | 400 | CS_ASSERT(MCOperand_isReg(MCInst_getOperand(MI, (op_num + 2)))); |
248 | 400 | SystemZ_set_detail_op_mem(MI, |
249 | 400 | op_num, |
250 | 400 | MCInst_getOpVal(MI, (op_num)), |
251 | 400 | MCInst_getOpVal(MI, (op_num + 1)), |
252 | 400 | MCInst_getOpVal(MI, (op_num + 2)), |
253 | 400 | 0, |
254 | 400 | SYSTEMZ_AM_BDL |
255 | 400 | ); |
256 | 400 | break; |
257 | 3.72k | case SystemZ_OP_GROUP_PCRelOperand: |
258 | 3.72k | SystemZ_set_detail_op_imm(MI, op_num, |
259 | 3.72k | MCInst_getOpVal(MI, op_num), 0); |
260 | 3.72k | break; |
261 | 749 | case SystemZ_OP_GROUP_U1ImmOperand: |
262 | 749 | SystemZ_set_detail_op_imm(MI, op_num, |
263 | 749 | MCInst_getOpVal(MI, op_num), 1); |
264 | 749 | break; |
265 | 500 | case SystemZ_OP_GROUP_U2ImmOperand: |
266 | 500 | SystemZ_set_detail_op_imm(MI, op_num, |
267 | 500 | MCInst_getOpVal(MI, op_num), 2); |
268 | 500 | break; |
269 | 487 | case SystemZ_OP_GROUP_U3ImmOperand: |
270 | 487 | SystemZ_set_detail_op_imm(MI, op_num, |
271 | 487 | MCInst_getOpVal(MI, op_num), 3); |
272 | 487 | break; |
273 | 14.6k | case SystemZ_OP_GROUP_U4ImmOperand: |
274 | 14.6k | SystemZ_set_detail_op_imm(MI, op_num, |
275 | 14.6k | MCInst_getOpVal(MI, op_num), 4); |
276 | 14.6k | break; |
277 | 4.34k | case SystemZ_OP_GROUP_U8ImmOperand: |
278 | 5.06k | case SystemZ_OP_GROUP_S8ImmOperand: |
279 | 5.06k | SystemZ_set_detail_op_imm(MI, op_num, |
280 | 5.06k | MCInst_getOpVal(MI, op_num), 8); |
281 | 5.06k | break; |
282 | 45 | case SystemZ_OP_GROUP_U12ImmOperand: |
283 | 45 | SystemZ_set_detail_op_imm(MI, op_num, |
284 | 45 | MCInst_getOpVal(MI, op_num), 12); |
285 | 45 | break; |
286 | 823 | case SystemZ_OP_GROUP_U16ImmOperand: |
287 | 2.36k | case SystemZ_OP_GROUP_S16ImmOperand: |
288 | 2.36k | SystemZ_set_detail_op_imm(MI, op_num, |
289 | 2.36k | MCInst_getOpVal(MI, op_num), 16); |
290 | 2.36k | break; |
291 | 631 | case SystemZ_OP_GROUP_U32ImmOperand: |
292 | 979 | case SystemZ_OP_GROUP_S32ImmOperand: |
293 | 979 | SystemZ_set_detail_op_imm(MI, op_num, |
294 | 979 | MCInst_getOpVal(MI, op_num), 32); |
295 | 979 | 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 | 183k | } |
301 | 183k | #endif |
302 | 183k | } |
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 | 28.5k | { |
308 | 28.5k | if (!detail_is_set(MI)) |
309 | 0 | return; |
310 | 28.5k | CS_ASSERT((map_get_op_type(MI, op_num) & ~CS_OP_MEM) == CS_OP_IMM); |
311 | | |
312 | 28.5k | SystemZ_get_detail_op(MI, 0)->type = SYSTEMZ_OP_IMM; |
313 | 28.5k | SystemZ_get_detail_op(MI, 0)->imm = Imm; |
314 | 28.5k | SystemZ_get_detail_op(MI, 0)->access = map_get_op_access(MI, op_num); |
315 | 28.5k | SystemZ_get_detail_op(MI, 0)->imm_width = width; |
316 | 28.5k | SystemZ_inc_op_count(MI); |
317 | 28.5k | } |
318 | | |
319 | | void SystemZ_set_detail_op_reg(MCInst *MI, unsigned op_num, systemz_reg Reg) |
320 | 109k | { |
321 | 109k | if (!detail_is_set(MI)) |
322 | 0 | return; |
323 | 109k | CS_ASSERT((map_get_op_type(MI, op_num) & ~CS_OP_MEM) == CS_OP_REG); |
324 | | |
325 | 109k | SystemZ_get_detail_op(MI, 0)->type = SYSTEMZ_OP_REG; |
326 | 109k | SystemZ_get_detail_op(MI, 0)->reg = Reg; |
327 | 109k | SystemZ_get_detail_op(MI, 0)->access = map_get_op_access(MI, op_num); |
328 | 109k | SystemZ_inc_op_count(MI); |
329 | 109k | } |
330 | | |
331 | | 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) |
332 | 46.2k | { |
333 | 46.2k | if (!detail_is_set(MI)) |
334 | 0 | return; |
335 | 46.2k | SystemZ_get_detail_op(MI, 0)->type = SYSTEMZ_OP_MEM; |
336 | 46.2k | SystemZ_get_detail_op(MI, 0)->access = map_get_op_access(MI, op_num); |
337 | 46.2k | SystemZ_get_detail_op(MI, 0)->mem.am = am; |
338 | 46.2k | switch(am) { |
339 | 0 | default: |
340 | 0 | CS_ASSERT(0 && "Address mode not handled\n"); |
341 | 0 | break; |
342 | 20.6k | case SYSTEMZ_AM_BD: |
343 | 20.6k | SystemZ_get_detail_op(MI, 0)->mem.base = base; |
344 | 20.6k | SystemZ_get_detail_op(MI, 0)->mem.disp = disp; |
345 | 20.6k | break; |
346 | 18.2k | case SYSTEMZ_AM_BDX: |
347 | 18.7k | case SYSTEMZ_AM_BDV: |
348 | 18.7k | SystemZ_get_detail_op(MI, 0)->mem.base = base; |
349 | 18.7k | SystemZ_get_detail_op(MI, 0)->mem.disp = disp; |
350 | 18.7k | SystemZ_get_detail_op(MI, 0)->mem.index = index; |
351 | 18.7k | break; |
352 | 6.89k | case SYSTEMZ_AM_BDL: |
353 | 6.89k | SystemZ_get_detail_op(MI, 0)->mem.base = base; |
354 | 6.89k | SystemZ_get_detail_op(MI, 0)->mem.disp = disp; |
355 | 6.89k | SystemZ_get_detail_op(MI, 0)->mem.length = length; |
356 | 6.89k | break; |
357 | 0 | case SYSTEMZ_AM_BDR: |
358 | 0 | SystemZ_get_detail_op(MI, 0)->mem.base = base; |
359 | 0 | SystemZ_get_detail_op(MI, 0)->mem.disp = disp; |
360 | 0 | SystemZ_get_detail_op(MI, 0)->mem.length = length; |
361 | 0 | break; |
362 | 46.2k | } |
363 | 46.2k | SystemZ_inc_op_count(MI); |
364 | 46.2k | } |
365 | | |
366 | | #endif |
367 | | |
368 | | #endif |