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