Commit | Line | Data |
---|---|---|
35c08157 | 1 | /* NDS32-specific support for 32-bit ELF. |
b90efa5b | 2 | Copyright (C) 2012-2015 Free Software Foundation, Inc. |
35c08157 KLC |
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 | |
40c7a7cb | 20 | 02110-1301, USA. */ |
35c08157 KLC |
21 | |
22 | #include "sysdep.h" | |
23 | #include <stdio.h> | |
24 | #include "ansidecl.h" | |
25 | #include "dis-asm.h" | |
26 | #include "bfd.h" | |
27 | #include "symcat.h" | |
28 | #include "libiberty.h" | |
29 | #include "opintl.h" | |
30 | #include "bfd_stdint.h" | |
40c7a7cb KLC |
31 | #include "hashtab.h" |
32 | #include "nds32-asm.h" | |
33 | #include "opcode/nds32.h" | |
35c08157 | 34 | |
40c7a7cb KLC |
35 | /* Get fields macro define. */ |
36 | #define MASK_OP(insn, mask) ((insn) & (0x3f << 25 | (mask))) | |
35c08157 KLC |
37 | |
38 | /* Default text to print if an instruction isn't recognized. */ | |
39 | #define UNKNOWN_INSN_MSG _("*unknown*") | |
40c7a7cb KLC |
40 | #define NDS32_PARSE_INSN16 0x01 |
41 | #define NDS32_PARSE_INSN32 0x02 | |
42 | #define NDS32_PARSE_EX9IT 0x04 | |
43 | #define NDS32_PARSE_EX9TAB 0x08 | |
44 | ||
45 | extern struct nds32_opcode nds32_opcodes[]; | |
46 | extern const field_t operand_fields[]; | |
47 | extern const keyword_t *keywords[]; | |
48 | extern const keyword_t keyword_gpr[]; | |
49 | static void print_insn16 (bfd_vma pc, disassemble_info *info, | |
50 | uint32_t insn, uint32_t parse_mode); | |
51 | static void print_insn32 (bfd_vma pc, disassemble_info *info, uint32_t insn, | |
52 | uint32_t parse_mode); | |
53 | static uint32_t nds32_mask_opcode (uint32_t); | |
54 | static void nds32_special_opcode (uint32_t, struct nds32_opcode **); | |
55 | ||
56 | /* define in objdump.c. */ | |
57 | struct objdump_disasm_info | |
35c08157 | 58 | { |
40c7a7cb KLC |
59 | bfd * abfd; |
60 | asection * sec; | |
61 | bfd_boolean require_sec; | |
62 | arelent ** dynrelbuf; | |
63 | long dynrelcount; | |
64 | disassembler_ftype disassemble_fn; | |
65 | arelent * reloc; | |
35c08157 KLC |
66 | }; |
67 | ||
40c7a7cb KLC |
68 | /* file_ptr ex9_filepos=NULL;. */ |
69 | bfd_byte *ex9_data = NULL; | |
70 | int ex9_ready = 0, ex9_base_offset = 0; | |
35c08157 | 71 | |
40c7a7cb | 72 | /* Hash function for disassemble. */ |
35c08157 | 73 | |
40c7a7cb | 74 | static htab_t opcode_htab; |
35c08157 | 75 | |
40c7a7cb KLC |
76 | static void |
77 | nds32_ex9_info (bfd_vma pc ATTRIBUTE_UNUSED, | |
78 | disassemble_info *info, uint32_t ex9_index) | |
35c08157 | 79 | { |
40c7a7cb KLC |
80 | uint32_t insn; |
81 | static asymbol *itb = NULL; | |
82 | bfd_byte buffer[4]; | |
83 | long unsigned int isec_vma; | |
35c08157 | 84 | |
40c7a7cb KLC |
85 | /* Lookup itb symbol. */ |
86 | if (!itb) | |
87 | { | |
88 | int i; | |
35c08157 | 89 | |
40c7a7cb KLC |
90 | for (i = 0; i < info->symtab_size; i++) |
91 | if (bfd_asymbol_name (info->symtab[i]) | |
92 | && (strcmp (bfd_asymbol_name (info->symtab[i]), "$_ITB_BASE_") == 0 | |
93 | || strcmp (bfd_asymbol_name (info->symtab[i]), | |
94 | "_ITB_BASE_") == 0)) | |
95 | { | |
96 | itb = info->symtab[i]; | |
97 | break; | |
98 | } | |
35c08157 | 99 | |
40c7a7cb KLC |
100 | /* Lookup it only once, in case _ITB_BASE_ doesn't exist at all. */ |
101 | if (itb == NULL) | |
102 | itb = (void *) -1; | |
103 | } | |
6b9d3259 | 104 | |
40c7a7cb KLC |
105 | if (itb == (void *) -1) |
106 | return; | |
107 | ||
108 | isec_vma = itb->section->vma; | |
109 | isec_vma = itb->section->vma - bfd_asymbol_value (itb); | |
110 | if (!itb->section || !itb->section->owner) | |
111 | return; | |
112 | bfd_get_section_contents (itb->section->owner, itb->section, buffer, | |
113 | ex9_index * 4 - isec_vma, 4); | |
114 | insn = bfd_getb32 (buffer); | |
115 | /* 16-bit instructions in ex9 table. */ | |
116 | if (insn & 0x80000000) | |
117 | print_insn16 (pc, info, (insn & 0x0000FFFF), | |
118 | NDS32_PARSE_INSN16 | NDS32_PARSE_EX9IT); | |
119 | /* 32-bit instructions in ex9 table. */ | |
120 | else | |
121 | print_insn32 (pc, info, insn, NDS32_PARSE_INSN32 | NDS32_PARSE_EX9IT); | |
122 | } | |
35c08157 | 123 | |
40c7a7cb | 124 | /* Find the value map register name. */ |
6b9d3259 | 125 | |
40c7a7cb KLC |
126 | static keyword_t * |
127 | nds32_find_reg_keyword (keyword_t *reg, int value) | |
35c08157 | 128 | { |
40c7a7cb KLC |
129 | if (!reg) |
130 | return NULL; | |
6b9d3259 | 131 | |
40c7a7cb KLC |
132 | while (reg->name != NULL && reg->value != value) |
133 | { | |
134 | reg++; | |
135 | } | |
136 | if (reg->name == NULL) | |
137 | return NULL; | |
138 | return reg; | |
139 | } | |
35c08157 KLC |
140 | |
141 | static void | |
40c7a7cb KLC |
142 | nds32_parse_audio_ext (const field_t *pfd, |
143 | disassemble_info *info, uint32_t insn) | |
35c08157 | 144 | { |
35c08157 KLC |
145 | fprintf_ftype func = info->fprintf_func; |
146 | void *stream = info->stream; | |
40c7a7cb KLC |
147 | keyword_t *psys_reg; |
148 | int int_value, new_value; | |
35c08157 | 149 | |
40c7a7cb | 150 | if (pfd->hw_res == HW_INT || pfd->hw_res == HW_UINT) |
35c08157 | 151 | { |
40c7a7cb KLC |
152 | if (pfd->hw_res == HW_INT) |
153 | int_value = | |
154 | N32_IMMS ((insn >> pfd->bitpos), pfd->bitsize) << pfd->shift; | |
155 | else | |
156 | int_value = __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift; | |
35c08157 | 157 | |
40c7a7cb KLC |
158 | if (int_value < 0) |
159 | func (stream, "#%d", int_value); | |
160 | else | |
161 | func (stream, "#0x%x", int_value); | |
35c08157 KLC |
162 | return; |
163 | } | |
40c7a7cb KLC |
164 | int_value = |
165 | __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift; | |
166 | new_value = int_value; | |
167 | psys_reg = (keyword_t*) keywords[pfd->hw_res]; | |
35c08157 | 168 | |
40c7a7cb KLC |
169 | /* p = bit[4].bit[1:0], r = bit[4].bit[3:2]. */ |
170 | if (strcmp (pfd->name, "im5_i") == 0) | |
35c08157 | 171 | { |
40c7a7cb KLC |
172 | new_value = int_value & 0x03; |
173 | new_value |= ((int_value & 0x10) >> 2); | |
35c08157 | 174 | } |
40c7a7cb | 175 | else if (strcmp (pfd->name, "im5_m") == 0) |
35c08157 | 176 | { |
40c7a7cb | 177 | new_value = ((int_value & 0x1C) >> 2); |
35c08157 | 178 | } |
40c7a7cb KLC |
179 | /* p = 0.bit[1:0], r = 0.bit[3:2]. */ |
180 | /* q = 1.bit[1:0], s = 1.bit[5:4]. */ | |
181 | else if (strcmp (pfd->name, "im6_iq") == 0) | |
35c08157 | 182 | { |
40c7a7cb | 183 | new_value |= 0x04; |
35c08157 | 184 | } |
40c7a7cb | 185 | else if (strcmp (pfd->name, "im6_ms") == 0) |
35c08157 | 186 | { |
40c7a7cb KLC |
187 | new_value |= 0x04; |
188 | } | |
189 | /* Rt CONCAT(c, t21, t0). */ | |
190 | else if (strcmp (pfd->name, "a_rt21") == 0) | |
191 | { | |
192 | new_value = (insn & 0x00000020) >> 5; | |
193 | new_value |= (insn & 0x00000C00) >> 9; | |
194 | new_value |= (insn & 0x00008000) >> 12; | |
195 | } | |
196 | else if (strcmp (pfd->name, "a_rte") == 0) | |
197 | { | |
198 | new_value = (insn & 0x00000C00) >> 9; | |
199 | new_value |= (insn & 0x00008000) >> 12; | |
200 | } | |
201 | else if (strcmp (pfd->name, "a_rte1") == 0) | |
202 | { | |
203 | new_value = (insn & 0x00000C00) >> 9; | |
204 | new_value |= (insn & 0x00008000) >> 12; | |
205 | new_value |= 0x01; | |
35c08157 | 206 | } |
40c7a7cb KLC |
207 | else if (strcmp (pfd->name, "a_rte69") == 0) |
208 | { | |
209 | new_value = int_value << 1; | |
210 | } | |
211 | else if (strcmp (pfd->name, "a_rte69_1") == 0) | |
212 | { | |
213 | new_value = int_value << 1; | |
214 | new_value |= 0x01; | |
215 | } | |
216 | ||
217 | psys_reg = nds32_find_reg_keyword (psys_reg, new_value); | |
218 | if (!psys_reg) | |
219 | func (stream, "???"); | |
220 | else | |
221 | func (stream, "$%s", psys_reg->name); | |
35c08157 KLC |
222 | } |
223 | ||
40c7a7cb | 224 | /* Dump instruction. If the opcode is unknown, return FALSE. */ |
35c08157 KLC |
225 | |
226 | static void | |
40c7a7cb KLC |
227 | nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED, |
228 | disassemble_info *info, uint32_t insn, | |
229 | uint32_t parse_mode) | |
35c08157 | 230 | { |
40c7a7cb | 231 | int op = 0; |
35c08157 KLC |
232 | fprintf_ftype func = info->fprintf_func; |
233 | void *stream = info->stream; | |
40c7a7cb KLC |
234 | const char *pstr_src; |
235 | char *pstr_tmp; | |
236 | char tmp_string[16]; | |
237 | unsigned int push25gpr = 0, lsmwRb, lsmwRe, lsmwEnb4, checkbit, i; | |
238 | int int_value, ifthe1st = 1; | |
239 | const field_t *pfd; | |
240 | keyword_t *psys_reg; | |
241 | ||
242 | if (opc == NULL) | |
35c08157 | 243 | { |
35c08157 KLC |
244 | func (stream, UNKNOWN_INSN_MSG); |
245 | return; | |
246 | } | |
35c08157 | 247 | |
40c7a7cb KLC |
248 | if (parse_mode & NDS32_PARSE_EX9IT) |
249 | func (stream, " !"); | |
35c08157 | 250 | |
40c7a7cb KLC |
251 | pstr_src = opc->instruction; |
252 | if (*pstr_src == 0) | |
35c08157 | 253 | { |
40c7a7cb | 254 | func (stream, "%s", opc->opcode); |
35c08157 KLC |
255 | return; |
256 | } | |
40c7a7cb KLC |
257 | /* NDS32_PARSE_INSN16. */ |
258 | if (parse_mode & NDS32_PARSE_INSN16) | |
259 | { | |
260 | func (stream, "%s ", opc->opcode); | |
261 | } | |
35c08157 | 262 | |
40c7a7cb KLC |
263 | /* NDS32_PARSE_INSN32. */ |
264 | else | |
35c08157 | 265 | { |
40c7a7cb KLC |
266 | op = N32_OP6 (insn); |
267 | if (op == N32_OP6_LSMW) | |
268 | func (stream, "%s.", opc->opcode); | |
269 | else if (strstr (opc->instruction, "tito")) | |
270 | func (stream, "%s", opc->opcode); | |
271 | else | |
272 | func (stream, "%s ", opc->opcode); | |
35c08157 KLC |
273 | } |
274 | ||
40c7a7cb | 275 | while (*pstr_src) |
35c08157 | 276 | { |
40c7a7cb KLC |
277 | switch (*pstr_src) |
278 | { | |
279 | case '%': | |
280 | case '=': | |
281 | case '&': | |
282 | pstr_src++; | |
283 | /* compare with operand_fields[].name. */ | |
284 | pstr_tmp = &tmp_string[0]; | |
285 | while (*pstr_src) | |
286 | { | |
287 | if ((*pstr_src == ',') || (*pstr_src == ' ') | |
288 | || (*pstr_src == '{') || (*pstr_src == '}') | |
289 | || (*pstr_src == '[') || (*pstr_src == ']') | |
290 | || (*pstr_src == '(') || (*pstr_src == ')') | |
291 | || (*pstr_src == '+') || (*pstr_src == '<')) | |
292 | break; | |
293 | *pstr_tmp++ = *pstr_src++; | |
294 | } | |
295 | *pstr_tmp = 0; | |
35c08157 | 296 | |
40c7a7cb KLC |
297 | pfd = (const field_t *) &operand_fields[0]; |
298 | while (1) | |
299 | { | |
300 | if (pfd->name == NULL) | |
301 | return; | |
302 | else if (strcmp (&tmp_string[0], pfd->name) == 0) | |
303 | break; | |
304 | pfd++; | |
305 | } | |
35c08157 | 306 | |
40c7a7cb KLC |
307 | /* for insn-16. */ |
308 | if (parse_mode & NDS32_PARSE_INSN16) | |
309 | { | |
310 | if (pfd->hw_res == HW_GPR) | |
311 | { | |
312 | int_value = | |
313 | __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift; | |
314 | /* push25/pop25. */ | |
315 | if ((opc->value == 0xfc00) || (opc->value == 0xfc80)) | |
316 | { | |
317 | if (int_value == 0) | |
318 | int_value = 6; | |
319 | else | |
320 | int_value = (6 + (0x01 << int_value)); | |
321 | push25gpr = int_value; | |
322 | } | |
323 | else if (strcmp (pfd->name, "rt4") == 0) | |
324 | { | |
325 | int_value = nds32_r45map[int_value]; | |
326 | } | |
327 | func (stream, "$%s", keyword_gpr[int_value].name); | |
328 | } | |
329 | else if ((pfd->hw_res == HW_INT) || (pfd->hw_res == HW_UINT)) | |
330 | { | |
331 | if (pfd->hw_res == HW_INT) | |
332 | int_value = | |
333 | N32_IMMS ((insn >> pfd->bitpos), | |
334 | pfd->bitsize) << pfd->shift; | |
335 | else | |
336 | int_value = | |
337 | __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift; | |
338 | ||
339 | /* movpi45. */ | |
340 | if (opc->value == 0xfa00) | |
341 | { | |
342 | int_value += 16; | |
343 | func (stream, "#0x%x", int_value); | |
344 | } | |
345 | /* lwi45.fe. */ | |
346 | else if (opc->value == 0xb200) | |
347 | { | |
348 | int_value = 0 - (128 - int_value); | |
349 | func (stream, "#%d", int_value); | |
350 | } | |
351 | /* beqz38/bnez38/beqs38/bnes38/j8/beqzs8/bnezs8/ifcall9. */ | |
352 | else if ((opc->value == 0xc000) || (opc->value == 0xc800) | |
353 | || (opc->value == 0xd000) || (opc->value == 0xd800) | |
354 | || (opc->value == 0xd500) || (opc->value == 0xe800) | |
355 | || (opc->value == 0xe900) | |
356 | || (opc->value == 0xf800)) | |
357 | { | |
358 | info->print_address_func (int_value + pc, info); | |
359 | } | |
360 | /* push25/pop25. */ | |
361 | else if ((opc->value == 0xfc00) || (opc->value == 0xfc80)) | |
362 | { | |
363 | func (stream, "#%d ! {$r6", int_value); | |
364 | if (push25gpr != 6) | |
365 | func (stream, "~$%s", keyword_gpr[push25gpr].name); | |
366 | func (stream, ", $fp, $gp, $lp}"); | |
367 | } | |
368 | /* ex9.it. */ | |
369 | else if ((opc->value == 0xdd40) || (opc->value == 0xea00)) | |
370 | { | |
371 | func (stream, "#%d", int_value); | |
372 | nds32_ex9_info (pc, info, int_value); | |
373 | } | |
374 | else if (pfd->hw_res == HW_INT) | |
375 | { | |
376 | if (int_value < 0) | |
377 | func (stream, "#%d", int_value); | |
378 | else | |
379 | func (stream, "#0x%x", int_value); | |
380 | } | |
381 | else /* if(pfd->hw_res == HW_UINT). */ | |
382 | func (stream, "#0x%x", int_value); | |
383 | } | |
35c08157 | 384 | |
40c7a7cb KLC |
385 | } |
386 | /* for audio-ext. */ | |
387 | else if (op == N32_OP6_AEXT) | |
388 | { | |
389 | nds32_parse_audio_ext (pfd, info, insn); | |
390 | } | |
391 | /* for insn-32. */ | |
392 | else if (pfd->hw_res < _HW_LAST) | |
393 | { | |
394 | int_value = | |
395 | __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift; | |
396 | ||
397 | psys_reg = (keyword_t*) keywords[pfd->hw_res]; | |
398 | ||
399 | psys_reg = nds32_find_reg_keyword (psys_reg, int_value); | |
400 | /* For HW_SR, dump the index when it can't | |
401 | map the register name. */ | |
402 | if (!psys_reg && pfd->hw_res == HW_SR) | |
403 | func (stream, "%d", int_value); | |
404 | else if (!psys_reg) | |
405 | func (stream, "???"); | |
406 | else | |
407 | { | |
408 | if (pfd->hw_res == HW_GPR || pfd->hw_res == HW_CPR | |
409 | || pfd->hw_res == HW_FDR || pfd->hw_res == HW_FSR | |
410 | || pfd->hw_res == HW_DXR || pfd->hw_res == HW_SR | |
411 | || pfd->hw_res == HW_USR) | |
412 | func (stream, "$%s", psys_reg->name); | |
413 | else if (pfd->hw_res == HW_DTITON | |
414 | || pfd->hw_res == HW_DTITOFF) | |
415 | func (stream, ".%s", psys_reg->name); | |
416 | else | |
417 | func (stream, "%s", psys_reg->name); | |
418 | } | |
419 | } | |
420 | else if ((pfd->hw_res == HW_INT) || (pfd->hw_res == HW_UINT)) | |
421 | { | |
422 | if (pfd->hw_res == HW_INT) | |
423 | int_value = | |
424 | N32_IMMS ((insn >> pfd->bitpos), pfd->bitsize) << pfd->shift; | |
425 | else | |
426 | int_value = | |
427 | __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift; | |
428 | ||
429 | if ((op == N32_OP6_BR1) || (op == N32_OP6_BR2)) | |
430 | { | |
431 | info->print_address_func (int_value + pc, info); | |
432 | } | |
433 | else if ((op == N32_OP6_BR3) && (pfd->bitpos == 0)) | |
434 | { | |
435 | info->print_address_func (int_value + pc, info); | |
436 | } | |
437 | else if (op == N32_OP6_JI) | |
438 | { | |
439 | /* FIXME: Handle relocation. */ | |
440 | if (info->flags & INSN_HAS_RELOC) | |
441 | pc = 0; | |
442 | /* Check if insn32 in ex9 table. */ | |
443 | if (parse_mode & NDS32_PARSE_EX9IT) | |
444 | info->print_address_func ((pc & 0xFE000000) | int_value, | |
445 | info); | |
446 | /* Check if decode ex9 table, PC(31,25)|Inst(23,0)<<1. */ | |
447 | else if (parse_mode & NDS32_PARSE_EX9TAB) | |
448 | func (stream, "PC(31,25)|#0x%x", int_value); | |
449 | else | |
450 | info->print_address_func (int_value + pc, info); | |
451 | } | |
452 | else if (op == N32_OP6_LSMW) | |
453 | { | |
454 | /* lmw.adm/smw.adm. */ | |
455 | func (stream, "#0x%x ! {", int_value); | |
456 | lsmwEnb4 = int_value; | |
457 | lsmwRb = ((insn >> 20) & 0x1F); | |
458 | lsmwRe = ((insn >> 10) & 0x1F); | |
459 | ||
460 | /* If [Rb, Re] specifies at least one register, | |
461 | Rb(4,0) <= Re(4,0) and 0 <= Rb(4,0), Re(4,0) < 28. | |
462 | Disassembling does not consider this currently because of | |
463 | the convience comparing with bsp320. */ | |
464 | if (lsmwRb != 31 || lsmwRe != 31) | |
465 | { | |
466 | func (stream, "$%s", keyword_gpr[lsmwRb].name); | |
467 | if (lsmwRb != lsmwRe) | |
468 | func (stream, "~$%s", keyword_gpr[lsmwRe].name); | |
469 | ifthe1st = 0; | |
470 | } | |
471 | if (lsmwEnb4 != 0) | |
472 | { | |
473 | /* $fp, $gp, $lp, $sp. */ | |
474 | checkbit = 0x08; | |
475 | for (i = 0; i < 4; i++) | |
476 | { | |
477 | if (lsmwEnb4 & checkbit) | |
478 | { | |
479 | if (ifthe1st == 1) | |
480 | { | |
481 | ifthe1st = 0; | |
482 | func (stream, "$%s", keyword_gpr[28 + i].name); | |
483 | } | |
484 | else | |
485 | func (stream, ", $%s", keyword_gpr[28 + i].name); | |
486 | } | |
487 | checkbit >>= 1; | |
488 | } | |
489 | } | |
490 | func (stream, "}"); | |
491 | } | |
492 | else if (pfd->hw_res == HW_INT) | |
493 | { | |
494 | if (int_value < 0) | |
495 | func (stream, "#%d", int_value); | |
496 | else | |
497 | func (stream, "#0x%x", int_value); | |
498 | } | |
499 | else /* if(pfd->hw_res == HW_UINT). */ | |
500 | { | |
501 | func (stream, "#0x%x", int_value); | |
502 | } | |
503 | } | |
504 | break; | |
35c08157 | 505 | |
40c7a7cb KLC |
506 | case '{': |
507 | case '}': | |
508 | pstr_src++; | |
509 | break; | |
510 | ||
511 | default: | |
512 | func (stream, "%c", *pstr_src++); | |
513 | break; | |
514 | } /* switch (*pstr_src). */ | |
515 | ||
516 | } /* while (*pstr_src). */ | |
517 | return; | |
35c08157 KLC |
518 | } |
519 | ||
40c7a7cb KLC |
520 | /* Filter instructions with some bits must be fixed. */ |
521 | ||
35c08157 | 522 | static void |
40c7a7cb | 523 | nds32_filter_unknown_insn (uint32_t insn, struct nds32_opcode **opc) |
35c08157 | 524 | { |
40c7a7cb KLC |
525 | if (!(*opc)) |
526 | return; | |
35c08157 | 527 | |
40c7a7cb | 528 | switch ((*opc)->value) |
35c08157 | 529 | { |
40c7a7cb KLC |
530 | case JREG (JR): |
531 | case JREG (JRNEZ): | |
532 | /* jr jr.xtoff */ | |
533 | if (__GF (insn, 6, 2) != 0 || __GF (insn, 15, 10) != 0) | |
534 | *opc = NULL; | |
35c08157 | 535 | break; |
40c7a7cb KLC |
536 | case MISC (STANDBY): |
537 | if (__GF (insn, 7, 18) != 0) | |
538 | *opc = NULL; | |
539 | break; | |
540 | case SIMD (PBSAD): | |
541 | case SIMD (PBSADA): | |
542 | if (__GF (insn, 5, 5) != 0) | |
543 | *opc = NULL; | |
544 | break; | |
545 | case BR2 (IFCALL): | |
546 | if (__GF (insn, 20, 5) != 0) | |
547 | *opc = NULL; | |
548 | break; | |
549 | case JREG (JRAL): | |
550 | if (__GF (insn, 5, 3) != 0 || __GF (insn, 15, 5) != 0) | |
551 | *opc = NULL; | |
552 | break; | |
553 | case ALU1 (NOR): | |
554 | case ALU1 (SLT): | |
555 | case ALU1 (SLTS): | |
556 | case ALU1 (SLLI): | |
557 | case ALU1 (SRLI): | |
558 | case ALU1 (SRAI): | |
559 | case ALU1 (ROTRI): | |
560 | case ALU1 (SLL): | |
561 | case ALU1 (SRL): | |
562 | case ALU1 (SRA): | |
563 | case ALU1 (ROTR): | |
564 | case ALU1 (SEB): | |
565 | case ALU1 (SEH): | |
566 | case ALU1 (ZEH): | |
567 | case ALU1 (WSBH): | |
568 | case ALU1 (SVA): | |
569 | case ALU1 (SVS): | |
570 | case ALU1 (CMOVZ): | |
571 | case ALU1 (CMOVN): | |
572 | if (__GF (insn, 5, 5) != 0) | |
573 | *opc = NULL; | |
574 | break; | |
575 | case MISC (IRET): | |
576 | case MISC (ISB): | |
577 | case MISC (DSB): | |
578 | if (__GF (insn, 5, 20) != 0) | |
579 | *opc = NULL; | |
35c08157 KLC |
580 | break; |
581 | } | |
582 | } | |
583 | ||
584 | static void | |
40c7a7cb KLC |
585 | print_insn32 (bfd_vma pc, disassemble_info *info, uint32_t insn, |
586 | uint32_t parse_mode) | |
35c08157 | 587 | { |
40c7a7cb KLC |
588 | /* Get the final correct opcode and parse. */ |
589 | struct nds32_opcode *opc; | |
590 | uint32_t opcode = nds32_mask_opcode (insn); | |
591 | opc = (struct nds32_opcode *) htab_find (opcode_htab, &opcode); | |
592 | ||
593 | nds32_special_opcode (insn, &opc); | |
594 | nds32_filter_unknown_insn (insn, &opc); | |
595 | nds32_parse_opcode (opc, pc, info, insn, parse_mode); | |
35c08157 KLC |
596 | } |
597 | ||
598 | static void | |
40c7a7cb KLC |
599 | print_insn16 (bfd_vma pc, disassemble_info *info, |
600 | uint32_t insn, uint32_t parse_mode) | |
35c08157 | 601 | { |
40c7a7cb KLC |
602 | struct nds32_opcode *opc; |
603 | uint32_t opcode; | |
604 | ||
605 | /* Get highest 7 bit in default. */ | |
606 | unsigned int mask = 0xfe00; | |
35c08157 | 607 | |
40c7a7cb KLC |
608 | /* Classify 16-bit instruction to 4 sets by bit 13 and 14. */ |
609 | switch (__GF (insn, 13, 2)) | |
35c08157 | 610 | { |
40c7a7cb KLC |
611 | case 0x0: |
612 | /* mov55 movi55 */ | |
613 | if (__GF (insn, 11, 2) == 0) | |
35c08157 | 614 | { |
40c7a7cb KLC |
615 | mask = 0xfc00; |
616 | /* ifret16 = mov55 $sp, $sp*/ | |
617 | if (__GF (insn, 0, 11) == 0x3ff) | |
618 | mask = 0xffff; | |
35c08157 | 619 | } |
40c7a7cb KLC |
620 | else if (__GF (insn, 9, 4) == 0xb) |
621 | mask = 0xfe07; | |
622 | break; | |
623 | case 0x1: | |
624 | /* lwi37 swi37 */ | |
625 | if (__GF (insn, 11, 2) == 0x3) | |
626 | mask = 0xf880; | |
627 | break; | |
628 | case 0x2: | |
629 | mask = 0xf800; | |
630 | /* Exclude beqz38, bnez38, beqs38, and bnes38. */ | |
631 | if (__GF (insn, 12, 1) == 0x1 | |
632 | && __GF (insn, 8, 3) == 0x5) | |
35c08157 | 633 | { |
40c7a7cb KLC |
634 | if (__GF (insn, 11, 1) == 0x0) |
635 | mask = 0xff00; | |
636 | else | |
637 | mask = 0xffe0; | |
35c08157 | 638 | } |
40c7a7cb KLC |
639 | break; |
640 | case 0x3: | |
641 | switch (__GF (insn, 11, 2)) | |
35c08157 | 642 | { |
35c08157 | 643 | case 0x1: |
40c7a7cb KLC |
644 | /* beqzs8 bnezs8 */ |
645 | if (__GF (insn, 9, 2) == 0x0) | |
646 | mask = 0xff00; | |
647 | /* addi10s */ | |
648 | else if (__GF(insn, 10, 1) == 0x1) | |
649 | mask = 0xfc00; | |
650 | break; | |
35c08157 | 651 | case 0x2: |
40c7a7cb KLC |
652 | /* lwi37.sp swi37.sp */ |
653 | mask = 0xf880; | |
654 | break; | |
35c08157 | 655 | case 0x3: |
40c7a7cb KLC |
656 | if (__GF (insn, 8, 3) == 0x5) |
657 | mask = 0xff00; | |
658 | else if (__GF (insn, 8, 3) == 0x4) | |
659 | mask = 0xff80; | |
660 | else if (__GF (insn, 9 , 2) == 0x3) | |
661 | mask = 0xfe07; | |
662 | break; | |
663 | } | |
664 | break; | |
665 | } | |
666 | opcode = insn & mask; | |
667 | opc = (struct nds32_opcode *) htab_find (opcode_htab, &opcode); | |
668 | ||
669 | nds32_special_opcode (insn, &opc); | |
670 | /* Get the final correct opcode and parse it. */ | |
671 | nds32_parse_opcode (opc, pc, info, insn, parse_mode); | |
672 | } | |
673 | ||
674 | static hashval_t | |
675 | htab_hash_hash (const void *p) | |
676 | { | |
677 | return (*(unsigned int *) p) % 49; | |
678 | } | |
679 | ||
680 | static int | |
681 | htab_hash_eq (const void *p, const void *q) | |
682 | { | |
683 | uint32_t pinsn = ((struct nds32_opcode *) p)->value; | |
684 | uint32_t qinsn = *((uint32_t *) q); | |
685 | ||
686 | return (pinsn == qinsn); | |
687 | } | |
688 | ||
689 | /* Get the format of instruction. */ | |
35c08157 | 690 | |
40c7a7cb KLC |
691 | static uint32_t |
692 | nds32_mask_opcode (uint32_t insn) | |
693 | { | |
694 | uint32_t opcode = N32_OP6 (insn); | |
695 | switch (opcode) | |
696 | { | |
697 | case N32_OP6_LBI: | |
698 | case N32_OP6_LHI: | |
699 | case N32_OP6_LWI: | |
700 | case N32_OP6_LDI: | |
701 | case N32_OP6_LBI_BI: | |
702 | case N32_OP6_LHI_BI: | |
703 | case N32_OP6_LWI_BI: | |
704 | case N32_OP6_LDI_BI: | |
705 | case N32_OP6_SBI: | |
706 | case N32_OP6_SHI: | |
707 | case N32_OP6_SWI: | |
708 | case N32_OP6_SDI: | |
709 | case N32_OP6_SBI_BI: | |
710 | case N32_OP6_SHI_BI: | |
711 | case N32_OP6_SWI_BI: | |
712 | case N32_OP6_SDI_BI: | |
713 | case N32_OP6_LBSI: | |
714 | case N32_OP6_LHSI: | |
715 | case N32_OP6_LWSI: | |
716 | case N32_OP6_LBSI_BI: | |
717 | case N32_OP6_LHSI_BI: | |
718 | case N32_OP6_LWSI_BI: | |
719 | case N32_OP6_MOVI: | |
720 | case N32_OP6_SETHI: | |
721 | case N32_OP6_ADDI: | |
722 | case N32_OP6_SUBRI: | |
723 | case N32_OP6_ANDI: | |
724 | case N32_OP6_XORI: | |
725 | case N32_OP6_ORI: | |
726 | case N32_OP6_SLTI: | |
727 | case N32_OP6_SLTSI: | |
728 | case N32_OP6_CEXT: | |
729 | case N32_OP6_BITCI: | |
730 | return MASK_OP (insn, 0); | |
731 | case N32_OP6_ALU2: | |
732 | /* FFBI */ | |
733 | if (__GF (insn, 0, 7) == (N32_ALU2_FFBI | __BIT (6))) | |
734 | return MASK_OP (insn, 0x7f); | |
735 | else if (__GF (insn, 0, 7) == (N32_ALU2_MFUSR | __BIT (6)) | |
736 | || __GF (insn, 0, 7) == (N32_ALU2_MTUSR | __BIT (6))) | |
737 | /* RDOV CLROV */ | |
738 | return MASK_OP (insn, 0xf81ff); | |
739 | return MASK_OP (insn, 0x1ff); | |
740 | case N32_OP6_ALU1: | |
741 | case N32_OP6_SIMD: | |
742 | return MASK_OP (insn, 0x1f); | |
743 | case N32_OP6_MEM: | |
744 | return MASK_OP (insn, 0xff); | |
745 | case N32_OP6_JREG: | |
746 | return MASK_OP (insn, 0x7f); | |
747 | case N32_OP6_LSMW: | |
748 | return MASK_OP (insn, 0x23); | |
749 | case N32_OP6_SBGP: | |
750 | case N32_OP6_LBGP: | |
751 | return MASK_OP (insn, 0x1 << 19); | |
752 | case N32_OP6_HWGP: | |
753 | if (__GF (insn, 18, 2) == 0x3) | |
754 | return MASK_OP (insn, 0x7 << 17); | |
755 | return MASK_OP (insn, 0x3 << 18); | |
756 | case N32_OP6_DPREFI: | |
757 | return MASK_OP (insn, 0x1 << 24); | |
758 | case N32_OP6_LWC: | |
759 | case N32_OP6_SWC: | |
760 | case N32_OP6_LDC: | |
761 | case N32_OP6_SDC: | |
762 | return MASK_OP (insn, 0x1 << 12); | |
763 | case N32_OP6_JI: | |
764 | return MASK_OP (insn, 0x1 << 24); | |
765 | case N32_OP6_BR1: | |
766 | return MASK_OP (insn, 0x1 << 14); | |
767 | case N32_OP6_BR2: | |
768 | return MASK_OP (insn, 0xf << 16); | |
769 | case N32_OP6_BR3: | |
770 | return MASK_OP (insn, 0x1 << 19); | |
771 | case N32_OP6_MISC: | |
772 | switch (__GF (insn, 0, 5)) | |
773 | { | |
774 | case N32_MISC_MTSR: | |
775 | /* SETGIE and SETEND */ | |
776 | if (__GF (insn, 5, 5) == 0x1 || __GF (insn, 5, 5) == 0x2) | |
777 | return MASK_OP (insn, 0x1fffff); | |
778 | return MASK_OP (insn, 0x1f); | |
779 | case N32_MISC_TLBOP: | |
780 | if (__GF (insn, 5, 5) == 5 || __GF (insn, 5, 5) == 7) | |
781 | /* PB FLUA */ | |
782 | return MASK_OP (insn, 0x3ff); | |
783 | return MASK_OP (insn, 0x1f); | |
784 | default: | |
785 | return MASK_OP (insn, 0x1f); | |
786 | } | |
787 | case N32_OP6_COP: | |
788 | if (__GF (insn, 4, 2) == 0) | |
789 | { | |
790 | /* FPU */ | |
791 | switch (__GF (insn, 0, 4)) | |
35c08157 KLC |
792 | { |
793 | case 0x0: | |
35c08157 | 794 | case 0x8: |
40c7a7cb KLC |
795 | /* FS1/F2OP FD1/F2OP */ |
796 | if (__GF (insn, 6, 4) == 0xf) | |
797 | return MASK_OP (insn, 0x7fff); | |
798 | /* FS1 FD1 */ | |
799 | return MASK_OP (insn, 0x3ff); | |
800 | case 0x4: | |
35c08157 | 801 | case 0xc: |
40c7a7cb KLC |
802 | /* FS2 */ |
803 | return MASK_OP (insn, 0x3ff); | |
804 | case 0x1: | |
805 | case 0x9: | |
806 | /* XR */ | |
807 | if (__GF (insn, 6, 4) == 0xc) | |
808 | return MASK_OP (insn, 0x7fff); | |
809 | /* MFCP MTCP */ | |
810 | return MASK_OP (insn, 0x3ff); | |
811 | default: | |
812 | return MASK_OP (insn, 0xff); | |
35c08157 KLC |
813 | } |
814 | } | |
40c7a7cb KLC |
815 | else if (__GF (insn, 0, 2) == 0) |
816 | return MASK_OP (insn, 0xf); | |
817 | return MASK_OP (insn, 0xcf); | |
818 | case N32_OP6_AEXT: | |
819 | /* AUDIO */ | |
820 | switch (__GF (insn, 23, 2)) | |
35c08157 KLC |
821 | { |
822 | case 0x0: | |
40c7a7cb KLC |
823 | if (__GF (insn, 5, 4) == 0) |
824 | /* AMxxx AMAyyS AMyyS AMAWzS AMWzS */ | |
825 | return MASK_OP (insn, (0x1f << 20) | 0x1ff); | |
826 | else if (__GF (insn, 5, 4) == 1) | |
827 | /* ALR ASR ALA ASA AUPI */ | |
828 | return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); | |
829 | else if (__GF (insn, 20, 3) == 0 && __GF (insn, 6, 3) == 1) | |
830 | /* ALR2 */ | |
831 | return MASK_OP (insn, (0x1f << 20) | (0x7 << 6)); | |
832 | else if (__GF (insn, 20 ,3) == 2 && __GF (insn, 6, 3) == 1) | |
833 | /* AWEXT ASATS48 */ | |
834 | return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); | |
835 | else if (__GF (insn, 20 ,3) == 3 && __GF (insn, 6, 3) == 1) | |
836 | /* AMTAR AMTAR2 AMFAR AMFAR2 */ | |
837 | return MASK_OP (insn, (0x1f << 20) | (0x1f << 5)); | |
838 | else if (__GF (insn, 7, 2) == 3) | |
839 | /* AMxxxSA */ | |
840 | return MASK_OP (insn, (0x1f << 20) | (0x3 << 7)); | |
841 | else if (__GF (insn, 6, 3) == 2) | |
842 | /* AMxxxL.S */ | |
843 | return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); | |
35c08157 | 844 | else |
40c7a7cb KLC |
845 | /* AmxxxL.l AmxxxL2.S AMxxxL2.L */ |
846 | return MASK_OP (insn, (0x1f << 20) | (0x7 << 6)); | |
35c08157 | 847 | case 0x1: |
40c7a7cb KLC |
848 | if (__GF (insn, 20, 3) == 0) |
849 | /* AADDL ASUBL */ | |
850 | return MASK_OP (insn, (0x1f << 20) | (0x1 << 5)); | |
851 | else if (__GF (insn, 20, 3) == 1) | |
852 | /* AMTARI Ix AMTARI Mx */ | |
853 | return MASK_OP (insn, (0x1f << 20)); | |
854 | else if (__GF (insn, 6, 3) == 2) | |
855 | /* AMAWzSl.S AMWzSl.S */ | |
856 | return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); | |
857 | else if (__GF (insn, 7, 2) == 3) | |
858 | /* AMAWzSSA AMWzSSA */ | |
859 | return MASK_OP (insn, (0x1f << 20) | (0x3 << 7)); | |
860 | else | |
861 | /* AMAWzSL.L AMAWzSL2.S AMAWzSL2.L AMWzSL.L AMWzSL.L AMWzSL2.S */ | |
862 | return MASK_OP (insn, (0x1f << 20) | (0x7 << 6)); | |
863 | case 0x2: | |
864 | if (__GF (insn, 6, 3) == 2) | |
865 | /* AMAyySl.S AMWyySl.S */ | |
866 | return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); | |
867 | else if (__GF (insn, 7, 2) == 3) | |
868 | /* AMAWyySSA AMWyySSA */ | |
869 | return MASK_OP (insn, (0x1f << 20) | (0x3 << 7)); | |
870 | else | |
871 | /* AMAWyySL.L AMAWyySL2.S AMAWyySL2.L AMWyySL.L AMWyySL.L AMWyySL2.S */ | |
872 | return MASK_OP (insn, (0x1f << 20) | (0x7 << 6)); | |
35c08157 | 873 | } |
40c7a7cb KLC |
874 | return MASK_OP (insn, 0x1f << 20); |
875 | default: | |
876 | return (1 << 31); | |
35c08157 KLC |
877 | } |
878 | } | |
879 | ||
40c7a7cb KLC |
880 | /* Define cctl subtype. */ |
881 | static char *cctl_subtype [] = | |
35c08157 | 882 | { |
40c7a7cb KLC |
883 | /* 0x0 */ |
884 | "st0", "st0", "st0", "st2", "st2", "st3", "st3", "st4", | |
885 | "st1", "st1", "st1", "st0", "st0", NULL, NULL, "st5", | |
886 | /* 0x10 */ | |
887 | "st0", NULL, NULL, "st2", "st2", "st3", "st3", NULL, | |
888 | "st1", NULL, NULL, "st0", "st0", NULL, NULL, NULL | |
889 | }; | |
35c08157 | 890 | |
40c7a7cb | 891 | /* Check the subset of opcode. */ |
35c08157 | 892 | |
40c7a7cb KLC |
893 | static void |
894 | nds32_special_opcode (uint32_t insn, struct nds32_opcode **opc) | |
895 | { | |
896 | char *string = NULL; | |
897 | uint32_t op; | |
35c08157 | 898 | |
40c7a7cb KLC |
899 | if (!(*opc)) |
900 | return; | |
35c08157 | 901 | |
40c7a7cb KLC |
902 | /* Check if special case. */ |
903 | switch ((*opc)->value) | |
904 | { | |
905 | case OP6 (LWC): | |
906 | case OP6 (SWC): | |
907 | case OP6 (LDC): | |
908 | case OP6 (SDC): | |
909 | case FPU_RA_IMMBI (LWC): | |
910 | case FPU_RA_IMMBI (SWC): | |
911 | case FPU_RA_IMMBI (LDC): | |
912 | case FPU_RA_IMMBI (SDC): | |
913 | /* Check if cp0 => FPU. */ | |
35c08157 | 914 | if (__GF (insn, 13, 2) == 0) |
35c08157 | 915 | { |
40c7a7cb KLC |
916 | while (!((*opc)->attr & ATTR (FPU)) && (*opc)->next) |
917 | *opc = (*opc)->next; | |
35c08157 | 918 | } |
40c7a7cb KLC |
919 | break; |
920 | case ALU1 (ADD): | |
921 | case ALU1 (SUB): | |
922 | case ALU1 (AND): | |
923 | case ALU1 (XOR): | |
924 | case ALU1 (OR): | |
925 | /* Check if (add/add_slli) (sub/sub_slli) (and/and_slli). */ | |
926 | if (N32_SH5(insn) != 0) | |
927 | string = "sh"; | |
928 | break; | |
929 | case ALU1 (SRLI): | |
930 | /* Check if nop. */ | |
931 | if (__GF (insn, 10, 15) == 0) | |
932 | string = "nop"; | |
933 | break; | |
934 | case MISC (CCTL): | |
935 | string = cctl_subtype [__GF (insn, 5, 5)]; | |
936 | break; | |
937 | case JREG (JR): | |
938 | case JREG (JRAL): | |
939 | case JREG (JR) | JREG_RET: | |
940 | if (__GF (insn, 8, 2) != 0) | |
941 | string = "tit"; | |
942 | break; | |
943 | case N32_OP6_COP: | |
944 | break; | |
945 | case 0xea00: | |
946 | /* break16 ex9 */ | |
947 | if (__GF (insn, 5, 4) != 0) | |
948 | string = "ex9"; | |
949 | break; | |
950 | case 0x9200: | |
951 | /* nop16 */ | |
952 | if (__GF (insn, 0, 9) == 0) | |
953 | string = "nop16"; | |
954 | break; | |
955 | } | |
956 | ||
957 | if (string) | |
958 | { | |
959 | while (strstr ((*opc)->opcode, string) == NULL | |
960 | && strstr ((*opc)->instruction, string) == NULL && (*opc)->next) | |
961 | *opc = (*opc)->next; | |
35c08157 KLC |
962 | return; |
963 | } | |
40c7a7cb KLC |
964 | |
965 | /* Classify instruction is COP or FPU. */ | |
966 | op = N32_OP6 (insn); | |
967 | if (op == N32_OP6_COP && __GF (insn, 4, 2) != 0) | |
968 | { | |
969 | while (((*opc)->attr & ATTR (FPU)) != 0 && (*opc)->next) | |
970 | *opc = (*opc)->next; | |
971 | } | |
35c08157 KLC |
972 | } |
973 | ||
974 | int | |
975 | print_insn_nds32 (bfd_vma pc, disassemble_info *info) | |
976 | { | |
977 | int status; | |
978 | bfd_byte buf[4]; | |
979 | uint32_t insn; | |
40c7a7cb KLC |
980 | static int init = 1; |
981 | int i = 0; | |
982 | struct nds32_opcode *opc; | |
983 | struct nds32_opcode **slot; | |
984 | ||
985 | if (init) | |
986 | { | |
987 | /* Build opcode table. */ | |
988 | opcode_htab = htab_create_alloc (1024, htab_hash_hash, htab_hash_eq, | |
989 | NULL, xcalloc, free); | |
35c08157 | 990 | |
40c7a7cb KLC |
991 | while (nds32_opcodes[i].opcode != NULL) |
992 | { | |
993 | opc = &nds32_opcodes[i]; | |
994 | slot = | |
995 | (struct nds32_opcode **) htab_find_slot (opcode_htab, &opc->value, | |
996 | INSERT); | |
997 | if (*slot == NULL) | |
998 | { | |
999 | /* This is the new one. */ | |
1000 | *slot = opc; | |
1001 | } | |
1002 | else | |
1003 | { | |
1004 | /* Already exists. Append to the list. */ | |
1005 | opc = *slot; | |
1006 | while (opc->next) | |
1007 | opc = opc->next; | |
1008 | opc->next = &nds32_opcodes[i]; | |
1009 | } | |
1010 | i++; | |
1011 | } | |
1012 | init = 0; | |
1013 | } | |
1014 | ||
1015 | status = info->read_memory_func (pc, (bfd_byte *) buf, 4, info); | |
35c08157 | 1016 | if (status) |
40c7a7cb KLC |
1017 | { |
1018 | /* for the last 16-bit instruction. */ | |
1019 | status = info->read_memory_func (pc, (bfd_byte *) buf, 2, info); | |
1020 | if (status) | |
1021 | { | |
1022 | (*info->memory_error_func)(status, pc, info); | |
1023 | return -1; | |
1024 | } | |
1025 | } | |
35c08157 | 1026 | |
40c7a7cb | 1027 | insn = bfd_getb32 (buf); |
35c08157 | 1028 | /* 16-bit instruction. */ |
40c7a7cb | 1029 | if (insn & 0x80000000) |
35c08157 | 1030 | { |
40c7a7cb KLC |
1031 | if (info->section && strstr (info->section->name, ".ex9.itable") != NULL) |
1032 | { | |
1033 | print_insn16 (pc, info, (insn & 0x0000FFFF), | |
1034 | NDS32_PARSE_INSN16 | NDS32_PARSE_EX9TAB); | |
1035 | return 4; | |
1036 | } | |
1037 | print_insn16 (pc, info, (insn >> 16), NDS32_PARSE_INSN16); | |
35c08157 KLC |
1038 | return 2; |
1039 | } | |
1040 | ||
1041 | /* 32-bit instructions. */ | |
40c7a7cb KLC |
1042 | else |
1043 | { | |
1044 | if (info->section | |
1045 | && strstr (info->section->name, ".ex9.itable") != NULL) | |
1046 | print_insn32 (pc, info, insn, NDS32_PARSE_INSN32 | NDS32_PARSE_EX9TAB); | |
1047 | else | |
1048 | print_insn32 (pc, info, insn, NDS32_PARSE_INSN32); | |
1049 | return 4; | |
1050 | } | |
35c08157 | 1051 | } |