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