/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-2024 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 | 507k | #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 | 165k | #define UNKNOWN_INSN_MSG _("*unknown*") |
65 | 3.23M | #define NDS32_PARSE_INSN16 0x01 |
66 | 564k | #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 | 848k | { |
84 | 848k | if (!reg) |
85 | 0 | return NULL; |
86 | | |
87 | 8.15M | while (reg->name != NULL && reg->value != value) |
88 | 7.30M | { |
89 | 7.30M | reg++; |
90 | 7.30M | } |
91 | 848k | if (reg->name == NULL) |
92 | 3.22k | return NULL; |
93 | 845k | return reg; |
94 | 848k | } |
95 | | |
96 | | static void |
97 | | nds32_parse_audio_ext (const field_t *pfd, |
98 | | disassemble_info *info, uint32_t insn) |
99 | 48.4k | { |
100 | 48.4k | fprintf_ftype func = info->fprintf_func; |
101 | 48.4k | void *stream = info->stream; |
102 | 48.4k | const keyword_t *psys_reg; |
103 | 48.4k | int int_value, new_value; |
104 | | |
105 | 48.4k | if (pfd->hw_res == HW_INT || pfd->hw_res == HW_UINT) |
106 | 386 | { |
107 | 386 | if (pfd->hw_res == HW_INT) |
108 | 0 | int_value = (unsigned) N32_IMMS (insn >> pfd->bitpos, |
109 | 0 | pfd->bitsize) << pfd->shift; |
110 | 386 | else |
111 | 386 | int_value = __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift; |
112 | | |
113 | 386 | if (int_value < 10) |
114 | 31 | func (stream, "#%d", int_value); |
115 | 355 | else |
116 | 355 | func (stream, "#0x%x", int_value); |
117 | 386 | return; |
118 | 386 | } |
119 | 48.0k | int_value = |
120 | 48.0k | __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift; |
121 | 48.0k | new_value = int_value; |
122 | 48.0k | psys_reg = (keyword_t*) nds32_keywords[pfd->hw_res]; |
123 | | |
124 | | /* p = bit[4].bit[1:0], r = bit[4].bit[3:2]. */ |
125 | 48.0k | if (strcmp (pfd->name, "im5_i") == 0) |
126 | 2.17k | { |
127 | 2.17k | new_value = int_value & 0x03; |
128 | 2.17k | new_value |= ((int_value & 0x10) >> 2); |
129 | 2.17k | } |
130 | 45.8k | else if (strcmp (pfd->name, "im5_m") == 0) |
131 | 2.17k | { |
132 | 2.17k | new_value = ((int_value & 0x1C) >> 2); |
133 | 2.17k | } |
134 | | /* p = 0.bit[1:0], r = 0.bit[3:2]. */ |
135 | | /* q = 1.bit[1:0], s = 1.bit[5:4]. */ |
136 | 43.7k | else if (strcmp (pfd->name, "im6_iq") == 0) |
137 | 3.96k | { |
138 | 3.96k | new_value |= 0x04; |
139 | 3.96k | } |
140 | 39.7k | else if (strcmp (pfd->name, "im6_ms") == 0) |
141 | 3.96k | { |
142 | 3.96k | new_value |= 0x04; |
143 | 3.96k | } |
144 | | /* Rt CONCAT(c, t21, t0). */ |
145 | 35.7k | else if (strcmp (pfd->name, "a_rt21") == 0) |
146 | 708 | { |
147 | 708 | new_value = (insn & 0x00000020) >> 5; |
148 | 708 | new_value |= (insn & 0x00000C00) >> 9; |
149 | 708 | new_value |= (insn & 0x00008000) >> 12; |
150 | 708 | } |
151 | 35.0k | else if (strcmp (pfd->name, "a_rte") == 0) |
152 | 2.59k | { |
153 | 2.59k | new_value = (insn & 0x00000C00) >> 9; |
154 | 2.59k | new_value |= (insn & 0x00008000) >> 12; |
155 | 2.59k | } |
156 | 32.4k | else if (strcmp (pfd->name, "a_rte1") == 0) |
157 | 2.59k | { |
158 | 2.59k | new_value = (insn & 0x00000C00) >> 9; |
159 | 2.59k | new_value |= (insn & 0x00008000) >> 12; |
160 | 2.59k | new_value |= 0x01; |
161 | 2.59k | } |
162 | 29.9k | else if (strcmp (pfd->name, "a_rte69") == 0) |
163 | 162 | { |
164 | 162 | new_value = int_value << 1; |
165 | 162 | } |
166 | 29.7k | else if (strcmp (pfd->name, "a_rte69_1") == 0) |
167 | 162 | { |
168 | 162 | new_value = int_value << 1; |
169 | 162 | new_value |= 0x01; |
170 | 162 | } |
171 | | |
172 | 48.0k | psys_reg = nds32_find_reg_keyword (psys_reg, new_value); |
173 | 48.0k | if (!psys_reg) |
174 | 61 | func (stream, "???"); |
175 | 48.0k | else |
176 | 48.0k | func (stream, "$%s", psys_reg->name); |
177 | 48.0k | } |
178 | | |
179 | | /* Match instruction opcode with keyword table. */ |
180 | | |
181 | | static field_t * |
182 | | match_field (char *name) |
183 | 2.05M | { |
184 | 2.05M | field_t *pfd; |
185 | 2.05M | int k; |
186 | | |
187 | 2.05M | for (k = 0; k < NDS32_CORE_COUNT; k++) |
188 | 2.05M | { |
189 | 2.05M | pfd = (field_t *) nds32_field_table[k]; |
190 | 68.6M | while (1) |
191 | 68.6M | { |
192 | 68.6M | if (pfd->name == NULL) |
193 | 0 | break; |
194 | 68.6M | if (strcmp (name, pfd->name) == 0) |
195 | 2.05M | return pfd; |
196 | 66.5M | pfd++; |
197 | 66.5M | } |
198 | 2.05M | } |
199 | | |
200 | 0 | return NULL; |
201 | 2.05M | } |
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 | 956k | { |
210 | 956k | int op = 0; |
211 | 956k | fprintf_ftype func = info->fprintf_func; |
212 | 956k | void *stream = info->stream; |
213 | 956k | const char *pstr_src; |
214 | 956k | char *pstr_tmp; |
215 | 956k | char tmp_string[16]; |
216 | 956k | unsigned int push25gpr = 0, lsmwRb, lsmwRe, lsmwEnb4, checkbit, i; |
217 | 956k | int int_value, ifthe1st = 1; |
218 | 956k | const field_t *pfd; |
219 | 956k | const keyword_t *psys_reg; |
220 | | |
221 | 956k | if (opc == NULL) |
222 | 165k | { |
223 | 165k | func (stream, UNKNOWN_INSN_MSG); |
224 | 165k | return; |
225 | 165k | } |
226 | | |
227 | 791k | pstr_src = opc->instruction; |
228 | 791k | if (*pstr_src == 0) |
229 | 94 | { |
230 | 94 | func (stream, "%s", opc->opcode); |
231 | 94 | return; |
232 | 94 | } |
233 | | /* NDS32_PARSE_INSN16. */ |
234 | 791k | if (parse_mode & NDS32_PARSE_INSN16) |
235 | 375k | { |
236 | 375k | func (stream, "%s ", opc->opcode); |
237 | 375k | } |
238 | | |
239 | | /* NDS32_PARSE_INSN32. */ |
240 | 415k | else |
241 | 415k | { |
242 | 415k | op = N32_OP6 (insn); |
243 | 415k | if (op == N32_OP6_LSMW) |
244 | 4.05k | func (stream, "%s.", opc->opcode); |
245 | 411k | else if (strstr (opc->instruction, "tito")) |
246 | 124 | func (stream, "%s", opc->opcode); |
247 | 411k | else |
248 | 411k | func (stream, "%s\t", opc->opcode); |
249 | 415k | } |
250 | | |
251 | 5.68M | while (*pstr_src) |
252 | 4.89M | { |
253 | 4.89M | switch (*pstr_src) |
254 | 4.89M | { |
255 | 1.51M | case '%': |
256 | 2.05M | case '=': |
257 | 2.05M | case '&': |
258 | 2.05M | pstr_src++; |
259 | | /* Compare with nds32_operand_fields[].name. */ |
260 | 2.05M | pstr_tmp = &tmp_string[0]; |
261 | 8.41M | while (*pstr_src) |
262 | 7.97M | { |
263 | 7.97M | if ((*pstr_src == ',') || (*pstr_src == ' ') |
264 | 7.97M | || (*pstr_src == '{') || (*pstr_src == '}') |
265 | 7.97M | || (*pstr_src == '[') || (*pstr_src == ']') |
266 | 7.97M | || (*pstr_src == '(') || (*pstr_src == ')') |
267 | 7.97M | || (*pstr_src == '+') || (*pstr_src == '<')) |
268 | 1.61M | break; |
269 | 6.36M | *pstr_tmp++ = *pstr_src++; |
270 | 6.36M | } |
271 | 2.05M | *pstr_tmp = 0; |
272 | | |
273 | 2.05M | if ((pfd = match_field (&tmp_string[0])) == NULL) |
274 | 0 | return; |
275 | | |
276 | | /* For insn-16. */ |
277 | 2.05M | if (parse_mode & NDS32_PARSE_INSN16) |
278 | 797k | { |
279 | 797k | if (pfd->hw_res == HW_GPR) |
280 | 544k | { |
281 | 544k | int_value = |
282 | 544k | __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift; |
283 | | /* push25/pop25. */ |
284 | 544k | if ((opc->value == 0xfc00) || (opc->value == 0xfc80)) |
285 | 5.02k | { |
286 | 5.02k | if (int_value == 0) |
287 | 1.06k | int_value = 6; |
288 | 3.96k | else |
289 | 3.96k | int_value = (6 + (0x01 << int_value)); |
290 | 5.02k | push25gpr = int_value; |
291 | 5.02k | } |
292 | 539k | else if (strcmp (pfd->name, "rt4") == 0) |
293 | 73.1k | { |
294 | 73.1k | int_value = nds32_r45map[int_value]; |
295 | 73.1k | } |
296 | 544k | func (stream, "$%s", nds32_keyword_gpr[int_value].name); |
297 | 544k | } |
298 | 253k | else if ((pfd->hw_res == HW_INT) || (pfd->hw_res == HW_UINT)) |
299 | 253k | { |
300 | 253k | if (pfd->hw_res == HW_INT) |
301 | 95.5k | int_value |
302 | 95.5k | = (unsigned) N32_IMMS (insn >> pfd->bitpos, |
303 | 95.5k | pfd->bitsize) << pfd->shift; |
304 | 157k | else |
305 | 157k | int_value = |
306 | 157k | __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift; |
307 | | |
308 | | /* movpi45. */ |
309 | 253k | if (opc->value == 0xfa00) |
310 | 5.59k | { |
311 | 5.59k | int_value += 16; |
312 | 5.59k | func (stream, "#0x%x", int_value); |
313 | 5.59k | } |
314 | | /* lwi45.fe. */ |
315 | 247k | else if (opc->value == 0xb200) |
316 | 3.90k | { |
317 | 3.90k | int_value = 0 - (128 - int_value); |
318 | 3.90k | func (stream, "#%d", int_value); |
319 | 3.90k | } |
320 | | /* beqz38/bnez38/beqs38/bnes38/j8/beqzs8/bnezs8. */ |
321 | 243k | else if ((opc->value == 0xc000) || (opc->value == 0xc800) |
322 | 243k | || (opc->value == 0xd000) || (opc->value == 0xd800) |
323 | 243k | || (opc->value == 0xd500) || (opc->value == 0xe800) |
324 | 243k | || (opc->value == 0xe900)) |
325 | 75.8k | { |
326 | 75.8k | info->print_address_func (int_value + pc, info); |
327 | 75.8k | } |
328 | | /* push25/pop25. */ |
329 | 167k | else if ((opc->value == 0xfc00) || (opc->value == 0xfc80)) |
330 | 5.02k | { |
331 | 5.02k | func (stream, "#%d ! {$r6", int_value); |
332 | 5.02k | if (push25gpr != 6) |
333 | 3.96k | func (stream, "~$%s", nds32_keyword_gpr[push25gpr].name); |
334 | 5.02k | func (stream, ", $fp, $gp, $lp}"); |
335 | 5.02k | } |
336 | 162k | else if (pfd->hw_res == HW_INT) |
337 | 19.7k | { |
338 | 19.7k | if (int_value < 10) |
339 | 13.8k | func (stream, "#%d", int_value); |
340 | 5.91k | else |
341 | 5.91k | func (stream, "#0x%x", int_value); |
342 | 19.7k | } |
343 | 142k | else /* if (pfd->hw_res == HW_UINT). */ |
344 | 142k | { |
345 | 142k | if (int_value < 10) |
346 | 60.7k | func (stream, "#%u", int_value); |
347 | 82.2k | else |
348 | 82.2k | func (stream, "#0x%x", int_value); |
349 | 142k | } |
350 | 253k | } |
351 | | |
352 | 797k | } |
353 | | /* for audio-ext. */ |
354 | 1.25M | else if (op == N32_OP6_AEXT) |
355 | 48.4k | { |
356 | 48.4k | nds32_parse_audio_ext (pfd, info, insn); |
357 | 48.4k | } |
358 | | /* for insn-32. */ |
359 | 1.20M | else if (pfd->hw_res < HW_INT) |
360 | 800k | { |
361 | 800k | int_value = |
362 | 800k | __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift; |
363 | | |
364 | 800k | psys_reg = *(nds32_keyword_table[pfd->hw_res >> 8] |
365 | 800k | + (pfd->hw_res & 0xff)); |
366 | | |
367 | 800k | 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 | 800k | if (!psys_reg && pfd->hw_res == HW_SR) |
371 | 485 | func (stream, "%d", int_value); |
372 | 800k | else if (!psys_reg) |
373 | 2.68k | func (stream, "???"); |
374 | 797k | else |
375 | 797k | { |
376 | 797k | if (pfd->hw_res == HW_GPR || pfd->hw_res == HW_CPR |
377 | 797k | || pfd->hw_res == HW_FDR || pfd->hw_res == HW_FSR |
378 | 797k | || pfd->hw_res == HW_DXR || pfd->hw_res == HW_SR |
379 | 797k | || pfd->hw_res == HW_USR) |
380 | 768k | func (stream, "$%s", psys_reg->name); |
381 | 28.5k | else if (pfd->hw_res == HW_DTITON |
382 | 28.5k | || pfd->hw_res == HW_DTITOFF) |
383 | 124 | func (stream, ".%s", psys_reg->name); |
384 | 28.4k | else |
385 | 28.4k | func (stream, "%s", psys_reg->name); |
386 | 797k | } |
387 | 800k | } |
388 | 407k | else if ((pfd->hw_res == HW_INT) || (pfd->hw_res == HW_UINT)) |
389 | 407k | { |
390 | 407k | if (pfd->hw_res == HW_INT) |
391 | 369k | int_value = (unsigned) N32_IMMS (insn >> pfd->bitpos, |
392 | 369k | pfd->bitsize) << pfd->shift; |
393 | 37.7k | else |
394 | 37.7k | int_value = |
395 | 37.7k | __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift; |
396 | | |
397 | 407k | if ((op == N32_OP6_BR1) || (op == N32_OP6_BR2)) |
398 | 7.72k | { |
399 | 7.72k | info->print_address_func (int_value + pc, info); |
400 | 7.72k | } |
401 | 399k | else if ((op == N32_OP6_BR3) && (pfd->bitpos == 0)) |
402 | 4.81k | { |
403 | 4.81k | info->print_address_func (int_value + pc, info); |
404 | 4.81k | } |
405 | 394k | else if (op == N32_OP6_JI) |
406 | 6.82k | { |
407 | | /* FIXME: Handle relocation. */ |
408 | 6.82k | if (info->flags & INSN_HAS_RELOC) |
409 | 0 | pc = 0; |
410 | 6.82k | info->print_address_func (int_value + pc, info); |
411 | 6.82k | } |
412 | 387k | else if (op == N32_OP6_LSMW) |
413 | 4.05k | { |
414 | | /* lmw.adm/smw.adm. */ |
415 | 4.05k | func (stream, "#0x%x ! {", int_value); |
416 | 4.05k | lsmwEnb4 = int_value; |
417 | 4.05k | lsmwRb = ((insn >> 20) & 0x1F); |
418 | 4.05k | 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 | 4.05k | if (lsmwRb != 31 || lsmwRe != 31) |
425 | 4.03k | { |
426 | 4.03k | func (stream, "$%s", nds32_keyword_gpr[lsmwRb].name); |
427 | 4.03k | if (lsmwRb != lsmwRe) |
428 | 3.85k | func (stream, "~$%s", nds32_keyword_gpr[lsmwRe].name); |
429 | 4.03k | ifthe1st = 0; |
430 | 4.03k | } |
431 | 4.05k | if (lsmwEnb4 != 0) |
432 | 3.47k | { |
433 | | /* $fp, $gp, $lp, $sp. */ |
434 | 3.47k | checkbit = 0x08; |
435 | 17.3k | for (i = 0; i < 4; i++) |
436 | 13.9k | { |
437 | 13.9k | if (lsmwEnb4 & checkbit) |
438 | 7.05k | { |
439 | 7.05k | if (ifthe1st == 1) |
440 | 20 | { |
441 | 20 | ifthe1st = 0; |
442 | 20 | func (stream, "$%s", nds32_keyword_gpr[28 + i].name); |
443 | 20 | } |
444 | 7.03k | else |
445 | 7.03k | func (stream, ", $%s", nds32_keyword_gpr[28 + i].name); |
446 | 7.05k | } |
447 | 13.9k | checkbit >>= 1; |
448 | 13.9k | } |
449 | 3.47k | } |
450 | 4.05k | func (stream, "}"); |
451 | 4.05k | } |
452 | 383k | else if (pfd->hw_res == HW_INT) |
453 | 350k | { |
454 | 350k | if (int_value < 10) |
455 | 182k | func (stream, "#%d", int_value); |
456 | 167k | else |
457 | 167k | func (stream, "#0x%x", int_value); |
458 | 350k | } |
459 | 33.6k | else /* if (pfd->hw_res == HW_UINT). */ |
460 | 33.6k | { |
461 | 33.6k | if (int_value < 10) |
462 | 4.27k | func (stream, "#%u", int_value); |
463 | 29.4k | else |
464 | 29.4k | func (stream, "#0x%x", int_value); |
465 | 33.6k | } |
466 | 407k | } |
467 | 2.05M | break; |
468 | | |
469 | 298k | case '{': |
470 | 597k | case '}': |
471 | 597k | pstr_src++; |
472 | 597k | break; |
473 | | |
474 | 981k | case ',': |
475 | 981k | func (stream, ", "); |
476 | 981k | pstr_src++; |
477 | 981k | break; |
478 | | |
479 | 333k | case '+': |
480 | 333k | func (stream, " + "); |
481 | 333k | pstr_src++; |
482 | 333k | break; |
483 | | |
484 | 1.68k | case '<': |
485 | 1.68k | if (pstr_src[1] == '<') |
486 | 1.68k | { |
487 | 1.68k | func (stream, " << "); |
488 | 1.68k | pstr_src += 2; |
489 | 1.68k | } |
490 | 0 | else |
491 | 0 | { |
492 | 0 | func (stream, " <"); |
493 | 0 | pstr_src++; |
494 | 0 | } |
495 | 1.68k | break; |
496 | | |
497 | 922k | default: |
498 | 922k | func (stream, "%c", *pstr_src++); |
499 | 922k | break; |
500 | 4.89M | } |
501 | 4.89M | } |
502 | 791k | } |
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 | 564k | { |
509 | 564k | if (!(*opc)) |
510 | 143k | return; |
511 | | |
512 | 421k | switch ((*opc)->value) |
513 | 421k | { |
514 | 255 | case JREG (JR): |
515 | 303 | case JREG (JRNEZ): |
516 | | /* jr jr.xtoff */ |
517 | 303 | if (__GF (insn, 6, 2) != 0 || __GF (insn, 15, 10) != 0) |
518 | 276 | *opc = NULL; |
519 | 303 | break; |
520 | 887 | case MISC (STANDBY): |
521 | 887 | if (__GF (insn, 7, 18) != 0) |
522 | 807 | *opc = NULL; |
523 | 887 | break; |
524 | 864 | case SIMD (PBSAD): |
525 | 1.14k | case SIMD (PBSADA): |
526 | 1.14k | if (__GF (insn, 5, 5) != 0) |
527 | 458 | *opc = NULL; |
528 | 1.14k | break; |
529 | 0 | case BR2 (SOP0): |
530 | 0 | if (__GF (insn, 20, 5) != 0) |
531 | 0 | *opc = NULL; |
532 | 0 | break; |
533 | 186 | case JREG (JRAL): |
534 | 186 | if (__GF (insn, 5, 3) != 0 || __GF (insn, 15, 5) != 0) |
535 | 160 | *opc = NULL; |
536 | 186 | break; |
537 | 220 | case ALU1 (NOR): |
538 | 346 | case ALU1 (SLT): |
539 | 567 | case ALU1 (SLTS): |
540 | 744 | case ALU1 (SLLI): |
541 | 856 | case ALU1 (SRLI): |
542 | 998 | case ALU1 (SRAI): |
543 | 1.14k | case ALU1 (ROTRI): |
544 | 1.29k | case ALU1 (SLL): |
545 | 1.43k | case ALU1 (SRL): |
546 | 1.69k | case ALU1 (SRA): |
547 | 1.81k | case ALU1 (ROTR): |
548 | 2.06k | case ALU1 (SEB): |
549 | 2.30k | case ALU1 (SEH): |
550 | 2.46k | case ALU1 (ZEH): |
551 | 2.53k | case ALU1 (WSBH): |
552 | 2.72k | case ALU1 (SVA): |
553 | 2.96k | case ALU1 (SVS): |
554 | 3.16k | case ALU1 (CMOVZ): |
555 | 3.30k | case ALU1 (CMOVN): |
556 | 3.30k | if (__GF (insn, 5, 5) != 0) |
557 | 3.15k | *opc = NULL; |
558 | 3.30k | break; |
559 | 452 | case MISC (IRET): |
560 | 633 | case MISC (ISB): |
561 | 786 | case MISC (DSB): |
562 | 786 | if (__GF (insn, 5, 20) != 0) |
563 | 778 | *opc = NULL; |
564 | 786 | break; |
565 | 421k | } |
566 | 421k | } |
567 | | |
568 | | static void |
569 | | print_insn32 (bfd_vma pc, disassemble_info *info, uint32_t insn, |
570 | | uint32_t parse_mode) |
571 | 564k | { |
572 | | /* Get the final correct opcode and parse. */ |
573 | 564k | struct nds32_opcode *opc; |
574 | 564k | uint32_t opcode = nds32_mask_opcode (insn); |
575 | 564k | opc = (struct nds32_opcode *) htab_find (opcode_htab, &opcode); |
576 | | |
577 | 564k | nds32_special_opcode (insn, &opc); |
578 | 564k | nds32_filter_unknown_insn (insn, &opc); |
579 | 564k | nds32_parse_opcode (opc, pc, info, insn, parse_mode); |
580 | 564k | } |
581 | | |
582 | | static void |
583 | | print_insn16 (bfd_vma pc, disassemble_info *info, |
584 | | uint32_t insn, uint32_t parse_mode) |
585 | 392k | { |
586 | 392k | struct nds32_opcode *opc; |
587 | 392k | uint32_t opcode; |
588 | | |
589 | | /* Get highest 7 bit in default. */ |
590 | 392k | unsigned int mask = 0xfe00; |
591 | | |
592 | | /* Classify 16-bit instruction to 4 sets by bit 13 and 14. */ |
593 | 392k | switch (__GF (insn, 13, 2)) |
594 | 392k | { |
595 | 85.7k | case 0x0: |
596 | | /* mov55 movi55 */ |
597 | 85.7k | if (__GF (insn, 11, 2) == 0) |
598 | 22.1k | { |
599 | 22.1k | mask = 0xfc00; |
600 | | /* ifret16 = mov55 $sp, $sp*/ |
601 | 22.1k | if (__GF (insn, 0, 11) == 0x3ff) |
602 | 74 | mask = 0xffff; |
603 | 22.1k | } |
604 | 63.5k | else if (__GF (insn, 9, 4) == 0xb) |
605 | 4.86k | mask = 0xfe07; |
606 | 85.7k | break; |
607 | 83.1k | case 0x1: |
608 | | /* lwi37 swi37 */ |
609 | 83.1k | if (__GF (insn, 11, 2) == 0x3) |
610 | 19.4k | mask = 0xf880; |
611 | 83.1k | break; |
612 | 73.6k | case 0x2: |
613 | 73.6k | mask = 0xf800; |
614 | | /* Exclude beqz38, bnez38, beqs38, and bnes38. */ |
615 | 73.6k | if (__GF (insn, 12, 1) == 0x1 |
616 | 73.6k | && __GF (insn, 8, 3) == 0x5) |
617 | 4.49k | { |
618 | 4.49k | if (__GF (insn, 11, 1) == 0x0) |
619 | 2.02k | mask = 0xff00; |
620 | 2.47k | else |
621 | 2.47k | mask = 0xffe0; |
622 | 4.49k | } |
623 | 73.6k | break; |
624 | 149k | case 0x3: |
625 | 149k | switch (__GF (insn, 11, 2)) |
626 | 149k | { |
627 | 19.9k | case 0x1: |
628 | | /* beqzs8 bnezs8 */ |
629 | 19.9k | if (__GF (insn, 9, 2) == 0x0) |
630 | 4.69k | mask = 0xff00; |
631 | | /* addi10s */ |
632 | 15.2k | else if (__GF(insn, 10, 1) == 0x1) |
633 | 10.0k | mask = 0xfc00; |
634 | 19.9k | break; |
635 | 22.3k | case 0x2: |
636 | | /* lwi37.sp swi37.sp */ |
637 | 22.3k | mask = 0xf880; |
638 | 22.3k | break; |
639 | 87.8k | case 0x3: |
640 | 87.8k | if (__GF (insn, 8, 3) == 0x5) |
641 | 3.35k | mask = 0xff00; |
642 | 84.5k | else if (__GF (insn, 8, 3) == 0x4) |
643 | 5.02k | mask = 0xff80; |
644 | 79.4k | else if (__GF (insn, 9 , 2) == 0x3) |
645 | 67.2k | mask = 0xfe07; |
646 | 87.8k | break; |
647 | 149k | } |
648 | 149k | break; |
649 | 392k | } |
650 | 392k | opcode = insn & mask; |
651 | 392k | opc = (struct nds32_opcode *) htab_find (opcode_htab, &opcode); |
652 | | |
653 | 392k | nds32_special_opcode (insn, &opc); |
654 | | /* Get the final correct opcode and parse it. */ |
655 | 392k | nds32_parse_opcode (opc, pc, info, insn, parse_mode); |
656 | 392k | } |
657 | | |
658 | | static hashval_t |
659 | | htab_hash_hash (const void *p) |
660 | 958k | { |
661 | 958k | return (*(unsigned int *) p) % 49; |
662 | 958k | } |
663 | | |
664 | | static int |
665 | | htab_hash_eq (const void *p, const void *q) |
666 | 15.9M | { |
667 | 15.9M | uint32_t pinsn = ((struct nds32_opcode *) p)->value; |
668 | 15.9M | uint32_t qinsn = *((uint32_t *) q); |
669 | | |
670 | 15.9M | return (pinsn == qinsn); |
671 | 15.9M | } |
672 | | |
673 | | /* Get the format of instruction. */ |
674 | | |
675 | | static uint32_t |
676 | | nds32_mask_opcode (uint32_t insn) |
677 | 564k | { |
678 | 564k | uint32_t opcode = N32_OP6 (insn); |
679 | 564k | switch (opcode) |
680 | 564k | { |
681 | 169k | case N32_OP6_LBI: |
682 | 184k | case N32_OP6_LHI: |
683 | 195k | case N32_OP6_LWI: |
684 | 202k | case N32_OP6_LDI: |
685 | 212k | case N32_OP6_LBI_BI: |
686 | 219k | case N32_OP6_LHI_BI: |
687 | 224k | case N32_OP6_LWI_BI: |
688 | 230k | case N32_OP6_LDI_BI: |
689 | 240k | case N32_OP6_SBI: |
690 | 245k | case N32_OP6_SHI: |
691 | 250k | case N32_OP6_SWI: |
692 | 255k | case N32_OP6_SDI: |
693 | 260k | case N32_OP6_SBI_BI: |
694 | 264k | case N32_OP6_SHI_BI: |
695 | 268k | case N32_OP6_SWI_BI: |
696 | 273k | case N32_OP6_SDI_BI: |
697 | 281k | case N32_OP6_LBSI: |
698 | 285k | case N32_OP6_LHSI: |
699 | 292k | case N32_OP6_LWSI: |
700 | 296k | case N32_OP6_LBSI_BI: |
701 | 301k | case N32_OP6_LHSI_BI: |
702 | 305k | case N32_OP6_LWSI_BI: |
703 | 312k | case N32_OP6_MOVI: |
704 | 318k | case N32_OP6_SETHI: |
705 | 321k | case N32_OP6_ADDI: |
706 | 327k | case N32_OP6_SUBRI: |
707 | 331k | case N32_OP6_ANDI: |
708 | 336k | case N32_OP6_XORI: |
709 | 340k | case N32_OP6_ORI: |
710 | 344k | case N32_OP6_SLTI: |
711 | 349k | case N32_OP6_SLTSI: |
712 | 355k | case N32_OP6_CEXT: |
713 | 361k | case N32_OP6_BITCI: |
714 | 361k | return MASK_OP (insn, 0); |
715 | 9.57k | case N32_OP6_ALU2: |
716 | | /* FFBI */ |
717 | 9.57k | if (__GF (insn, 0, 7) == (N32_ALU2_FFBI | N32_BIT (6))) |
718 | 38 | return MASK_OP (insn, 0x7f); |
719 | 9.53k | else if (__GF (insn, 0, 7) == (N32_ALU2_MFUSR | N32_BIT (6)) |
720 | 9.53k | || __GF (insn, 0, 7) == (N32_ALU2_MTUSR | N32_BIT (6))) |
721 | | /* RDOV CLROV */ |
722 | 194 | return MASK_OP (insn, 0xf81ff); |
723 | 9.33k | else if (__GF (insn, 0, 10) == (N32_ALU2_ONEOP | N32_BIT (7))) |
724 | 10 | { |
725 | | /* INSB */ |
726 | 10 | if (__GF (insn, 12, 3) == 4) |
727 | 7 | return MASK_OP (insn, 0x73ff); |
728 | 3 | return MASK_OP (insn, 0x7fff); |
729 | 10 | } |
730 | 9.32k | return MASK_OP (insn, 0x3ff); |
731 | 9.63k | case N32_OP6_ALU1: |
732 | 15.9k | case N32_OP6_SIMD: |
733 | 15.9k | return MASK_OP (insn, 0x1f); |
734 | 9.49k | case N32_OP6_MEM: |
735 | 9.49k | return MASK_OP (insn, 0xff); |
736 | 5.64k | case N32_OP6_JREG: |
737 | 5.64k | return MASK_OP (insn, 0x7f); |
738 | 5.38k | case N32_OP6_LSMW: |
739 | 5.38k | return MASK_OP (insn, 0x23); |
740 | 5.73k | case N32_OP6_SBGP: |
741 | 12.0k | case N32_OP6_LBGP: |
742 | 12.0k | return MASK_OP (insn, 0x1 << 19); |
743 | 7.23k | case N32_OP6_HWGP: |
744 | 7.23k | if (__GF (insn, 18, 2) == 0x3) |
745 | 2.81k | return MASK_OP (insn, 0x7 << 17); |
746 | 4.42k | return MASK_OP (insn, 0x3 << 18); |
747 | 4.66k | case N32_OP6_DPREFI: |
748 | 4.66k | return MASK_OP (insn, 0x1 << 24); |
749 | 8.54k | case N32_OP6_LWC: |
750 | 15.0k | case N32_OP6_SWC: |
751 | 21.0k | case N32_OP6_LDC: |
752 | 26.3k | case N32_OP6_SDC: |
753 | 26.3k | return MASK_OP (insn, 0x1 << 12); |
754 | 6.82k | case N32_OP6_JI: |
755 | 6.82k | return MASK_OP (insn, 0x1 << 24); |
756 | 5.66k | case N32_OP6_BR1: |
757 | 5.66k | return MASK_OP (insn, 0x1 << 14); |
758 | 5.80k | case N32_OP6_BR2: |
759 | 5.80k | if (__GF (insn, 16, 4) == 0) |
760 | 509 | return MASK_OP (insn, 0x1ff << 16); |
761 | 5.29k | else |
762 | 5.29k | return MASK_OP (insn, 0xf << 16); |
763 | 4.81k | case N32_OP6_BR3: |
764 | 4.81k | return MASK_OP (insn, 0x1 << 19); |
765 | 8.57k | case N32_OP6_MISC: |
766 | 8.57k | switch (__GF (insn, 0, 5)) |
767 | 8.57k | { |
768 | 516 | case N32_MISC_MTSR: |
769 | | /* SETGIE and SETEND */ |
770 | 516 | if (__GF (insn, 5, 5) == 0x1 || __GF (insn, 5, 5) == 0x2) |
771 | 97 | return MASK_OP (insn, 0x1fffff); |
772 | 419 | return MASK_OP (insn, 0x1f); |
773 | 189 | case N32_MISC_TLBOP: |
774 | 189 | if (__GF (insn, 5, 5) == 5 || __GF (insn, 5, 5) == 7) |
775 | | /* PB FLUA */ |
776 | 1 | return MASK_OP (insn, 0x3ff); |
777 | 188 | return MASK_OP (insn, 0x1f); |
778 | 7.87k | default: |
779 | 7.87k | return MASK_OP (insn, 0x1f); |
780 | 8.57k | } |
781 | 4.52k | case N32_OP6_COP: |
782 | 4.52k | if (__GF (insn, 4, 2) == 0) |
783 | 1.41k | { |
784 | | /* FPU */ |
785 | 1.41k | switch (__GF (insn, 0, 4)) |
786 | 1.41k | { |
787 | 399 | case 0x0: |
788 | 565 | case 0x8: |
789 | | /* FS1/F2OP FD1/F2OP */ |
790 | 565 | if (__GF (insn, 6, 4) == 0xf) |
791 | 4 | return MASK_OP (insn, 0x7fff); |
792 | | /* FS1 FD1 */ |
793 | 561 | return MASK_OP (insn, 0x3ff); |
794 | 115 | case 0x4: |
795 | 131 | case 0xc: |
796 | | /* FS2 */ |
797 | 131 | return MASK_OP (insn, 0x3ff); |
798 | 112 | case 0x1: |
799 | 195 | case 0x9: |
800 | | /* XR */ |
801 | 195 | if (__GF (insn, 6, 4) == 0xc) |
802 | 6 | return MASK_OP (insn, 0x7fff); |
803 | | /* MFCP MTCP */ |
804 | 189 | return MASK_OP (insn, 0x3ff); |
805 | 528 | default: |
806 | 528 | return MASK_OP (insn, 0xff); |
807 | 1.41k | } |
808 | 1.41k | } |
809 | 3.10k | else if (__GF (insn, 0, 2) == 0) |
810 | 653 | return MASK_OP (insn, 0xf); |
811 | 2.45k | return MASK_OP (insn, 0xcf); |
812 | 13.8k | case N32_OP6_AEXT: |
813 | | /* AUDIO */ |
814 | 13.8k | switch (__GF (insn, 23, 2)) |
815 | 13.8k | { |
816 | 5.52k | case 0x0: |
817 | 5.52k | if (__GF (insn, 5, 4) == 0) |
818 | | /* AMxxx AMAyyS AMyyS AMAWzS AMWzS */ |
819 | 669 | return MASK_OP (insn, (0x1f << 20) | 0x1ff); |
820 | 4.85k | else if (__GF (insn, 5, 4) == 1) |
821 | | /* ALR ASR ALA ASA AUPI */ |
822 | 178 | return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); |
823 | 4.68k | else if (__GF (insn, 20, 3) == 0 && __GF (insn, 6, 3) == 1) |
824 | | /* ALR2 */ |
825 | 92 | return MASK_OP (insn, (0x1f << 20) | (0x7 << 6)); |
826 | 4.58k | else if (__GF (insn, 20 ,3) == 2 && __GF (insn, 6, 3) == 1) |
827 | | /* AWEXT ASATS48 */ |
828 | 186 | return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); |
829 | 4.40k | else if (__GF (insn, 20 ,3) == 3 && __GF (insn, 6, 3) == 1) |
830 | | /* AMTAR AMTAR2 AMFAR AMFAR2 */ |
831 | 259 | return MASK_OP (insn, (0x1f << 20) | (0x1f << 5)); |
832 | 4.14k | else if (__GF (insn, 7, 2) == 3) |
833 | | /* AMxxxSA */ |
834 | 457 | return MASK_OP (insn, (0x1f << 20) | (0x3 << 7)); |
835 | 3.68k | else if (__GF (insn, 6, 3) == 2) |
836 | | /* AMxxxL.S */ |
837 | 229 | return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); |
838 | 3.45k | else |
839 | | /* AmxxxL.l AmxxxL2.S AMxxxL2.L */ |
840 | 3.45k | return MASK_OP (insn, (0x1f << 20) | (0x7 << 6)); |
841 | 1.64k | case 0x1: |
842 | 1.64k | if (__GF (insn, 20, 3) == 0) |
843 | | /* AADDL ASUBL */ |
844 | 162 | return MASK_OP (insn, (0x1f << 20) | (0x1 << 5)); |
845 | 1.48k | else if (__GF (insn, 20, 3) == 1) |
846 | | /* AMTARI Ix AMTARI Mx */ |
847 | 200 | return MASK_OP (insn, (0x1f << 20)); |
848 | 1.28k | else if (__GF (insn, 6, 3) == 2) |
849 | | /* AMAWzSl.S AMWzSl.S */ |
850 | 135 | return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); |
851 | 1.15k | else if (__GF (insn, 7, 2) == 3) |
852 | | /* AMAWzSSA AMWzSSA */ |
853 | 326 | return MASK_OP (insn, (0x1f << 20) | (0x3 << 7)); |
854 | 826 | else |
855 | | /* AMAWzSL.L AMAWzSL2.S AMAWzSL2.L |
856 | | AMWzSL.L AMWzSL.L AMWzSL2.S */ |
857 | 826 | return MASK_OP (insn, (0x1f << 20) | (0x7 << 6)); |
858 | 5.09k | case 0x2: |
859 | 5.09k | if (__GF (insn, 6, 3) == 2) |
860 | | /* AMAyySl.S AMWyySl.S */ |
861 | 157 | return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); |
862 | 4.93k | else if (__GF (insn, 7, 2) == 3) |
863 | | /* AMAWyySSA AMWyySSA */ |
864 | 500 | return MASK_OP (insn, (0x1f << 20) | (0x3 << 7)); |
865 | 4.43k | else |
866 | | /* AMAWyySL.L AMAWyySL2.S AMAWyySL2.L |
867 | | AMWyySL.L AMWyySL.L AMWyySL2.S */ |
868 | 4.43k | return MASK_OP (insn, (0x1f << 20) | (0x7 << 6)); |
869 | 13.8k | } |
870 | 1.58k | return MASK_OP (insn, 0x1f << 20); |
871 | 56.7k | default: |
872 | 56.7k | return 1u << 31; |
873 | 564k | } |
874 | 564k | } |
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 | 956k | { |
892 | 956k | char *string = NULL; |
893 | 956k | uint32_t op; |
894 | | |
895 | 956k | if (!(*opc)) |
896 | 159k | return; |
897 | | |
898 | | /* Check if special case. */ |
899 | 797k | switch ((*opc)->value) |
900 | 797k | { |
901 | 3.97k | case OP6 (LWC): |
902 | 6.56k | case OP6 (SWC): |
903 | 8.94k | case OP6 (LDC): |
904 | 11.3k | case OP6 (SDC): |
905 | 15.9k | case FPU_RA_IMMBI (LWC): |
906 | 19.8k | case FPU_RA_IMMBI (SWC): |
907 | 23.4k | case FPU_RA_IMMBI (LDC): |
908 | 26.3k | case FPU_RA_IMMBI (SDC): |
909 | | /* Check if cp0 => FPU. */ |
910 | 26.3k | if (__GF (insn, 13, 2) == 0) |
911 | 6.34k | { |
912 | 12.6k | while (!((*opc)->attr & ATTR (FPU)) && (*opc)->next) |
913 | 6.34k | *opc = (*opc)->next; |
914 | 6.34k | } |
915 | 26.3k | break; |
916 | 2.22k | case ALU1 (ADD): |
917 | 4.10k | case ALU1 (SUB): |
918 | 4.35k | case ALU1 (AND): |
919 | 4.53k | case ALU1 (XOR): |
920 | 4.87k | case ALU1 (OR): |
921 | | /* Check if (add/add_slli) (sub/sub_slli) (and/and_slli). */ |
922 | 4.87k | if (N32_SH5(insn) != 0) |
923 | 3.93k | string = "sh"; |
924 | 4.87k | break; |
925 | 112 | case ALU1 (SRLI): |
926 | | /* Check if nop. */ |
927 | 112 | if (__GF (insn, 10, 15) == 0) |
928 | 1 | string = "nop"; |
929 | 112 | break; |
930 | 425 | case MISC (CCTL): |
931 | 425 | string = cctl_subtype [__GF (insn, 5, 5)]; |
932 | 425 | break; |
933 | 255 | case JREG (JR): |
934 | 441 | case JREG (JRAL): |
935 | 569 | case JREG (JR) | JREG_RET: |
936 | 569 | if (__GF (insn, 8, 2) != 0) |
937 | 387 | string = "tit"; |
938 | 569 | break; |
939 | 0 | case N32_OP6_COP: |
940 | 0 | break; |
941 | 4.42k | case 0x9200: |
942 | | /* nop16 */ |
943 | 4.42k | if (__GF (insn, 0, 9) == 0) |
944 | 85 | string = "nop16"; |
945 | 4.42k | break; |
946 | 797k | } |
947 | | |
948 | 797k | if (string) |
949 | 4.83k | { |
950 | 9.57k | while (strstr ((*opc)->opcode, string) == NULL |
951 | 9.57k | && strstr ((*opc)->instruction, string) == NULL && (*opc)->next) |
952 | 4.73k | *opc = (*opc)->next; |
953 | 4.83k | return; |
954 | 4.83k | } |
955 | | |
956 | | /* Classify instruction is COP or FPU. */ |
957 | 792k | op = N32_OP6 (insn); |
958 | 792k | if (op == N32_OP6_COP && __GF (insn, 4, 2) != 0) |
959 | 1.43k | { |
960 | 3.08k | while (((*opc)->attr & ATTR (FPU)) != 0 && (*opc)->next) |
961 | 1.65k | *opc = (*opc)->next; |
962 | 1.43k | } |
963 | 792k | } |
964 | | |
965 | | int |
966 | | print_insn_nds32 (bfd_vma pc, disassemble_info *info) |
967 | 957k | { |
968 | 957k | int status; |
969 | 957k | bfd_byte buf[4]; |
970 | 957k | bfd_byte buf_data[16]; |
971 | 957k | uint64_t given; |
972 | 957k | uint64_t given1; |
973 | 957k | uint32_t insn; |
974 | 957k | int n; |
975 | 957k | int last_symbol_index = -1; |
976 | 957k | bfd_vma addr; |
977 | 957k | int is_data = false; |
978 | 957k | bool found = false; |
979 | 957k | struct nds32_private_data *private_data; |
980 | 957k | unsigned int size; |
981 | 957k | enum map_type mapping_type = MAP_CODE; |
982 | | |
983 | 957k | if (info->private_data == NULL) |
984 | 530 | { |
985 | | /* Note: remain lifecycle throughout whole execution. */ |
986 | 530 | static struct nds32_private_data private; |
987 | 530 | private.has_mapping_symbols = -1; /* unknown yet. */ |
988 | 530 | private.last_symbol_index = -1; |
989 | 530 | private.last_addr = 0; |
990 | 530 | info->private_data = &private; |
991 | 530 | } |
992 | 957k | private_data = info->private_data; |
993 | | |
994 | 957k | 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 | 957k | 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 | 957k | size = 4; |
1150 | 957k | status = info->read_memory_func (pc, buf, 4, info); |
1151 | 957k | if (status) |
1152 | 625 | { |
1153 | | /* For the last 16-bit instruction. */ |
1154 | 625 | size = 2; |
1155 | 625 | status = info->read_memory_func (pc, buf, 2, info); |
1156 | 625 | if (status) |
1157 | 182 | { |
1158 | 182 | (*info->memory_error_func) (status, pc, info); |
1159 | 182 | return -1; |
1160 | 182 | } |
1161 | 443 | buf[2] = 0; |
1162 | 443 | buf[3] = 0; |
1163 | 443 | } |
1164 | | |
1165 | 957k | insn = bfd_getb32 (buf); |
1166 | | /* 16-bit instruction. */ |
1167 | 957k | if (insn & 0x80000000) |
1168 | 392k | { |
1169 | 392k | print_insn16 (pc, info, (insn >> 16), NDS32_PARSE_INSN16); |
1170 | 392k | return 2; |
1171 | 392k | } |
1172 | | |
1173 | | /* 32-bit instructions. */ |
1174 | 564k | if (size == 4) |
1175 | 564k | print_insn32 (pc, info, insn, NDS32_PARSE_INSN32); |
1176 | 254 | else |
1177 | 254 | info->fprintf_func (info->stream, |
1178 | 254 | _("insufficient data to decode instruction")); |
1179 | 564k | return 4; |
1180 | 957k | } |
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 | 534 | { |
1239 | 534 | static unsigned init_done = 0; |
1240 | 534 | unsigned k; |
1241 | | |
1242 | | /* Set up symbol checking function. */ |
1243 | 534 | 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 | 534 | if (init_done) |
1249 | 532 | 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 | } |