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 | |
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')
-rw-r--r-- | opcodes/ChangeLog | 22 | ||||
-rw-r--r-- | opcodes/nios2-dis.c | 550 | ||||
-rw-r--r-- | opcodes/nios2-opc.c | 436 |
3 files changed, 952 insertions, 56 deletions
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index 138536a..a3fbc43 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,25 @@ +2015-07-01 Sandra Loosemore <sandra@codesourcery.com> + Cesar Philippidis <cesar@codesourcery.com> + + * 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. + 2015-06-30 Amit Pawar <Amit.Pawar@amd.com> * i386-dis.c (OP_Mwaitx): New. 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 diff --git a/opcodes/nios2-opc.c b/opcodes/nios2-opc.c index d5ec06f..d119f9a 100644 --- a/opcodes/nios2-opc.c +++ b/opcodes/nios2-opc.c @@ -30,36 +30,36 @@ const struct nios2_reg nios2_builtin_regs[] = { /* Standard register names. */ {"zero", 0, REG_NORMAL}, {"at", 1, REG_NORMAL}, /* assembler temporary */ - {"r2", 2, REG_NORMAL}, - {"r3", 3, REG_NORMAL}, - {"r4", 4, REG_NORMAL}, - {"r5", 5, REG_NORMAL}, - {"r6", 6, REG_NORMAL}, - {"r7", 7, REG_NORMAL}, - {"r8", 8, REG_NORMAL}, - {"r9", 9, REG_NORMAL}, - {"r10", 10, REG_NORMAL}, - {"r11", 11, REG_NORMAL}, - {"r12", 12, REG_NORMAL}, - {"r13", 13, REG_NORMAL}, - {"r14", 14, REG_NORMAL}, - {"r15", 15, REG_NORMAL}, - {"r16", 16, REG_NORMAL}, - {"r17", 17, REG_NORMAL}, - {"r18", 18, REG_NORMAL}, - {"r19", 19, REG_NORMAL}, - {"r20", 20, REG_NORMAL}, - {"r21", 21, REG_NORMAL}, - {"r22", 22, REG_NORMAL}, - {"r23", 23, REG_NORMAL}, + {"r2", 2, REG_NORMAL | REG_3BIT | REG_LDWM}, + {"r3", 3, REG_NORMAL | REG_3BIT | REG_LDWM}, + {"r4", 4, REG_NORMAL | REG_3BIT | REG_LDWM}, + {"r5", 5, REG_NORMAL | REG_3BIT | REG_LDWM}, + {"r6", 6, REG_NORMAL | REG_3BIT | REG_LDWM}, + {"r7", 7, REG_NORMAL | REG_3BIT | REG_LDWM}, + {"r8", 8, REG_NORMAL | REG_LDWM}, + {"r9", 9, REG_NORMAL | REG_LDWM}, + {"r10", 10, REG_NORMAL | REG_LDWM}, + {"r11", 11, REG_NORMAL | REG_LDWM}, + {"r12", 12, REG_NORMAL | REG_LDWM}, + {"r13", 13, REG_NORMAL | REG_LDWM}, + {"r14", 14, REG_NORMAL | REG_LDWM}, + {"r15", 15, REG_NORMAL | REG_LDWM}, + {"r16", 16, REG_NORMAL | REG_3BIT | REG_LDWM | REG_POP}, + {"r17", 17, REG_NORMAL | REG_3BIT | REG_LDWM | REG_POP}, + {"r18", 18, REG_NORMAL | REG_LDWM | REG_POP}, + {"r19", 19, REG_NORMAL | REG_LDWM | REG_POP}, + {"r20", 20, REG_NORMAL | REG_LDWM | REG_POP}, + {"r21", 21, REG_NORMAL | REG_LDWM | REG_POP}, + {"r22", 22, REG_NORMAL | REG_LDWM | REG_POP}, + {"r23", 23, REG_NORMAL | REG_LDWM | REG_POP}, {"et", 24, REG_NORMAL}, {"bt", 25, REG_NORMAL}, {"gp", 26, REG_NORMAL}, /* global pointer */ {"sp", 27, REG_NORMAL}, /* stack pointer */ - {"fp", 28, REG_NORMAL}, /* frame pointer */ + {"fp", 28, REG_NORMAL | REG_LDWM | REG_POP}, /* frame pointer */ {"ea", 29, REG_NORMAL}, /* exception return address */ {"sstatus", 30, REG_NORMAL}, /* saved processor status */ - {"ra", 31, REG_NORMAL}, /* return address */ + {"ra", 31, REG_NORMAL | REG_LDWM | REG_POP}, /* return address */ /* Alternative names for special registers. */ {"r0", 0, REG_NORMAL}, @@ -68,11 +68,11 @@ const struct nios2_reg nios2_builtin_regs[] = { {"r25", 25, REG_NORMAL}, {"r26", 26, REG_NORMAL}, {"r27", 27, REG_NORMAL}, - {"r28", 28, REG_NORMAL}, + {"r28", 28, REG_NORMAL | REG_LDWM | REG_POP}, {"r29", 29, REG_NORMAL}, {"r30", 30, REG_NORMAL}, {"ba", 30, REG_NORMAL}, /* breakpoint return address */ - {"r31", 31, REG_NORMAL}, + {"r31", 31, REG_NORMAL | REG_LDWM | REG_POP}, /* Control register names. */ {"status", 0, REG_CONTROL}, @@ -398,10 +398,386 @@ const struct nios2_opcode nios2_r1_opcodes[] = MATCH_R1_XORI, MASK_R1_XORI, 0, unsigned_immed16_overflow} }; -#define NIOS2_NUM_OPCODES \ +#define NIOS2_NUM_R1_OPCODES \ ((sizeof nios2_r1_opcodes) / (sizeof (nios2_r1_opcodes[0]))) -const int nios2_num_r1_opcodes = NIOS2_NUM_OPCODES; +const int nios2_num_r1_opcodes = NIOS2_NUM_R1_OPCODES; + +const struct nios2_opcode nios2_r2_opcodes[] = +{ + /* { name, args, args_test, num_args, size, format, + match, mask, pinfo, overflow } */ + {"add", "d,s,t", "d,s,t,E", 3, 4, iw_F3X6_type, + MATCH_R2_ADD, MASK_R2_ADD, 0, no_overflow}, + {"addi", "t,s,i", "t,s,i,E", 3, 4, iw_F2I16_type, + MATCH_R2_ADDI, MASK_R2_ADDI, 0, signed_immed16_overflow}, + {"add.n", "D,S,T", "D,S,T,E", 3, 2, iw_T3X1_type, + MATCH_R2_ADD_N, MASK_R2_ADD_N, 0, no_overflow}, + {"addi.n", "D,S,e", "D,S,e,E", 3, 2, iw_T2X1I3_type, + MATCH_R2_ADDI_N, MASK_R2_ADDI_N, 0, enumeration_overflow}, + {"and", "d,s,t", "d,s,t,E", 3, 4, iw_F3X6_type, + MATCH_R2_AND, MASK_R2_AND, 0, no_overflow}, + {"andchi", "t,s,u", "t,s,u,E", 3, 4, iw_F2I16_type, + MATCH_R2_ANDCHI, MASK_R2_ANDCHI, 0, unsigned_immed16_overflow}, + {"andci", "t,s,u", "t,s,u,E", 3, 4, iw_F2I16_type, + MATCH_R2_ANDCI, MASK_R2_ANDCI, 0, unsigned_immed16_overflow}, + {"andhi", "t,s,u", "t,s,u,E", 3, 4, iw_F2I16_type, + MATCH_R2_ANDHI, MASK_R2_ANDHI, 0, unsigned_immed16_overflow}, + {"andi", "t,s,u", "t,s,u,E", 3, 4, iw_F2I16_type, + MATCH_R2_ANDI, MASK_R2_ANDI, 0, unsigned_immed16_overflow}, + {"andi.n", "T,S,g", "T,S,g,E", 3, 2, iw_T2I4_type, + MATCH_R2_ANDI_N, MASK_R2_ANDI_N, 0, enumeration_overflow}, + {"and.n", "D,S,T", "D,S,T,E", 3, 2, iw_T2X3_type, + MATCH_R2_AND_N, MASK_R2_AND_N, 0, no_overflow}, + {"beq", "s,t,o", "s,t,o,E", 3, 4, iw_F2I16_type, + MATCH_R2_BEQ, MASK_R2_BEQ, NIOS2_INSN_CBRANCH, branch_target_overflow}, + {"beqz.n", "S,P", "S,P,E", 2, 2, iw_T1I7_type, + MATCH_R2_BEQZ_N, MASK_R2_BEQZ_N, NIOS2_INSN_CBRANCH, branch_target_overflow}, + {"bge", "s,t,o", "s,t,o,E", 3, 4, iw_F2I16_type, + MATCH_R2_BGE, MASK_R2_BGE, NIOS2_INSN_CBRANCH, branch_target_overflow}, + {"bgeu", "s,t,o", "s,t,o,E", 3, 4, iw_F2I16_type, + MATCH_R2_BGEU, MASK_R2_BGEU, NIOS2_INSN_CBRANCH, branch_target_overflow}, + {"bgt", "s,t,o", "s,t,o,E", 3, 4, iw_F2I16_type, + MATCH_R2_BGT, MASK_R2_BGT, + NIOS2_INSN_MACRO|NIOS2_INSN_CBRANCH, branch_target_overflow}, + {"bgtu", "s,t,o", "s,t,o,E", 3, 4, iw_F2I16_type, + MATCH_R2_BGTU, MASK_R2_BGTU, + NIOS2_INSN_MACRO|NIOS2_INSN_CBRANCH, branch_target_overflow}, + {"ble", "s,t,o", "s,t,o,E", 3, 4, iw_F2I16_type, + MATCH_R2_BLE, MASK_R2_BLE, + NIOS2_INSN_MACRO|NIOS2_INSN_CBRANCH, branch_target_overflow}, + {"bleu", "s,t,o", "s,t,o,E", 3, 4, iw_F2I16_type, + MATCH_R2_BLEU, MASK_R2_BLEU, + NIOS2_INSN_MACRO|NIOS2_INSN_CBRANCH, branch_target_overflow}, + {"blt", "s,t,o", "s,t,o,E", 3, 4, iw_F2I16_type, + MATCH_R2_BLT, MASK_R2_BLT, NIOS2_INSN_CBRANCH, branch_target_overflow}, + {"bltu", "s,t,o", "s,t,o,E", 3, 4, iw_F2I16_type, + MATCH_R2_BLTU, MASK_R2_BLTU, NIOS2_INSN_CBRANCH, branch_target_overflow}, + {"bne", "s,t,o", "s,t,o,E", 3, 4, iw_F2I16_type, + MATCH_R2_BNE, MASK_R2_BNE, NIOS2_INSN_CBRANCH, branch_target_overflow}, + {"bnez.n", "S,P", "S,P,E", 2, 2, iw_T1I7_type, + MATCH_R2_BNEZ_N, MASK_R2_BNEZ_N, NIOS2_INSN_CBRANCH, branch_target_overflow}, + {"br", "o", "o,E", 1, 4, iw_F2I16_type, + MATCH_R2_BR, MASK_R2_BR, NIOS2_INSN_UBRANCH, branch_target_overflow}, + {"break", "j", "j,E", 1, 4, iw_F3X6L5_type, + MATCH_R2_BREAK, MASK_R2_BREAK, NIOS2_INSN_OPTARG, no_overflow}, + {"break.n", "j", "j,E", 1, 2, iw_X2L5_type, + MATCH_R2_BREAK_N, MASK_R2_BREAK_N, NIOS2_INSN_OPTARG, no_overflow}, + {"bret", "", "E", 0, 4, iw_F3X6_type, + MATCH_R2_BRET, MASK_R2_BRET, 0, no_overflow}, + {"br.n", "O", "O,E", 1, 2, iw_I10_type, + MATCH_R2_BR_N, MASK_R2_BR_N, NIOS2_INSN_UBRANCH, branch_target_overflow}, + {"call", "m", "m,E", 1, 4, iw_L26_type, + MATCH_R2_CALL, MASK_R2_CALL, NIOS2_INSN_CALL, call_target_overflow}, + {"callr", "s", "s,E", 1, 4, iw_F3X6_type, + MATCH_R2_CALLR, MASK_R2_CALLR, 0, no_overflow}, + {"callr.n", "s", "s,E", 1, 2, iw_F1X1_type, + MATCH_R2_CALLR_N, MASK_R2_CALLR_N, 0, no_overflow}, + {"cmpeq", "d,s,t", "d,s,t,E", 3, 4, iw_F3X6_type, + MATCH_R2_CMPEQ, MASK_R2_CMPEQ, 0, no_overflow}, + {"cmpeqi", "t,s,i", "t,s,i,E", 3, 4, iw_F2I16_type, + MATCH_R2_CMPEQI, MASK_R2_CMPEQI, 0, signed_immed16_overflow}, + {"cmpge", "d,s,t", "d,s,t,E", 3, 4, iw_F3X6_type, + MATCH_R2_CMPGE, MASK_R2_CMPGE, 0, no_overflow}, + {"cmpgei", "t,s,i", "t,s,i,E", 3, 4, iw_F2I16_type, + MATCH_R2_CMPGEI, MASK_R2_CMPGEI, 0, signed_immed16_overflow}, + {"cmpgeu", "d,s,t", "d,s,t,E", 3, 4, iw_F3X6_type, + MATCH_R2_CMPGEU, MASK_R2_CMPGEU, 0, no_overflow}, + {"cmpgeui", "t,s,u", "t,s,u,E", 3, 4, iw_F2I16_type, + MATCH_R2_CMPGEUI, MASK_R2_CMPGEUI, 0, unsigned_immed16_overflow}, + {"cmpgt", "d,s,t", "d,s,t,E", 3, 4, iw_F3X6_type, + MATCH_R2_CMPGT, MASK_R2_CMPGT, NIOS2_INSN_MACRO, no_overflow}, + {"cmpgti", "t,s,i", "t,s,i,E", 3, 4, iw_F2I16_type, + MATCH_R2_CMPGTI, MASK_R2_CMPGTI, NIOS2_INSN_MACRO, signed_immed16_overflow}, + {"cmpgtu", "d,s,t", "d,s,t,E", 3, 4, iw_F3X6_type, + MATCH_R2_CMPGTU, MASK_R2_CMPGTU, NIOS2_INSN_MACRO, no_overflow}, + {"cmpgtui", "t,s,u", "t,s,u,E", 3, 4, iw_F2I16_type, + MATCH_R2_CMPGTUI, MASK_R2_CMPGTUI, + NIOS2_INSN_MACRO, unsigned_immed16_overflow}, + {"cmple", "d,s,t", "d,s,t,E", 3, 4, iw_F3X6_type, + MATCH_R2_CMPLE, MASK_R2_CMPLE, NIOS2_INSN_MACRO, no_overflow}, + {"cmplei", "t,s,i", "t,s,i,E", 3, 4, iw_F2I16_type, + MATCH_R2_CMPLEI, MASK_R2_CMPLEI, NIOS2_INSN_MACRO, signed_immed16_overflow}, + {"cmpleu", "d,s,t", "d,s,t,E", 3, 4, iw_F3X6_type, + MATCH_R2_CMPLEU, MASK_R2_CMPLEU, NIOS2_INSN_MACRO, no_overflow}, + {"cmpleui", "t,s,u", "t,s,u,E", 3, 4, iw_F2I16_type, + MATCH_R2_CMPLEUI, MASK_R2_CMPLEUI, + NIOS2_INSN_MACRO, unsigned_immed16_overflow}, + {"cmplt", "d,s,t", "d,s,t,E", 3, 4, iw_F3X6_type, + MATCH_R2_CMPLT, MASK_R2_CMPLT, 0, no_overflow}, + {"cmplti", "t,s,i", "t,s,i,E", 3, 4, iw_F2I16_type, + MATCH_R2_CMPLTI, MASK_R2_CMPLTI, 0, signed_immed16_overflow}, + {"cmpltu", "d,s,t", "d,s,t,E", 3, 4, iw_F3X6_type, + MATCH_R2_CMPLTU, MASK_R2_CMPLTU, 0, no_overflow}, + {"cmpltui", "t,s,u", "t,s,u,E", 3, 4, iw_F2I16_type, + MATCH_R2_CMPLTUI, MASK_R2_CMPLTUI, 0, unsigned_immed16_overflow}, + {"cmpne", "d,s,t", "d,s,t,E", 3, 4, iw_F3X6_type, + MATCH_R2_CMPNE, MASK_R2_CMPNE, 0, no_overflow}, + {"cmpnei", "t,s,i", "t,s,i,E", 3, 4, iw_F2I16_type, + MATCH_R2_CMPNEI, MASK_R2_CMPNEI, 0, signed_immed16_overflow}, + {"custom", "l,d,s,t", "l,d,s,t,E", 4, 4, iw_F3X8_type, + MATCH_R2_CUSTOM, MASK_R2_CUSTOM, 0, custom_opcode_overflow}, + {"div", "d,s,t", "d,s,t,E", 3, 4, iw_F3X6_type, + MATCH_R2_DIV, MASK_R2_DIV, 0, no_overflow}, + {"divu", "d,s,t", "d,s,t,E", 3, 4, iw_F3X6_type, + MATCH_R2_DIVU, MASK_R2_DIVU, 0, no_overflow}, + {"eni", "j", "j,E", 1, 4, iw_F3X6L5_type, + MATCH_R2_ENI, MASK_R2_ENI, NIOS2_INSN_OPTARG, no_overflow}, + {"eret", "", "E", 0, 4, iw_F3X6_type, + MATCH_R2_ERET, MASK_R2_ERET, 0, no_overflow}, + {"extract", "t,s,j,k", "t,s,j,k,E", 4, 4, iw_F2X6L10_type, + MATCH_R2_EXTRACT, MASK_R2_EXTRACT, 0, no_overflow}, + {"flushd", "I(s)", "I(s),E", 2, 4, iw_F1X4I12_type, + MATCH_R2_FLUSHD, MASK_R2_FLUSHD, 0, address_offset_overflow}, + {"flushda", "I(s)", "I(s),E", 2, 4, iw_F1X4I12_type, + MATCH_R2_FLUSHDA, MASK_R2_FLUSHDA, 0, address_offset_overflow}, + {"flushi", "s", "s,E", 1, 4, iw_F3X6_type, + MATCH_R2_FLUSHI, MASK_R2_FLUSHI, 0, no_overflow}, + {"flushp", "", "E", 0, 4, iw_F3X6_type, + MATCH_R2_FLUSHP, MASK_R2_FLUSHP, 0, no_overflow}, + {"initd", "I(s)", "I(s),E", 2, 4, iw_F1X4I12_type, + MATCH_R2_INITD, MASK_R2_INITD, 0, address_offset_overflow}, + {"initda", "I(s)", "I(s),E", 2, 4, iw_F1X4I12_type, + MATCH_R2_INITDA, MASK_R2_INITDA, 0, address_offset_overflow}, + {"initi", "s", "s,E", 1, 4, iw_F3X6_type, + MATCH_R2_INITI, MASK_R2_INITI, 0, no_overflow}, + {"insert", "t,s,j,k", "t,s,j,k,E", 4, 4, iw_F2X6L10_type, + MATCH_R2_INSERT, MASK_R2_INSERT, 0, no_overflow}, + {"jmp", "s", "s,E", 1, 4, iw_F3X6_type, + MATCH_R2_JMP, MASK_R2_JMP, 0, no_overflow}, + {"jmpi", "m", "m,E", 1, 4, iw_L26_type, + MATCH_R2_JMPI, MASK_R2_JMPI, 0, call_target_overflow}, + {"jmpr.n", "s", "s,E", 1, 2, iw_F1X1_type, + MATCH_R2_JMPR_N, MASK_R2_JMPR_N, 0, no_overflow}, + {"ldb", "t,i(s)", "t,i(s),E", 3, 4, iw_F2I16_type, + MATCH_R2_LDB, MASK_R2_LDB, 0, address_offset_overflow}, + {"ldbio", "t,I(s)", "t,I(s),E", 3, 4, iw_F2X4I12_type, + MATCH_R2_LDBIO, MASK_R2_LDBIO, 0, signed_immed12_overflow}, + {"ldbu", "t,i(s)", "t,i(s),E", 3, 4, iw_F2I16_type, + MATCH_R2_LDBU, MASK_R2_LDBU, 0, address_offset_overflow}, + {"ldbuio", "t,I(s)", "t,I(s),E", 3, 4, iw_F2X4I12_type, + MATCH_R2_LDBUIO, MASK_R2_LDBUIO, 0, signed_immed12_overflow}, + {"ldbu.n", "T,Y(S)", "T,Y(S),E", 3, 2, iw_T2I4_type, + MATCH_R2_LDBU_N, MASK_R2_LDBU_N, 0, address_offset_overflow}, + {"ldex", "d,(s)", "d,(s),E", 2, 4, iw_F3X6_type, + MATCH_R2_LDEX, MASK_R2_LDEX, 0, no_overflow}, + {"ldh", "t,i(s)", "t,i(s),E", 3, 4, iw_F2I16_type, + MATCH_R2_LDH, MASK_R2_LDH, 0, address_offset_overflow}, + {"ldhio", "t,I(s)", "t,I(s),E", 3, 4, iw_F2X4I12_type, + MATCH_R2_LDHIO, MASK_R2_LDHIO, 0, signed_immed12_overflow}, + {"ldhu", "t,i(s)", "t,i(s),E", 3, 4, iw_F2I16_type, + MATCH_R2_LDHU, MASK_R2_LDHU, 0, address_offset_overflow}, + {"ldhuio", "t,I(s)", "t,I(s),E", 3, 4, iw_F2X4I12_type, + MATCH_R2_LDHUIO, MASK_R2_LDHUIO, 0, signed_immed12_overflow}, + {"ldhu.n", "T,X(S)", "T,X(S),E", 3, 2, iw_T2I4_type, + MATCH_R2_LDHU_N, MASK_R2_LDHU_N, 0, address_offset_overflow}, + {"ldsex", "d,(s)", "d,(s),E", 2, 4, iw_F3X6_type, + MATCH_R2_LDSEX, MASK_R2_LDSEX, 0, no_overflow}, + {"ldw", "t,i(s)", "t,i(s),E", 3, 4, iw_F2I16_type, + MATCH_R2_LDW, MASK_R2_LDW, 0, address_offset_overflow}, + {"ldwio", "t,I(s)", "t,I(s),E", 3, 4, iw_F2X4I12_type, + MATCH_R2_LDWIO, MASK_R2_LDWIO, 0, signed_immed12_overflow}, + {"ldwm", "R,B", "R,B,E", 2, 4, iw_F1X4L17_type, + MATCH_R2_LDWM, MASK_R2_LDWM, 0, no_overflow}, + {"ldw.n", "T,W(S)", "T,W(S),E", 3, 2, iw_T2I4_type, + MATCH_R2_LDW_N, MASK_R2_LDW_N, 0, address_offset_overflow}, + {"ldwsp.n", "t,V(s)", "t,V(s),E", 3, 2, iw_F1I5_type, + MATCH_R2_LDWSP_N, MASK_R2_LDWSP_N, 0, address_offset_overflow}, + {"merge", "t,s,j,k", "t,s,j,k,E", 4, 4, iw_F2X6L10_type, + MATCH_R2_MERGE, MASK_R2_MERGE, 0, no_overflow}, + {"mov", "d,s", "d,s,E", 2, 4, iw_F3X6_type, + MATCH_R2_MOV, MASK_R2_MOV, NIOS2_INSN_MACRO_MOV, no_overflow}, + {"mov.n", "d,s", "d,s,E", 2, 2, iw_F2_type, + MATCH_R2_MOV_N, MASK_R2_MOV_N, 0, no_overflow}, + {"movi.n", "D,h", "D,h,E", 2, 2, iw_T1I7_type, + MATCH_R2_MOVI_N, MASK_R2_MOVI_N, 0, enumeration_overflow}, + {"movhi", "t,u", "t,u,E", 2, 4, iw_F2I16_type, + MATCH_R2_MOVHI, MASK_R2_MOVHI, + NIOS2_INSN_MACRO_MOVI, unsigned_immed16_overflow}, + {"movi", "t,i", "t,i,E", 2, 4, iw_F2I16_type, + MATCH_R2_MOVI, MASK_R2_MOVI, NIOS2_INSN_MACRO_MOVI, signed_immed16_overflow}, + {"movia", "t,o", "t,o,E", 2, 4, iw_F2I16_type, + MATCH_R2_ORHI, MASK_R2_ORHI, NIOS2_INSN_MACRO_MOVIA, no_overflow}, + {"movui", "t,u", "t,u,E", 2, 4, iw_F2I16_type, + MATCH_R2_MOVUI, MASK_R2_MOVUI, + NIOS2_INSN_MACRO_MOVI, unsigned_immed16_overflow}, + {"mul", "d,s,t", "d,s,t,E", 3, 4, iw_F3X6_type, + MATCH_R2_MUL, MASK_R2_MUL, 0, no_overflow}, + {"muli", "t,s,i", "t,s,i,E", 3, 4, iw_F2I16_type, + MATCH_R2_MULI, MASK_R2_MULI, 0, signed_immed16_overflow}, + {"mulxss", "d,s,t", "d,s,t,E", 3, 4, iw_F3X6_type, + MATCH_R2_MULXSS, MASK_R2_MULXSS, 0, no_overflow}, + {"mulxsu", "d,s,t", "d,s,t,E", 3, 4, iw_F3X6_type, + MATCH_R2_MULXSU, MASK_R2_MULXSU, 0, no_overflow}, + {"mulxuu", "d,s,t", "d,s,t,E", 3, 4, iw_F3X6_type, + MATCH_R2_MULXUU, MASK_R2_MULXUU, 0, no_overflow}, + /* The encoding of the neg.n operands is backwards, not + the interpretation -- the first operand is still the + destination and the second the source. */ + {"neg.n", "S,D", "S,D,E", 2, 2, iw_T2X3_type, + MATCH_R2_NEG_N, MASK_R2_NEG_N, 0, no_overflow}, + {"nextpc", "d", "d,E", 1, 4, iw_F3X6_type, + MATCH_R2_NEXTPC, MASK_R2_NEXTPC, 0, no_overflow}, + {"nop", "", "E", 0, 4, iw_F3X6_type, + MATCH_R2_NOP, MASK_R2_NOP, NIOS2_INSN_MACRO_MOV, no_overflow}, + {"nop.n", "", "E", 0, 2, iw_F2_type, + MATCH_R2_NOP_N, MASK_R2_NOP_N, NIOS2_INSN_MACRO_MOV, no_overflow}, + {"nor", "d,s,t", "d,s,t,E", 3, 4, iw_F3X6_type, + MATCH_R2_NOR, MASK_R2_NOR, 0, no_overflow}, + {"not.n", "D,S", "D,S,E", 2, 2, iw_T2X3_type, + MATCH_R2_NOT_N, MASK_R2_NOT_N, 0, no_overflow}, + {"or", "d,s,t", "d,s,t,E", 3, 4, iw_F3X6_type, + MATCH_R2_OR, MASK_R2_OR, 0, no_overflow}, + {"orhi", "t,s,u", "t,s,u,E", 3, 4, iw_F2I16_type, + MATCH_R2_ORHI, MASK_R2_ORHI, 0, unsigned_immed16_overflow}, + {"ori", "t,s,u", "t,s,u,E", 3, 4, iw_F2I16_type, + MATCH_R2_ORI, MASK_R2_ORI, 0, unsigned_immed16_overflow}, + {"or.n", "D,S,T", "D,S,T,E", 3, 2, iw_T2X3_type, + MATCH_R2_OR_N, MASK_R2_OR_N, 0, no_overflow}, + {"pop.n", "R,W", "R,W,E", 2, 2, iw_L5I4X1_type, + MATCH_R2_POP_N, MASK_R2_POP_N, NIOS2_INSN_OPTARG, no_overflow}, + {"push.n", "R,W", "R,W,E", 2, 2, iw_L5I4X1_type, + MATCH_R2_PUSH_N, MASK_R2_PUSH_N, NIOS2_INSN_OPTARG, no_overflow}, + {"rdctl", "d,c", "d,c,E", 2, 4, iw_F3X6L5_type, + MATCH_R2_RDCTL, MASK_R2_RDCTL, 0, no_overflow}, + {"rdprs", "t,s,I", "t,s,I,E", 3, 4, iw_F2X4I12_type, + MATCH_R2_RDPRS, MASK_R2_RDPRS, 0, signed_immed12_overflow}, + {"ret", "", "E", 0, 4, iw_F3X6_type, + MATCH_R2_RET, MASK_R2_RET, 0, no_overflow}, + {"ret.n", "", "E", 0, 2, iw_X2L5_type, + MATCH_R2_RET_N, MASK_R2_RET_N, 0, no_overflow}, + {"rol", "d,s,t", "d,s,t,E", 3, 4, iw_F3X6_type, + MATCH_R2_ROL, MASK_R2_ROL, 0, no_overflow}, + {"roli", "d,s,j", "d,s,j,E", 3, 4, iw_F3X6L5_type, + MATCH_R2_ROLI, MASK_R2_ROLI, 0, unsigned_immed5_overflow}, + {"ror", "d,s,t", "d,s,t,E", 3, 4, iw_F3X6_type, + MATCH_R2_ROR, MASK_R2_ROR, 0, no_overflow}, + {"sll", "d,s,t", "d,s,t,E", 3, 4, iw_F3X6_type, + MATCH_R2_SLL, MASK_R2_SLL, 0, no_overflow}, + {"slli", "d,s,j", "d,s,j,E", 3, 4, iw_F3X6L5_type, + MATCH_R2_SLLI, MASK_R2_SLLI, 0, unsigned_immed5_overflow}, + {"sll.n", "D,S,T", "D,S,T,E", 3, 2, iw_T2X3_type, + MATCH_R2_SLL_N, MASK_R2_SLL_N, 0, no_overflow}, + {"slli.n", "D,S,f", "D,S,f,E", 3, 2, iw_T2X1L3_type, + MATCH_R2_SLLI_N, MASK_R2_SLLI_N, 0, enumeration_overflow}, + {"spaddi.n", "D,U", "D,U,E", 2, 2, iw_T1I7_type, + MATCH_R2_SPADDI_N, MASK_R2_SPADDI_N, 0, address_offset_overflow}, + {"spdeci.n", "U", "U,E", 1, 2, iw_X1I7_type, + MATCH_R2_SPDECI_N, MASK_R2_SPDECI_N, 0, address_offset_overflow}, + {"spinci.n", "U", "U,E", 1, 2, iw_X1I7_type, + MATCH_R2_SPINCI_N, MASK_R2_SPINCI_N, 0, address_offset_overflow}, + {"sra", "d,s,t", "d,s,t,E", 3, 4, iw_F3X6_type, + MATCH_R2_SRA, MASK_R2_SRA, 0, no_overflow}, + {"srai", "d,s,j", "d,s,j,E", 3, 4, iw_F3X6L5_type, + MATCH_R2_SRAI, MASK_R2_SRAI, 0, unsigned_immed5_overflow}, + {"srl", "d,s,t", "d,s,t,E", 3, 4, iw_F3X6_type, + MATCH_R2_SRL, MASK_R2_SRL, 0, no_overflow}, + {"srli", "d,s,j", "d,s,j,E", 3, 4, iw_F3X6L5_type, + MATCH_R2_SRLI, MASK_R2_SRLI, 0, unsigned_immed5_overflow}, + {"srl.n", "D,S,T", "D,S,T,E", 3, 2, iw_T2X3_type, + MATCH_R2_SRL_N, MASK_R2_SRL_N, 0, no_overflow}, + {"srli.n", "D,S,f", "D,S,f,E", 3, 2, iw_T2X1L3_type, + MATCH_R2_SRLI_N, MASK_R2_SRLI_N, 0, enumeration_overflow}, + {"stb", "t,i(s)", "t,i(s),E", 3, 4, iw_F2I16_type, + MATCH_R2_STB, MASK_R2_STB, 0, address_offset_overflow}, + {"stbio", "t,I(s)", "t,I(s),E", 3, 4, iw_F2X4I12_type, + MATCH_R2_STBIO, MASK_R2_STBIO, 0, signed_immed12_overflow}, + {"stb.n", "T,Y(S)", "T,Y(S),E", 3, 2, iw_T2I4_type, + MATCH_R2_STB_N, MASK_R2_STB_N, 0, address_offset_overflow}, + {"stbz.n", "t,M(S)", "t,M(S),E", 3, 2, iw_T1X1I6_type, + MATCH_R2_STBZ_N, MASK_R2_STBZ_N, 0, address_offset_overflow}, + {"stex", "d,t,(s)", "d,t,(s),E", 3, 4, iw_F3X6_type, + MATCH_R2_STEX, MASK_R2_STEX, 0, no_overflow}, + {"sth", "t,i(s)", "t,i(s),E", 3, 4, iw_F2I16_type, + MATCH_R2_STH, MASK_R2_STH, 0, address_offset_overflow}, + {"sthio", "t,I(s)", "t,I(s),E", 3, 4, iw_F2X4I12_type, + MATCH_R2_STHIO, MASK_R2_STHIO, 0, signed_immed12_overflow}, + {"sth.n", "T,X(S)", "T,X(S),E", 3, 2, iw_T2I4_type, + MATCH_R2_STH_N, MASK_R2_STH_N, 0, address_offset_overflow}, + {"stsex", "d,t,(s)", "d,t,(s),E", 3, 4, iw_F3X6_type, + MATCH_R2_STSEX, MASK_R2_STSEX, 0, no_overflow}, + {"stw", "t,i(s)", "t,i(s),E", 3, 4, iw_F2I16_type, + MATCH_R2_STW, MASK_R2_STW, 0, address_offset_overflow}, + {"stwio", "t,I(s)", "t,I(s),E", 3, 4, iw_F2X4I12_type, + MATCH_R2_STWIO, MASK_R2_STWIO, 0, signed_immed12_overflow}, + {"stwm", "R,B", "R,B,E", 2, 4, iw_F1X4L17_type, + MATCH_R2_STWM, MASK_R2_STWM, 0, no_overflow}, + {"stwsp.n", "t,V(s)", "t,V(s),E", 3, 2, iw_F1I5_type, + MATCH_R2_STWSP_N, MASK_R2_STWSP_N, 0, address_offset_overflow}, + {"stw.n", "T,W(S)", "T,W(S),E", 3, 2, iw_T2I4_type, + MATCH_R2_STW_N, MASK_R2_STW_N, 0, address_offset_overflow}, + {"stwz.n", "t,N(S)", "t,N(S),E", 3, 2, iw_T1X1I6_type, + MATCH_R2_STWZ_N, MASK_R2_STWZ_N, 0, address_offset_overflow}, + {"sub", "d,s,t", "d,s,t,E", 3, 4, iw_F3X6_type, + MATCH_R2_SUB, MASK_R2_SUB, 0, no_overflow}, + {"subi", "t,s,i", "t,s,i,E", 3, 4, iw_F2I16_type, + MATCH_R2_SUBI, MASK_R2_SUBI, NIOS2_INSN_MACRO, signed_immed16_overflow}, + {"sub.n", "D,S,T", "D,S,T,E", 3, 2, iw_T3X1_type, + MATCH_R2_SUB_N, MASK_R2_SUB_N, 0, no_overflow}, + {"subi.n", "D,S,e", "D,S,e,E", 3, 2, iw_T2X1I3_type, + MATCH_R2_SUBI_N, MASK_R2_SUBI_N, 0, enumeration_overflow}, + {"sync", "", "E", 0, 4, iw_F3X6_type, + MATCH_R2_SYNC, MASK_R2_SYNC, 0, no_overflow}, + {"trap", "j", "j,E", 1, 4, iw_F3X6L5_type, + MATCH_R2_TRAP, MASK_R2_TRAP, NIOS2_INSN_OPTARG, no_overflow}, + {"trap.n", "j", "j,E", 1, 2, iw_X2L5_type, + MATCH_R2_TRAP_N, MASK_R2_TRAP_N, NIOS2_INSN_OPTARG, no_overflow}, + {"wrctl", "c,s", "c,s,E", 2, 4, iw_F3X6L5_type, + MATCH_R2_WRCTL, MASK_R2_WRCTL, 0, no_overflow}, + {"wrpie", "d,s", "d,s,E", 2, 4, iw_F3X6L5_type, + MATCH_R2_WRPIE, MASK_R2_WRPIE, 0, no_overflow}, + {"wrprs", "d,s", "d,s,E", 2, 4, iw_F3X6_type, + MATCH_R2_WRPRS, MASK_R2_WRPRS, 0, no_overflow}, + {"xor", "d,s,t", "d,s,t,E", 3, 4, iw_F3X6_type, + MATCH_R2_XOR, MASK_R2_XOR, 0, no_overflow}, + {"xorhi", "t,s,u", "t,s,u,E", 3, 4, iw_F2I16_type, + MATCH_R2_XORHI, MASK_R2_XORHI, 0, unsigned_immed16_overflow}, + {"xori", "t,s,u", "t,s,u,E", 3, 4, iw_F2I16_type, + MATCH_R2_XORI, MASK_R2_XORI, 0, unsigned_immed16_overflow}, + {"xor.n", "D,S,T", "D,S,T,E", 3, 2, iw_T2X3_type, + MATCH_R2_XOR_N, MASK_R2_XOR_N, 0, no_overflow}, +}; + +#define NIOS2_NUM_R2_OPCODES \ + ((sizeof nios2_r2_opcodes) / (sizeof (nios2_r2_opcodes[0]))) +const int nios2_num_r2_opcodes = NIOS2_NUM_R2_OPCODES; + +/* Default to using the R1 instruction tables. */ struct nios2_opcode *nios2_opcodes = (struct nios2_opcode *) nios2_r1_opcodes; -int nios2_num_opcodes = NIOS2_NUM_OPCODES; -#undef NIOS2_NUM_OPCODES +int nios2_num_opcodes = NIOS2_NUM_R1_OPCODES; +#undef NIOS2_NUM_R1_OPCODES +#undef NIOS2_NUM_R2_OPCODES + +/* Decodings for R2 asi.n (addi.n/subi.n) immediate values. */ +unsigned int nios2_r2_asi_n_mappings[] = + {1, 2, 4, 8, 16, 32, 64, 128}; +const int nios2_num_r2_asi_n_mappings = 8; + +/* Decodings for R2 shi.n (slli.n/srli.n) immediate values. */ +unsigned int nios2_r2_shi_n_mappings[] = + {1, 2, 3, 8, 12, 16, 24, 31}; +const int nios2_num_r2_shi_n_mappings = 8; + +/* Decodings for R2 andi.n immediate values. */ +unsigned int nios2_r2_andi_n_mappings[] = + {1, 2, 3, 4, 8, 0xf, 0x10, 0x1f, + 0x20, 0x3f, 0x7f, 0x80, 0xff, 0x7ff, 0xff00, 0xffff}; +const int nios2_num_r2_andi_n_mappings = 16; + +/* Decodings for R2 3-bit register fields. */ +int nios2_r2_reg3_mappings[] = + {16, 17, 2, 3, 4, 5, 6, 7}; +const int nios2_num_r2_reg3_mappings = 8; + +/* Decodings for R2 push.n/pop.n REG_RANGE value list. */ +unsigned long nios2_r2_reg_range_mappings[] = { + 0x00010000, + 0x00030000, + 0x00070000, + 0x000f0000, + 0x001f0000, + 0x003f0000, + 0x007f0000, + 0x00ff0000 +}; +const int nios2_num_r2_reg_range_mappings = 8; |