diff options
author | Sandra Loosemore <sandra@codesourcery.com> | 2015-07-01 16:08:03 -0700 |
---|---|---|
committer | Sandra Loosemore <sandra@codesourcery.com> | 2015-07-01 16:08:03 -0700 |
commit | c8c8175b623c597cf18442ff1e13456beb41931d (patch) | |
tree | 8298618df52745c2d1478a000477c379e833c3d4 /opcodes/nios2-dis.c | |
parent | 8c163c5a87f3e16f34ea9a0565767a23dccd5983 (diff) | |
download | gdb-c8c8175b623c597cf18442ff1e13456beb41931d.zip gdb-c8c8175b623c597cf18442ff1e13456beb41931d.tar.gz gdb-c8c8175b623c597cf18442ff1e13456beb41931d.tar.bz2 |
Opcodes and assembler support for Nios II R2
2015-07-01 Sandra Loosemore <sandra@codesourcery.com>
Cesar Philippidis <cesar@codesourcery.com>
gas/
* config/tc-nios2.c (nios2_min_align): New.
(nop): Replace with....
(nop_r1, nop_r2, nop_r2_cdx, nop32, nop16): New.
(nios2_align): Handle alignment on 2-byte boundaries when CDX
instructions may be present.
(s_nios2_align): Adjust reference to nop.
(CDXBRANCH, IS_CDXBRANCH): New.
(CDX_UBRANCH_SUBTYPE, CDX_CBRANCH_SUBTYPE): New.
(nios2_relax_subtype_size): Handle 2-byte CDX branches.
(nios2_relax_frag): Likewise.
(md_convert_frag): Handle R2 encodings.
(nios2_check_overflow): Check that low-order bits are zero
before applying rightshift from howto.
(nios2_check_overflow): Correct negative overflow calculation.
(nios2_diagnose_overflow): Handle signed_immed12_overflow. Issue
generic overflow messages for miscellaneous instruction formats.
(md_apply_fix): Recognize new R2 relocations. For pc_relative
relocations, store fixup in *valP.
(nios2_reglist_mask, nios2_reglist_dir): New.
(nios2_parse_reglist): New.
(nios2_parse_base_register): New.
(nios2_assemble_expression): Handle constant expressions designated
by BFD_RELOC_NONE.
(nios2_assemble_reg3): New.
(nios2_assemble_arg_c): Handle R2 instruction formats.
(nios2_assemble_arg_d): Likewise.
(nios2_assemble_arg_s): Likewise.
(nios2_assemble_arg_t): Likewise.
(nios2_assemble_arg_D): New.
(nios2_assemble_arg_S): New.
(nios2_assemble_arg_T): New.
(nios2_assemble_arg_i): Handle R2 instruction formats.
(nios2_assemble_arg_I): New.
(nios2_assemble_arg_u): Handle R2 instruction formats.
(nios2_assemble_arg_U): New.
(nios2_assemble_arg_V): New.
(nios2_assemble_arg_W): New.
(nios2_assemble_arg_X): New.
(nios2_assemble_arg_Y): New.
(nios2_assemble_arg_o): Handle R2 instruction formats.
(nios2_assemble_arg_O): New.
(nios2_assemble_arg_P): New.
(nios2_assemble_arg_j): Handle R2 instruction formats.
(nios2_assemble_arg_k): New.
(nios2_assemble_arg_l): Handle R2 instruction formats.
(nios2_assemble_arg_m): Likewise.
(nios2_assemble_arg_M): New.
(nios2_assemble_arg_N): New.
(nios2_assemble_arg_e): New.
(nios2_assemble_arg_f): New.
(nios2_assemble_arg_g): New.
(nios2_assemble_arg_h): New.
(nios2_assemble_arg_R): New.
(nios2_assemble_arg_B): New.
(nios2_assemble_args): Handle new argument letters.
(nios2_consume_arg): Likewise.
(nios2_translate_pseudo_insn): Avoid dereferencing null pointer
in error message.
(nios2_ps_insn_info_structs): Add nop.n.
(output_ubranch): Handle CDX branches.
(output_cbranch): Likewise.
(output_call): Handle R2 encodings.
(output_movia): Likewise.
(md_begin): Initialize nios2_min_align.
(md_assemble): Align to nios2_min_align. Adjust nios2_min_align
if a 16-bit instruction is seen.
(nios2_cons_align): Use appropriate nop pattern.
include/opcode/
* nios2.h (enum iw_format_type): Add R2 formats.
(enum overflow_type): Add signed_immed12_overflow and
enumeration_overflow for R2.
(struct nios2_opcode): Document new argument letters for R2.
(REG_3BIT, REG_LDWM, REG_POP): Define.
(includes): Include nios2r2.h.
(nios2_r2_opcodes, nios2_num_r2_opcodes): Declare.
(nios2_r2_asi_n_mappings, nios2_num_r2_asi_n_mappings): Declare.
(nios2_r2_shi_n_mappings, nios2_num_r2_shi_n_mappings): Declare.
(nios2_r2_andi_n_mappings, nios2_num_r2_andi_n_mappings): Declare.
(nios2_r2_reg3_mappings, nios2_num_r2_reg3_mappings): Declare.
(nios2_r2_reg_range_mappings, nios2_num_r2_reg_range_mappings):
Declare.
* nios2r2.h: New file.
opcodes/
* nios2-dis.c (nios2_extract_opcode): New.
(nios2_disassembler_state): New.
(nios2_find_opcode_hash): Use mach parameter to select correct
disassembler state.
(nios2_print_insn_arg): Extend to support new R2 argument letters
and formats.
(print_insn_nios2): Check for 16-bit instruction at end of memory.
* nios2-opc.c (nios2_builtin_regs): Add R2 register attributes.
(NIOS2_NUM_OPCODES): Rename to...
(NIOS2_NUM_R1_OPCODES): This.
(nios2_r2_opcodes): New.
(NIOS2_NUM_R2_OPCODES): New.
(nios2_num_r2_opcodes): New.
(nios2_r2_asi_n_mappings, nios2_num_r2_asi_n_mappings): New.
(nios2_r2_shi_n_mappings, nios2_num_r2_shi_n_mappings): New.
(nios2_r2_andi_n_mappings, nios2_num_r2_andi_n_mappings): New.
(nios2_r2_reg3_mappings, nios2_num_r2_reg3_mappings): New.
(nios2_r2_reg_range_mappings, nios2_num_r2_reg_range_mappings): New.
Diffstat (limited to 'opcodes/nios2-dis.c')
-rw-r--r-- | opcodes/nios2-dis.c | 550 |
1 files changed, 524 insertions, 26 deletions
diff --git a/opcodes/nios2-dis.c b/opcodes/nios2-dis.c index 80951f1..2735aad 100644 --- a/opcodes/nios2-dis.c +++ b/opcodes/nios2-dis.c @@ -55,7 +55,14 @@ nios2_r1_extract_opcode (unsigned int x) return GET_IW_R1_OP (x); } -/* Pseudo-ops are stored in a different table than regular instructions. */ +static unsigned int +nios2_r2_extract_opcode (unsigned int x) +{ + return GET_IW_R2_OP (x); +} + +/* We maintain separate hash tables for R1 and R2 opcodes, and pseudo-ops + are stored in a different table than regular instructions. */ typedef struct _nios2_disassembler_state { @@ -79,6 +86,17 @@ nios2_r1_disassembler_state = { 0 }; +static nios2_disassembler_state +nios2_r2_disassembler_state = { + nios2_r2_opcodes, + &nios2_num_r2_opcodes, + nios2_r2_extract_opcode, + {}, + {}, + NULL, + 0 +}; + /* Function to initialize the opcode hash table. */ static void nios2_init_opcode_hash (nios2_disassembler_state *state) @@ -155,13 +173,17 @@ nios2_init_opcode_hash (nios2_disassembler_state *state) /* Return a pointer to an nios2_opcode struct for a given instruction word OPCODE for bfd machine MACH, or NULL if there is an error. */ const struct nios2_opcode * -nios2_find_opcode_hash (unsigned long opcode, - unsigned long mach ATTRIBUTE_UNUSED) +nios2_find_opcode_hash (unsigned long opcode, unsigned long mach) { nios2_opcode_hash *entry; nios2_disassembler_state *state; - state = &nios2_r1_disassembler_state; + /* Select the right instruction set, hash tables, and opcode accessor + for the mach variant. */ + if (mach == bfd_mach_nios2r2) + state = &nios2_r2_disassembler_state; + else + state = &nios2_r1_disassembler_state; /* Build a hash table to shorten the search time. */ if (!state->init) @@ -260,19 +282,46 @@ nios2_print_insn_arg (const char *argptr, (*info->fprintf_func) (info->stream, "%c", *argptr); break; + case 'c': + /* Control register index. */ + switch (op->format) + { + case iw_r_type: + i = GET_IW_R_IMM5 (opcode); + break; + case iw_F3X6L5_type: + i = GET_IW_F3X6L5_IMM5 (opcode); + break; + default: + bad_opcode (op); + } + reg_base = nios2_control_regs (); + (*info->fprintf_func) (info->stream, "%s", reg_base[i].name); + break; + case 'd': + reg_base = nios2_regs; switch (op->format) { case iw_r_type: i = GET_IW_R_C (opcode); - reg_base = nios2_regs; break; case iw_custom_type: i = GET_IW_CUSTOM_C (opcode); if (GET_IW_CUSTOM_READC (opcode) == 0) reg_base = nios2_coprocessor_regs (); - else - reg_base = nios2_regs; + break; + case iw_F3X6L5_type: + case iw_F3X6_type: + i = GET_IW_F3X6L5_C (opcode); + break; + case iw_F3X8_type: + i = GET_IW_F3X8_C (opcode); + if (GET_IW_F3X8_READC (opcode) == 0) + reg_base = nios2_coprocessor_regs (); + break; + case iw_F2_type: + i = GET_IW_F2_B (opcode); break; default: bad_opcode (op); @@ -284,22 +333,52 @@ nios2_print_insn_arg (const char *argptr, break; case 's': + reg_base = nios2_regs; switch (op->format) { case iw_r_type: i = GET_IW_R_A (opcode); - reg_base = nios2_regs; break; case iw_i_type: i = GET_IW_I_A (opcode); - reg_base = nios2_regs; break; case iw_custom_type: i = GET_IW_CUSTOM_A (opcode); if (GET_IW_CUSTOM_READA (opcode) == 0) reg_base = nios2_coprocessor_regs (); - else - reg_base = nios2_regs; + break; + case iw_F2I16_type: + i = GET_IW_F2I16_A (opcode); + break; + case iw_F2X4I12_type: + i = GET_IW_F2X4I12_A (opcode); + break; + case iw_F1X4I12_type: + i = GET_IW_F1X4I12_A (opcode); + break; + case iw_F1X4L17_type: + i = GET_IW_F1X4L17_A (opcode); + break; + case iw_F3X6L5_type: + case iw_F3X6_type: + i = GET_IW_F3X6L5_A (opcode); + break; + case iw_F2X6L10_type: + i = GET_IW_F2X6L10_A (opcode); + break; + case iw_F3X8_type: + i = GET_IW_F3X8_A (opcode); + if (GET_IW_F3X8_READA (opcode) == 0) + reg_base = nios2_coprocessor_regs (); + break; + case iw_F1X1_type: + i = GET_IW_F1X1_A (opcode); + break; + case iw_F1I5_type: + i = 27; /* Implicit stack pointer reference. */ + break; + case iw_F2_type: + i = GET_IW_F2_A (opcode); break; default: bad_opcode (op); @@ -311,22 +390,46 @@ nios2_print_insn_arg (const char *argptr, break; case 't': + reg_base = nios2_regs; switch (op->format) { case iw_r_type: i = GET_IW_R_B (opcode); - reg_base = nios2_regs; break; case iw_i_type: i = GET_IW_I_B (opcode); - reg_base = nios2_regs; break; case iw_custom_type: i = GET_IW_CUSTOM_B (opcode); if (GET_IW_CUSTOM_READB (opcode) == 0) reg_base = nios2_coprocessor_regs (); - else - reg_base = nios2_regs; + break; + case iw_F2I16_type: + i = GET_IW_F2I16_B (opcode); + break; + case iw_F2X4I12_type: + i = GET_IW_F2X4I12_B (opcode); + break; + case iw_F3X6L5_type: + case iw_F3X6_type: + i = GET_IW_F3X6L5_B (opcode); + break; + case iw_F2X6L10_type: + i = GET_IW_F2X6L10_B (opcode); + break; + case iw_F3X8_type: + i = GET_IW_F3X8_B (opcode); + if (GET_IW_F3X8_READB (opcode) == 0) + reg_base = nios2_coprocessor_regs (); + break; + case iw_F1I5_type: + i = GET_IW_F1I5_B (opcode); + break; + case iw_F2_type: + i = GET_IW_F2_B (opcode); + break; + case iw_T1X1I6_type: + i = 0; break; default: bad_opcode (op); @@ -337,6 +440,110 @@ nios2_print_insn_arg (const char *argptr, (*info->fprintf_func) (info->stream, "unknown"); break; + case 'D': + switch (op->format) + { + case iw_T1I7_type: + i = GET_IW_T1I7_A3 (opcode); + break; + case iw_T2X1L3_type: + i = GET_IW_T2X1L3_B3 (opcode); + break; + case iw_T2X1I3_type: + i = GET_IW_T2X1I3_B3 (opcode); + break; + case iw_T3X1_type: + i = GET_IW_T3X1_C3 (opcode); + break; + case iw_T2X3_type: + if (op->num_args == 3) + i = GET_IW_T2X3_A3 (opcode); + else + i = GET_IW_T2X3_B3 (opcode); + break; + default: + bad_opcode (op); + } + i = nios2_r2_reg3_mappings[i]; + (*info->fprintf_func) (info->stream, "%s", nios2_regs[i].name); + break; + + case 'M': + /* 6-bit unsigned immediate with no shift. */ + switch (op->format) + { + case iw_T1X1I6_type: + i = GET_IW_T1X1I6_IMM6 (opcode); + break; + default: + bad_opcode (op); + } + (*info->fprintf_func) (info->stream, "%ld", i); + break; + + case 'N': + /* 6-bit unsigned immediate with 2-bit shift. */ + switch (op->format) + { + case iw_T1X1I6_type: + i = GET_IW_T1X1I6_IMM6 (opcode) << 2; + break; + default: + bad_opcode (op); + } + (*info->fprintf_func) (info->stream, "%ld", i); + break; + + case 'S': + switch (op->format) + { + case iw_T1I7_type: + i = GET_IW_T1I7_A3 (opcode); + break; + case iw_T2I4_type: + i = GET_IW_T2I4_A3 (opcode); + break; + case iw_T2X1L3_type: + i = GET_IW_T2X1L3_A3 (opcode); + break; + case iw_T2X1I3_type: + i = GET_IW_T2X1I3_A3 (opcode); + break; + case iw_T3X1_type: + i = GET_IW_T3X1_A3 (opcode); + break; + case iw_T2X3_type: + i = GET_IW_T2X3_A3 (opcode); + break; + case iw_T1X1I6_type: + i = GET_IW_T1X1I6_A3 (opcode); + break; + default: + bad_opcode (op); + } + i = nios2_r2_reg3_mappings[i]; + (*info->fprintf_func) (info->stream, "%s", nios2_regs[i].name); + break; + + case 'T': + switch (op->format) + { + case iw_T2I4_type: + i = GET_IW_T2I4_B3 (opcode); + break; + case iw_T3X1_type: + i = GET_IW_T3X1_B3 (opcode); + break; + case iw_T2X3_type: + i = GET_IW_T2X3_B3 (opcode); + break; + default: + bad_opcode (op); + } + i = nios2_r2_reg3_mappings[i]; + (*info->fprintf_func) (info->stream, "%s", nios2_regs[i].name); + break; + case 'i': /* 16-bit signed immediate. */ switch (op->format) @@ -344,6 +551,25 @@ nios2_print_insn_arg (const char *argptr, case iw_i_type: i = (signed) (GET_IW_I_IMM16 (opcode) << 16) >> 16; break; + case iw_F2I16_type: + i = (signed) (GET_IW_F2I16_IMM16 (opcode) << 16) >> 16; + break; + default: + bad_opcode (op); + } + (*info->fprintf_func) (info->stream, "%ld", i); + break; + + case 'I': + /* 12-bit signed immediate. */ + switch (op->format) + { + case iw_F2X4I12_type: + i = (signed) (GET_IW_F2X4I12_IMM12 (opcode) << 20) >> 20; + break; + case iw_F1X4I12_type: + i = (signed) (GET_IW_F1X4I12_IMM12 (opcode) << 20) >> 20; + break; default: bad_opcode (op); } @@ -357,6 +583,80 @@ nios2_print_insn_arg (const char *argptr, case iw_i_type: i = GET_IW_I_IMM16 (opcode); break; + case iw_F2I16_type: + i = GET_IW_F2I16_IMM16 (opcode); + break; + default: + bad_opcode (op); + } + (*info->fprintf_func) (info->stream, "%ld", i); + break; + + case 'U': + /* 7-bit unsigned immediate with 2-bit shift. */ + switch (op->format) + { + case iw_T1I7_type: + i = GET_IW_T1I7_IMM7 (opcode) << 2; + break; + case iw_X1I7_type: + i = GET_IW_X1I7_IMM7 (opcode) << 2; + break; + default: + bad_opcode (op); + } + (*info->fprintf_func) (info->stream, "%ld", i); + break; + + case 'V': + /* 5-bit unsigned immediate with 2-bit shift. */ + switch (op->format) + { + case iw_F1I5_type: + i = GET_IW_F1I5_IMM5 (opcode) << 2; + break; + default: + bad_opcode (op); + } + (*info->fprintf_func) (info->stream, "%ld", i); + break; + + case 'W': + /* 4-bit unsigned immediate with 2-bit shift. */ + switch (op->format) + { + case iw_T2I4_type: + i = GET_IW_T2I4_IMM4 (opcode) << 2; + break; + case iw_L5I4X1_type: + i = GET_IW_L5I4X1_IMM4 (opcode) << 2; + break; + default: + bad_opcode (op); + } + (*info->fprintf_func) (info->stream, "%ld", i); + break; + + case 'X': + /* 4-bit unsigned immediate with 1-bit shift. */ + switch (op->format) + { + case iw_T2I4_type: + i = GET_IW_T2I4_IMM4 (opcode) << 1; + break; + default: + bad_opcode (op); + } + (*info->fprintf_func) (info->stream, "%ld", i); + break; + + case 'Y': + /* 4-bit unsigned immediate without shift. */ + switch (op->format) + { + case iw_T2I4_type: + i = GET_IW_T2I4_IMM4 (opcode); + break; default: bad_opcode (op); } @@ -370,6 +670,9 @@ nios2_print_insn_arg (const char *argptr, case iw_i_type: i = (signed) (GET_IW_I_IMM16 (opcode) << 16) >> 16; break; + case iw_F2I16_type: + i = (signed) (GET_IW_F2I16_IMM16 (opcode) << 16) >> 16; + break; default: bad_opcode (op); } @@ -377,6 +680,34 @@ nios2_print_insn_arg (const char *argptr, (*info->print_address_func) (address, info); break; + case 'O': + /* 10-bit signed address offset with 1-bit shift. */ + switch (op->format) + { + case iw_I10_type: + i = (signed) (GET_IW_I10_IMM10 (opcode) << 22) >> 21; + break; + default: + bad_opcode (op); + } + address = address + 2 + i; + (*info->print_address_func) (address, info); + break; + + case 'P': + /* 7-bit signed address offset with 1-bit shift. */ + switch (op->format) + { + case iw_T1I7_type: + i = (signed) (GET_IW_T1I7_IMM7 (opcode) << 25) >> 24; + break; + default: + bad_opcode (op); + } + address = address + 2 + i; + (*info->print_address_func) (address, info); + break; + case 'j': /* 5-bit unsigned immediate. */ switch (op->format) @@ -384,6 +715,28 @@ nios2_print_insn_arg (const char *argptr, case iw_r_type: i = GET_IW_R_IMM5 (opcode); break; + case iw_F3X6L5_type: + i = GET_IW_F3X6L5_IMM5 (opcode); + break; + case iw_F2X6L10_type: + i = GET_IW_F2X6L10_MSB (opcode); + break; + case iw_X2L5_type: + i = GET_IW_X2L5_IMM5 (opcode); + break; + default: + bad_opcode (op); + } + (*info->fprintf_func) (info->stream, "%ld", i); + break; + + case 'k': + /* Second 5-bit unsigned immediate field. */ + switch (op->format) + { + case iw_F2X6L10_type: + i = GET_IW_F2X6L10_LSB (opcode); + break; default: bad_opcode (op); } @@ -397,6 +750,9 @@ nios2_print_insn_arg (const char *argptr, case iw_custom_type: i = GET_IW_CUSTOM_N (opcode); break; + case iw_F3X8_type: + i = GET_IW_F3X8_N (opcode); + break; default: bad_opcode (op); } @@ -410,6 +766,9 @@ nios2_print_insn_arg (const char *argptr, case iw_j_type: i = GET_IW_J_IMM26 (opcode); break; + case iw_L26_type: + i = GET_IW_L26_IMM26 (opcode); + break; default: bad_opcode (op); } @@ -419,18 +778,144 @@ nios2_print_insn_arg (const char *argptr, (*info->print_address_func) (address, info); break; - case 'c': - /* Control register index. */ + case 'e': + /* Encoded enumeration for addi.n/subi.n. */ switch (op->format) { - case iw_r_type: - i = GET_IW_R_IMM5 (opcode); + case iw_T2X1I3_type: + i = nios2_r2_asi_n_mappings[GET_IW_T2X1I3_IMM3 (opcode)]; + break; + default: + bad_opcode (op); + } + (*info->fprintf_func) (info->stream, "%lu", i); + break; + + case 'f': + /* Encoded enumeration for slli.n/srli.n. */ + switch (op->format) + { + case iw_T2X1L3_type: + i = nios2_r2_shi_n_mappings[GET_IW_T2X1I3_IMM3 (opcode)]; + break; + default: + bad_opcode (op); + } + (*info->fprintf_func) (info->stream, "%lu", i); + break; + + case 'g': + /* Encoded enumeration for andi.n. */ + switch (op->format) + { + case iw_T2I4_type: + i = nios2_r2_andi_n_mappings[GET_IW_T2I4_IMM4 (opcode)]; + break; + default: + bad_opcode (op); + } + (*info->fprintf_func) (info->stream, "%lu", i); + break; + + case 'h': + /* Encoded enumeration for movi.n. */ + switch (op->format) + { + case iw_T1I7_type: + i = GET_IW_T1I7_IMM7 (opcode); + if (i == 125) + i = 0xff; + else if (i == 126) + i = -2; + else if (i == 127) + i = -1; + break; + default: + bad_opcode (op); + } + (*info->fprintf_func) (info->stream, "%ld", i); + break; + + case 'R': + { + unsigned long reglist = 0; + int dir = 1; + int k, t; + + switch (op->format) + { + case iw_F1X4L17_type: + /* Encoding for ldwm/stwm. */ + i = GET_IW_F1X4L17_REGMASK (opcode); + if (GET_IW_F1X4L17_RS (opcode)) + { + reglist = ((i << 14) & 0x00ffc000); + if (i & (1 << 10)) + reglist |= (1 << 28); + if (i & (1 << 11)) + reglist |= (1 << 31); + } + else + reglist = i << 2; + dir = GET_IW_F1X4L17_REGMASK (opcode) ? 1 : -1; + break; + + case iw_L5I4X1_type: + /* Encoding for push.n/pop.n. */ + reglist |= (1 << 31); + if (GET_IW_L5I4X1_FP (opcode)) + reglist |= (1 << 28); + if (GET_IW_L5I4X1_CS (opcode)) + { + int val = GET_IW_L5I4X1_REGRANGE (opcode); + reglist |= nios2_r2_reg_range_mappings[val]; + } + dir = (op->match == MATCH_R2_POP_N ? 1 : -1); + break; + + default: + bad_opcode (op); + } + + t = 0; + (*info->fprintf_func) (info->stream, "{"); + for (k = (dir == 1 ? 0 : 31); + (dir == 1 && k < 32) || (dir == -1 && k >= 0); + k += dir) + if (reglist & (1 << k)) + { + if (t) + (*info->fprintf_func) (info->stream, ","); + else + t++; + (*info->fprintf_func) (info->stream, "%s", nios2_regs[k].name); + } + (*info->fprintf_func) (info->stream, "}"); + break; + } + + case 'B': + /* Base register and options for ldwm/stwm. */ + switch (op->format) + { + case iw_F1X4L17_type: + if (GET_IW_F1X4L17_ID (opcode) == 0) + (*info->fprintf_func) (info->stream, "--"); + + i = GET_IW_F1X4I12_A (opcode); + (*info->fprintf_func) (info->stream, "(%s)", + nios2_builtin_regs[i].name); + + if (GET_IW_F1X4L17_ID (opcode)) + (*info->fprintf_func) (info->stream, "++"); + if (GET_IW_F1X4L17_WB (opcode)) + (*info->fprintf_func) (info->stream, ",writeback"); + if (GET_IW_F1X4L17_PC (opcode)) + (*info->fprintf_func) (info->stream, ",ret"); break; default: bad_opcode (op); } - reg_base = nios2_control_regs (); - (*info->fprintf_func) (info->stream, "%s", reg_base[i].name); break; default: @@ -512,14 +997,27 @@ print_insn_nios2 (bfd_vma address, disassemble_info *info, insn = (unsigned long) bfd_getb32 (buffer); else insn = (unsigned long) bfd_getl32 (buffer); - status = nios2_disassemble (address, insn, info); + return nios2_disassemble (address, insn, info); } - else + + /* We might have a 16-bit R2 instruction at the end of memory. Try that. */ + if (info->mach == bfd_mach_nios2r2) { - (*info->memory_error_func) (status, address, info); - status = -1; + status = (*info->read_memory_func) (address, buffer, 2, info); + if (status == 0) + { + unsigned long insn; + if (endianness == BFD_ENDIAN_BIG) + insn = (unsigned long) bfd_getb16 (buffer); + else + insn = (unsigned long) bfd_getl16 (buffer); + return nios2_disassemble (address, insn, info); + } } - return status; + + /* If we got here, we couldn't read anything. */ + (*info->memory_error_func) (status, address, info); + return -1; } /* These two functions are the main entry points, accessed from |