/src/binutils-gdb/opcodes/nds32-dis.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* NDS32-specific support for 32-bit ELF. |
2 | | Copyright (C) 2012-2023 Free Software Foundation, Inc. |
3 | | Contributed by Andes Technology Corporation. |
4 | | |
5 | | This file is part of BFD, the Binary File Descriptor library. |
6 | | |
7 | | This program is free software; you can redistribute it and/or modify |
8 | | it under the terms of the GNU General Public License as published by |
9 | | the Free Software Foundation; either version 3 of the License, or |
10 | | (at your option) any later version. |
11 | | |
12 | | This program is distributed in the hope that it will be useful, |
13 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | | GNU General Public License for more details. |
16 | | |
17 | | You should have received a copy of the GNU General Public License |
18 | | along with this program; if not, write to the Free Software |
19 | | Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA |
20 | | 02110-1301, USA. */ |
21 | | |
22 | | #include "sysdep.h" |
23 | | #include <stdio.h> |
24 | | #include "ansidecl.h" |
25 | | #include "disassemble.h" |
26 | | #include "bfd.h" |
27 | | #include "symcat.h" |
28 | | #include "libiberty.h" |
29 | | #include "opintl.h" |
30 | | #include <stdint.h> |
31 | | #include "hashtab.h" |
32 | | #include "nds32-asm.h" |
33 | | #include "opcode/nds32.h" |
34 | | |
35 | | /* Get fields macro define. */ |
36 | 1.11M | #define MASK_OP(insn, mask) ((insn) & (0x3f << 25 | (mask))) |
37 | | |
38 | | /* For mapping symbol. */ |
39 | | enum map_type |
40 | | { |
41 | | MAP_DATA0, |
42 | | MAP_DATA1, |
43 | | MAP_DATA2, |
44 | | MAP_DATA3, |
45 | | MAP_DATA4, |
46 | | MAP_CODE, |
47 | | }; |
48 | | |
49 | | struct nds32_private_data |
50 | | { |
51 | | /* Whether any mapping symbols are present in the provided symbol |
52 | | table. -1 if we do not know yet, otherwise 0 or 1. */ |
53 | | int has_mapping_symbols; |
54 | | |
55 | | /* Track the last type (although this doesn't seem to be useful). */ |
56 | | enum map_type last_mapping_type; |
57 | | |
58 | | /* Tracking symbol table information. */ |
59 | | int last_symbol_index; |
60 | | bfd_vma last_addr; |
61 | | }; |
62 | | |
63 | | /* Default text to print if an instruction isn't recognized. */ |
64 | 326k | #define UNKNOWN_INSN_MSG _("*unknown*") |
65 | 6.96M | #define NDS32_PARSE_INSN16 0x01 |
66 | 1.23M | #define NDS32_PARSE_INSN32 0x02 |
67 | | |
68 | | static uint32_t nds32_mask_opcode (uint32_t); |
69 | | static void nds32_special_opcode (uint32_t, struct nds32_opcode **); |
70 | | static int get_mapping_symbol_type (struct disassemble_info *, int, |
71 | | enum map_type *); |
72 | | static int is_mapping_symbol (struct disassemble_info *, int, |
73 | | enum map_type *); |
74 | | |
75 | | /* Hash function for disassemble. */ |
76 | | |
77 | | static htab_t opcode_htab; |
78 | | |
79 | | /* Find the value map register name. */ |
80 | | |
81 | | static const keyword_t * |
82 | | nds32_find_reg_keyword (const keyword_t *reg, int value) |
83 | 1.89M | { |
84 | 1.89M | if (!reg) |
85 | 0 | return NULL; |
86 | | |
87 | 17.3M | while (reg->name != NULL && reg->value != value) |
88 | 15.4M | { |
89 | 15.4M | reg++; |
90 | 15.4M | } |
91 | 1.89M | if (reg->name == NULL) |
92 | 6.61k | return NULL; |
93 | 1.88M | return reg; |
94 | 1.89M | } |
95 | | |
96 | | static void |
97 | | nds32_parse_audio_ext (const field_t *pfd, |
98 | | disassemble_info *info, uint32_t insn) |
99 | 77.0k | { |
100 | 77.0k | fprintf_ftype func = info->fprintf_func; |
101 | 77.0k | void *stream = info->stream; |
102 | 77.0k | const keyword_t *psys_reg; |
103 | 77.0k | int int_value, new_value; |
104 | | |
105 | 77.0k | if (pfd->hw_res == HW_INT || pfd->hw_res == HW_UINT) |
106 | 753 | { |
107 | 753 | if (pfd->hw_res == HW_INT) |
108 | 0 | int_value = (unsigned) N32_IMMS (insn >> pfd->bitpos, |
109 | 0 | pfd->bitsize) << pfd->shift; |
110 | 753 | else |
111 | 753 | int_value = __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift; |
112 | | |
113 | 753 | if (int_value < 10) |
114 | 82 | func (stream, "#%d", int_value); |
115 | 671 | else |
116 | 671 | func (stream, "#0x%x", int_value); |
117 | 753 | return; |
118 | 753 | } |
119 | 76.2k | int_value = |
120 | 76.2k | __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift; |
121 | 76.2k | new_value = int_value; |
122 | 76.2k | psys_reg = (keyword_t*) nds32_keywords[pfd->hw_res]; |
123 | | |
124 | | /* p = bit[4].bit[1:0], r = bit[4].bit[3:2]. */ |
125 | 76.2k | if (strcmp (pfd->name, "im5_i") == 0) |
126 | 3.89k | { |
127 | 3.89k | new_value = int_value & 0x03; |
128 | 3.89k | new_value |= ((int_value & 0x10) >> 2); |
129 | 3.89k | } |
130 | 72.3k | else if (strcmp (pfd->name, "im5_m") == 0) |
131 | 3.89k | { |
132 | 3.89k | new_value = ((int_value & 0x1C) >> 2); |
133 | 3.89k | } |
134 | | /* p = 0.bit[1:0], r = 0.bit[3:2]. */ |
135 | | /* q = 1.bit[1:0], s = 1.bit[5:4]. */ |
136 | 68.4k | else if (strcmp (pfd->name, "im6_iq") == 0) |
137 | 5.98k | { |
138 | 5.98k | new_value |= 0x04; |
139 | 5.98k | } |
140 | 62.5k | else if (strcmp (pfd->name, "im6_ms") == 0) |
141 | 5.98k | { |
142 | 5.98k | new_value |= 0x04; |
143 | 5.98k | } |
144 | | /* Rt CONCAT(c, t21, t0). */ |
145 | 56.5k | else if (strcmp (pfd->name, "a_rt21") == 0) |
146 | 1.10k | { |
147 | 1.10k | new_value = (insn & 0x00000020) >> 5; |
148 | 1.10k | new_value |= (insn & 0x00000C00) >> 9; |
149 | 1.10k | new_value |= (insn & 0x00008000) >> 12; |
150 | 1.10k | } |
151 | 55.4k | else if (strcmp (pfd->name, "a_rte") == 0) |
152 | 4.00k | { |
153 | 4.00k | new_value = (insn & 0x00000C00) >> 9; |
154 | 4.00k | new_value |= (insn & 0x00008000) >> 12; |
155 | 4.00k | } |
156 | 51.4k | else if (strcmp (pfd->name, "a_rte1") == 0) |
157 | 4.00k | { |
158 | 4.00k | new_value = (insn & 0x00000C00) >> 9; |
159 | 4.00k | new_value |= (insn & 0x00008000) >> 12; |
160 | 4.00k | new_value |= 0x01; |
161 | 4.00k | } |
162 | 47.4k | else if (strcmp (pfd->name, "a_rte69") == 0) |
163 | 366 | { |
164 | 366 | new_value = int_value << 1; |
165 | 366 | } |
166 | 47.0k | else if (strcmp (pfd->name, "a_rte69_1") == 0) |
167 | 366 | { |
168 | 366 | new_value = int_value << 1; |
169 | 366 | new_value |= 0x01; |
170 | 366 | } |
171 | | |
172 | 76.2k | psys_reg = nds32_find_reg_keyword (psys_reg, new_value); |
173 | 76.2k | if (!psys_reg) |
174 | 77 | func (stream, "???"); |
175 | 76.2k | else |
176 | 76.2k | func (stream, "$%s", psys_reg->name); |
177 | 76.2k | } |
178 | | |
179 | | /* Match instruction opcode with keyword table. */ |
180 | | |
181 | | static field_t * |
182 | | match_field (char *name) |
183 | 4.45M | { |
184 | 4.45M | field_t *pfd; |
185 | 4.45M | int k; |
186 | | |
187 | 4.45M | for (k = 0; k < NDS32_CORE_COUNT; k++) |
188 | 4.45M | { |
189 | 4.45M | pfd = (field_t *) nds32_field_table[k]; |
190 | 144M | while (1) |
191 | 144M | { |
192 | 144M | if (pfd->name == NULL) |
193 | 0 | break; |
194 | 144M | if (strcmp (name, pfd->name) == 0) |
195 | 4.45M | return pfd; |
196 | 139M | pfd++; |
197 | 139M | } |
198 | 4.45M | } |
199 | | |
200 | 0 | return NULL; |
201 | 4.45M | } |
202 | | |
203 | | /* Dump instruction. If the opcode is unknown, return FALSE. */ |
204 | | |
205 | | static void |
206 | | nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED, |
207 | | disassemble_info *info, uint32_t insn, |
208 | | uint32_t parse_mode) |
209 | 2.03M | { |
210 | 2.03M | int op = 0; |
211 | 2.03M | fprintf_ftype func = info->fprintf_func; |
212 | 2.03M | void *stream = info->stream; |
213 | 2.03M | const char *pstr_src; |
214 | 2.03M | char *pstr_tmp; |
215 | 2.03M | char tmp_string[16]; |
216 | 2.03M | unsigned int push25gpr = 0, lsmwRb, lsmwRe, lsmwEnb4, checkbit, i; |
217 | 2.03M | int int_value, ifthe1st = 1; |
218 | 2.03M | const field_t *pfd; |
219 | 2.03M | const keyword_t *psys_reg; |
220 | | |
221 | 2.03M | if (opc == NULL) |
222 | 326k | { |
223 | 326k | func (stream, UNKNOWN_INSN_MSG); |
224 | 326k | return; |
225 | 326k | } |
226 | | |
227 | 1.71M | pstr_src = opc->instruction; |
228 | 1.71M | if (*pstr_src == 0) |
229 | 290 | { |
230 | 290 | func (stream, "%s", opc->opcode); |
231 | 290 | return; |
232 | 290 | } |
233 | | /* NDS32_PARSE_INSN16. */ |
234 | 1.71M | if (parse_mode & NDS32_PARSE_INSN16) |
235 | 774k | { |
236 | 774k | func (stream, "%s ", opc->opcode); |
237 | 774k | } |
238 | | |
239 | | /* NDS32_PARSE_INSN32. */ |
240 | 937k | else |
241 | 937k | { |
242 | 937k | op = N32_OP6 (insn); |
243 | 937k | if (op == N32_OP6_LSMW) |
244 | 7.64k | func (stream, "%s.", opc->opcode); |
245 | 929k | else if (strstr (opc->instruction, "tito")) |
246 | 108 | func (stream, "%s", opc->opcode); |
247 | 929k | else |
248 | 929k | func (stream, "%s\t", opc->opcode); |
249 | 937k | } |
250 | | |
251 | 12.4M | while (*pstr_src) |
252 | 10.7M | { |
253 | 10.7M | switch (*pstr_src) |
254 | 10.7M | { |
255 | 3.28M | case '%': |
256 | 4.45M | case '=': |
257 | 4.45M | case '&': |
258 | 4.45M | pstr_src++; |
259 | | /* Compare with nds32_operand_fields[].name. */ |
260 | 4.45M | pstr_tmp = &tmp_string[0]; |
261 | 18.1M | while (*pstr_src) |
262 | 17.2M | { |
263 | 17.2M | if ((*pstr_src == ',') || (*pstr_src == ' ') |
264 | 17.2M | || (*pstr_src == '{') || (*pstr_src == '}') |
265 | 17.2M | || (*pstr_src == '[') || (*pstr_src == ']') |
266 | 17.2M | || (*pstr_src == '(') || (*pstr_src == ')') |
267 | 17.2M | || (*pstr_src == '+') || (*pstr_src == '<')) |
268 | 3.52M | break; |
269 | 13.6M | *pstr_tmp++ = *pstr_src++; |
270 | 13.6M | } |
271 | 4.45M | *pstr_tmp = 0; |
272 | | |
273 | 4.45M | if ((pfd = match_field (&tmp_string[0])) == NULL) |
274 | 0 | return; |
275 | | |
276 | | /* For insn-16. */ |
277 | 4.45M | if (parse_mode & NDS32_PARSE_INSN16) |
278 | 1.63M | { |
279 | 1.63M | if (pfd->hw_res == HW_GPR) |
280 | 1.10M | { |
281 | 1.10M | int_value = |
282 | 1.10M | __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift; |
283 | | /* push25/pop25. */ |
284 | 1.10M | if ((opc->value == 0xfc00) || (opc->value == 0xfc80)) |
285 | 8.50k | { |
286 | 8.50k | if (int_value == 0) |
287 | 2.17k | int_value = 6; |
288 | 6.32k | else |
289 | 6.32k | int_value = (6 + (0x01 << int_value)); |
290 | 8.50k | push25gpr = int_value; |
291 | 8.50k | } |
292 | 1.09M | else if (strcmp (pfd->name, "rt4") == 0) |
293 | 174k | { |
294 | 174k | int_value = nds32_r45map[int_value]; |
295 | 174k | } |
296 | 1.10M | func (stream, "$%s", nds32_keyword_gpr[int_value].name); |
297 | 1.10M | } |
298 | 530k | else if ((pfd->hw_res == HW_INT) || (pfd->hw_res == HW_UINT)) |
299 | 530k | { |
300 | 530k | if (pfd->hw_res == HW_INT) |
301 | 209k | int_value |
302 | 209k | = (unsigned) N32_IMMS (insn >> pfd->bitpos, |
303 | 209k | pfd->bitsize) << pfd->shift; |
304 | 320k | else |
305 | 320k | int_value = |
306 | 320k | __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift; |
307 | | |
308 | | /* movpi45. */ |
309 | 530k | if (opc->value == 0xfa00) |
310 | 13.8k | { |
311 | 13.8k | int_value += 16; |
312 | 13.8k | func (stream, "#0x%x", int_value); |
313 | 13.8k | } |
314 | | /* lwi45.fe. */ |
315 | 517k | else if (opc->value == 0xb200) |
316 | 9.13k | { |
317 | 9.13k | int_value = 0 - (128 - int_value); |
318 | 9.13k | func (stream, "#%d", int_value); |
319 | 9.13k | } |
320 | | /* beqz38/bnez38/beqs38/bnes38/j8/beqzs8/bnezs8. */ |
321 | 507k | else if ((opc->value == 0xc000) || (opc->value == 0xc800) |
322 | 507k | || (opc->value == 0xd000) || (opc->value == 0xd800) |
323 | 507k | || (opc->value == 0xd500) || (opc->value == 0xe800) |
324 | 507k | || (opc->value == 0xe900)) |
325 | 171k | { |
326 | 171k | info->print_address_func (int_value + pc, info); |
327 | 171k | } |
328 | | /* push25/pop25. */ |
329 | 336k | else if ((opc->value == 0xfc00) || (opc->value == 0xfc80)) |
330 | 8.50k | { |
331 | 8.50k | func (stream, "#%d ! {$r6", int_value); |
332 | 8.50k | if (push25gpr != 6) |
333 | 6.32k | func (stream, "~$%s", nds32_keyword_gpr[push25gpr].name); |
334 | 8.50k | func (stream, ", $fp, $gp, $lp}"); |
335 | 8.50k | } |
336 | 327k | else if (pfd->hw_res == HW_INT) |
337 | 38.4k | { |
338 | 38.4k | if (int_value < 10) |
339 | 26.8k | func (stream, "#%d", int_value); |
340 | 11.6k | else |
341 | 11.6k | func (stream, "#0x%x", int_value); |
342 | 38.4k | } |
343 | 289k | else /* if (pfd->hw_res == HW_UINT). */ |
344 | 289k | { |
345 | 289k | if (int_value < 10) |
346 | 117k | func (stream, "#%u", int_value); |
347 | 172k | else |
348 | 172k | func (stream, "#0x%x", int_value); |
349 | 289k | } |
350 | 530k | } |
351 | | |
352 | 1.63M | } |
353 | | /* for audio-ext. */ |
354 | 2.81M | else if (op == N32_OP6_AEXT) |
355 | 77.0k | { |
356 | 77.0k | nds32_parse_audio_ext (pfd, info, insn); |
357 | 77.0k | } |
358 | | /* for insn-32. */ |
359 | 2.73M | else if (pfd->hw_res < HW_INT) |
360 | 1.81M | { |
361 | 1.81M | int_value = |
362 | 1.81M | __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift; |
363 | | |
364 | 1.81M | psys_reg = *(nds32_keyword_table[pfd->hw_res >> 8] |
365 | 1.81M | + (pfd->hw_res & 0xff)); |
366 | | |
367 | 1.81M | psys_reg = nds32_find_reg_keyword (psys_reg, int_value); |
368 | | /* For HW_SR, dump the index when it can't |
369 | | map the register name. */ |
370 | 1.81M | if (!psys_reg && pfd->hw_res == HW_SR) |
371 | 753 | func (stream, "%d", int_value); |
372 | 1.81M | else if (!psys_reg) |
373 | 5.78k | func (stream, "???"); |
374 | 1.80M | else |
375 | 1.80M | { |
376 | 1.80M | if (pfd->hw_res == HW_GPR || pfd->hw_res == HW_CPR |
377 | 1.80M | || pfd->hw_res == HW_FDR || pfd->hw_res == HW_FSR |
378 | 1.80M | || pfd->hw_res == HW_DXR || pfd->hw_res == HW_SR |
379 | 1.80M | || pfd->hw_res == HW_USR) |
380 | 1.75M | func (stream, "$%s", psys_reg->name); |
381 | 57.8k | else if (pfd->hw_res == HW_DTITON |
382 | 57.8k | || pfd->hw_res == HW_DTITOFF) |
383 | 108 | func (stream, ".%s", psys_reg->name); |
384 | 57.7k | else |
385 | 57.7k | func (stream, "%s", psys_reg->name); |
386 | 1.80M | } |
387 | 1.81M | } |
388 | 923k | else if ((pfd->hw_res == HW_INT) || (pfd->hw_res == HW_UINT)) |
389 | 923k | { |
390 | 923k | if (pfd->hw_res == HW_INT) |
391 | 846k | int_value = (unsigned) N32_IMMS (insn >> pfd->bitpos, |
392 | 846k | pfd->bitsize) << pfd->shift; |
393 | 76.6k | else |
394 | 76.6k | int_value = |
395 | 76.6k | __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift; |
396 | | |
397 | 923k | if ((op == N32_OP6_BR1) || (op == N32_OP6_BR2)) |
398 | 21.9k | { |
399 | 21.9k | info->print_address_func (int_value + pc, info); |
400 | 21.9k | } |
401 | 901k | else if ((op == N32_OP6_BR3) && (pfd->bitpos == 0)) |
402 | 8.71k | { |
403 | 8.71k | info->print_address_func (int_value + pc, info); |
404 | 8.71k | } |
405 | 892k | else if (op == N32_OP6_JI) |
406 | 14.8k | { |
407 | | /* FIXME: Handle relocation. */ |
408 | 14.8k | if (info->flags & INSN_HAS_RELOC) |
409 | 0 | pc = 0; |
410 | 14.8k | info->print_address_func (int_value + pc, info); |
411 | 14.8k | } |
412 | 877k | else if (op == N32_OP6_LSMW) |
413 | 7.64k | { |
414 | | /* lmw.adm/smw.adm. */ |
415 | 7.64k | func (stream, "#0x%x ! {", int_value); |
416 | 7.64k | lsmwEnb4 = int_value; |
417 | 7.64k | lsmwRb = ((insn >> 20) & 0x1F); |
418 | 7.64k | lsmwRe = ((insn >> 10) & 0x1F); |
419 | | |
420 | | /* If [Rb, Re] specifies at least one register, |
421 | | Rb(4,0) <= Re(4,0) and 0 <= Rb(4,0), Re(4,0) < 28. |
422 | | Disassembling does not consider this currently because of |
423 | | the convience comparing with bsp320. */ |
424 | 7.64k | if (lsmwRb != 31 || lsmwRe != 31) |
425 | 7.61k | { |
426 | 7.61k | func (stream, "$%s", nds32_keyword_gpr[lsmwRb].name); |
427 | 7.61k | if (lsmwRb != lsmwRe) |
428 | 7.21k | func (stream, "~$%s", nds32_keyword_gpr[lsmwRe].name); |
429 | 7.61k | ifthe1st = 0; |
430 | 7.61k | } |
431 | 7.64k | if (lsmwEnb4 != 0) |
432 | 6.01k | { |
433 | | /* $fp, $gp, $lp, $sp. */ |
434 | 6.01k | checkbit = 0x08; |
435 | 30.0k | for (i = 0; i < 4; i++) |
436 | 24.0k | { |
437 | 24.0k | if (lsmwEnb4 & checkbit) |
438 | 11.1k | { |
439 | 11.1k | if (ifthe1st == 1) |
440 | 22 | { |
441 | 22 | ifthe1st = 0; |
442 | 22 | func (stream, "$%s", nds32_keyword_gpr[28 + i].name); |
443 | 22 | } |
444 | 11.1k | else |
445 | 11.1k | func (stream, ", $%s", nds32_keyword_gpr[28 + i].name); |
446 | 11.1k | } |
447 | 24.0k | checkbit >>= 1; |
448 | 24.0k | } |
449 | 6.01k | } |
450 | 7.64k | func (stream, "}"); |
451 | 7.64k | } |
452 | 869k | else if (pfd->hw_res == HW_INT) |
453 | 800k | { |
454 | 800k | if (int_value < 10) |
455 | 398k | func (stream, "#%d", int_value); |
456 | 402k | else |
457 | 402k | func (stream, "#0x%x", int_value); |
458 | 800k | } |
459 | 69.0k | else /* if (pfd->hw_res == HW_UINT). */ |
460 | 69.0k | { |
461 | 69.0k | if (int_value < 10) |
462 | 7.48k | func (stream, "#%u", int_value); |
463 | 61.5k | else |
464 | 61.5k | func (stream, "#0x%x", int_value); |
465 | 69.0k | } |
466 | 923k | } |
467 | 4.45M | break; |
468 | | |
469 | 687k | case '{': |
470 | 1.37M | case '}': |
471 | 1.37M | pstr_src++; |
472 | 1.37M | break; |
473 | | |
474 | 2.08M | case ',': |
475 | 2.08M | func (stream, ", "); |
476 | 2.08M | pstr_src++; |
477 | 2.08M | break; |
478 | | |
479 | 758k | case '+': |
480 | 758k | func (stream, " + "); |
481 | 758k | pstr_src++; |
482 | 758k | break; |
483 | | |
484 | 3.17k | case '<': |
485 | 3.17k | if (pstr_src[1] == '<') |
486 | 3.17k | { |
487 | 3.17k | func (stream, " << "); |
488 | 3.17k | pstr_src += 2; |
489 | 3.17k | } |
490 | 0 | else |
491 | 0 | { |
492 | 0 | func (stream, " <"); |
493 | 0 | pstr_src++; |
494 | 0 | } |
495 | 3.17k | break; |
496 | | |
497 | 2.02M | default: |
498 | 2.02M | func (stream, "%c", *pstr_src++); |
499 | 2.02M | break; |
500 | 10.7M | } |
501 | 10.7M | } |
502 | 1.71M | } |
503 | | |
504 | | /* Filter instructions with some bits must be fixed. */ |
505 | | |
506 | | static void |
507 | | nds32_filter_unknown_insn (uint32_t insn, struct nds32_opcode **opc) |
508 | 1.23M | { |
509 | 1.23M | if (!(*opc)) |
510 | 288k | return; |
511 | | |
512 | 948k | switch ((*opc)->value) |
513 | 948k | { |
514 | 653 | case JREG (JR): |
515 | 730 | case JREG (JRNEZ): |
516 | | /* jr jr.xtoff */ |
517 | 730 | if (__GF (insn, 6, 2) != 0 || __GF (insn, 15, 10) != 0) |
518 | 678 | *opc = NULL; |
519 | 730 | break; |
520 | 1.41k | case MISC (STANDBY): |
521 | 1.41k | if (__GF (insn, 7, 18) != 0) |
522 | 1.19k | *opc = NULL; |
523 | 1.41k | break; |
524 | 1.02k | case SIMD (PBSAD): |
525 | 1.55k | case SIMD (PBSADA): |
526 | 1.55k | if (__GF (insn, 5, 5) != 0) |
527 | 898 | *opc = NULL; |
528 | 1.55k | break; |
529 | 0 | case BR2 (SOP0): |
530 | 0 | if (__GF (insn, 20, 5) != 0) |
531 | 0 | *opc = NULL; |
532 | 0 | break; |
533 | 307 | case JREG (JRAL): |
534 | 307 | if (__GF (insn, 5, 3) != 0 || __GF (insn, 15, 5) != 0) |
535 | 299 | *opc = NULL; |
536 | 307 | break; |
537 | 329 | case ALU1 (NOR): |
538 | 510 | case ALU1 (SLT): |
539 | 844 | case ALU1 (SLTS): |
540 | 1.43k | case ALU1 (SLLI): |
541 | 1.64k | case ALU1 (SRLI): |
542 | 2.32k | case ALU1 (SRAI): |
543 | 2.48k | case ALU1 (ROTRI): |
544 | 2.81k | case ALU1 (SLL): |
545 | 3.14k | case ALU1 (SRL): |
546 | 3.40k | case ALU1 (SRA): |
547 | 3.66k | case ALU1 (ROTR): |
548 | 4.20k | case ALU1 (SEB): |
549 | 4.70k | case ALU1 (SEH): |
550 | 5.06k | case ALU1 (ZEH): |
551 | 5.28k | case ALU1 (WSBH): |
552 | 5.75k | case ALU1 (SVA): |
553 | 5.94k | case ALU1 (SVS): |
554 | 6.24k | case ALU1 (CMOVZ): |
555 | 6.47k | case ALU1 (CMOVN): |
556 | 6.47k | if (__GF (insn, 5, 5) != 0) |
557 | 5.80k | *opc = NULL; |
558 | 6.47k | break; |
559 | 996 | case MISC (IRET): |
560 | 1.40k | case MISC (ISB): |
561 | 1.75k | case MISC (DSB): |
562 | 1.75k | if (__GF (insn, 5, 20) != 0) |
563 | 1.72k | *opc = NULL; |
564 | 1.75k | break; |
565 | 948k | } |
566 | 948k | } |
567 | | |
568 | | static void |
569 | | print_insn32 (bfd_vma pc, disassemble_info *info, uint32_t insn, |
570 | | uint32_t parse_mode) |
571 | 1.23M | { |
572 | | /* Get the final correct opcode and parse. */ |
573 | 1.23M | struct nds32_opcode *opc; |
574 | 1.23M | uint32_t opcode = nds32_mask_opcode (insn); |
575 | 1.23M | opc = (struct nds32_opcode *) htab_find (opcode_htab, &opcode); |
576 | | |
577 | 1.23M | nds32_special_opcode (insn, &opc); |
578 | 1.23M | nds32_filter_unknown_insn (insn, &opc); |
579 | 1.23M | nds32_parse_opcode (opc, pc, info, insn, parse_mode); |
580 | 1.23M | } |
581 | | |
582 | | static void |
583 | | print_insn16 (bfd_vma pc, disassemble_info *info, |
584 | | uint32_t insn, uint32_t parse_mode) |
585 | 802k | { |
586 | 802k | struct nds32_opcode *opc; |
587 | 802k | uint32_t opcode; |
588 | | |
589 | | /* Get highest 7 bit in default. */ |
590 | 802k | unsigned int mask = 0xfe00; |
591 | | |
592 | | /* Classify 16-bit instruction to 4 sets by bit 13 and 14. */ |
593 | 802k | switch (__GF (insn, 13, 2)) |
594 | 802k | { |
595 | 195k | case 0x0: |
596 | | /* mov55 movi55 */ |
597 | 195k | if (__GF (insn, 11, 2) == 0) |
598 | 43.8k | { |
599 | 43.8k | mask = 0xfc00; |
600 | | /* ifret16 = mov55 $sp, $sp*/ |
601 | 43.8k | if (__GF (insn, 0, 11) == 0x3ff) |
602 | 190 | mask = 0xffff; |
603 | 43.8k | } |
604 | 151k | else if (__GF (insn, 9, 4) == 0xb) |
605 | 9.24k | mask = 0xfe07; |
606 | 195k | break; |
607 | 158k | case 0x1: |
608 | | /* lwi37 swi37 */ |
609 | 158k | if (__GF (insn, 11, 2) == 0x3) |
610 | 39.1k | mask = 0xf880; |
611 | 158k | break; |
612 | 164k | case 0x2: |
613 | 164k | mask = 0xf800; |
614 | | /* Exclude beqz38, bnez38, beqs38, and bnes38. */ |
615 | 164k | if (__GF (insn, 12, 1) == 0x1 |
616 | 164k | && __GF (insn, 8, 3) == 0x5) |
617 | 8.98k | { |
618 | 8.98k | if (__GF (insn, 11, 1) == 0x0) |
619 | 4.64k | mask = 0xff00; |
620 | 4.34k | else |
621 | 4.34k | mask = 0xffe0; |
622 | 8.98k | } |
623 | 164k | break; |
624 | 284k | case 0x3: |
625 | 284k | switch (__GF (insn, 11, 2)) |
626 | 284k | { |
627 | 41.1k | case 0x1: |
628 | | /* beqzs8 bnezs8 */ |
629 | 41.1k | if (__GF (insn, 9, 2) == 0x0) |
630 | 11.4k | mask = 0xff00; |
631 | | /* addi10s */ |
632 | 29.7k | else if (__GF(insn, 10, 1) == 0x1) |
633 | 20.2k | mask = 0xfc00; |
634 | 41.1k | break; |
635 | 45.5k | case 0x2: |
636 | | /* lwi37.sp swi37.sp */ |
637 | 45.5k | mask = 0xf880; |
638 | 45.5k | break; |
639 | 155k | case 0x3: |
640 | 155k | if (__GF (insn, 8, 3) == 0x5) |
641 | 5.81k | mask = 0xff00; |
642 | 149k | else if (__GF (insn, 8, 3) == 0x4) |
643 | 8.50k | mask = 0xff80; |
644 | 140k | else if (__GF (insn, 9 , 2) == 0x3) |
645 | 116k | mask = 0xfe07; |
646 | 155k | break; |
647 | 284k | } |
648 | 284k | break; |
649 | 802k | } |
650 | 802k | opcode = insn & mask; |
651 | 802k | opc = (struct nds32_opcode *) htab_find (opcode_htab, &opcode); |
652 | | |
653 | 802k | nds32_special_opcode (insn, &opc); |
654 | | /* Get the final correct opcode and parse it. */ |
655 | 802k | nds32_parse_opcode (opc, pc, info, insn, parse_mode); |
656 | 802k | } |
657 | | |
658 | | static hashval_t |
659 | | htab_hash_hash (const void *p) |
660 | 2.04M | { |
661 | 2.04M | return (*(unsigned int *) p) % 49; |
662 | 2.04M | } |
663 | | |
664 | | static int |
665 | | htab_hash_eq (const void *p, const void *q) |
666 | 31.5M | { |
667 | 31.5M | uint32_t pinsn = ((struct nds32_opcode *) p)->value; |
668 | 31.5M | uint32_t qinsn = *((uint32_t *) q); |
669 | | |
670 | 31.5M | return (pinsn == qinsn); |
671 | 31.5M | } |
672 | | |
673 | | /* Get the format of instruction. */ |
674 | | |
675 | | static uint32_t |
676 | | nds32_mask_opcode (uint32_t insn) |
677 | 1.23M | { |
678 | 1.23M | uint32_t opcode = N32_OP6 (insn); |
679 | 1.23M | switch (opcode) |
680 | 1.23M | { |
681 | 392k | case N32_OP6_LBI: |
682 | 424k | case N32_OP6_LHI: |
683 | 455k | case N32_OP6_LWI: |
684 | 478k | case N32_OP6_LDI: |
685 | 495k | case N32_OP6_LBI_BI: |
686 | 508k | case N32_OP6_LHI_BI: |
687 | 522k | case N32_OP6_LWI_BI: |
688 | 536k | case N32_OP6_LDI_BI: |
689 | 576k | case N32_OP6_SBI: |
690 | 587k | case N32_OP6_SHI: |
691 | 596k | case N32_OP6_SWI: |
692 | 609k | case N32_OP6_SDI: |
693 | 618k | case N32_OP6_SBI_BI: |
694 | 630k | case N32_OP6_SHI_BI: |
695 | 639k | case N32_OP6_SWI_BI: |
696 | 648k | case N32_OP6_SDI_BI: |
697 | 663k | case N32_OP6_LBSI: |
698 | 673k | case N32_OP6_LHSI: |
699 | 685k | case N32_OP6_LWSI: |
700 | 694k | case N32_OP6_LBSI_BI: |
701 | 705k | case N32_OP6_LHSI_BI: |
702 | 714k | case N32_OP6_LWSI_BI: |
703 | 725k | case N32_OP6_MOVI: |
704 | 735k | case N32_OP6_SETHI: |
705 | 745k | case N32_OP6_ADDI: |
706 | 757k | case N32_OP6_SUBRI: |
707 | 766k | case N32_OP6_ANDI: |
708 | 775k | case N32_OP6_XORI: |
709 | 788k | case N32_OP6_ORI: |
710 | 797k | case N32_OP6_SLTI: |
711 | 809k | case N32_OP6_SLTSI: |
712 | 823k | case N32_OP6_CEXT: |
713 | 834k | case N32_OP6_BITCI: |
714 | 834k | return MASK_OP (insn, 0); |
715 | 9.65k | case N32_OP6_ALU2: |
716 | | /* FFBI */ |
717 | 9.65k | if (__GF (insn, 0, 7) == (N32_ALU2_FFBI | N32_BIT (6))) |
718 | 219 | return MASK_OP (insn, 0x7f); |
719 | 9.43k | else if (__GF (insn, 0, 7) == (N32_ALU2_MFUSR | N32_BIT (6)) |
720 | 9.43k | || __GF (insn, 0, 7) == (N32_ALU2_MTUSR | N32_BIT (6))) |
721 | | /* RDOV CLROV */ |
722 | 169 | return MASK_OP (insn, 0xf81ff); |
723 | 9.26k | else if (__GF (insn, 0, 10) == (N32_ALU2_ONEOP | N32_BIT (7))) |
724 | 68 | { |
725 | | /* INSB */ |
726 | 68 | if (__GF (insn, 12, 3) == 4) |
727 | 15 | return MASK_OP (insn, 0x73ff); |
728 | 53 | return MASK_OP (insn, 0x7fff); |
729 | 68 | } |
730 | 9.20k | return MASK_OP (insn, 0x3ff); |
731 | 16.9k | case N32_OP6_ALU1: |
732 | 28.9k | case N32_OP6_SIMD: |
733 | 28.9k | return MASK_OP (insn, 0x1f); |
734 | 16.6k | case N32_OP6_MEM: |
735 | 16.6k | return MASK_OP (insn, 0xff); |
736 | 12.9k | case N32_OP6_JREG: |
737 | 12.9k | return MASK_OP (insn, 0x7f); |
738 | 9.91k | case N32_OP6_LSMW: |
739 | 9.91k | return MASK_OP (insn, 0x23); |
740 | 11.0k | case N32_OP6_SBGP: |
741 | 24.6k | case N32_OP6_LBGP: |
742 | 24.6k | return MASK_OP (insn, 0x1 << 19); |
743 | 14.4k | case N32_OP6_HWGP: |
744 | 14.4k | if (__GF (insn, 18, 2) == 0x3) |
745 | 3.81k | return MASK_OP (insn, 0x7 << 17); |
746 | 10.6k | return MASK_OP (insn, 0x3 << 18); |
747 | 10.2k | case N32_OP6_DPREFI: |
748 | 10.2k | return MASK_OP (insn, 0x1 << 24); |
749 | 16.2k | case N32_OP6_LWC: |
750 | 28.8k | case N32_OP6_SWC: |
751 | 42.3k | case N32_OP6_LDC: |
752 | 53.2k | case N32_OP6_SDC: |
753 | 53.2k | return MASK_OP (insn, 0x1 << 12); |
754 | 14.8k | case N32_OP6_JI: |
755 | 14.8k | return MASK_OP (insn, 0x1 << 24); |
756 | 17.1k | case N32_OP6_BR1: |
757 | 17.1k | return MASK_OP (insn, 0x1 << 14); |
758 | 11.3k | case N32_OP6_BR2: |
759 | 11.3k | if (__GF (insn, 16, 4) == 0) |
760 | 1.54k | return MASK_OP (insn, 0x1ff << 16); |
761 | 9.78k | else |
762 | 9.78k | return MASK_OP (insn, 0xf << 16); |
763 | 8.71k | case N32_OP6_BR3: |
764 | 8.71k | return MASK_OP (insn, 0x1 << 19); |
765 | 15.1k | case N32_OP6_MISC: |
766 | 15.1k | switch (__GF (insn, 0, 5)) |
767 | 15.1k | { |
768 | 560 | case N32_MISC_MTSR: |
769 | | /* SETGIE and SETEND */ |
770 | 560 | if (__GF (insn, 5, 5) == 0x1 || __GF (insn, 5, 5) == 0x2) |
771 | 108 | return MASK_OP (insn, 0x1fffff); |
772 | 452 | return MASK_OP (insn, 0x1f); |
773 | 417 | case N32_MISC_TLBOP: |
774 | 417 | if (__GF (insn, 5, 5) == 5 || __GF (insn, 5, 5) == 7) |
775 | | /* PB FLUA */ |
776 | 7 | return MASK_OP (insn, 0x3ff); |
777 | 410 | return MASK_OP (insn, 0x1f); |
778 | 14.1k | default: |
779 | 14.1k | return MASK_OP (insn, 0x1f); |
780 | 15.1k | } |
781 | 9.49k | case N32_OP6_COP: |
782 | 9.49k | if (__GF (insn, 4, 2) == 0) |
783 | 2.95k | { |
784 | | /* FPU */ |
785 | 2.95k | switch (__GF (insn, 0, 4)) |
786 | 2.95k | { |
787 | 757 | case 0x0: |
788 | 926 | case 0x8: |
789 | | /* FS1/F2OP FD1/F2OP */ |
790 | 926 | if (__GF (insn, 6, 4) == 0xf) |
791 | 9 | return MASK_OP (insn, 0x7fff); |
792 | | /* FS1 FD1 */ |
793 | 917 | return MASK_OP (insn, 0x3ff); |
794 | 245 | case 0x4: |
795 | 345 | case 0xc: |
796 | | /* FS2 */ |
797 | 345 | return MASK_OP (insn, 0x3ff); |
798 | 200 | case 0x1: |
799 | 281 | case 0x9: |
800 | | /* XR */ |
801 | 281 | if (__GF (insn, 6, 4) == 0xc) |
802 | 19 | return MASK_OP (insn, 0x7fff); |
803 | | /* MFCP MTCP */ |
804 | 262 | return MASK_OP (insn, 0x3ff); |
805 | 1.40k | default: |
806 | 1.40k | return MASK_OP (insn, 0xff); |
807 | 2.95k | } |
808 | 2.95k | } |
809 | 6.53k | else if (__GF (insn, 0, 2) == 0) |
810 | 2.00k | return MASK_OP (insn, 0xf); |
811 | 4.53k | return MASK_OP (insn, 0xcf); |
812 | 21.6k | case N32_OP6_AEXT: |
813 | | /* AUDIO */ |
814 | 21.6k | switch (__GF (insn, 23, 2)) |
815 | 21.6k | { |
816 | 6.88k | case 0x0: |
817 | 6.88k | if (__GF (insn, 5, 4) == 0) |
818 | | /* AMxxx AMAyyS AMyyS AMAWzS AMWzS */ |
819 | 938 | return MASK_OP (insn, (0x1f << 20) | 0x1ff); |
820 | 5.94k | else if (__GF (insn, 5, 4) == 1) |
821 | | /* ALR ASR ALA ASA AUPI */ |
822 | 222 | return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); |
823 | 5.72k | else if (__GF (insn, 20, 3) == 0 && __GF (insn, 6, 3) == 1) |
824 | | /* ALR2 */ |
825 | 124 | return MASK_OP (insn, (0x1f << 20) | (0x7 << 6)); |
826 | 5.59k | else if (__GF (insn, 20 ,3) == 2 && __GF (insn, 6, 3) == 1) |
827 | | /* AWEXT ASATS48 */ |
828 | 275 | return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); |
829 | 5.32k | else if (__GF (insn, 20 ,3) == 3 && __GF (insn, 6, 3) == 1) |
830 | | /* AMTAR AMTAR2 AMFAR AMFAR2 */ |
831 | 346 | return MASK_OP (insn, (0x1f << 20) | (0x1f << 5)); |
832 | 4.97k | else if (__GF (insn, 7, 2) == 3) |
833 | | /* AMxxxSA */ |
834 | 449 | return MASK_OP (insn, (0x1f << 20) | (0x3 << 7)); |
835 | 4.52k | else if (__GF (insn, 6, 3) == 2) |
836 | | /* AMxxxL.S */ |
837 | 521 | return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); |
838 | 4.00k | else |
839 | | /* AmxxxL.l AmxxxL2.S AMxxxL2.L */ |
840 | 4.00k | return MASK_OP (insn, (0x1f << 20) | (0x7 << 6)); |
841 | 3.24k | case 0x1: |
842 | 3.24k | if (__GF (insn, 20, 3) == 0) |
843 | | /* AADDL ASUBL */ |
844 | 366 | return MASK_OP (insn, (0x1f << 20) | (0x1 << 5)); |
845 | 2.88k | else if (__GF (insn, 20, 3) == 1) |
846 | | /* AMTARI Ix AMTARI Mx */ |
847 | 490 | return MASK_OP (insn, (0x1f << 20)); |
848 | 2.39k | else if (__GF (insn, 6, 3) == 2) |
849 | | /* AMAWzSl.S AMWzSl.S */ |
850 | 199 | return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); |
851 | 2.19k | else if (__GF (insn, 7, 2) == 3) |
852 | | /* AMAWzSSA AMWzSSA */ |
853 | 907 | return MASK_OP (insn, (0x1f << 20) | (0x3 << 7)); |
854 | 1.28k | else |
855 | | /* AMAWzSL.L AMAWzSL2.S AMAWzSL2.L |
856 | | AMWzSL.L AMWzSL.L AMWzSL2.S */ |
857 | 1.28k | return MASK_OP (insn, (0x1f << 20) | (0x7 << 6)); |
858 | 8.88k | case 0x2: |
859 | 8.88k | if (__GF (insn, 6, 3) == 2) |
860 | | /* AMAyySl.S AMWyySl.S */ |
861 | 476 | return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); |
862 | 8.41k | else if (__GF (insn, 7, 2) == 3) |
863 | | /* AMAWyySSA AMWyySSA */ |
864 | 1.08k | return MASK_OP (insn, (0x1f << 20) | (0x3 << 7)); |
865 | 7.32k | else |
866 | | /* AMAWyySL.L AMAWyySL2.S AMAWyySL2.L |
867 | | AMWyySL.L AMWyySL.L AMWyySL2.S */ |
868 | 7.32k | return MASK_OP (insn, (0x1f << 20) | (0x7 << 6)); |
869 | 21.6k | } |
870 | 2.67k | return MASK_OP (insn, 0x1f << 20); |
871 | 122k | default: |
872 | 122k | return 1u << 31; |
873 | 1.23M | } |
874 | 1.23M | } |
875 | | |
876 | | /* Define cctl subtype. */ |
877 | | static char *cctl_subtype [] = |
878 | | { |
879 | | /* 0x0 */ |
880 | | "st0", "st0", "st0", "st2", "st2", "st3", "st3", "st4", |
881 | | "st1", "st1", "st1", "st0", "st0", NULL, NULL, "st5", |
882 | | /* 0x10 */ |
883 | | "st0", NULL, NULL, "st2", "st2", "st3", "st3", NULL, |
884 | | "st1", NULL, NULL, "st0", "st0", NULL, NULL, NULL |
885 | | }; |
886 | | |
887 | | /* Check the subset of opcode. */ |
888 | | |
889 | | static void |
890 | | nds32_special_opcode (uint32_t insn, struct nds32_opcode **opc) |
891 | 2.03M | { |
892 | 2.03M | char *string = NULL; |
893 | 2.03M | uint32_t op; |
894 | | |
895 | 2.03M | if (!(*opc)) |
896 | 315k | return; |
897 | | |
898 | | /* Check if special case. */ |
899 | 1.72M | switch ((*opc)->value) |
900 | 1.72M | { |
901 | 8.26k | case OP6 (LWC): |
902 | 12.9k | case OP6 (SWC): |
903 | 18.3k | case OP6 (LDC): |
904 | 23.0k | case OP6 (SDC): |
905 | 31.0k | case FPU_RA_IMMBI (LWC): |
906 | 38.9k | case FPU_RA_IMMBI (SWC): |
907 | 47.0k | case FPU_RA_IMMBI (LDC): |
908 | 53.2k | case FPU_RA_IMMBI (SDC): |
909 | | /* Check if cp0 => FPU. */ |
910 | 53.2k | if (__GF (insn, 13, 2) == 0) |
911 | 12.6k | { |
912 | 25.2k | while (!((*opc)->attr & ATTR (FPU)) && (*opc)->next) |
913 | 12.6k | *opc = (*opc)->next; |
914 | 12.6k | } |
915 | 53.2k | break; |
916 | 4.56k | case ALU1 (ADD): |
917 | 6.41k | case ALU1 (SUB): |
918 | 6.84k | case ALU1 (AND): |
919 | 7.19k | case ALU1 (XOR): |
920 | 7.53k | case ALU1 (OR): |
921 | | /* Check if (add/add_slli) (sub/sub_slli) (and/and_slli). */ |
922 | 7.53k | if (N32_SH5(insn) != 0) |
923 | 4.87k | string = "sh"; |
924 | 7.53k | break; |
925 | 214 | case ALU1 (SRLI): |
926 | | /* Check if nop. */ |
927 | 214 | if (__GF (insn, 10, 15) == 0) |
928 | 1 | string = "nop"; |
929 | 214 | break; |
930 | 544 | case MISC (CCTL): |
931 | 544 | string = cctl_subtype [__GF (insn, 5, 5)]; |
932 | 544 | break; |
933 | 653 | case JREG (JR): |
934 | 960 | case JREG (JRAL): |
935 | 1.14k | case JREG (JR) | JREG_RET: |
936 | 1.14k | if (__GF (insn, 8, 2) != 0) |
937 | 614 | string = "tit"; |
938 | 1.14k | break; |
939 | 0 | case N32_OP6_COP: |
940 | 0 | break; |
941 | 11.1k | case 0x9200: |
942 | | /* nop16 */ |
943 | 11.1k | if (__GF (insn, 0, 9) == 0) |
944 | 263 | string = "nop16"; |
945 | 11.1k | break; |
946 | 1.72M | } |
947 | | |
948 | 1.72M | if (string) |
949 | 6.24k | { |
950 | 12.6k | while (strstr ((*opc)->opcode, string) == NULL |
951 | 12.6k | && strstr ((*opc)->instruction, string) == NULL && (*opc)->next) |
952 | 6.43k | *opc = (*opc)->next; |
953 | 6.24k | return; |
954 | 6.24k | } |
955 | | |
956 | | /* Classify instruction is COP or FPU. */ |
957 | 1.71M | op = N32_OP6 (insn); |
958 | 1.71M | if (op == N32_OP6_COP && __GF (insn, 4, 2) != 0) |
959 | 3.49k | { |
960 | 7.05k | while (((*opc)->attr & ATTR (FPU)) != 0 && (*opc)->next) |
961 | 3.56k | *opc = (*opc)->next; |
962 | 3.49k | } |
963 | 1.71M | } |
964 | | |
965 | | int |
966 | | print_insn_nds32 (bfd_vma pc, disassemble_info *info) |
967 | 2.03M | { |
968 | 2.03M | int status; |
969 | 2.03M | bfd_byte buf[4]; |
970 | 2.03M | bfd_byte buf_data[16]; |
971 | 2.03M | uint64_t given; |
972 | 2.03M | uint64_t given1; |
973 | 2.03M | uint32_t insn; |
974 | 2.03M | int n; |
975 | 2.03M | int last_symbol_index = -1; |
976 | 2.03M | bfd_vma addr; |
977 | 2.03M | int is_data = false; |
978 | 2.03M | bool found = false; |
979 | 2.03M | struct nds32_private_data *private_data; |
980 | 2.03M | unsigned int size; |
981 | 2.03M | enum map_type mapping_type = MAP_CODE; |
982 | | |
983 | 2.03M | if (info->private_data == NULL) |
984 | 799 | { |
985 | | /* Note: remain lifecycle throughout whole execution. */ |
986 | 799 | static struct nds32_private_data private; |
987 | 799 | private.has_mapping_symbols = -1; /* unknown yet. */ |
988 | 799 | private.last_symbol_index = -1; |
989 | 799 | private.last_addr = 0; |
990 | 799 | info->private_data = &private; |
991 | 799 | } |
992 | 2.03M | private_data = info->private_data; |
993 | | |
994 | 2.03M | if (info->symtab_size != 0) |
995 | 0 | { |
996 | 0 | int start; |
997 | 0 | if (pc == 0) |
998 | 0 | start = 0; |
999 | 0 | else |
1000 | 0 | { |
1001 | 0 | start = info->symtab_pos; |
1002 | 0 | if (start < private_data->last_symbol_index) |
1003 | 0 | start = private_data->last_symbol_index; |
1004 | 0 | } |
1005 | |
|
1006 | 0 | if (0 > start) |
1007 | 0 | start = 0; |
1008 | |
|
1009 | 0 | if (private_data->has_mapping_symbols != 0 |
1010 | 0 | && ((strncmp (".text", info->section->name, 5) == 0))) |
1011 | 0 | { |
1012 | 0 | for (n = start; n < info->symtab_size; n++) |
1013 | 0 | { |
1014 | 0 | addr = bfd_asymbol_value (info->symtab[n]); |
1015 | 0 | if (addr > pc) |
1016 | 0 | break; |
1017 | 0 | if (get_mapping_symbol_type (info, n, &mapping_type)) |
1018 | 0 | { |
1019 | 0 | last_symbol_index = n; |
1020 | 0 | found = true; |
1021 | 0 | } |
1022 | 0 | } |
1023 | |
|
1024 | 0 | if (found) |
1025 | 0 | private_data->has_mapping_symbols = 1; |
1026 | 0 | else if (!found && private_data->has_mapping_symbols == -1) |
1027 | 0 | { |
1028 | | /* Make sure there are no any mapping symbol. */ |
1029 | 0 | for (n = 0; n < info->symtab_size; n++) |
1030 | 0 | { |
1031 | 0 | if (is_mapping_symbol (info, n, &mapping_type)) |
1032 | 0 | { |
1033 | 0 | private_data->has_mapping_symbols = -1; |
1034 | 0 | break; |
1035 | 0 | } |
1036 | 0 | } |
1037 | 0 | if (private_data->has_mapping_symbols == -1) |
1038 | 0 | private_data->has_mapping_symbols = 0; |
1039 | 0 | } |
1040 | |
|
1041 | 0 | private_data->last_symbol_index = last_symbol_index; |
1042 | 0 | private_data->last_mapping_type = mapping_type; |
1043 | 0 | is_data = (private_data->last_mapping_type == MAP_DATA0 |
1044 | 0 | || private_data->last_mapping_type == MAP_DATA1 |
1045 | 0 | || private_data->last_mapping_type == MAP_DATA2 |
1046 | 0 | || private_data->last_mapping_type == MAP_DATA3 |
1047 | 0 | || private_data->last_mapping_type == MAP_DATA4); |
1048 | 0 | } |
1049 | 0 | } |
1050 | | |
1051 | | /* Wonder data or instruction. */ |
1052 | 2.03M | if (is_data) |
1053 | 0 | { |
1054 | 0 | unsigned int i1; |
1055 | | |
1056 | | /* Fix corner case: there is no next mapping symbol, |
1057 | | let mapping type decides size */ |
1058 | 0 | size = 16; |
1059 | 0 | if (last_symbol_index + 1 >= info->symtab_size) |
1060 | 0 | { |
1061 | 0 | if (mapping_type == MAP_DATA0) |
1062 | 0 | size = 1; |
1063 | 0 | if (mapping_type == MAP_DATA1) |
1064 | 0 | size = 2; |
1065 | 0 | if (mapping_type == MAP_DATA2) |
1066 | 0 | size = 4; |
1067 | 0 | if (mapping_type == MAP_DATA3) |
1068 | 0 | size = 8; |
1069 | 0 | if (mapping_type == MAP_DATA4) |
1070 | 0 | size = 16; |
1071 | 0 | } |
1072 | 0 | for (n = last_symbol_index + 1; n < info->symtab_size; n++) |
1073 | 0 | { |
1074 | 0 | addr = bfd_asymbol_value (info->symtab[n]); |
1075 | |
|
1076 | 0 | enum map_type fake_mapping_type; |
1077 | 0 | if (get_mapping_symbol_type (info, n, &fake_mapping_type) |
1078 | 0 | && (addr > pc |
1079 | 0 | && ((info->section == NULL) |
1080 | 0 | || (info->section == info->symtab[n]->section))) |
1081 | 0 | && (addr - pc < size)) |
1082 | 0 | { |
1083 | 0 | size = addr - pc; |
1084 | 0 | break; |
1085 | 0 | } |
1086 | 0 | } |
1087 | |
|
1088 | 0 | if (size == 3) |
1089 | 0 | size = (pc & 1) ? 1 : 2; |
1090 | | |
1091 | | /* Read bytes from BFD. */ |
1092 | 0 | info->read_memory_func (pc, buf_data, size, info); |
1093 | 0 | given = 0; |
1094 | 0 | given1 = 0; |
1095 | | /* Start assembling data. */ |
1096 | | /* Little endian of data. */ |
1097 | 0 | if (info->endian == BFD_ENDIAN_LITTLE) |
1098 | 0 | { |
1099 | 0 | for (i1 = size - 1;; i1--) |
1100 | 0 | { |
1101 | 0 | if (i1 >= 8) |
1102 | 0 | given1 = buf_data[i1] | (given1 << 8); |
1103 | 0 | else |
1104 | 0 | given = buf_data[i1] | (given << 8); |
1105 | |
|
1106 | 0 | if (i1 == 0) |
1107 | 0 | break; |
1108 | 0 | } |
1109 | 0 | } |
1110 | 0 | else |
1111 | 0 | { |
1112 | | /* Big endian of data. */ |
1113 | 0 | for (i1 = 0; i1 < size; i1++) |
1114 | 0 | { |
1115 | 0 | if (i1 <= 7) |
1116 | 0 | given = buf_data[i1] | (given << 8); |
1117 | 0 | else |
1118 | 0 | given1 = buf_data[i1] | (given1 << 8); |
1119 | 0 | } |
1120 | 0 | } |
1121 | |
|
1122 | 0 | info->bytes_per_line = 4; |
1123 | |
|
1124 | 0 | if (size == 16) |
1125 | 0 | info->fprintf_func (info->stream, ".qword\t0x%016" PRIx64 "%016" PRIx64, |
1126 | 0 | given, given1); |
1127 | 0 | else if (size == 8) |
1128 | 0 | info->fprintf_func (info->stream, ".dword\t0x%016" PRIx64, given); |
1129 | 0 | else if (size == 4) |
1130 | 0 | info->fprintf_func (info->stream, ".word\t0x%08" PRIx64, given); |
1131 | 0 | else if (size == 2) |
1132 | 0 | { |
1133 | | /* short */ |
1134 | 0 | if (mapping_type == MAP_DATA0) |
1135 | 0 | info->fprintf_func (info->stream, ".byte\t0x%02" PRIx64, |
1136 | 0 | given & 0xFF); |
1137 | 0 | else |
1138 | 0 | info->fprintf_func (info->stream, ".short\t0x%04" PRIx64, given); |
1139 | 0 | } |
1140 | 0 | else |
1141 | 0 | { |
1142 | | /* byte */ |
1143 | 0 | info->fprintf_func (info->stream, ".byte\t0x%02" PRIx64, given); |
1144 | 0 | } |
1145 | |
|
1146 | 0 | return size; |
1147 | 0 | } |
1148 | | |
1149 | 2.03M | size = 4; |
1150 | 2.03M | status = info->read_memory_func (pc, buf, 4, info); |
1151 | 2.03M | if (status) |
1152 | 1.32k | { |
1153 | | /* For the last 16-bit instruction. */ |
1154 | 1.32k | size = 2; |
1155 | 1.32k | status = info->read_memory_func (pc, buf, 2, info); |
1156 | 1.32k | if (status) |
1157 | 229 | { |
1158 | 229 | (*info->memory_error_func) (status, pc, info); |
1159 | 229 | return -1; |
1160 | 229 | } |
1161 | 1.10k | buf[2] = 0; |
1162 | 1.10k | buf[3] = 0; |
1163 | 1.10k | } |
1164 | | |
1165 | 2.03M | insn = bfd_getb32 (buf); |
1166 | | /* 16-bit instruction. */ |
1167 | 2.03M | if (insn & 0x80000000) |
1168 | 802k | { |
1169 | 802k | print_insn16 (pc, info, (insn >> 16), NDS32_PARSE_INSN16); |
1170 | 802k | return 2; |
1171 | 802k | } |
1172 | | |
1173 | | /* 32-bit instructions. */ |
1174 | 1.23M | if (size == 4) |
1175 | 1.23M | print_insn32 (pc, info, insn, NDS32_PARSE_INSN32); |
1176 | 529 | else |
1177 | 529 | info->fprintf_func (info->stream, |
1178 | 529 | _("insufficient data to decode instruction")); |
1179 | 1.23M | return 4; |
1180 | 2.03M | } |
1181 | | |
1182 | | /* Ignore disassembling unnecessary name. */ |
1183 | | |
1184 | | static bool |
1185 | | nds32_symbol_is_valid (asymbol *sym, |
1186 | | struct disassemble_info *info ATTRIBUTE_UNUSED) |
1187 | 0 | { |
1188 | 0 | const char *name; |
1189 | |
|
1190 | 0 | if (sym == NULL) |
1191 | 0 | return false; |
1192 | | |
1193 | 0 | name = bfd_asymbol_name (sym); |
1194 | | |
1195 | | /* Mapping symbol is invalid. */ |
1196 | 0 | if (name[0] == '$') |
1197 | 0 | return false; |
1198 | 0 | return true; |
1199 | 0 | } |
1200 | | |
1201 | | static void |
1202 | | nds32_add_opcode_hash_table (unsigned indx) |
1203 | 2 | { |
1204 | 2 | opcode_t *opc; |
1205 | | |
1206 | 2 | opc = nds32_opcode_table[indx]; |
1207 | 2 | if (opc == NULL) |
1208 | 0 | return; |
1209 | | |
1210 | 1.49k | while (opc->opcode != NULL) |
1211 | 1.49k | { |
1212 | 1.49k | opcode_t **slot; |
1213 | | |
1214 | 1.49k | slot = (opcode_t **) htab_find_slot |
1215 | 1.49k | (opcode_htab, &opc->value, INSERT); |
1216 | 1.49k | if (*slot == NULL) |
1217 | 1.27k | { |
1218 | | /* This is the new one. */ |
1219 | 1.27k | *slot = opc; |
1220 | 1.27k | } |
1221 | 218 | else |
1222 | 218 | { |
1223 | 218 | opcode_t *tmp; |
1224 | | |
1225 | | /* Already exists. Append to the list. */ |
1226 | 218 | tmp = *slot; |
1227 | 280 | while (tmp->next) |
1228 | 62 | tmp = tmp->next; |
1229 | 218 | tmp->next = opc; |
1230 | 218 | opc->next = NULL; |
1231 | 218 | } |
1232 | 1.49k | opc++; |
1233 | 1.49k | } |
1234 | 2 | } |
1235 | | |
1236 | | void |
1237 | | disassemble_init_nds32 (struct disassemble_info *info) |
1238 | 802 | { |
1239 | 802 | static unsigned init_done = 0; |
1240 | 802 | unsigned k; |
1241 | | |
1242 | | /* Set up symbol checking function. */ |
1243 | 802 | info->symbol_is_valid = nds32_symbol_is_valid; |
1244 | | |
1245 | | /* Only need to initialize once: |
1246 | | High level will call this function for every object file. |
1247 | | For example, when disassemble all members of a library. */ |
1248 | 802 | if (init_done) |
1249 | 800 | return; |
1250 | | |
1251 | | /* Setup main core. */ |
1252 | 2 | nds32_keyword_table[NDS32_MAIN_CORE] = &nds32_keywords[0]; |
1253 | 2 | nds32_opcode_table[NDS32_MAIN_CORE] = &nds32_opcodes[0]; |
1254 | 2 | nds32_field_table[NDS32_MAIN_CORE] = &nds32_operand_fields[0]; |
1255 | | |
1256 | | /* Build opcode table. */ |
1257 | 2 | opcode_htab = htab_create_alloc (1024, htab_hash_hash, htab_hash_eq, |
1258 | 2 | NULL, xcalloc, free); |
1259 | | |
1260 | 4 | for (k = 0; k < NDS32_CORE_COUNT; k++) |
1261 | 2 | { |
1262 | | /* Add op-codes. */ |
1263 | 2 | nds32_add_opcode_hash_table (k); |
1264 | 2 | } |
1265 | | |
1266 | 2 | init_done = 1; |
1267 | 2 | } |
1268 | | |
1269 | | static int |
1270 | | is_mapping_symbol (struct disassemble_info *info, int n, |
1271 | | enum map_type *map_type) |
1272 | 0 | { |
1273 | 0 | const char *name = NULL; |
1274 | | |
1275 | | /* Get symbol name. */ |
1276 | 0 | name = bfd_asymbol_name (info->symtab[n]); |
1277 | |
|
1278 | 0 | if (name[1] == 'c') |
1279 | 0 | { |
1280 | 0 | *map_type = MAP_CODE; |
1281 | 0 | return true; |
1282 | 0 | } |
1283 | 0 | else if (name[1] == 'd' && name[2] == '0') |
1284 | 0 | { |
1285 | 0 | *map_type = MAP_DATA0; |
1286 | 0 | return true; |
1287 | 0 | } |
1288 | 0 | else if (name[1] == 'd' && name[2] == '1') |
1289 | 0 | { |
1290 | 0 | *map_type = MAP_DATA1; |
1291 | 0 | return true; |
1292 | 0 | } |
1293 | 0 | else if (name[1] == 'd' && name[2] == '2') |
1294 | 0 | { |
1295 | 0 | *map_type = MAP_DATA2; |
1296 | 0 | return true; |
1297 | 0 | } |
1298 | 0 | else if (name[1] == 'd' && name[2] == '3') |
1299 | 0 | { |
1300 | 0 | *map_type = MAP_DATA3; |
1301 | 0 | return true; |
1302 | 0 | } |
1303 | 0 | else if (name[1] == 'd' && name[2] == '4') |
1304 | 0 | { |
1305 | 0 | *map_type = MAP_DATA4; |
1306 | 0 | return true; |
1307 | 0 | } |
1308 | | |
1309 | 0 | return false; |
1310 | 0 | } |
1311 | | |
1312 | | static int |
1313 | | get_mapping_symbol_type (struct disassemble_info *info, int n, |
1314 | | enum map_type *map_type) |
1315 | 0 | { |
1316 | | /* If the symbol is in a different section, ignore it. */ |
1317 | 0 | if (info->section != NULL |
1318 | 0 | && info->section != info->symtab[n]->section) |
1319 | 0 | return false; |
1320 | | |
1321 | 0 | return is_mapping_symbol (info, n, map_type); |
1322 | 0 | } |