/src/capstonenext/arch/Alpha/AlphaMapping.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Capstone Disassembly Engine */ |
2 | | /* By Dmitry Sibirtsev <sibirtsevdl@gmail.com>, 2023 */ |
3 | | |
4 | | #ifdef CAPSTONE_HAS_ALPHA |
5 | | |
6 | | #include <stdio.h> // debug |
7 | | #include <string.h> |
8 | | |
9 | | #include "../../Mapping.h" |
10 | | #include "../../cs_priv.h" |
11 | | #include "../../cs_simple_types.h" |
12 | | #include "../../utils.h" |
13 | | |
14 | | #include "AlphaLinkage.h" |
15 | | #include "AlphaMapping.h" |
16 | | #include "./AlphaDisassembler.h" |
17 | | |
18 | | #define GET_INSTRINFO_ENUM |
19 | | |
20 | | #include "AlphaGenInstrInfo.inc" |
21 | | |
22 | | static const insn_map insns[] = { |
23 | | #include "AlphaGenCSMappingInsn.inc" |
24 | | }; |
25 | | |
26 | | static const map_insn_ops insn_operands[] = { |
27 | | #include "AlphaGenCSMappingInsnOp.inc" |
28 | | }; |
29 | | |
30 | | void Alpha_init_cs_detail(MCInst *MI) |
31 | 0 | { |
32 | 0 | if (detail_is_set(MI)) { |
33 | 0 | memset(get_detail(MI), 0, |
34 | 0 | offsetof(cs_detail, alpha) + sizeof(cs_alpha)); |
35 | 0 | } |
36 | 0 | } |
37 | | |
38 | | void Alpha_add_cs_detail(MCInst *MI, unsigned OpNum) |
39 | 0 | { |
40 | 0 | if (!detail_is_set(MI)) |
41 | 0 | return; |
42 | | |
43 | 0 | cs_op_type op_type = map_get_op_type(MI, OpNum); |
44 | 0 | if (op_type == CS_OP_IMM) |
45 | 0 | Alpha_set_detail_op_imm(MI, OpNum, ALPHA_OP_IMM, |
46 | 0 | MCInst_getOpVal(MI, OpNum)); |
47 | 0 | else if (op_type == CS_OP_REG) |
48 | 0 | Alpha_set_detail_op_reg(MI, OpNum, MCInst_getOpVal(MI, OpNum)); |
49 | 0 | else |
50 | 0 | CS_ASSERT_RET(0 && "Op type not handled."); |
51 | 0 | } |
52 | | |
53 | | void Alpha_set_detail_op_imm(MCInst *MI, unsigned OpNum, alpha_op_type ImmType, |
54 | | int64_t Imm) |
55 | 0 | { |
56 | 0 | if (!detail_is_set(MI)) |
57 | 0 | return; |
58 | 0 | CS_ASSERT_RET(!(map_get_op_type(MI, OpNum) & CS_OP_MEM)); |
59 | 0 | CS_ASSERT_RET(map_get_op_type(MI, OpNum) == CS_OP_IMM); |
60 | 0 | CS_ASSERT_RET(ImmType == ALPHA_OP_IMM); |
61 | |
|
62 | 0 | Alpha_get_detail_op(MI, 0)->type = ImmType; |
63 | 0 | Alpha_get_detail_op(MI, 0)->imm = Imm; |
64 | 0 | Alpha_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum); |
65 | 0 | Alpha_inc_op_count(MI); |
66 | 0 | } |
67 | | |
68 | | void Alpha_set_detail_op_reg(MCInst *MI, unsigned OpNum, alpha_op_type Reg) |
69 | 0 | { |
70 | 0 | if (!detail_is_set(MI)) |
71 | 0 | return; |
72 | 0 | CS_ASSERT_RET(!(map_get_op_type(MI, OpNum) & CS_OP_MEM)); |
73 | 0 | CS_ASSERT_RET(map_get_op_type(MI, OpNum) == CS_OP_REG); |
74 | |
|
75 | 0 | Alpha_get_detail_op(MI, 0)->type = ALPHA_OP_REG; |
76 | 0 | Alpha_get_detail_op(MI, 0)->reg = Reg; |
77 | 0 | Alpha_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum); |
78 | 0 | Alpha_inc_op_count(MI); |
79 | 0 | } |
80 | | |
81 | | // given internal insn id, return public instruction info |
82 | | void Alpha_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id) |
83 | 0 | { |
84 | 0 | unsigned short i; |
85 | |
|
86 | 0 | i = insn_find(insns, ARR_SIZE(insns), id, &h->insn_cache); |
87 | 0 | if (i == 0) { |
88 | 0 | return; |
89 | 0 | } |
90 | 0 | insn->id = insns[i].mapid; |
91 | |
|
92 | 0 | if (insn->detail) { |
93 | 0 | #ifndef CAPSTONE_DIET |
94 | 0 | memcpy(insn->detail->regs_read, insns[i].regs_use, |
95 | 0 | sizeof(insns[i].regs_use)); |
96 | 0 | insn->detail->regs_read_count = |
97 | 0 | (uint8_t)count_positive(insns[i].regs_use); |
98 | |
|
99 | 0 | memcpy(insn->detail->regs_write, insns[i].regs_mod, |
100 | 0 | sizeof(insns[i].regs_mod)); |
101 | 0 | insn->detail->regs_write_count = |
102 | 0 | (uint8_t)count_positive(insns[i].regs_mod); |
103 | |
|
104 | 0 | memcpy(insn->detail->groups, insns[i].groups, |
105 | 0 | sizeof(insns[i].groups)); |
106 | 0 | insn->detail->groups_count = |
107 | 0 | (uint8_t)count_positive8(insns[i].groups); |
108 | 0 | #endif |
109 | 0 | } |
110 | 0 | } |
111 | | |
112 | | #ifndef CAPSTONE_DIET |
113 | | |
114 | | static const char *const insn_names[] = { |
115 | | #include "AlphaGenCSMappingInsnName.inc" |
116 | | }; |
117 | | |
118 | | // special alias insn |
119 | | // static name_map alias_insn_names[] = {{0, NULL}}; |
120 | | #endif |
121 | | |
122 | | const char *Alpha_insn_name(csh handle, unsigned int id) |
123 | 0 | { |
124 | 0 | #ifndef CAPSTONE_DIET |
125 | 0 | if (id >= ALPHA_INS_ENDING) |
126 | 0 | return NULL; |
127 | | |
128 | 0 | if (id < ARR_SIZE(insn_names)) |
129 | 0 | return insn_names[id]; |
130 | | |
131 | 0 | return NULL; |
132 | | #else |
133 | | return NULL; |
134 | | #endif |
135 | 0 | } |
136 | | |
137 | | #ifndef CAPSTONE_DIET |
138 | | static const name_map group_name_maps[] = { |
139 | | { Alpha_GRP_INVALID, NULL }, |
140 | | { Alpha_GRP_CALL, "call" }, |
141 | | { Alpha_GRP_JUMP, "jump" }, |
142 | | { Alpha_GRP_BRANCH_RELATIVE, "branch_relative" }, |
143 | | }; |
144 | | #endif |
145 | | |
146 | | const char *Alpha_group_name(csh handle, unsigned int id) |
147 | 0 | { |
148 | 0 | #ifndef CAPSTONE_DIET |
149 | 0 | return id2name(group_name_maps, ARR_SIZE(group_name_maps), id); |
150 | | #else |
151 | | return NULL; |
152 | | #endif |
153 | 0 | } |
154 | | |
155 | | const char *Alpha_getRegisterName(csh handle, unsigned int id) |
156 | 0 | { |
157 | 0 | return Alpha_LLVM_getRegisterName(handle, id); |
158 | 0 | } |
159 | | |
160 | | void Alpha_printInst(MCInst *MI, SStream *O, void *Info) |
161 | 0 | { |
162 | 0 | Alpha_LLVM_printInstruction(MI, O, Info); |
163 | 0 | } |
164 | | |
165 | | void Alpha_set_instr_map_data(MCInst *MI) |
166 | 0 | { |
167 | 0 | map_cs_id(MI, insns, ARR_SIZE(insns)); |
168 | 0 | map_implicit_reads(MI, insns); |
169 | 0 | map_implicit_writes(MI, insns); |
170 | 0 | map_groups(MI, insns); |
171 | 0 | } |
172 | | |
173 | | bool Alpha_getInstruction(csh handle, const uint8_t *code, size_t code_len, |
174 | | MCInst *instr, uint16_t *size, uint64_t address, |
175 | | void *info) |
176 | 0 | { |
177 | 0 | Alpha_init_cs_detail(instr); |
178 | 0 | DecodeStatus Result = Alpha_LLVM_getInstruction( |
179 | 0 | handle, code, code_len, instr, size, address, info); |
180 | 0 | Alpha_set_instr_map_data(instr); |
181 | 0 | if (Result == MCDisassembler_SoftFail) { |
182 | 0 | MCInst_setSoftFail(instr); |
183 | 0 | } |
184 | 0 | return Result != MCDisassembler_Fail; |
185 | 0 | } |
186 | | |
187 | | #ifndef CAPSTONE_DIET |
188 | | void Alpha_reg_access(const cs_insn *insn, cs_regs regs_read, |
189 | | uint8_t *regs_read_count, cs_regs regs_write, |
190 | | uint8_t *regs_write_count) |
191 | 0 | { |
192 | 0 | uint8_t i; |
193 | 0 | uint8_t read_count, write_count; |
194 | 0 | cs_alpha *alpha = &(insn->detail->alpha); |
195 | |
|
196 | 0 | read_count = insn->detail->regs_read_count; |
197 | 0 | write_count = insn->detail->regs_write_count; |
198 | | |
199 | | // implicit registers |
200 | 0 | memcpy(regs_read, insn->detail->regs_read, |
201 | 0 | read_count * sizeof(insn->detail->regs_read[0])); |
202 | 0 | memcpy(regs_write, insn->detail->regs_write, |
203 | 0 | write_count * sizeof(insn->detail->regs_write[0])); |
204 | | |
205 | | // explicit registers |
206 | 0 | for (i = 0; i < alpha->op_count; i++) { |
207 | 0 | cs_alpha_op *op = &(alpha->operands[i]); |
208 | 0 | switch ((int)op->type) { |
209 | 0 | case ALPHA_OP_REG: |
210 | 0 | if ((op->access & CS_AC_READ) && |
211 | 0 | !arr_exist(regs_read, read_count, op->reg)) { |
212 | 0 | regs_read[read_count] = (uint16_t)op->reg; |
213 | 0 | read_count++; |
214 | 0 | } |
215 | 0 | if ((op->access & CS_AC_WRITE) && |
216 | 0 | !arr_exist(regs_write, write_count, op->reg)) { |
217 | 0 | regs_write[write_count] = (uint16_t)op->reg; |
218 | 0 | write_count++; |
219 | 0 | } |
220 | 0 | break; |
221 | 0 | default: |
222 | 0 | break; |
223 | 0 | } |
224 | 0 | } |
225 | | |
226 | 0 | *regs_read_count = read_count; |
227 | 0 | *regs_write_count = write_count; |
228 | 0 | } |
229 | | #endif |
230 | | |
231 | | #endif |