1 /* Altera Nios II disassemble routines
2 Copyright (C) 2012-2019 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. */
24 #include "disassemble.h"
26 #include "opcode/nios2.h"
27 #include "libiberty.h"
31 /* No symbol table is available when this code runs out in an embedded
32 system as when it is used for disassembler support in a monitor. */
33 #if !defined(EMBEDDED_ENV)
34 #define SYMTAB_AVAILABLE 1
36 #include "elf/nios2.h"
39 /* Default length of Nios II instruction in bytes. */
42 /* Data structures used by the opcode hash table. */
43 typedef struct _nios2_opcode_hash
45 const struct nios2_opcode
*opcode
;
46 struct _nios2_opcode_hash
*next
;
49 /* Hash table size. */
50 #define OPCODE_HASH_SIZE (IW_R1_OP_UNSHIFTED_MASK + 1)
52 /* Extract the opcode from an instruction word. */
54 nios2_r1_extract_opcode (unsigned int x
)
56 return GET_IW_R1_OP (x
);
60 nios2_r2_extract_opcode (unsigned int x
)
62 return GET_IW_R2_OP (x
);
65 /* We maintain separate hash tables for R1 and R2 opcodes, and pseudo-ops
66 are stored in a different table than regular instructions. */
68 typedef struct _nios2_disassembler_state
70 const struct nios2_opcode
*opcodes
;
71 const int *num_opcodes
;
72 unsigned int (*extract_opcode
) (unsigned int);
73 nios2_opcode_hash
*hash
[OPCODE_HASH_SIZE
];
74 nios2_opcode_hash
*ps_hash
[OPCODE_HASH_SIZE
];
75 const struct nios2_opcode
*nop
;
77 } nios2_disassembler_state
;
79 static nios2_disassembler_state
80 nios2_r1_disassembler_state
= {
82 &nios2_num_r1_opcodes
,
83 nios2_r1_extract_opcode
,
90 static nios2_disassembler_state
91 nios2_r2_disassembler_state
= {
93 &nios2_num_r2_opcodes
,
94 nios2_r2_extract_opcode
,
101 /* Function to initialize the opcode hash table. */
103 nios2_init_opcode_hash (nios2_disassembler_state
*state
)
106 register const struct nios2_opcode
*op
;
108 for (i
= 0; i
< OPCODE_HASH_SIZE
; i
++)
109 for (op
= state
->opcodes
; op
< &state
->opcodes
[*(state
->num_opcodes
)]; op
++)
111 nios2_opcode_hash
*new_hash
;
112 nios2_opcode_hash
**bucket
= NULL
;
114 if ((op
->pinfo
& NIOS2_INSN_MACRO
) == NIOS2_INSN_MACRO
)
116 if (i
== state
->extract_opcode (op
->match
)
117 && (op
->pinfo
& (NIOS2_INSN_MACRO_MOV
| NIOS2_INSN_MACRO_MOVI
)
120 bucket
= &(state
->ps_hash
[i
]);
121 if (strcmp (op
->name
, "nop") == 0)
125 else if (i
== state
->extract_opcode (op
->match
))
126 bucket
= &(state
->hash
[i
]);
131 (nios2_opcode_hash
*) malloc (sizeof (nios2_opcode_hash
));
132 if (new_hash
== NULL
)
134 /* xgettext:c-format */
135 opcodes_error_handler (_("out of memory"));
138 new_hash
->opcode
= op
;
139 new_hash
->next
= NULL
;
141 bucket
= &((*bucket
)->next
);
147 #ifdef DEBUG_HASHTABLE
148 for (i
= 0; i
< OPCODE_HASH_SIZE
; ++i
)
150 nios2_opcode_hash
*tmp_hash
= state
->hash
[i
];
151 printf ("index: 0x%02X ops: ", i
);
152 while (tmp_hash
!= NULL
)
154 printf ("%s ", tmp_hash
->opcode
->name
);
155 tmp_hash
= tmp_hash
->next
;
160 for (i
= 0; i
< OPCODE_HASH_SIZE
; ++i
)
162 nios2_opcode_hash
*tmp_hash
= state
->ps_hash
[i
];
163 printf ("index: 0x%02X ops: ", i
);
164 while (tmp_hash
!= NULL
)
166 printf ("%s ", tmp_hash
->opcode
->name
);
167 tmp_hash
= tmp_hash
->next
;
171 #endif /* DEBUG_HASHTABLE */
174 /* Return a pointer to an nios2_opcode struct for a given instruction
175 word OPCODE for bfd machine MACH, or NULL if there is an error. */
176 const struct nios2_opcode
*
177 nios2_find_opcode_hash (unsigned long opcode
, unsigned long mach
)
179 nios2_opcode_hash
*entry
;
180 nios2_disassembler_state
*state
;
182 /* Select the right instruction set, hash tables, and opcode accessor
183 for the mach variant. */
184 if (mach
== bfd_mach_nios2r2
)
185 state
= &nios2_r2_disassembler_state
;
187 state
= &nios2_r1_disassembler_state
;
189 /* Build a hash table to shorten the search time. */
191 nios2_init_opcode_hash (state
);
193 /* Check for NOP first. Both NOP and MOV are macros that expand into
194 an ADD instruction, and we always want to give priority to NOP. */
195 if (state
->nop
->match
== (opcode
& state
->nop
->mask
))
198 /* First look in the pseudo-op hashtable. */
199 for (entry
= state
->ps_hash
[state
->extract_opcode (opcode
)];
200 entry
; entry
= entry
->next
)
201 if (entry
->opcode
->match
== (opcode
& entry
->opcode
->mask
))
202 return entry
->opcode
;
204 /* Otherwise look in the main hashtable. */
205 for (entry
= state
->hash
[state
->extract_opcode (opcode
)];
206 entry
; entry
= entry
->next
)
207 if (entry
->opcode
->match
== (opcode
& entry
->opcode
->mask
))
208 return entry
->opcode
;
213 /* There are 32 regular registers, 32 coprocessor registers,
214 and 32 control registers. */
215 #define NUMREGNAMES 32
217 /* Return a pointer to the base of the coprocessor register name array. */
218 static struct nios2_reg
*
219 nios2_coprocessor_regs (void)
221 static struct nios2_reg
*cached
= NULL
;
226 for (i
= NUMREGNAMES
; i
< nios2_num_regs
; i
++)
227 if (!strcmp (nios2_regs
[i
].name
, "c0"))
229 cached
= nios2_regs
+ i
;
237 /* Return a pointer to the base of the control register name array. */
238 static struct nios2_reg
*
239 nios2_control_regs (void)
241 static struct nios2_reg
*cached
= NULL
;
246 for (i
= NUMREGNAMES
; i
< nios2_num_regs
; i
++)
247 if (!strcmp (nios2_regs
[i
].name
, "status"))
249 cached
= nios2_regs
+ i
;
257 /* Helper routine to report internal errors. */
259 bad_opcode (const struct nios2_opcode
*op
)
261 opcodes_error_handler
262 /* xgettext:c-format */
263 (_("internal error: broken opcode descriptor for `%s %s'"),
268 /* The function nios2_print_insn_arg uses the character pointed
269 to by ARGPTR to determine how it print the next token or separator
270 character in the arguments to an instruction. */
272 nios2_print_insn_arg (const char *argptr
,
273 unsigned long opcode
, bfd_vma address
,
274 disassemble_info
*info
,
275 const struct nios2_opcode
*op
)
279 bfd_signed_vma o
= 0;
280 struct nios2_reg
*reg_base
;
287 (*info
->fprintf_func
) (info
->stream
, "%c", *argptr
);
291 /* Control register index. */
295 i
= GET_IW_R_IMM5 (opcode
);
298 i
= GET_IW_F3X6L5_IMM5 (opcode
);
303 reg_base
= nios2_control_regs ();
304 (*info
->fprintf_func
) (info
->stream
, "%s", reg_base
[i
].name
);
308 reg_base
= nios2_regs
;
312 i
= GET_IW_R_C (opcode
);
315 i
= GET_IW_CUSTOM_C (opcode
);
316 if (GET_IW_CUSTOM_READC (opcode
) == 0)
317 reg_base
= nios2_coprocessor_regs ();
321 i
= GET_IW_F3X6L5_C (opcode
);
324 i
= GET_IW_F3X8_C (opcode
);
325 if (GET_IW_F3X8_READC (opcode
) == 0)
326 reg_base
= nios2_coprocessor_regs ();
329 i
= GET_IW_F2_B (opcode
);
335 (*info
->fprintf_func
) (info
->stream
, "%s", reg_base
[i
].name
);
337 (*info
->fprintf_func
) (info
->stream
, "unknown");
341 reg_base
= nios2_regs
;
345 i
= GET_IW_R_A (opcode
);
348 i
= GET_IW_I_A (opcode
);
351 i
= GET_IW_CUSTOM_A (opcode
);
352 if (GET_IW_CUSTOM_READA (opcode
) == 0)
353 reg_base
= nios2_coprocessor_regs ();
356 i
= GET_IW_F2I16_A (opcode
);
358 case iw_F2X4I12_type
:
359 i
= GET_IW_F2X4I12_A (opcode
);
361 case iw_F1X4I12_type
:
362 i
= GET_IW_F1X4I12_A (opcode
);
364 case iw_F1X4L17_type
:
365 i
= GET_IW_F1X4L17_A (opcode
);
369 i
= GET_IW_F3X6L5_A (opcode
);
371 case iw_F2X6L10_type
:
372 i
= GET_IW_F2X6L10_A (opcode
);
375 i
= GET_IW_F3X8_A (opcode
);
376 if (GET_IW_F3X8_READA (opcode
) == 0)
377 reg_base
= nios2_coprocessor_regs ();
380 i
= GET_IW_F1X1_A (opcode
);
383 i
= 27; /* Implicit stack pointer reference. */
386 i
= GET_IW_F2_A (opcode
);
392 (*info
->fprintf_func
) (info
->stream
, "%s", reg_base
[i
].name
);
394 (*info
->fprintf_func
) (info
->stream
, "unknown");
398 reg_base
= nios2_regs
;
402 i
= GET_IW_R_B (opcode
);
405 i
= GET_IW_I_B (opcode
);
408 i
= GET_IW_CUSTOM_B (opcode
);
409 if (GET_IW_CUSTOM_READB (opcode
) == 0)
410 reg_base
= nios2_coprocessor_regs ();
413 i
= GET_IW_F2I16_B (opcode
);
415 case iw_F2X4I12_type
:
416 i
= GET_IW_F2X4I12_B (opcode
);
420 i
= GET_IW_F3X6L5_B (opcode
);
422 case iw_F2X6L10_type
:
423 i
= GET_IW_F2X6L10_B (opcode
);
426 i
= GET_IW_F3X8_B (opcode
);
427 if (GET_IW_F3X8_READB (opcode
) == 0)
428 reg_base
= nios2_coprocessor_regs ();
431 i
= GET_IW_F1I5_B (opcode
);
434 i
= GET_IW_F2_B (opcode
);
443 (*info
->fprintf_func
) (info
->stream
, "%s", reg_base
[i
].name
);
445 (*info
->fprintf_func
) (info
->stream
, "unknown");
452 i
= GET_IW_T1I7_A3 (opcode
);
455 i
= GET_IW_T2X1L3_B3 (opcode
);
458 i
= GET_IW_T2X1I3_B3 (opcode
);
461 i
= GET_IW_T3X1_C3 (opcode
);
464 if (op
->num_args
== 3)
465 i
= GET_IW_T2X3_A3 (opcode
);
467 i
= GET_IW_T2X3_B3 (opcode
);
472 i
= nios2_r2_reg3_mappings
[i
];
473 (*info
->fprintf_func
) (info
->stream
, "%s", nios2_regs
[i
].name
);
477 /* 6-bit unsigned immediate with no shift. */
481 i
= GET_IW_T1X1I6_IMM6 (opcode
);
486 (*info
->fprintf_func
) (info
->stream
, "%ld", i
);
490 /* 6-bit unsigned immediate with 2-bit shift. */
494 i
= GET_IW_T1X1I6_IMM6 (opcode
) << 2;
499 (*info
->fprintf_func
) (info
->stream
, "%ld", i
);
506 i
= GET_IW_T1I7_A3 (opcode
);
509 i
= GET_IW_T2I4_A3 (opcode
);
512 i
= GET_IW_T2X1L3_A3 (opcode
);
515 i
= GET_IW_T2X1I3_A3 (opcode
);
518 i
= GET_IW_T3X1_A3 (opcode
);
521 i
= GET_IW_T2X3_A3 (opcode
);
524 i
= GET_IW_T1X1I6_A3 (opcode
);
529 i
= nios2_r2_reg3_mappings
[i
];
530 (*info
->fprintf_func
) (info
->stream
, "%s", nios2_regs
[i
].name
);
537 i
= GET_IW_T2I4_B3 (opcode
);
540 i
= GET_IW_T3X1_B3 (opcode
);
543 i
= GET_IW_T2X3_B3 (opcode
);
548 i
= nios2_r2_reg3_mappings
[i
];
549 (*info
->fprintf_func
) (info
->stream
, "%s", nios2_regs
[i
].name
);
553 /* 16-bit signed immediate. */
557 s
= (int32_t) (GET_IW_I_IMM16 (opcode
) << 16) >> 16;
560 s
= (int32_t) (GET_IW_F2I16_IMM16 (opcode
) << 16) >> 16;
565 (*info
->fprintf_func
) (info
->stream
, "%ld", s
);
569 /* 12-bit signed immediate. */
572 case iw_F2X4I12_type
:
573 s
= (int32_t) (GET_IW_F2X4I12_IMM12 (opcode
) << 20) >> 20;
575 case iw_F1X4I12_type
:
576 s
= (int32_t) (GET_IW_F1X4I12_IMM12 (opcode
) << 20) >> 20;
581 (*info
->fprintf_func
) (info
->stream
, "%ld", s
);
585 /* 16-bit unsigned immediate. */
589 i
= GET_IW_I_IMM16 (opcode
);
592 i
= GET_IW_F2I16_IMM16 (opcode
);
597 (*info
->fprintf_func
) (info
->stream
, "%ld", i
);
601 /* 7-bit unsigned immediate with 2-bit shift. */
605 i
= GET_IW_T1I7_IMM7 (opcode
) << 2;
608 i
= GET_IW_X1I7_IMM7 (opcode
) << 2;
613 (*info
->fprintf_func
) (info
->stream
, "%ld", i
);
617 /* 5-bit unsigned immediate with 2-bit shift. */
621 i
= GET_IW_F1I5_IMM5 (opcode
) << 2;
626 (*info
->fprintf_func
) (info
->stream
, "%ld", i
);
630 /* 4-bit unsigned immediate with 2-bit shift. */
634 i
= GET_IW_T2I4_IMM4 (opcode
) << 2;
637 i
= GET_IW_L5I4X1_IMM4 (opcode
) << 2;
642 (*info
->fprintf_func
) (info
->stream
, "%ld", i
);
646 /* 4-bit unsigned immediate with 1-bit shift. */
650 i
= GET_IW_T2I4_IMM4 (opcode
) << 1;
655 (*info
->fprintf_func
) (info
->stream
, "%ld", i
);
659 /* 4-bit unsigned immediate without shift. */
663 i
= GET_IW_T2I4_IMM4 (opcode
);
668 (*info
->fprintf_func
) (info
->stream
, "%ld", i
);
672 /* 16-bit signed immediate address offset. */
676 o
= (int32_t) (GET_IW_I_IMM16 (opcode
) << 16) >> 16;
679 o
= (int32_t) (GET_IW_F2I16_IMM16 (opcode
) << 16) >> 16;
684 address
= address
+ 4 + o
;
685 (*info
->print_address_func
) (address
, info
);
689 /* 10-bit signed address offset with 1-bit shift. */
693 o
= (int32_t) (GET_IW_I10_IMM10 (opcode
) << 22) >> 21;
698 address
= address
+ 2 + o
;
699 (*info
->print_address_func
) (address
, info
);
703 /* 7-bit signed address offset with 1-bit shift. */
707 o
= (int32_t) (GET_IW_T1I7_IMM7 (opcode
) << 25) >> 24;
712 address
= address
+ 2 + o
;
713 (*info
->print_address_func
) (address
, info
);
717 /* 5-bit unsigned immediate. */
721 i
= GET_IW_R_IMM5 (opcode
);
724 i
= GET_IW_F3X6L5_IMM5 (opcode
);
726 case iw_F2X6L10_type
:
727 i
= GET_IW_F2X6L10_MSB (opcode
);
730 i
= GET_IW_X2L5_IMM5 (opcode
);
735 (*info
->fprintf_func
) (info
->stream
, "%ld", i
);
739 /* Second 5-bit unsigned immediate field. */
742 case iw_F2X6L10_type
:
743 i
= GET_IW_F2X6L10_LSB (opcode
);
748 (*info
->fprintf_func
) (info
->stream
, "%ld", i
);
752 /* 8-bit unsigned immediate. */
756 i
= GET_IW_CUSTOM_N (opcode
);
759 i
= GET_IW_F3X8_N (opcode
);
764 (*info
->fprintf_func
) (info
->stream
, "%lu", i
);
768 /* 26-bit unsigned immediate. */
772 i
= GET_IW_J_IMM26 (opcode
);
775 i
= GET_IW_L26_IMM26 (opcode
);
780 /* This translates to an address because it's only used in call
782 address
= (address
& 0xf0000000) | (i
<< 2);
783 (*info
->print_address_func
) (address
, info
);
787 /* Encoded enumeration for addi.n/subi.n. */
791 i
= nios2_r2_asi_n_mappings
[GET_IW_T2X1I3_IMM3 (opcode
)];
796 (*info
->fprintf_func
) (info
->stream
, "%lu", i
);
800 /* Encoded enumeration for slli.n/srli.n. */
804 i
= nios2_r2_shi_n_mappings
[GET_IW_T2X1I3_IMM3 (opcode
)];
809 (*info
->fprintf_func
) (info
->stream
, "%lu", i
);
813 /* Encoded enumeration for andi.n. */
817 i
= nios2_r2_andi_n_mappings
[GET_IW_T2I4_IMM4 (opcode
)];
822 (*info
->fprintf_func
) (info
->stream
, "%lu", i
);
826 /* Encoded enumeration for movi.n. */
830 i
= GET_IW_T1I7_IMM7 (opcode
);
841 (*info
->fprintf_func
) (info
->stream
, "%ld", i
);
846 unsigned long reglist
= 0;
852 case iw_F1X4L17_type
:
853 /* Encoding for ldwm/stwm. */
854 i
= GET_IW_F1X4L17_REGMASK (opcode
);
855 if (GET_IW_F1X4L17_RS (opcode
))
857 reglist
= ((i
<< 14) & 0x00ffc000);
859 reglist
|= (1 << 28);
861 reglist
|= (1 << 31);
865 dir
= GET_IW_F1X4L17_REGMASK (opcode
) ? 1 : -1;
869 /* Encoding for push.n/pop.n. */
870 reglist
|= (1 << 31);
871 if (GET_IW_L5I4X1_FP (opcode
))
872 reglist
|= (1 << 28);
873 if (GET_IW_L5I4X1_CS (opcode
))
875 int val
= GET_IW_L5I4X1_REGRANGE (opcode
);
876 reglist
|= nios2_r2_reg_range_mappings
[val
];
878 dir
= (op
->match
== MATCH_R2_POP_N
? 1 : -1);
886 (*info
->fprintf_func
) (info
->stream
, "{");
887 for (k
= (dir
== 1 ? 0 : 31);
888 (dir
== 1 && k
< 32) || (dir
== -1 && k
>= 0);
890 if (reglist
& (1 << k
))
893 (*info
->fprintf_func
) (info
->stream
, ",");
896 (*info
->fprintf_func
) (info
->stream
, "%s", nios2_regs
[k
].name
);
898 (*info
->fprintf_func
) (info
->stream
, "}");
903 /* Base register and options for ldwm/stwm. */
906 case iw_F1X4L17_type
:
907 if (GET_IW_F1X4L17_ID (opcode
) == 0)
908 (*info
->fprintf_func
) (info
->stream
, "--");
910 i
= GET_IW_F1X4I12_A (opcode
);
911 (*info
->fprintf_func
) (info
->stream
, "(%s)",
912 nios2_builtin_regs
[i
].name
);
914 if (GET_IW_F1X4L17_ID (opcode
))
915 (*info
->fprintf_func
) (info
->stream
, "++");
916 if (GET_IW_F1X4L17_WB (opcode
))
917 (*info
->fprintf_func
) (info
->stream
, ",writeback");
918 if (GET_IW_F1X4L17_PC (opcode
))
919 (*info
->fprintf_func
) (info
->stream
, ",ret");
927 (*info
->fprintf_func
) (info
->stream
, "unknown");
933 /* nios2_disassemble does all the work of disassembling a Nios II
934 instruction opcode. */
936 nios2_disassemble (bfd_vma address
, unsigned long opcode
,
937 disassemble_info
*info
)
939 const struct nios2_opcode
*op
;
941 info
->bytes_per_line
= INSNLEN
;
942 info
->bytes_per_chunk
= INSNLEN
;
943 info
->display_endian
= info
->endian
;
944 info
->insn_info_valid
= 1;
945 info
->branch_delay_insns
= 0;
947 info
->insn_type
= dis_nonbranch
;
951 /* Find the major opcode and use this to disassemble
952 the instruction and its arguments. */
953 op
= nios2_find_opcode_hash (opcode
, info
->mach
);
957 const char *argstr
= op
->args
;
958 (*info
->fprintf_func
) (info
->stream
, "%s", op
->name
);
959 if (argstr
!= NULL
&& *argstr
!= '\0')
961 (*info
->fprintf_func
) (info
->stream
, "\t");
962 while (*argstr
!= '\0')
964 nios2_print_insn_arg (argstr
, opcode
, address
, info
, op
);
968 /* Tell the caller how far to advance the program counter. */
969 info
->bytes_per_chunk
= op
->size
;
974 /* Handle undefined instructions. */
975 info
->insn_type
= dis_noninsn
;
976 (*info
->fprintf_func
) (info
->stream
, "0x%lx", opcode
);
982 /* print_insn_nios2 is the main disassemble function for Nios II.
983 The function diassembler(abfd) (source in disassemble.c) returns a
984 pointer to this either print_insn_big_nios2 or
985 print_insn_little_nios2, which in turn call this function when the
986 bfd machine type is Nios II. print_insn_nios2 reads the
987 instruction word at the address given, and prints the disassembled
988 instruction on the stream info->stream using info->fprintf_func. */
991 print_insn_nios2 (bfd_vma address
, disassemble_info
*info
,
992 enum bfd_endian endianness
)
994 bfd_byte buffer
[INSNLEN
];
997 status
= (*info
->read_memory_func
) (address
, buffer
, INSNLEN
, info
);
1001 if (endianness
== BFD_ENDIAN_BIG
)
1002 insn
= (unsigned long) bfd_getb32 (buffer
);
1004 insn
= (unsigned long) bfd_getl32 (buffer
);
1005 return nios2_disassemble (address
, insn
, info
);
1008 /* We might have a 16-bit R2 instruction at the end of memory. Try that. */
1009 if (info
->mach
== bfd_mach_nios2r2
)
1011 status
= (*info
->read_memory_func
) (address
, buffer
, 2, info
);
1015 if (endianness
== BFD_ENDIAN_BIG
)
1016 insn
= (unsigned long) bfd_getb16 (buffer
);
1018 insn
= (unsigned long) bfd_getl16 (buffer
);
1019 return nios2_disassemble (address
, insn
, info
);
1023 /* If we got here, we couldn't read anything. */
1024 (*info
->memory_error_func
) (status
, address
, info
);
1028 /* These two functions are the main entry points, accessed from
1031 print_insn_big_nios2 (bfd_vma address
, disassemble_info
*info
)
1033 return print_insn_nios2 (address
, info
, BFD_ENDIAN_BIG
);
1037 print_insn_little_nios2 (bfd_vma address
, disassemble_info
*info
)
1039 return print_insn_nios2 (address
, info
, BFD_ENDIAN_LITTLE
);