1 /* Altera Nios II disassemble routines
2 Copyright (C) 2012-2014 Free Software Foundation, Inc.
3 Contributed by Nigel Gray (ngray@altera.com).
4 Contributed by Mentor Graphics, Inc.
6 This file is part of the GNU opcodes library.
8 This library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 It is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this file; see the file COPYING. If not, write to the
20 Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
25 #include "opcode/nios2.h"
26 #include "libiberty.h"
30 /* No symbol table is available when this code runs out in an embedded
31 system as when it is used for disassembler support in a monitor. */
32 #if !defined(EMBEDDED_ENV)
33 #define SYMTAB_AVAILABLE 1
35 #include "elf/nios2.h"
38 /* Length of Nios II instruction in bytes. */
41 /* Data structures used by the opcode hash table. */
42 typedef struct _nios2_opcode_hash
44 const struct nios2_opcode
*opcode
;
45 struct _nios2_opcode_hash
*next
;
48 static bfd_boolean nios2_hash_init
= 0;
49 static nios2_opcode_hash
*nios2_hash
[(OP_MASK_OP
) + 1];
51 /* Separate hash table for pseudo-ops. */
52 static nios2_opcode_hash
*nios2_ps_hash
[(OP_MASK_OP
) + 1];
54 /* Function to initialize the opcode hash table. */
56 nios2_init_opcode_hash (void)
59 register const struct nios2_opcode
*op
;
61 for (i
= 0; i
<= OP_MASK_OP
; ++i
)
63 for (i
= 0; i
<= OP_MASK_OP
; i
++)
64 for (op
= nios2_opcodes
; op
< &nios2_opcodes
[NUMOPCODES
]; op
++)
66 nios2_opcode_hash
*new_hash
;
67 nios2_opcode_hash
**bucket
= NULL
;
69 if ((op
->pinfo
& NIOS2_INSN_MACRO
) == NIOS2_INSN_MACRO
)
71 if (i
== ((op
->match
>> OP_SH_OP
) & OP_MASK_OP
)
72 && (op
->pinfo
& (NIOS2_INSN_MACRO_MOV
| NIOS2_INSN_MACRO_MOVI
)
74 bucket
= &(nios2_ps_hash
[i
]);
76 else if (i
== ((op
->match
>> OP_SH_OP
) & OP_MASK_OP
))
77 bucket
= &(nios2_hash
[i
]);
82 (nios2_opcode_hash
*) malloc (sizeof (nios2_opcode_hash
));
86 "error allocating memory...broken disassembler\n");
89 new_hash
->opcode
= op
;
90 new_hash
->next
= NULL
;
92 bucket
= &((*bucket
)->next
);
97 #ifdef DEBUG_HASHTABLE
98 for (i
= 0; i
<= OP_MASK_OP
; ++i
)
100 nios2_opcode_hash
*tmp_hash
= nios2_hash
[i
];
101 printf ("index: 0x%02X ops: ", i
);
102 while (tmp_hash
!= NULL
)
104 printf ("%s ", tmp_hash
->opcode
->name
);
105 tmp_hash
= tmp_hash
->next
;
110 for (i
= 0; i
<= OP_MASK_OP
; ++i
)
112 nios2_opcode_hash
*tmp_hash
= nios2_ps_hash
[i
];
113 printf ("index: 0x%02X ops: ", i
);
114 while (tmp_hash
!= NULL
)
116 printf ("%s ", tmp_hash
->opcode
->name
);
117 tmp_hash
= tmp_hash
->next
;
121 #endif /* DEBUG_HASHTABLE */
124 /* Return a pointer to an nios2_opcode struct for a given instruction
125 opcode, or NULL if there is an error. */
126 const struct nios2_opcode
*
127 nios2_find_opcode_hash (unsigned long opcode
)
129 nios2_opcode_hash
*entry
;
131 /* Build a hash table to shorten the search time. */
132 if (!nios2_hash_init
)
133 nios2_init_opcode_hash ();
135 /* First look in the pseudo-op hashtable. */
136 for (entry
= nios2_ps_hash
[(opcode
>> OP_SH_OP
) & OP_MASK_OP
];
137 entry
; entry
= entry
->next
)
138 if (entry
->opcode
->match
== (opcode
& entry
->opcode
->mask
))
139 return entry
->opcode
;
141 /* Otherwise look in the main hashtable. */
142 for (entry
= nios2_hash
[(opcode
>> OP_SH_OP
) & OP_MASK_OP
];
143 entry
; entry
= entry
->next
)
144 if (entry
->opcode
->match
== (opcode
& entry
->opcode
->mask
))
145 return entry
->opcode
;
150 /* There are 32 regular registers, 32 coprocessor registers,
151 and 32 control registers. */
152 #define NUMREGNAMES 32
154 /* Return a pointer to the base of the coprocessor register name array. */
155 static struct nios2_reg
*
156 nios2_coprocessor_regs (void)
158 static struct nios2_reg
*cached
= NULL
;
163 for (i
= NUMREGNAMES
; i
< nios2_num_regs
; i
++)
164 if (!strcmp (nios2_regs
[i
].name
, "c0"))
166 cached
= nios2_regs
+ i
;
174 /* Return a pointer to the base of the control register name array. */
175 static struct nios2_reg
*
176 nios2_control_regs (void)
178 static struct nios2_reg
*cached
= NULL
;
183 for (i
= NUMREGNAMES
; i
< nios2_num_regs
; i
++)
184 if (!strcmp (nios2_regs
[i
].name
, "status"))
186 cached
= nios2_regs
+ i
;
194 /* The function nios2_print_insn_arg uses the character pointed
195 to by ARGPTR to determine how it print the next token or separator
196 character in the arguments to an instruction. */
198 nios2_print_insn_arg (const char *argptr
,
199 unsigned long opcode
, bfd_vma address
,
200 disassemble_info
*info
)
203 struct nios2_reg
*reg_base
;
210 (*info
->fprintf_func
) (info
->stream
, "%c", *argptr
);
213 i
= GET_INSN_FIELD (RRD
, opcode
);
215 if (GET_INSN_FIELD (OP
, opcode
) == OP_MATCH_CUSTOM
216 && GET_INSN_FIELD (CUSTOM_C
, opcode
) == 0)
217 reg_base
= nios2_coprocessor_regs ();
219 reg_base
= nios2_regs
;
222 (*info
->fprintf_func
) (info
->stream
, "%s", reg_base
[i
].name
);
224 (*info
->fprintf_func
) (info
->stream
, "unknown");
227 i
= GET_INSN_FIELD (RRS
, opcode
);
229 if (GET_INSN_FIELD (OP
, opcode
) == OP_MATCH_CUSTOM
230 && GET_INSN_FIELD (CUSTOM_A
, opcode
) == 0)
231 reg_base
= nios2_coprocessor_regs ();
233 reg_base
= nios2_regs
;
236 (*info
->fprintf_func
) (info
->stream
, "%s", reg_base
[i
].name
);
238 (*info
->fprintf_func
) (info
->stream
, "unknown");
241 i
= GET_INSN_FIELD (RRT
, opcode
);
243 if (GET_INSN_FIELD (OP
, opcode
) == OP_MATCH_CUSTOM
244 && GET_INSN_FIELD (CUSTOM_B
, opcode
) == 0)
245 reg_base
= nios2_coprocessor_regs ();
247 reg_base
= nios2_regs
;
250 (*info
->fprintf_func
) (info
->stream
, "%s", reg_base
[i
].name
);
252 (*info
->fprintf_func
) (info
->stream
, "unknown");
255 /* 16-bit signed immediate. */
256 i
= (signed) (GET_INSN_FIELD (IMM16
, opcode
) << 16) >> 16;
257 (*info
->fprintf_func
) (info
->stream
, "%ld", i
);
260 /* 16-bit unsigned immediate. */
261 i
= GET_INSN_FIELD (IMM16
, opcode
);
262 (*info
->fprintf_func
) (info
->stream
, "%ld", i
);
265 /* 16-bit signed immediate address offset. */
266 i
= (signed) (GET_INSN_FIELD (IMM16
, opcode
) << 16) >> 16;
267 address
= address
+ 4 + i
;
268 (*info
->print_address_func
) (address
, info
);
271 /* 5-bit unsigned immediate. */
272 i
= GET_INSN_FIELD (CACHE_OPX
, opcode
);
273 (*info
->fprintf_func
) (info
->stream
, "%ld", i
);
276 /* 5-bit unsigned immediate. */
277 i
= GET_INSN_FIELD (IMM5
, opcode
);
278 (*info
->fprintf_func
) (info
->stream
, "%ld", i
);
281 /* 8-bit unsigned immediate. */
282 /* FIXME - not yet implemented */
283 i
= GET_INSN_FIELD (CUSTOM_N
, opcode
);
284 (*info
->fprintf_func
) (info
->stream
, "%lu", i
);
287 /* 26-bit unsigned immediate. */
288 i
= GET_INSN_FIELD (IMM26
, opcode
);
289 /* This translates to an address because it's only used in call
291 address
= (address
& 0xf0000000) | (i
<< 2);
292 (*info
->print_address_func
) (address
, info
);
295 /* Control register index. */
296 i
= GET_INSN_FIELD (IMM5
, opcode
);
297 reg_base
= nios2_control_regs ();
298 (*info
->fprintf_func
) (info
->stream
, "%s", reg_base
[i
].name
);
301 i
= GET_INSN_FIELD (IMM5
, opcode
);
302 (*info
->fprintf_func
) (info
->stream
, "%ld", i
);
305 (*info
->fprintf_func
) (info
->stream
, "unknown");
311 /* nios2_disassemble does all the work of disassembling a Nios II
312 instruction opcode. */
314 nios2_disassemble (bfd_vma address
, unsigned long opcode
,
315 disassemble_info
*info
)
317 const struct nios2_opcode
*op
;
319 info
->bytes_per_line
= INSNLEN
;
320 info
->bytes_per_chunk
= INSNLEN
;
321 info
->display_endian
= info
->endian
;
322 info
->insn_info_valid
= 1;
323 info
->branch_delay_insns
= 0;
325 info
->insn_type
= dis_nonbranch
;
329 /* Find the major opcode and use this to disassemble
330 the instruction and its arguments. */
331 op
= nios2_find_opcode_hash (opcode
);
335 bfd_boolean is_nop
= FALSE
;
336 if (op
->pinfo
== NIOS2_INSN_MACRO_MOV
)
338 /* Check for mov r0, r0 and change to nop. */
340 dst
= GET_INSN_FIELD (RRD
, opcode
);
341 src
= GET_INSN_FIELD (RRS
, opcode
);
342 if (dst
== 0 && src
== 0)
344 (*info
->fprintf_func
) (info
->stream
, "nop");
348 (*info
->fprintf_func
) (info
->stream
, "%s", op
->name
);
351 (*info
->fprintf_func
) (info
->stream
, "%s", op
->name
);
355 const char *argstr
= op
->args
;
356 if (argstr
!= NULL
&& *argstr
!= '\0')
358 (*info
->fprintf_func
) (info
->stream
, "\t");
359 while (*argstr
!= '\0')
361 nios2_print_insn_arg (argstr
, opcode
, address
, info
);
369 /* Handle undefined instructions. */
370 info
->insn_type
= dis_noninsn
;
371 (*info
->fprintf_func
) (info
->stream
, "0x%lx", opcode
);
373 /* Tell the caller how far to advance the program counter. */
378 /* print_insn_nios2 is the main disassemble function for Nios II.
379 The function diassembler(abfd) (source in disassemble.c) returns a
380 pointer to this either print_insn_big_nios2 or
381 print_insn_little_nios2, which in turn call this function when the
382 bfd machine type is Nios II. print_insn_nios2 reads the
383 instruction word at the address given, and prints the disassembled
384 instruction on the stream info->stream using info->fprintf_func. */
387 print_insn_nios2 (bfd_vma address
, disassemble_info
*info
,
388 enum bfd_endian endianness
)
390 bfd_byte buffer
[INSNLEN
];
393 status
= (*info
->read_memory_func
) (address
, buffer
, INSNLEN
, info
);
397 if (endianness
== BFD_ENDIAN_BIG
)
398 insn
= (unsigned long) bfd_getb32 (buffer
);
400 insn
= (unsigned long) bfd_getl32 (buffer
);
401 status
= nios2_disassemble (address
, insn
, info
);
405 (*info
->memory_error_func
) (status
, address
, info
);
411 /* These two functions are the main entry points, accessed from
414 print_insn_big_nios2 (bfd_vma address
, disassemble_info
*info
)
416 return print_insn_nios2 (address
, info
, BFD_ENDIAN_BIG
);
420 print_insn_little_nios2 (bfd_vma address
, disassemble_info
*info
)
422 return print_insn_nios2 (address
, info
, BFD_ENDIAN_LITTLE
);