+ if (!is_r2 && (op->match == MATCH_R1_ADD || op->match == MATCH_R1_MOV))
+ {
+ *ra = GET_IW_R_A (insn);
+ *rb = GET_IW_R_B (insn);
+ *rc = GET_IW_R_C (insn);
+ return 1;
+ }
+ else if (!is_r2)
+ return 0;
+ else if (op->match == MATCH_R2_ADD || op->match == MATCH_R2_MOV)
+ {
+ *ra = GET_IW_F3X6L5_A (insn);
+ *rb = GET_IW_F3X6L5_B (insn);
+ *rc = GET_IW_F3X6L5_C (insn);
+ return 1;
+ }
+ else if (op->match == MATCH_R2_ADD_N)
+ {
+ *ra = nios2_r2_reg3_mappings[GET_IW_T3X1_A3 (insn)];
+ *rb = nios2_r2_reg3_mappings[GET_IW_T3X1_B3 (insn)];
+ *rc = nios2_r2_reg3_mappings[GET_IW_T3X1_C3 (insn)];
+ return 1;
+ }
+ else if (op->match == MATCH_R2_MOV_N)
+ {
+ *ra = GET_IW_F2_A (insn);
+ *rb = 0;
+ *rc = GET_IW_F2_B (insn);
+ return 1;
+ }
+ return 0;
+}
+
+/* Match and disassemble a SUB-type instruction, with 3 register operands.
+ Returns true on success, and fills in the operand pointers. */
+
+static int
+nios2_match_sub (uint32_t insn, const struct nios2_opcode *op,
+ unsigned long mach, int *ra, int *rb, int *rc)
+{
+ int is_r2 = (mach == bfd_mach_nios2r2);
+
+ if (!is_r2 && op->match == MATCH_R1_SUB)
+ {
+ *ra = GET_IW_R_A (insn);
+ *rb = GET_IW_R_B (insn);
+ *rc = GET_IW_R_C (insn);
+ return 1;
+ }
+ else if (!is_r2)
+ return 0;
+ else if (op->match == MATCH_R2_SUB)
+ {
+ *ra = GET_IW_F3X6L5_A (insn);
+ *rb = GET_IW_F3X6L5_B (insn);
+ *rc = GET_IW_F3X6L5_C (insn);
+ return 1;
+ }
+ else if (op->match == MATCH_R2_SUB_N)
+ {
+ *ra = nios2_r2_reg3_mappings[GET_IW_T3X1_A3 (insn)];
+ *rb = nios2_r2_reg3_mappings[GET_IW_T3X1_B3 (insn)];
+ *rc = nios2_r2_reg3_mappings[GET_IW_T3X1_C3 (insn)];
+ return 1;
+ }
+ return 0;
+}
+
+/* Match and disassemble an ADDI-type instruction, with 2 register operands
+ and one immediate operand.
+ Returns true on success, and fills in the operand pointers. */
+
+static int
+nios2_match_addi (uint32_t insn, const struct nios2_opcode *op,
+ unsigned long mach, int *ra, int *rb, int *imm)
+{
+ int is_r2 = (mach == bfd_mach_nios2r2);
+
+ if (!is_r2 && op->match == MATCH_R1_ADDI)
+ {
+ *ra = GET_IW_I_A (insn);
+ *rb = GET_IW_I_B (insn);
+ *imm = (signed) (GET_IW_I_IMM16 (insn) << 16) >> 16;
+ return 1;
+ }
+ else if (!is_r2)
+ return 0;
+ else if (op->match == MATCH_R2_ADDI)
+ {
+ *ra = GET_IW_F2I16_A (insn);
+ *rb = GET_IW_F2I16_B (insn);
+ *imm = (signed) (GET_IW_F2I16_IMM16 (insn) << 16) >> 16;
+ return 1;
+ }
+ else if (op->match == MATCH_R2_ADDI_N || op->match == MATCH_R2_SUBI_N)
+ {
+ *ra = nios2_r2_reg3_mappings[GET_IW_T2X1I3_A3 (insn)];
+ *rb = nios2_r2_reg3_mappings[GET_IW_T2X1I3_B3 (insn)];
+ *imm = nios2_r2_asi_n_mappings[GET_IW_T2X1I3_IMM3 (insn)];
+ if (op->match == MATCH_R2_SUBI_N)
+ *imm = - (*imm);
+ return 1;
+ }
+ else if (op->match == MATCH_R2_SPADDI_N)
+ {
+ *ra = nios2_r2_reg3_mappings[GET_IW_T1I7_A3 (insn)];
+ *rb = NIOS2_SP_REGNUM;
+ *imm = GET_IW_T1I7_IMM7 (insn) << 2;
+ return 1;
+ }
+ else if (op->match == MATCH_R2_SPINCI_N || op->match == MATCH_R2_SPDECI_N)
+ {
+ *ra = NIOS2_SP_REGNUM;
+ *rb = NIOS2_SP_REGNUM;
+ *imm = GET_IW_X1I7_IMM7 (insn) << 2;
+ if (op->match == MATCH_R2_SPDECI_N)
+ *imm = - (*imm);
+ return 1;
+ }
+ return 0;
+}
+
+/* Match and disassemble an ORHI-type instruction, with 2 register operands
+ and one unsigned immediate operand.
+ Returns true on success, and fills in the operand pointers. */
+
+static int
+nios2_match_orhi (uint32_t insn, const struct nios2_opcode *op,
+ unsigned long mach, int *ra, int *rb, unsigned int *uimm)
+{
+ int is_r2 = (mach == bfd_mach_nios2r2);
+
+ if (!is_r2 && op->match == MATCH_R1_ORHI)
+ {
+ *ra = GET_IW_I_A (insn);
+ *rb = GET_IW_I_B (insn);
+ *uimm = GET_IW_I_IMM16 (insn);
+ return 1;
+ }
+ else if (!is_r2)
+ return 0;
+ else if (op->match == MATCH_R2_ORHI)
+ {
+ *ra = GET_IW_F2I16_A (insn);
+ *rb = GET_IW_F2I16_B (insn);
+ *uimm = GET_IW_F2I16_IMM16 (insn);
+ return 1;
+ }
+ return 0;
+}
+
+/* Match and disassemble a STW-type instruction, with 2 register operands
+ and one immediate operand.
+ Returns true on success, and fills in the operand pointers. */
+
+static int
+nios2_match_stw (uint32_t insn, const struct nios2_opcode *op,
+ unsigned long mach, int *ra, int *rb, int *imm)
+{
+ int is_r2 = (mach == bfd_mach_nios2r2);
+
+ if (!is_r2 && (op->match == MATCH_R1_STW || op->match == MATCH_R1_STWIO))
+ {
+ *ra = GET_IW_I_A (insn);
+ *rb = GET_IW_I_B (insn);
+ *imm = (signed) (GET_IW_I_IMM16 (insn) << 16) >> 16;
+ return 1;
+ }
+ else if (!is_r2)
+ return 0;
+ else if (op->match == MATCH_R2_STW)
+ {
+ *ra = GET_IW_F2I16_A (insn);
+ *rb = GET_IW_F2I16_B (insn);
+ *imm = (signed) (GET_IW_F2I16_IMM16 (insn) << 16) >> 16;
+ return 1;
+ }
+ else if (op->match == MATCH_R2_STWIO)
+ {
+ *ra = GET_IW_F2X4I12_A (insn);
+ *rb = GET_IW_F2X4I12_B (insn);
+ *imm = (signed) (GET_IW_F2X4I12_IMM12 (insn) << 20) >> 20;
+ return 1;
+ }
+ else if (op->match == MATCH_R2_STW_N)
+ {
+ *ra = nios2_r2_reg3_mappings[GET_IW_T2I4_A3 (insn)];
+ *rb = nios2_r2_reg3_mappings[GET_IW_T2I4_B3 (insn)];
+ *imm = GET_IW_T2I4_IMM4 (insn) << 2;
+ return 1;
+ }
+ else if (op->match == MATCH_R2_STWSP_N)
+ {
+ *ra = NIOS2_SP_REGNUM;
+ *rb = GET_IW_F1I5_B (insn);
+ *imm = GET_IW_F1I5_IMM5 (insn) << 2;
+ return 1;
+ }
+ else if (op->match == MATCH_R2_STWZ_N)
+ {
+ *ra = nios2_r2_reg3_mappings[GET_IW_T1X1I6_A3 (insn)];
+ *rb = 0;
+ *imm = GET_IW_T1X1I6_IMM6 (insn) << 2;
+ return 1;
+ }
+ return 0;
+}
+
+/* Match and disassemble a LDW-type instruction, with 2 register operands
+ and one immediate operand.
+ Returns true on success, and fills in the operand pointers. */
+
+static int
+nios2_match_ldw (uint32_t insn, const struct nios2_opcode *op,
+ unsigned long mach, int *ra, int *rb, int *imm)
+{
+ int is_r2 = (mach == bfd_mach_nios2r2);
+
+ if (!is_r2 && (op->match == MATCH_R1_LDW || op->match == MATCH_R1_LDWIO))
+ {
+ *ra = GET_IW_I_A (insn);
+ *rb = GET_IW_I_B (insn);
+ *imm = (signed) (GET_IW_I_IMM16 (insn) << 16) >> 16;
+ return 1;
+ }
+ else if (!is_r2)
+ return 0;
+ else if (op->match == MATCH_R2_LDW)
+ {
+ *ra = GET_IW_F2I16_A (insn);
+ *rb = GET_IW_F2I16_B (insn);
+ *imm = (signed) (GET_IW_F2I16_IMM16 (insn) << 16) >> 16;
+ return 1;
+ }
+ else if (op->match == MATCH_R2_LDWIO)
+ {
+ *ra = GET_IW_F2X4I12_A (insn);
+ *rb = GET_IW_F2X4I12_B (insn);
+ *imm = (signed) (GET_IW_F2X4I12_IMM12 (insn) << 20) >> 20;
+ return 1;
+ }
+ else if (op->match == MATCH_R2_LDW_N)
+ {
+ *ra = nios2_r2_reg3_mappings[GET_IW_T2I4_A3 (insn)];
+ *rb = nios2_r2_reg3_mappings[GET_IW_T2I4_B3 (insn)];
+ *imm = GET_IW_T2I4_IMM4 (insn) << 2;
+ return 1;
+ }
+ else if (op->match == MATCH_R2_LDWSP_N)
+ {
+ *ra = NIOS2_SP_REGNUM;
+ *rb = GET_IW_F1I5_B (insn);
+ *imm = GET_IW_F1I5_IMM5 (insn) << 2;
+ return 1;
+ }
+ return 0;
+}
+
+/* Match and disassemble a RDCTL instruction, with 2 register operands.
+ Returns true on success, and fills in the operand pointers. */
+
+static int
+nios2_match_rdctl (uint32_t insn, const struct nios2_opcode *op,
+ unsigned long mach, int *ra, int *rc)
+{
+ int is_r2 = (mach == bfd_mach_nios2r2);
+
+ if (!is_r2 && (op->match == MATCH_R1_RDCTL))
+ {
+ *ra = GET_IW_R_IMM5 (insn);
+ *rc = GET_IW_R_C (insn);
+ return 1;
+ }
+ else if (!is_r2)
+ return 0;
+ else if (op->match == MATCH_R2_RDCTL)