]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/nios2-tdep.c
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdb / nios2-tdep.c
index 5b9e2e6a373a34eecf7fbb414517f03799178ecd..196f50bc8694271000a3a2b3b87b85521ced60d4 100644 (file)
@@ -1,5 +1,5 @@
 /* Target-machine dependent code for Nios II, for GDB.
-   Copyright (C) 2012-2013 Free Software Foundation, Inc.
+   Copyright (C) 2012-2024 Free Software Foundation, Inc.
    Contributed by Peter Brookes (pbrookes@altera.com)
    and Andrew Draper (adraper@altera.com).
    Contributed by Mentor Graphics, Inc.
@@ -24,7 +24,7 @@
 #include "frame-unwind.h"
 #include "frame-base.h"
 #include "trad-frame.h"
-#include "dwarf2-frame.h"
+#include "dwarf2/frame.h"
 #include "symtab.h"
 #include "inferior.h"
 #include "gdbtypes.h"
 #include "value.h"
 #include "symfile.h"
 #include "arch-utils.h"
-#include "floatformat.h"
-#include "gdb_assert.h"
 #include "infcall.h"
 #include "regset.h"
 #include "target-descriptions.h"
 
 /* To get entry_point_address.  */
 #include "objfiles.h"
-
-/* Nios II ISA specific encodings and macros.  */
-#include "opcode/nios2.h"
+#include <algorithm>
 
 /* Nios II specific header.  */
 #include "nios2-tdep.h"
 
 /* Control debugging information emitted in this file.  */
 
-static int nios2_debug = 0;
+static bool nios2_debug = false;
 
 /* The following structures are used in the cache for prologue
    analysis; see the reg_value and reg_saved tables in
    struct nios2_unwind_cache, respectively.  */
 
-/* struct reg_value is used to record that a register has the same value
-   as reg at the given offset from the start of a function.  */
+/* struct reg_value is used to record that a register has reg's initial
+   value at the start of a function plus the given constant offset.
+   If reg == 0, then the value is just the offset.
+   If reg < 0, then the value is unknown.  */
 
 struct reg_value
 {
   int reg;
-  unsigned int offset;
+  int offset;
 };
 
 /* struct reg_saved is used to record that a register value has been saved at
@@ -142,17 +140,15 @@ static int nios2_dwarf2gdb_regno_map[] =
   NIOS2_MPUACC_REGNUM     /* 48 */
 };
 
+static_assert (ARRAY_SIZE (nios2_dwarf2gdb_regno_map) == NIOS2_NUM_REGS);
 
 /* Implement the dwarf2_reg_to_regnum gdbarch method.  */
 
 static int
 nios2_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int dw_reg)
 {
-  if (dw_reg < 0 || dw_reg > NIOS2_NUM_REGS)
-    {
-      warning (_("Dwarf-2 uses unmapped register #%d"), dw_reg);
-      return dw_reg;
-    }
+  if (dw_reg < 0 || dw_reg >= NIOS2_NUM_REGS)
+    return -1;
 
   return nios2_dwarf2gdb_regno_map[dw_reg];
 }
@@ -164,7 +160,7 @@ static const char *const nios2_reg_names[NIOS2_NUM_REGS] =
   "zero", "at", "r2", "r3", "r4", "r5", "r6", "r7",
   "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
   "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
-  "et", "bt", "gp", "sp", "fp", "ea", "ba", "ra",
+  "et", "bt", "gp", "sp", "fp", "ea", "sstatus", "ra",
   "pc",
   "status", "estatus", "bstatus", "ienable",
   "ipending", "cpuid", "ctl6", "exception",
@@ -178,7 +174,7 @@ static const char *
 nios2_register_name (struct gdbarch *gdbarch, int regno)
 {
   /* Use mnemonic aliases for GPRs.  */
-  if (regno >= 0 && regno < NIOS2_NUM_REGS)
+  if (regno < NIOS2_NUM_REGS)
     return nios2_reg_names[regno];
   else
     return tdesc_register_name (gdbarch, regno);
@@ -209,17 +205,17 @@ static void
 nios2_extract_return_value (struct gdbarch *gdbarch, struct type *valtype,
                            struct regcache *regcache, gdb_byte *valbuf)
 {
-  int len = TYPE_LENGTH (valtype);
+  int len = valtype->length ();
 
   /* Return values of up to 8 bytes are returned in $r2 $r3.  */
   if (len <= register_size (gdbarch, NIOS2_R2_REGNUM))
-    regcache_cooked_read (regcache, NIOS2_R2_REGNUM, valbuf);
+    regcache->cooked_read (NIOS2_R2_REGNUM, valbuf);
   else
     {
       gdb_assert (len <= (register_size (gdbarch, NIOS2_R2_REGNUM)
                          + register_size (gdbarch, NIOS2_R3_REGNUM)));
-      regcache_cooked_read (regcache, NIOS2_R2_REGNUM, valbuf);
-      regcache_cooked_read (regcache, NIOS2_R3_REGNUM, valbuf + 4);
+      regcache->cooked_read (NIOS2_R2_REGNUM, valbuf);
+      regcache->cooked_read (NIOS2_R3_REGNUM, valbuf + 4);
     }
 }
 
@@ -230,17 +226,17 @@ static void
 nios2_store_return_value (struct gdbarch *gdbarch, struct type *valtype,
                          struct regcache *regcache, const gdb_byte *valbuf)
 {
-  int len = TYPE_LENGTH (valtype);
+  int len = valtype->length ();
 
   /* Return values of up to 8 bytes are returned in $r2 $r3.  */
   if (len <= register_size (gdbarch, NIOS2_R2_REGNUM))
-    regcache_cooked_write (regcache, NIOS2_R2_REGNUM, valbuf);
+    regcache->cooked_write (NIOS2_R2_REGNUM, valbuf);
   else
     {
       gdb_assert (len <= (register_size (gdbarch, NIOS2_R2_REGNUM)
                          + register_size (gdbarch, NIOS2_R3_REGNUM)));
-      regcache_cooked_write (regcache, NIOS2_R2_REGNUM, valbuf);
-      regcache_cooked_write (regcache, NIOS2_R3_REGNUM, valbuf + 4);
+      regcache->cooked_write (NIOS2_R2_REGNUM, valbuf);
+      regcache->cooked_write (NIOS2_R3_REGNUM, valbuf + 4);
     }
 }
 
@@ -253,15 +249,15 @@ nios2_setup_default (struct nios2_unwind_cache *cache)
   int i;
 
   for (i = 0; i < NIOS2_NUM_REGS; i++)
-  {
-    /* All registers start off holding their previous values.  */
-    cache->reg_value[i].reg    = i;
-    cache->reg_value[i].offset = 0;
-
-    /* All registers start off not saved.  */
-    cache->reg_saved[i].basereg = -1;
-    cache->reg_saved[i].addr    = 0;
-  }
+    {
+      /* All registers start off holding their previous values.  */
+      cache->reg_value[i].reg    = i;
+      cache->reg_value[i].offset = 0;
+
+      /* All registers start off not saved.  */
+      cache->reg_saved[i].basereg = -1;
+      cache->reg_saved[i].addr    = 0;
+    }
 }
 
 /* Initialize the unwind cache.  */
@@ -276,112 +272,855 @@ nios2_init_cache (struct nios2_unwind_cache *cache, CORE_ADDR pc)
   nios2_setup_default (cache);
 }
 
-/* Helper function to identify when we're in a function epilogue;
-   that is, the part of the function from the point at which the
-   stack adjustment is made, to the return or sibcall.  On Nios II,
-   we want to check that the CURRENT_PC is a return-type instruction
-   and that the previous instruction is a stack adjustment.
-   START_PC is the beginning of the function in question.  */
+/* Read and identify an instruction at PC.  If INSNP is non-null,
+   store the instruction word into that location.  Return the opcode
+   pointer or NULL if the memory couldn't be read or disassembled.  */
+
+static const struct nios2_opcode *
+nios2_fetch_insn (struct gdbarch *gdbarch, CORE_ADDR pc,
+                 unsigned int *insnp)
+{
+  LONGEST memword;
+  unsigned long mach = gdbarch_bfd_arch_info (gdbarch)->mach;
+  unsigned int insn;
+
+  if (mach == bfd_mach_nios2r2)
+    {
+      if (!safe_read_memory_integer (pc, NIOS2_OPCODE_SIZE,
+                                    BFD_ENDIAN_LITTLE, &memword)
+         && !safe_read_memory_integer (pc, NIOS2_CDX_OPCODE_SIZE,
+                                       BFD_ENDIAN_LITTLE, &memword))
+       return NULL;
+    }
+  else if (!safe_read_memory_integer (pc, NIOS2_OPCODE_SIZE,
+                                     gdbarch_byte_order (gdbarch), &memword))
+    return NULL;
+
+  insn = (unsigned int) memword;
+  if (insnp)
+    *insnp = insn;
+  return nios2_find_opcode_hash (insn, mach);
+}
+
+
+/* Match and disassemble an ADD-type instruction, with 3 register operands.
+   Returns true on success, and fills in the operand pointers.  */
 
 static int
-nios2_in_epilogue_p (struct gdbarch *gdbarch,
-                    CORE_ADDR current_pc,
-                    CORE_ADDR start_pc)
+nios2_match_add (uint32_t insn, const struct nios2_opcode *op,
+                unsigned long mach, int *ra, int *rb, int *rc)
 {
-  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  int is_r2 = (mach == bfd_mach_nios2r2);
 
-  /* There has to be a previous instruction in the function.  */
-  if (current_pc > start_pc)
+  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.  */
 
-      /* Check whether the previous instruction was a stack
-        adjustment.  */
-      unsigned int insn
-        = read_memory_unsigned_integer (current_pc - NIOS2_OPCODE_SIZE,
-                                       NIOS2_OPCODE_SIZE, byte_order);
+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 ((insn & 0xffc0003c) == 0xdec00004    /* ADDI sp, sp, */
-         || (insn & 0xffc1ffff) == 0xdec1883a  /* ADD  sp, sp, */
-         || (insn & 0xffc0003f) == 0xdec00017) /* LDW  sp, constant(sp) */
+  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)
+    {
+      *ra = GET_IW_F3X6L5_IMM5 (insn);
+      *rc = GET_IW_F3X6L5_C (insn);
+      return 1;
+    }
+  return 0;
+}
+
+/* Match and disassemble a PUSH.N or STWM instruction.
+   Returns true on success, and fills in the operand pointers.  */
+
+static int
+nios2_match_stwm (uint32_t insn, const struct nios2_opcode *op,
+                 unsigned long mach, unsigned int *reglist,
+                 int *ra, int *imm, int *wb, int *id)
+{
+  int is_r2 = (mach == bfd_mach_nios2r2);
+
+  if (!is_r2)
+    return 0;
+  else if (op->match == MATCH_R2_PUSH_N)
+    {
+      *reglist = 1 << 31;
+      if (GET_IW_L5I4X1_FP (insn))
+       *reglist |= (1 << 28);
+      if (GET_IW_L5I4X1_CS (insn))
+       {
+         int val = GET_IW_L5I4X1_REGRANGE (insn);
+         *reglist |= nios2_r2_reg_range_mappings[val];
+       }
+      *ra = NIOS2_SP_REGNUM;
+      *imm = GET_IW_L5I4X1_IMM4 (insn) << 2;
+      *wb = 1;
+      *id = 0;
+      return 1;
+    }
+  else if (op->match == MATCH_R2_STWM)
+    {
+      unsigned int rawmask = GET_IW_F1X4L17_REGMASK (insn);
+      if (GET_IW_F1X4L17_RS (insn))
        {
-         /* Then check if it's followed by a return or a tail
-            call.  */
-          insn = read_memory_unsigned_integer (current_pc, NIOS2_OPCODE_SIZE,
-                                              byte_order);
-
-         if (insn == 0xf800283a                        /* RET */
-             || insn == 0xe800083a                     /* ERET */
-             || (insn & 0x07ffffff) == 0x0000683a      /* JMP */
-             || (insn & 0xffc0003f) == 6)              /* BR */
-           return 1;
+         *reglist = ((rawmask << 14) & 0x00ffc000);
+         if (rawmask & (1 << 10))
+           *reglist |= (1 << 28);
+         if (rawmask & (1 << 11))
+           *reglist |= (1 << 31);
        }
+      else
+       *reglist = rawmask << 2;
+      *ra = GET_IW_F1X4L17_A (insn);
+      *imm = 0;
+      *wb = GET_IW_F1X4L17_WB (insn);
+      *id = GET_IW_F1X4L17_ID (insn);
+      return 1;
     }
   return 0;
 }
 
-/* Implement the in_function_epilogue_p gdbarch method.  */
+/* Match and disassemble a POP.N or LDWM instruction.
+   Returns true on success, and fills in the operand pointers.  */
 
 static int
-nios2_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+nios2_match_ldwm (uint32_t insn, const struct nios2_opcode *op,
+                 unsigned long mach, unsigned int *reglist,
+                 int *ra, int *imm, int *wb, int *id, int *ret)
 {
-  CORE_ADDR func_addr;
+  int is_r2 = (mach == bfd_mach_nios2r2);
 
-  if (find_pc_partial_function (pc, NULL, &func_addr, NULL))
-    return nios2_in_epilogue_p (gdbarch, pc, func_addr);
+  if (!is_r2)
+    return 0;
+  else if (op->match == MATCH_R2_POP_N)
+    {
+      *reglist = 1 << 31;
+      if (GET_IW_L5I4X1_FP (insn))
+       *reglist |= (1 << 28);
+      if (GET_IW_L5I4X1_CS (insn))
+       {
+         int val = GET_IW_L5I4X1_REGRANGE (insn);
+         *reglist |= nios2_r2_reg_range_mappings[val];
+       }
+      *ra = NIOS2_SP_REGNUM;
+      *imm = GET_IW_L5I4X1_IMM4 (insn) << 2;
+      *wb = 1;
+      *id = 1;
+      *ret = 1;
+      return 1;
+    }
+  else if (op->match == MATCH_R2_LDWM)
+    {
+      unsigned int rawmask = GET_IW_F1X4L17_REGMASK (insn);
+      if (GET_IW_F1X4L17_RS (insn))
+       {
+         *reglist = ((rawmask << 14) & 0x00ffc000);
+         if (rawmask & (1 << 10))
+           *reglist |= (1 << 28);
+         if (rawmask & (1 << 11))
+           *reglist |= (1 << 31);
+       }
+      else
+       *reglist = rawmask << 2;
+      *ra = GET_IW_F1X4L17_A (insn);
+      *imm = 0;
+      *wb = GET_IW_F1X4L17_WB (insn);
+      *id = GET_IW_F1X4L17_ID (insn);
+      *ret = GET_IW_F1X4L17_PC (insn);
+      return 1;
+    }
+  return 0;
+}
+
+/* Match and disassemble a branch instruction, with (potentially)
+   2 register operands and one immediate operand.
+   Returns true on success, and fills in the operand pointers.  */
+
+enum branch_condition {
+  branch_none,
+  branch_eq,
+  branch_ne,
+  branch_ge,
+  branch_geu,
+  branch_lt,
+  branch_ltu
+};
+  
+static int
+nios2_match_branch (uint32_t insn, const struct nios2_opcode *op,
+                   unsigned long mach, int *ra, int *rb, int *imm,
+                   enum branch_condition *cond)
+{
+  int is_r2 = (mach == bfd_mach_nios2r2);
 
+  if (!is_r2)
+    {
+      switch (op->match)
+       {
+       case MATCH_R1_BR:
+         *cond = branch_none;
+         break;
+       case MATCH_R1_BEQ:
+         *cond = branch_eq;
+         break;
+       case MATCH_R1_BNE:
+         *cond = branch_ne;
+         break;
+       case MATCH_R1_BGE:
+         *cond = branch_ge;
+         break;
+       case MATCH_R1_BGEU:
+         *cond = branch_geu;
+         break;
+       case MATCH_R1_BLT:
+         *cond = branch_lt;
+         break;
+       case MATCH_R1_BLTU:
+         *cond = branch_ltu;
+         break;
+       default:
+         return 0;
+       }
+      *imm = (signed) (GET_IW_I_IMM16 (insn) << 16) >> 16;
+      *ra = GET_IW_I_A (insn);
+      *rb = GET_IW_I_B (insn);
+      return 1;
+    }
+  else
+    {
+      switch (op->match)
+       {
+       case MATCH_R2_BR_N:
+         *cond = branch_none;
+         *ra = NIOS2_Z_REGNUM;
+         *rb = NIOS2_Z_REGNUM;
+         *imm = (signed) ((GET_IW_I10_IMM10 (insn) << 1) << 21) >> 21;
+         return 1;
+       case MATCH_R2_BEQZ_N:
+         *cond = branch_eq;
+         *ra = nios2_r2_reg3_mappings[GET_IW_T1I7_A3 (insn)];
+         *rb = NIOS2_Z_REGNUM;
+         *imm = (signed) ((GET_IW_T1I7_IMM7 (insn) << 1) << 24) >> 24;
+         return 1;
+       case MATCH_R2_BNEZ_N:
+         *cond = branch_ne;
+         *ra = nios2_r2_reg3_mappings[GET_IW_T1I7_A3 (insn)];
+         *rb = NIOS2_Z_REGNUM;
+         *imm = (signed) ((GET_IW_T1I7_IMM7 (insn) << 1) << 24) >> 24;
+         return 1;
+       case MATCH_R2_BR:
+         *cond = branch_none;
+         break;
+       case MATCH_R2_BEQ:
+         *cond = branch_eq;
+         break;
+       case MATCH_R2_BNE:
+         *cond = branch_ne;
+         break;
+       case MATCH_R2_BGE:
+         *cond = branch_ge;
+         break;
+       case MATCH_R2_BGEU:
+         *cond = branch_geu;
+         break;
+       case MATCH_R2_BLT:
+         *cond = branch_lt;
+         break;
+       case MATCH_R2_BLTU:
+         *cond = branch_ltu;
+         break;
+       default:
+         return 0;
+       }
+      *ra = GET_IW_F2I16_A (insn);
+      *rb = GET_IW_F2I16_B (insn);
+      *imm = (signed) (GET_IW_F2I16_IMM16 (insn) << 16) >> 16;
+      return 1;
+    }
   return 0;
 }
 
-/* Define some instruction patterns supporting wildcard bits via a
-   mask.  */
+/* Match and disassemble a direct jump instruction, with an
+   unsigned operand.  Returns true on success, and fills in the operand
+   pointer.  */
 
-typedef struct
+static int
+nios2_match_jmpi (uint32_t insn, const struct nios2_opcode *op,
+                 unsigned long mach, unsigned int *uimm)
 {
-  unsigned int insn;
-  unsigned int mask;
-} wild_insn;
+  int is_r2 = (mach == bfd_mach_nios2r2);
+
+  if (!is_r2 && op->match == MATCH_R1_JMPI)
+    {
+      *uimm = GET_IW_J_IMM26 (insn) << 2;
+      return 1;
+    }
+  else if (!is_r2)
+    return 0;
+  else if (op->match == MATCH_R2_JMPI)
+    {
+      *uimm = GET_IW_L26_IMM26 (insn) << 2;
+      return 1;
+    }
+  return 0;
+}
+
+/* Match and disassemble a direct call instruction, with an
+   unsigned operand.  Returns true on success, and fills in the operand
+   pointer.  */
 
-static const wild_insn profiler_insn[] =
+static int
+nios2_match_calli (uint32_t insn, const struct nios2_opcode *op,
+                  unsigned long mach, unsigned int *uimm)
 {
-  { 0x0010e03a, 0x00000000 }, /* nextpc r8 */
-  { 0xf813883a, 0x00000000 }, /* mov    r9,ra */
-  { 0x02800034, 0x003fffc0 }, /* movhi  r10,257 */
-  { 0x52800004, 0x003fffc0 }, /* addi   r10,r10,-31992 */
-  { 0x00000000, 0xffffffc0 }, /* call   <mcount> */
-  { 0x483f883a, 0x00000000 }  /* mov    ra,r9 */
-};
+  int is_r2 = (mach == bfd_mach_nios2r2);
+
+  if (!is_r2 && op->match == MATCH_R1_CALL)
+    {
+      *uimm = GET_IW_J_IMM26 (insn) << 2;
+      return 1;
+    }
+  else if (!is_r2)
+    return 0;
+  else if (op->match == MATCH_R2_CALL)
+    {
+      *uimm = GET_IW_L26_IMM26 (insn) << 2;
+      return 1;
+    }
+  return 0;
+}
+
+/* Match and disassemble an indirect jump instruction, with a
+   (possibly implicit) register operand.  Returns true on success, and fills
+   in the operand pointer.  */
 
-static const wild_insn irqentry_insn[] =
+static int
+nios2_match_jmpr (uint32_t insn, const struct nios2_opcode *op,
+                 unsigned long mach, int *ra)
 {
-  { 0x0031307a, 0x00000000 }, /* rdctl  et,estatus */
-  { 0xc600004c, 0x00000000 }, /* andi   et,et,1 */
-  { 0xc0000026, 0x003fffc0 }, /* beq    et,zero, <software_exception> */
-  { 0x0031313a, 0x00000000 }, /* rdctl  et,ipending */
-  { 0xc0000026, 0x003fffc0 }  /* beq    et,zero, <software_exception> */
-};
+  int is_r2 = (mach == bfd_mach_nios2r2);
+
+  if (!is_r2)
+    switch (op->match)
+      {
+      case MATCH_R1_JMP:
+       *ra = GET_IW_I_A (insn);
+       return 1;
+      case MATCH_R1_RET:
+       *ra = NIOS2_RA_REGNUM;
+       return 1;
+      case MATCH_R1_ERET:
+       *ra = NIOS2_EA_REGNUM;
+       return 1;
+      case MATCH_R1_BRET:
+       *ra = NIOS2_BA_REGNUM;
+       return 1;
+      default:
+       return 0;
+      }
+  else
+    switch (op->match)
+      {
+      case MATCH_R2_JMP:
+       *ra = GET_IW_F2I16_A (insn);
+       return 1;
+      case MATCH_R2_JMPR_N:
+       *ra = GET_IW_F1X1_A (insn);
+       return 1;
+      case MATCH_R2_RET:
+      case MATCH_R2_RET_N:
+       *ra = NIOS2_RA_REGNUM;
+       return 1;
+      case MATCH_R2_ERET:
+       *ra = NIOS2_EA_REGNUM;
+       return 1;
+      case MATCH_R2_BRET:
+       *ra = NIOS2_BA_REGNUM;
+       return 1;
+      default:
+       return 0;
+      }
+  return 0;
+}
 
+/* Match and disassemble an indirect call instruction, with a register
+   operand.  Returns true on success, and fills in the operand pointer.  */
 
-/* Attempt to match SEQUENCE, which is COUNT insns long, at START_PC.  */
+static int
+nios2_match_callr (uint32_t insn, const struct nios2_opcode *op,
+                  unsigned long mach, int *ra)
+{
+  int is_r2 = (mach == bfd_mach_nios2r2);
+
+  if (!is_r2 && op->match == MATCH_R1_CALLR)
+    {
+      *ra = GET_IW_I_A (insn);
+      return 1;
+    }
+  else if (!is_r2)
+    return 0;
+  else if (op->match == MATCH_R2_CALLR)
+    {
+      *ra = GET_IW_F2I16_A (insn);
+      return 1;
+    }
+  else if (op->match == MATCH_R2_CALLR_N)
+    {
+      *ra = GET_IW_F1X1_A (insn);
+      return 1;
+    }
+  return 0;
+}
+
+/* Match and disassemble a break instruction, with an unsigned operand.
+   Returns true on success, and fills in the operand pointer.  */
 
 static int
-nios2_match_sequence (struct gdbarch *gdbarch, CORE_ADDR start_pc,
-                     const wild_insn *sequence, int count)
+nios2_match_break (uint32_t insn, const struct nios2_opcode *op,
+                 unsigned long mach, unsigned int *uimm)
 {
-  CORE_ADDR pc = start_pc;
-  int i;
+  int is_r2 = (mach == bfd_mach_nios2r2);
+
+  if (!is_r2 && op->match == MATCH_R1_BREAK)
+    {
+      *uimm = GET_IW_R_IMM5 (insn);
+      return 1;
+    }
+  else if (!is_r2)
+    return 0;
+  else if (op->match == MATCH_R2_BREAK)
+    {
+      *uimm = GET_IW_F3X6L5_IMM5 (insn);
+      return 1;
+    }
+  else if (op->match == MATCH_R2_BREAK_N)
+    {
+      *uimm = GET_IW_X2L5_IMM5 (insn);
+      return 1;
+    }
+  return 0;
+}
+
+/* Match and disassemble a trap instruction, with an unsigned operand.
+   Returns true on success, and fills in the operand pointer.  */
+
+static int
+nios2_match_trap (uint32_t insn, const struct nios2_opcode *op,
+                 unsigned long mach, unsigned int *uimm)
+{
+  int is_r2 = (mach == bfd_mach_nios2r2);
+
+  if (!is_r2 && op->match == MATCH_R1_TRAP)
+    {
+      *uimm = GET_IW_R_IMM5 (insn);
+      return 1;
+    }
+  else if (!is_r2)
+    return 0;
+  else if (op->match == MATCH_R2_TRAP)
+    {
+      *uimm = GET_IW_F3X6L5_IMM5 (insn);
+      return 1;
+    }
+  else if (op->match == MATCH_R2_TRAP_N)
+    {
+      *uimm = GET_IW_X2L5_IMM5 (insn);
+      return 1;
+    }
+  return 0;
+}
+
+/* Helper function to identify when we're in a function epilogue;
+   that is, the part of the function from the point at which the
+   stack adjustments are made, to the return or sibcall.
+   Note that we may have several stack adjustment instructions, and
+   this function needs to test whether the stack teardown has already
+   started before current_pc, not whether it has completed.  */
+
+static int
+nios2_in_epilogue_p (struct gdbarch *gdbarch,
+                    CORE_ADDR current_pc,
+                    CORE_ADDR start_pc)
+{
+  unsigned long mach = gdbarch_bfd_arch_info (gdbarch)->mach;
+  int is_r2 = (mach == bfd_mach_nios2r2);
+  /* Maximum number of possibly-epilogue instructions to check.
+     Note that this number should not be too large, else we can
+     potentially end up iterating through unmapped memory.  */
+  int ninsns, max_insns = 5;
   unsigned int insn;
-  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  const struct nios2_opcode *op = NULL;
+  unsigned int uimm;
+  int imm;
+  int wb, id, ret;
+  int ra, rb, rc;
+  enum branch_condition cond;
+  CORE_ADDR pc;
+
+  /* There has to be a previous instruction in the function.  */
+  if (current_pc <= start_pc)
+    return 0;
 
-  for (i = 0 ; i < count ; i++)
+  /* Find the previous instruction before current_pc.  For R2, it might
+     be either a 16-bit or 32-bit instruction; the only way to know for
+     sure is to scan through from the beginning of the function,
+     disassembling as we go.  */
+  if (is_r2)
+    for (pc = start_pc; ; )
+      {
+       op = nios2_fetch_insn (gdbarch, pc, &insn);
+       if (op == NULL)
+         return 0;
+       if (pc + op->size < current_pc)
+         pc += op->size;
+       else
+         break;
+       /* We can skip over insns to a forward branch target.  Since
+          the branch offset is relative to the next instruction,
+          it's correct to do this after incrementing the pc above.  */
+       if (nios2_match_branch (insn, op, mach, &ra, &rb, &imm, &cond)
+           && imm > 0
+           && pc + imm < current_pc)
+         pc += imm;
+      }
+  /* Otherwise just go back to the previous 32-bit insn.  */
+  else
+    pc = current_pc - NIOS2_OPCODE_SIZE;
+
+  /* Beginning with the previous instruction we just located, check whether
+     we are in a sequence of at least one stack adjustment instruction.
+     Possible instructions here include:
+        ADDI sp, sp, n
+        ADD sp, sp, rn
+        LDW sp, n(sp)
+        SPINCI.N n
+        LDWSP.N sp, n(sp)
+        LDWM {reglist}, (sp)++, wb */
+  for (ninsns = 0; ninsns < max_insns; ninsns++)
     {
-      insn = read_memory_unsigned_integer (pc, NIOS2_OPCODE_SIZE, byte_order);
-      if ((insn & ~sequence[i].mask) != sequence[i].insn)
-       return 0;
+      int ok = 0;
 
-      pc += NIOS2_OPCODE_SIZE;
+      /* Fetch the insn at pc.  */
+      op = nios2_fetch_insn (gdbarch, pc, &insn);
+      if (op == NULL)
+       return 0;
+      pc += op->size;
+
+      /* Was it a stack adjustment?  */
+      if (nios2_match_addi (insn, op, mach, &ra, &rb, &imm))
+       ok = (rb == NIOS2_SP_REGNUM);
+      else if (nios2_match_add (insn, op, mach, &ra, &rb, &rc))
+       ok = (rc == NIOS2_SP_REGNUM);
+      else if (nios2_match_ldw (insn, op, mach, &ra, &rb, &imm))
+       ok = (rb == NIOS2_SP_REGNUM);
+      else if (nios2_match_ldwm (insn, op, mach, &uimm, &ra,
+                                &imm, &wb, &ret, &id))
+       ok = (ra == NIOS2_SP_REGNUM && wb && id);
+      if (!ok)
+       break;
     }
 
-  return 1;
+  /* No stack adjustments found.  */
+  if (ninsns == 0)
+    return 0;
+
+  /* We found more stack adjustments than we expect GCC to be generating.
+     Since it looks like a stack unwind might be in progress tell GDB to
+     treat it as such.  */
+  if (ninsns == max_insns)
+    return 1;
+
+  /* The next instruction following the stack adjustments must be a
+     return, jump, or unconditional branch, or a CDX pop.n or ldwm
+     that does an implicit return.  */
+  if (nios2_match_jmpr (insn, op, mach, &ra)
+      || nios2_match_jmpi (insn, op, mach, &uimm)
+      || (nios2_match_ldwm (insn, op, mach, &uimm, &ra, &imm, &wb, &id, &ret)
+         && ret)
+      || (nios2_match_branch (insn, op, mach, &ra, &rb, &imm, &cond)
+         && cond == branch_none))
+    return 1;
+
+  return 0;
+}
+
+/* Implement the stack_frame_destroyed_p gdbarch method.  */
+
+static int
+nios2_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  CORE_ADDR func_addr;
+
+  if (find_pc_partial_function (pc, NULL, &func_addr, NULL))
+    return nios2_in_epilogue_p (gdbarch, pc, func_addr);
+
+  return 0;
 }
 
 /* Do prologue analysis, returning the PC of the first instruction
@@ -390,92 +1129,74 @@ nios2_match_sequence (struct gdbarch *gdbarch, CORE_ADDR start_pc,
    interested in skipping the prologue.  Otherwise CACHE is filled in
    from the frame information.
 
-   The prologue will consist of the following parts:
-     1) Optional profiling instrumentation.  The old version uses six
-        instructions.  We step over this if there is an exact match.
-         nextpc r8
-         mov    r9, ra
-         movhi  r10, %hiadj(.LP2)
-         addi   r10, r10, %lo(.LP2)
-         call   mcount
-         mov    ra, r9
-       The new version uses two or three instructions (the last of
-       these might get merged in with the STW which saves RA to the
-       stack).  We interpret these.
+   The prologue may consist of the following parts:
+     1) Profiling instrumentation.  For non-PIC code it looks like:
          mov    r8, ra
          call   mcount
          mov    ra, r8
 
-     2) Optional interrupt entry decision.  Again, we step over
-        this if there is an exact match.
-         rdctl  et,estatus
-         andi   et,et,1
-         beq    et,zero, <software_exception>
-         rdctl  et,ipending
-         beq    et,zero, <software_exception>
-
-     3) A stack adjustment or stack which, which will be one of:
-         addi   sp, sp, -constant
-       or:
-         movi   r8, constant
-         sub    sp, sp, r8
-       or
-         movhi  r8, constant
-         addi   r8, r8, constant
-         sub    sp, sp, r8
-       or
+     2) A stack adjustment and save of R4-R7 for varargs functions.
+       For R2 CDX this is typically handled with a STWM, otherwise
+       this is typically merged with item 3.
+
+     3) A stack adjustment and save of the callee-saved registers.
+       For R2 CDX these are typically handled with a PUSH.N or STWM,
+       otherwise as an explicit SP decrement and individual register
+       saves.
+
+       There may also be a stack switch here in an exception handler
+       in place of a stack adjustment.  It looks like:
          movhi  rx, %hiadj(newstack)
          addhi  rx, rx, %lo(newstack)
          stw    sp, constant(rx)
          mov    sp, rx
 
-     4) An optional stack check, which can take either of these forms:
+     4) A frame pointer save, which can be either a MOV or ADDI.
+
+     5) A further stack pointer adjustment.  This is normally included
+       adjustment in step 3 unless the total adjustment is too large
+       to be done in one step.
+
+     7) A stack overflow check, which can take either of these forms:
          bgeu   sp, rx, +8
-         break  3
+         trap  3
        or
          bltu   sp, rx, .Lstack_overflow
          ...
        .Lstack_overflow:
-         break  3
+         trap  3
+         
+       Older versions of GCC emitted "break 3" instead of "trap 3" here,
+       so we check for both cases.
 
-     5) Saving any registers which need to be saved.  These will
-        normally just be stored onto the stack:
-         stw    rx, constant(sp)
-       but in the large frame case will use r8 as an offset back
-       to the cfa:
-         add    r8, r8, sp
-         stw    rx, -constant(r8)
+       Older GCC versions emitted stack overflow checks after the SP
+       adjustments in both steps 3 and 4.  Starting with GCC 6, there is
+       at most one overflow check, which is placed before the first
+       stack adjustment for R2 CDX and after the first stack adjustment
+       otherwise.
 
-       Saving control registers looks slightly different:
-         rdctl  rx, ctlN
-         stw    rx, constant(sp)
-
-     6) An optional FP setup, either if the user has requested a
-        frame pointer or if the function calls alloca.
-        This is always:
-         mov    fp, sp
-
-    The prologue instructions may be interleaved, and the register
-    saves and FP setup can occur in either order.
+    The prologue instructions may be combined or interleaved with other
+    instructions.
 
     To cope with all this variability we decode all the instructions
-    from the start of the prologue until we hit a branch, call or
-    return.  For each of the instructions mentioned in 3, 4 and 5 we
-    handle the limited cases of stores to the stack and operations
-    on constant values.  */
+    from the start of the prologue until we hit an instruction that
+    cannot possibly be a prologue instruction, such as a branch, call,
+    return, or epilogue instruction.  The prologue is considered to end
+    at the last instruction that can definitely be considered a
+    prologue instruction.  */
 
 static CORE_ADDR
 nios2_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR start_pc,
                        const CORE_ADDR current_pc,
                        struct nios2_unwind_cache *cache,
-                       struct frame_info *this_frame)
+                       frame_info_ptr this_frame)
 {
-  /* Maximum lines of prologue to check.
+  /* Maximum number of possibly-prologue instructions to check.
      Note that this number should not be too large, else we can
      potentially end up iterating through unmapped memory.  */
-  CORE_ADDR limit_pc = start_pc + 200;
-  int regno;
+  int ninsns, max_insns = 50;
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  unsigned long mach = gdbarch_bfd_arch_info (gdbarch)->mach;
 
   /* Does the frame set up the FP register?  */
   int base_reg = 0;
@@ -483,8 +1204,6 @@ nios2_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR start_pc,
   struct reg_value *value = cache->reg_value;
   struct reg_value temp_value[NIOS2_NUM_REGS];
 
-  int i;
-
   /* Save the starting PC so we can correct the pc after running
      through the prolog, using symbol info.  */
   CORE_ADDR pc = start_pc;
@@ -496,77 +1215,66 @@ nios2_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR start_pc,
      functions which switch stacks?  */
   CORE_ADDR frame_high;
 
-  /* Is this the end of the prologue?  */
-  int within_prologue = 1;
-
+  /* The last definitely-prologue instruction seen.  */
   CORE_ADDR prologue_end;
 
   /* Is this the innermost function?  */
   int innermost = (this_frame ? (frame_relative_level (this_frame) == 0) : 1);
 
   if (nios2_debug)
-    fprintf_unfiltered (gdb_stdlog,
-                       "{ nios2_analyze_prologue start=%s, current=%s ",
-                       paddress (gdbarch, start_pc),
-                       paddress (gdbarch, current_pc));
+    gdb_printf (gdb_stdlog,
+               "{ nios2_analyze_prologue start=%s, current=%s ",
+               paddress (gdbarch, start_pc),
+               paddress (gdbarch, current_pc));
 
   /* Set up the default values of the registers.  */
   nios2_setup_default (cache);
 
-  /* If the first few instructions are the profile entry, then skip
-     over them.  Newer versions of the compiler use more efficient
-     profiling code.  */
-  if (nios2_match_sequence (gdbarch, pc, profiler_insn,
-                           ARRAY_SIZE (profiler_insn)))
-    pc += ARRAY_SIZE (profiler_insn) * NIOS2_OPCODE_SIZE;
-
-  /* If the first few instructions are an interrupt entry, then skip
-     over them too.  */
-  if (nios2_match_sequence (gdbarch, pc, irqentry_insn,
-                           ARRAY_SIZE (irqentry_insn)))
-    {
-      pc += ARRAY_SIZE (irqentry_insn) * NIOS2_OPCODE_SIZE;
-      exception_handler = 1;
-    }
-
-  prologue_end = start_pc;
-
   /* Find the prologue instructions.  */
-  while (pc < limit_pc && within_prologue)
+  prologue_end = start_pc;
+  for (ninsns = 0; ninsns < max_insns; ninsns++)
     {
       /* Present instruction.  */
       uint32_t insn;
-
-      int prologue_insn = 0;
+      const struct nios2_opcode *op;
+      int ra, rb, rc, imm;
+      unsigned int uimm;
+      unsigned int reglist;
+      int wb, id, ret;
+      enum branch_condition cond;
 
       if (pc == current_pc)
-      {
-       /* When we reach the current PC we must save the current
-          register state (for the backtrace) but keep analysing
-          because there might be more to find out (eg. is this an
-          exception handler).  */
-       memcpy (temp_value, value, sizeof (temp_value));
-       value = temp_value;
-       if (nios2_debug)
-         fprintf_unfiltered (gdb_stdlog, "*");
-      }
+       {
+         /* When we reach the current PC we must save the current
+            register state (for the backtrace) but keep analysing
+            because there might be more to find out (eg. is this an
+            exception handler).  */
+         memcpy (temp_value, value, sizeof (temp_value));
+         value = temp_value;
+         if (nios2_debug)
+           gdb_printf (gdb_stdlog, "*");
+       }
+
+      op = nios2_fetch_insn (gdbarch, pc, &insn);
 
-      insn = read_memory_unsigned_integer (pc, NIOS2_OPCODE_SIZE, byte_order);
-      pc += NIOS2_OPCODE_SIZE;
+      /* Unknown opcode?  Stop scanning.  */
+      if (op == NULL)
+       break;
+      pc += op->size;
 
       if (nios2_debug)
-       fprintf_unfiltered (gdb_stdlog, "[%08X]", insn);
+       {
+         if (op->size == 2)
+           gdb_printf (gdb_stdlog, "[%04X]", insn & 0xffff);
+         else
+           gdb_printf (gdb_stdlog, "[%08X]", insn);
+       }
 
       /* The following instructions can appear in the prologue.  */
 
-      if ((insn & 0x0001ffff) == 0x0001883a)
+      if (nios2_match_add (insn, op, mach, &ra, &rb, &rc))
        {
          /* ADD   rc, ra, rb  (also used for MOV) */
-
-         int ra = GET_IW_A (insn);
-         int rb = GET_IW_B (insn);
-         int rc = GET_IW_C (insn);
-
          if (rc == NIOS2_SP_REGNUM
              && rb == 0
              && value[ra].reg == cache->reg_saved[NIOS2_SP_REGNUM].basereg)
@@ -577,7 +1285,7 @@ nios2_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR start_pc,
 
              /* If any registers were saved on the stack before then
                 we can't backtrace into them now.  */
-             for (i = 0 ; i < NIOS2_NUM_REGS ; i++)
+             for (int i = 0 ; i < NIOS2_NUM_REGS ; i++)
                {
                  if (cache->reg_saved[i].basereg == NIOS2_SP_REGNUM)
                    cache->reg_saved[i].basereg = -1;
@@ -597,6 +1305,11 @@ nios2_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR start_pc,
              cache->reg_saved[NIOS2_SP_REGNUM].addr = -4;
            }
 
+         else if (rc == NIOS2_SP_REGNUM && ra == NIOS2_FP_REGNUM)
+           /* This is setting SP from FP.  This only happens in the
+              function epilogue.  */
+           break;
+
          else if (rc != 0)
            {
              if (value[rb].reg == 0)
@@ -607,18 +1320,22 @@ nios2_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR start_pc,
                value[rc].reg = -1;
              value[rc].offset = value[ra].offset + value[rb].offset;
            }
-         prologue_insn = 1;
-       }
 
-      else if ((insn & 0x0001ffff) == 0x0001983a)
+         /* The add/move is only considered a prologue instruction
+            if the destination is SP or FP.  */
+         if (rc == NIOS2_SP_REGNUM || rc == NIOS2_FP_REGNUM)
+           prologue_end = pc;
+       }
+      
+      else if (nios2_match_sub (insn, op, mach, &ra, &rb, &rc))
        {
          /* SUB   rc, ra, rb */
-
-         int ra = GET_IW_A (insn);
-         int rb = GET_IW_B (insn);
-         int rc = GET_IW_C (insn);
-
-         if (rc != 0)
+         if (rc == NIOS2_SP_REGNUM && rb == NIOS2_SP_REGNUM
+             && value[rc].reg != 0)
+           /* If we are decrementing the SP by a non-constant amount,
+              this is alloca, not part of the prologue.  */
+           break;
+         else if (rc != 0)
            {
              if (value[rb].reg == 0)
                value[rc].reg = value[ra].reg;
@@ -628,185 +1345,195 @@ nios2_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR start_pc,
            }
        }
 
-      else if ((insn & 0x0000003f) == 0x00000004)
+      else if (nios2_match_addi (insn, op, mach, &ra, &rb, &imm))
        {
-         /* ADDI  rb, ra, immed   (also used for MOVI) */
-         short immed = GET_IW_IMM16 (insn);
-         int ra = GET_IW_A (insn);
-         int rb = GET_IW_B (insn);
-
-         /* The first stack adjustment is part of the prologue.
-            Any subsequent stack adjustments are either down to
-            alloca or the epilogue so stop analysing when we hit
-            them.  */
+         /* ADDI    rb, ra, imm */
+
+         /* A positive stack adjustment has to be part of the epilogue.  */
          if (rb == NIOS2_SP_REGNUM
-             && (value[rb].offset != 0 || value[ra].reg != NIOS2_SP_REGNUM))
+             && (imm > 0 || value[ra].reg != NIOS2_SP_REGNUM))
+           break;
+
+         /* Likewise restoring SP from FP.  */
+         else if (rb == NIOS2_SP_REGNUM && ra == NIOS2_FP_REGNUM)
            break;
 
          if (rb != 0)
            {
              value[rb].reg    = value[ra].reg;
-             value[rb].offset = value[ra].offset + immed;
+             value[rb].offset = value[ra].offset + imm;
            }
 
-         prologue_insn = 1;
+         /* The add is only considered a prologue instruction
+            if the destination is SP or FP.  */
+         if (rb == NIOS2_SP_REGNUM || rb == NIOS2_FP_REGNUM)
+           prologue_end = pc;
        }
 
-      else if ((insn & 0x0000003f) == 0x00000034)
+      else if (nios2_match_orhi (insn, op, mach, &ra, &rb, &uimm))
        {
-         /* ORHI  rb, ra, immed   (also used for MOVHI) */
-         unsigned int immed = GET_IW_IMM16 (insn);
-         int ra = GET_IW_A (insn);
-         int rb = GET_IW_B (insn);
-
+         /* ORHI  rb, ra, uimm   (also used for MOVHI) */
          if (rb != 0)
            {
-             value[rb].reg    = (value[ra].reg == 0) ? 0 : -1;
-             value[rb].offset = value[ra].offset | (immed << 16);
+             value[rb].reg    = (value[ra].reg == 0) ? 0 : -1;
+             value[rb].offset = value[ra].offset | (uimm << 16);
            }
        }
 
-      else if ((insn & IW_OP_MASK) == OP_STW
-              || (insn & IW_OP_MASK) == OP_STWIO)
-        {
-         /* STW rb, immediate(ra) */
-
-         short immed16 = GET_IW_IMM16 (insn);
-         int ra = GET_IW_A (insn);
-         int rb = GET_IW_B (insn);
+      else if (nios2_match_stw (insn, op, mach, &ra, &rb, &imm))
+       {
+         /* STW rb, imm(ra) */
 
-         /* Are we storing the original value of a register?
+         /* Are we storing the original value of a register to the stack?
             For exception handlers the value of EA-4 (return
             address from interrupts etc) is sometimes stored.  */
          int orig = value[rb].reg;
          if (orig > 0
              && (value[rb].offset == 0
-                 || (orig == NIOS2_EA_REGNUM && value[rb].offset == -4)))
+                 || (orig == NIOS2_EA_REGNUM && value[rb].offset == -4))
+             && value[ra].reg == NIOS2_SP_REGNUM)
            {
-             /* We are most interested in stores to the stack, but
-                also take note of stores to other places as they
-                might be useful later.  */
-             if ((value[ra].reg == NIOS2_SP_REGNUM
-                  && cache->reg_saved[orig].basereg != NIOS2_SP_REGNUM)
-                 || cache->reg_saved[orig].basereg == -1)
+             if (pc < current_pc)
                {
-                 if (pc < current_pc)
-                   {
-                     /* Save off callee saved registers.  */
-                     cache->reg_saved[orig].basereg = value[ra].reg;
-                     cache->reg_saved[orig].addr
-                       = value[ra].offset + GET_IW_IMM16 (insn);
-                   }
-
-                 prologue_insn = 1;
-
-                 if (orig == NIOS2_EA_REGNUM || orig == NIOS2_ESTATUS_REGNUM)
-                   exception_handler = 1;
+                 /* Save off callee saved registers.  */
+                 cache->reg_saved[orig].basereg = value[ra].reg;
+                 cache->reg_saved[orig].addr = value[ra].offset + imm;
                }
+             
+             prologue_end = pc;
+             
+             if (orig == NIOS2_EA_REGNUM || orig == NIOS2_ESTATUS_REGNUM)
+               exception_handler = 1;
            }
          else
-           /* Non-stack memory writes are not part of the
-              prologue.  */
-           within_prologue = 0;
-        }
+           /* Non-stack memory writes cannot appear in the prologue.  */
+           break;
+       }
 
-      else if ((insn & 0xffc1f83f) == 0x0001303a)
+      else if (nios2_match_stwm (insn, op, mach,
+                                &reglist, &ra, &imm, &wb, &id))
        {
-         /* RDCTL rC, ctlN */
-         int rc = GET_IW_C (insn);
-         int n = GET_IW_CONTROL_REGNUM (insn);
+         /* PUSH.N {reglist}, adjust
+            or
+            STWM {reglist}, --(SP)[, writeback] */
+         int off = 0;
+
+         if (ra != NIOS2_SP_REGNUM || id != 0)
+           /* This is a non-stack-push memory write and cannot be
+              part of the prologue.  */
+           break;
+
+         for (int i = 31; i >= 0; i--)
+           if (reglist & (1 << i))
+             {
+               int orig = value[i].reg;
+               
+               off += 4;
+               if (orig > 0 && value[i].offset == 0 && pc < current_pc)
+                 {
+                   cache->reg_saved[orig].basereg
+                     = value[NIOS2_SP_REGNUM].reg;
+                   cache->reg_saved[orig].addr
+                     = value[NIOS2_SP_REGNUM].offset - off;
+                 }
+             }
+
+         if (wb)
+           value[NIOS2_SP_REGNUM].offset -= off;
+         value[NIOS2_SP_REGNUM].offset -= imm;
+
+         prologue_end = pc;
+       }
 
+      else if (nios2_match_rdctl (insn, op, mach, &ra, &rc))
+       {
+         /* RDCTL rC, ctlN
+            This can appear in exception handlers in combination with
+            a subsequent save to the stack frame.  */
          if (rc != 0)
            {
-             value[rc].reg    = NIOS2_STATUS_REGNUM + n;
+             value[rc].reg    = NIOS2_STATUS_REGNUM + ra;
              value[rc].offset = 0;
            }
-
-         prologue_insn = 1;
-        }
-
-      else if ((insn & 0x0000003f) == 0
-              && value[8].reg == NIOS2_RA_REGNUM
-              && value[8].offset == 0
-              && value[NIOS2_SP_REGNUM].reg == NIOS2_SP_REGNUM
-              && value[NIOS2_SP_REGNUM].offset == 0)
-       {
-         /* A CALL instruction.  This is treated as a call to mcount
-            if ra has been stored into r8 beforehand and if it's
-            before the stack adjust.
-            Note mcount corrupts r2-r3, r9-r15 & ra.  */
-         for (i = 2 ; i <= 3 ; i++)
-           value[i].reg = -1;
-         for (i = 9 ; i <= 15 ; i++)
-           value[i].reg = -1;
-         value[NIOS2_RA_REGNUM].reg = -1;
-
-         prologue_insn = 1;
        }
 
-      else if ((insn & 0xf83fffff) == 0xd800012e)
+      else if (nios2_match_calli (insn, op, mach, &uimm))
        {
-          /* BGEU sp, rx, +8
-             BREAK 3
-             This instruction sequence is used in stack checking;
-             we can ignore it.  */
-         unsigned int next_insn
-           = read_memory_unsigned_integer (pc, NIOS2_OPCODE_SIZE, byte_order);
-
-         if (next_insn != 0x003da0fa)
-           within_prologue = 0;
-         else
-           pc += NIOS2_OPCODE_SIZE;
-       }
+         if (value[8].reg == NIOS2_RA_REGNUM
+             && value[8].offset == 0
+             && value[NIOS2_SP_REGNUM].reg == NIOS2_SP_REGNUM
+             && value[NIOS2_SP_REGNUM].offset == 0)
+           {
+             /* A CALL instruction.  This is treated as a call to mcount
+                if ra has been stored into r8 beforehand and if it's
+                before the stack adjust.
+                Note mcount corrupts r2-r3, r9-r15 & ra.  */
+             for (int i = 2 ; i <= 3 ; i++)
+               value[i].reg = -1;
+             for (int i = 9 ; i <= 15 ; i++)
+               value[i].reg = -1;
+             value[NIOS2_RA_REGNUM].reg = -1;
+
+             prologue_end = pc;
+           }
 
-      else if ((insn & 0xf800003f) == 0xd8000036)
-       {
-          /* BLTU sp, rx, .Lstackoverflow
-             If the location branched to holds a BREAK 3 instruction
-             then this is also stack overflow detection.  We can
-             ignore it.  */
-         CORE_ADDR target_pc = pc + ((insn & 0x3fffc0) >> 6);
-         unsigned int target_insn
-           = read_memory_unsigned_integer (target_pc, NIOS2_OPCODE_SIZE,
-                                           byte_order);
-
-         if (target_insn != 0x003da0fa)
-           within_prologue = 0;
+         /* Other calls are not part of the prologue.  */
+         else
+           break;
        }
 
-      /* Any other instructions are allowed to be moved up into the
-        prologue.  If we reach a branch, call or return then the
-        prologue is considered over.  We also consider a second stack
-        adjustment as terminating the prologue (see above).  */
-      else
+      else if (nios2_match_branch (insn, op, mach, &ra, &rb, &imm, &cond))
        {
-         switch (GET_IW_OP (insn))
+         /* Branches not involving a stack overflow check aren't part of
+            the prologue.  */
+         if (ra != NIOS2_SP_REGNUM)
+           break;
+         else if (cond == branch_geu)
            {
-           case OP_BEQ:
-           case OP_BGE:
-           case OP_BGEU:
-           case OP_BLT:
-           case OP_BLTU:
-           case OP_BNE:
-           case OP_BR:
-           case OP_CALL:
-             within_prologue = 0;
-             break;
-           case OP_OPX:
-             if (GET_IW_OPX (insn) == OPX_RET
-                 || GET_IW_OPX (insn) == OPX_ERET
-                 || GET_IW_OPX (insn) == OPX_BRET
-                 || GET_IW_OPX (insn) == OPX_CALLR
-                 || GET_IW_OPX (insn) == OPX_JMP)
-               within_prologue = 0;
-             break;
-           default:
-             break;
+             /* BGEU sp, rx, +8
+                TRAP 3  (or BREAK 3)
+                This instruction sequence is used in stack checking;
+                we can ignore it.  */
+             unsigned int next_insn;
+             const struct nios2_opcode *next_op
+               = nios2_fetch_insn (gdbarch, pc, &next_insn);
+             if (next_op != NULL
+                 && (nios2_match_trap (next_insn, op, mach, &uimm)
+                     || nios2_match_break (next_insn, op, mach, &uimm)))
+               pc += next_op->size;
+             else
+               break;
            }
+         else if (cond == branch_ltu)
+           {
+             /* BLTU sp, rx, .Lstackoverflow
+                If the location branched to holds a TRAP or BREAK
+                instruction then this is also stack overflow detection.  */
+             unsigned int next_insn;
+             const struct nios2_opcode *next_op
+               = nios2_fetch_insn (gdbarch, pc + imm, &next_insn);
+             if (next_op != NULL
+                 && (nios2_match_trap (next_insn, op, mach, &uimm)
+                     || nios2_match_break (next_insn, op, mach, &uimm)))
+               ;
+             else
+               break;
+           }
+         else
+           break;
        }
 
-      if (prologue_insn)
-       prologue_end = pc;
+      /* All other calls, jumps, returns, TRAPs, or BREAKs terminate
+        the prologue.  */
+      else if (nios2_match_callr (insn, op, mach, &ra)
+              || nios2_match_jmpr (insn, op, mach, &ra)
+              || nios2_match_jmpi (insn, op, mach, &uimm)
+              || (nios2_match_ldwm (insn, op, mach, &reglist, &ra,
+                                    &imm, &wb, &id, &ret)
+                  && ret)
+              || nios2_match_trap (insn, op, mach, &uimm)
+              || nios2_match_break (insn, op, mach, &uimm))
+       break;
     }
 
   /* If THIS_FRAME is NULL, we are being called from skip_prologue
@@ -827,7 +1554,7 @@ nios2_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR start_pc,
     cache->return_regnum = NIOS2_EA_REGNUM;
 
   if (nios2_debug)
-    fprintf_unfiltered (gdb_stdlog, "\n-> retreg=%d, ", cache->return_regnum);
+    gdb_printf (gdb_stdlog, "\n-> retreg=%d, ", cache->return_regnum);
 
   if (cache->reg_value[NIOS2_FP_REGNUM].reg == NIOS2_SP_REGNUM)
     /* If the FP now holds an offset from the CFA then this is a
@@ -844,7 +1571,7 @@ nios2_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR start_pc,
       /* Somehow the stack pointer has been corrupted.
         We can't return.  */
       if (nios2_debug)
-       fprintf_unfiltered (gdb_stdlog, "<can't reach cfa> }\n");
+       gdb_printf (gdb_stdlog, "<can't reach cfa> }\n");
       return 0;
     }
 
@@ -871,7 +1598,7 @@ nios2_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR start_pc,
          if (ra == current_pc)
            {
              if (nios2_debug)
-               fprintf_unfiltered
+               gdb_printf
                  (gdb_stdlog,
                   "<noreturn ADJUST %s, r31@r%d+?>, r%d@r%d+?> }\n",
                   paddress (gdbarch, cache->reg_value[base_reg].offset),
@@ -893,14 +1620,14 @@ nios2_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR start_pc,
 
   /* Adjust all the saved registers such that they contain addresses
      instead of offsets.  */
-  for (i = 0; i < NIOS2_NUM_REGS; i++)
+  for (int i = 0; i < NIOS2_NUM_REGS; i++)
     if (cache->reg_saved[i].basereg == NIOS2_SP_REGNUM)
       {
        cache->reg_saved[i].basereg = NIOS2_Z_REGNUM;
        cache->reg_saved[i].addr += frame_high;
       }
 
-  for (i = 0; i < NIOS2_NUM_REGS; i++)
+  for (int i = 0; i < NIOS2_NUM_REGS; i++)
     if (cache->reg_saved[i].basereg == NIOS2_GP_REGNUM)
       {
        CORE_ADDR gp = get_frame_register_unsigned (this_frame,
@@ -933,8 +1660,8 @@ nios2_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR start_pc,
     }
 
   if (nios2_debug)
-    fprintf_unfiltered (gdb_stdlog, "cfa=%s }\n",
-                       paddress (gdbarch, cache->cfa));
+    gdb_printf (gdb_stdlog, "cfa=%s }\n",
+               paddress (gdbarch, cache->cfa));
 
   return prologue_end;
 }
@@ -944,7 +1671,6 @@ nios2_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR start_pc,
 static CORE_ADDR
 nios2_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
 {
-  CORE_ADDR limit_pc;
   CORE_ADDR func_addr;
 
   struct nios2_unwind_cache cache;
@@ -955,10 +1681,10 @@ nios2_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
   if (find_pc_partial_function (start_pc, NULL, &func_addr, NULL))
     {
       CORE_ADDR post_prologue_pc
-        = skip_prologue_using_sal (gdbarch, func_addr);
+       = skip_prologue_using_sal (gdbarch, func_addr);
 
       if (post_prologue_pc != 0)
-        return max (start_pc, post_prologue_pc);
+       return std::max (start_pc, post_prologue_pc);
     }
 
   /* Prologue analysis does the rest....  */
@@ -966,40 +1692,83 @@ nios2_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
   return nios2_analyze_prologue (gdbarch, start_pc, start_pc, &cache, NULL);
 }
 
-/* Implement the breakpoint_from_pc gdbarch hook.  */
+/* Implement the breakpoint_kind_from_pc gdbarch method.  */
 
-static const gdb_byte*
-nios2_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *bp_addr,
-                         int *bp_size)
+static int
+nios2_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
 {
-  /* break encoding: 31->27  26->22  21->17  16->11 10->6 5->0 */
-  /*                 00000   00000   0x1d    0x2d   11111 0x3a */
-  /*                 00000   00000   11101   101101 11111 111010 */
-  /* In bytes:       00000000 00111011 01101111 11111010 */
-  /*                 0x0       0x3b    0x6f     0xfa */
-  static const gdb_byte breakpoint_le[] = {0xfa, 0x6f, 0x3b, 0x0};
-  static const gdb_byte breakpoint_be[] = {0x0, 0x3b, 0x6f, 0xfa};
-
-  enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
-
-  *bp_size = 4;
-  if (gdbarch_byte_order_for_code (gdbarch) == BFD_ENDIAN_BIG)
-    return breakpoint_be;
+  unsigned long mach = gdbarch_bfd_arch_info (gdbarch)->mach;
+
+  if (mach == bfd_mach_nios2r2)
+    {
+      unsigned int insn;
+      const struct nios2_opcode *op
+       = nios2_fetch_insn (gdbarch, *pcptr, &insn);
+
+      if (op && op->size == NIOS2_CDX_OPCODE_SIZE)
+       return NIOS2_CDX_OPCODE_SIZE;
+      else
+       return NIOS2_OPCODE_SIZE;
+    }
   else
-    return breakpoint_le;
+    return NIOS2_OPCODE_SIZE;
 }
 
-/* Implement the print_insn gdbarch method.  */
+/* Implement the sw_breakpoint_from_kind gdbarch method.  */
 
-static int
-nios2_print_insn (bfd_vma memaddr, disassemble_info *info)
+static const gdb_byte *
+nios2_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
 {
-  if (info->endian == BFD_ENDIAN_BIG)
-    return print_insn_big_nios2 (memaddr, info);
+/* The Nios II ABI for Linux says: "Userspace programs should not use
+   the break instruction and userspace debuggers should not insert
+   one." and "Userspace breakpoints are accomplished using the trap
+   instruction with immediate operand 31 (all ones)."
+
+   So, we use "trap 31" consistently as the breakpoint on bare-metal
+   as well as Linux targets.  */
+
+  /* R2 trap encoding:
+     ((0x2d << 26) | (0x1f << 21) | (0x1d << 16) | (0x20 << 0))
+     0xb7fd0020
+     CDX trap.n encoding:
+     ((0xd << 12) | (0x1f << 6) | (0x9 << 0))
+     0xd7c9
+     Note that code is always little-endian on R2.  */
+  *size = kind;
+
+  if (kind == NIOS2_CDX_OPCODE_SIZE)
+    {
+      static const gdb_byte cdx_breakpoint_le[] = {0xc9, 0xd7};
+
+      return cdx_breakpoint_le;
+    }
   else
-    return print_insn_little_nios2 (memaddr, info);
-}
+    {
+      unsigned long mach = gdbarch_bfd_arch_info (gdbarch)->mach;
 
+      if (mach == bfd_mach_nios2r2)
+       {
+         static const gdb_byte r2_breakpoint_le[] = {0x20, 0x00, 0xfd, 0xb7};
+
+         return r2_breakpoint_le;
+       }
+      else
+       {
+         enum bfd_endian byte_order_for_code
+           = gdbarch_byte_order_for_code (gdbarch);
+         /* R1 trap encoding:
+            ((0x1d << 17) | (0x2d << 11) | (0x1f << 6) | (0x3a << 0))
+            0x003b6ffa */
+         static const gdb_byte r1_breakpoint_le[] = {0xfa, 0x6f, 0x3b, 0x0};
+         static const gdb_byte r1_breakpoint_be[] = {0x0, 0x3b, 0x6f, 0xfa};
+
+         if (byte_order_for_code == BFD_ENDIAN_BIG)
+           return r1_breakpoint_be;
+         else
+           return r1_breakpoint_le;
+       }
+    }
+}
 
 /* Implement the frame_align gdbarch method.  */
 
@@ -1017,7 +1786,7 @@ nios2_return_value (struct gdbarch *gdbarch, struct value *function,
                    struct type *type, struct regcache *regcache,
                    gdb_byte *readbuf, const gdb_byte *writebuf)
 {
-  if (TYPE_LENGTH (type) > 8)
+  if (type->length () > 8)
     return RETURN_VALUE_STRUCT_CONVENTION;
 
   if (readbuf)
@@ -1028,30 +1797,19 @@ nios2_return_value (struct gdbarch *gdbarch, struct value *function,
   return RETURN_VALUE_REGISTER_CONVENTION;
 }
 
-/* Implement the dummy_id gdbarch method.  */
-
-static struct frame_id
-nios2_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
-{
-  return frame_id_build
-    (get_frame_register_unsigned (this_frame, NIOS2_SP_REGNUM),
-     get_frame_pc (this_frame));
-}
-
 /* Implement the push_dummy_call gdbarch method.  */
 
 static CORE_ADDR
 nios2_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
-                       struct regcache *regcache, CORE_ADDR bp_addr,
-                       int nargs, struct value **args, CORE_ADDR sp,
-                       int struct_return, CORE_ADDR struct_addr)
+                      struct regcache *regcache, CORE_ADDR bp_addr,
+                      int nargs, struct value **args, CORE_ADDR sp,
+                      function_call_return_method return_method,
+                      CORE_ADDR struct_addr)
 {
   int argreg;
-  int float_argreg;
   int argnum;
-  int len = 0;
+  int arg_space = 0;
   int stack_offset = 0;
-  CORE_ADDR func_addr = find_function_addr (function, NULL);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
 
   /* Set the return address register to point to the entry point of
@@ -1060,15 +1818,15 @@ nios2_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 
   /* Now make space on the stack for the args.  */
   for (argnum = 0; argnum < nargs; argnum++)
-    len += align_up (TYPE_LENGTH (value_type (args[argnum])), 4);
-  sp -= len;
+    arg_space += align_up (args[argnum]->type ()->length (), 4);
+  sp -= arg_space;
 
   /* Initialize the register pointer.  */
   argreg = NIOS2_FIRST_ARGREG;
 
   /* The struct_return pointer occupies the first parameter-passing
      register.  */
-  if (struct_return)
+  if (return_method == return_method_struct)
     regcache_cooked_write_unsigned (regcache, argreg++, struct_addr);
 
   /* Now load as many as possible of the first arguments into
@@ -1077,19 +1835,17 @@ nios2_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   for (argnum = 0; argnum < nargs; argnum++)
     {
       const gdb_byte *val;
-      gdb_byte valbuf[MAX_REGISTER_SIZE];
       struct value *arg = args[argnum];
-      struct type *arg_type = check_typedef (value_type (arg));
-      int len = TYPE_LENGTH (arg_type);
-      enum type_code typecode = TYPE_CODE (arg_type);
+      struct type *arg_type = check_typedef (arg->type ());
+      int len = arg_type->length ();
 
-      val = value_contents (arg);
+      val = arg->contents ().data ();
 
       /* Copy the argument to general registers or the stack in
-         register-sized pieces.  Large arguments are split between
-         registers and stack.  */
+        register-sized pieces.  Large arguments are split between
+        registers and stack.  */
       while (len > 0)
-        {
+       {
          int partial_len = (len < 4 ? len : 4);
 
          if (argreg <= NIOS2_LAST_ARGREG)
@@ -1124,7 +1880,7 @@ nios2_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 /* Implement the unwind_pc gdbarch method.  */
 
 static CORE_ADDR
-nios2_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
+nios2_unwind_pc (struct gdbarch *gdbarch, frame_info_ptr next_frame)
 {
   gdb_byte buf[4];
 
@@ -1132,29 +1888,20 @@ nios2_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
   return extract_typed_address (buf, builtin_type (gdbarch)->builtin_func_ptr);
 }
 
-/* Implement the unwind_sp gdbarch method.  */
-
-static CORE_ADDR
-nios2_unwind_sp (struct gdbarch *gdbarch, struct frame_info *this_frame)
-{
-  return frame_unwind_register_unsigned (this_frame, NIOS2_SP_REGNUM);
-}
-
 /* Use prologue analysis to fill in the register cache
    *THIS_PROLOGUE_CACHE for THIS_FRAME.  This function initializes
    *THIS_PROLOGUE_CACHE first.  */
 
 static struct nios2_unwind_cache *
-nios2_frame_unwind_cache (struct frame_info *this_frame,
+nios2_frame_unwind_cache (frame_info_ptr this_frame,
                          void **this_prologue_cache)
 {
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
   CORE_ADDR current_pc;
   struct nios2_unwind_cache *cache;
-  int i;
 
   if (*this_prologue_cache)
-    return *this_prologue_cache;
+    return (struct nios2_unwind_cache *) *this_prologue_cache;
 
   cache = FRAME_OBSTACK_ZALLOC (struct nios2_unwind_cache);
   *this_prologue_cache = cache;
@@ -1173,7 +1920,7 @@ nios2_frame_unwind_cache (struct frame_info *this_frame,
 /* Implement the this_id function for the normal unwinder.  */
 
 static void
-nios2_frame_this_id (struct frame_info *this_frame, void **this_cache,
+nios2_frame_this_id (frame_info_ptr this_frame, void **this_cache,
                     struct frame_id *this_id)
 {
   struct nios2_unwind_cache *cache =
@@ -1189,7 +1936,7 @@ nios2_frame_this_id (struct frame_info *this_frame, void **this_cache,
 /* Implement the prev_register function for the normal unwinder.  */
 
 static struct value *
-nios2_frame_prev_register (struct frame_info *this_frame, void **this_cache,
+nios2_frame_prev_register (frame_info_ptr this_frame, void **this_cache,
                           int regnum)
 {
   struct nios2_unwind_cache *cache =
@@ -1219,7 +1966,7 @@ nios2_frame_prev_register (struct frame_info *this_frame, void **this_cache,
    for the normal unwinder.  */
 
 static CORE_ADDR
-nios2_frame_base_address (struct frame_info *this_frame, void **this_cache)
+nios2_frame_base_address (frame_info_ptr this_frame, void **this_cache)
 {
   struct nios2_unwind_cache *info
     = nios2_frame_unwind_cache (this_frame, this_cache);
@@ -1232,6 +1979,7 @@ nios2_frame_base_address (struct frame_info *this_frame, void **this_cache)
 
 static const struct frame_unwind nios2_frame_unwind =
 {
+  "nios2 prologue",
   NORMAL_FRAME,
   default_frame_unwind_stop_reason,
   nios2_frame_this_id,
@@ -1252,24 +2000,23 @@ static const struct frame_base nios2_frame_base =
    in the stub unwinder.  */
 
 static struct trad_frame_cache *
-nios2_stub_frame_cache (struct frame_info *this_frame, void **this_cache)
+nios2_stub_frame_cache (frame_info_ptr this_frame, void **this_cache)
 {
   CORE_ADDR pc;
   CORE_ADDR start_addr;
   CORE_ADDR stack_addr;
   struct trad_frame_cache *this_trad_cache;
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
-  int num_regs = gdbarch_num_regs (gdbarch);
 
   if (*this_cache != NULL)
-    return *this_cache;
+    return (struct trad_frame_cache *) *this_cache;
   this_trad_cache = trad_frame_cache_zalloc (this_frame);
   *this_cache = this_trad_cache;
 
   /* The return address is in the link register.  */
   trad_frame_set_reg_realreg (this_trad_cache,
-                              gdbarch_pc_regnum (gdbarch),
-                              NIOS2_RA_REGNUM);
+                             gdbarch_pc_regnum (gdbarch),
+                             NIOS2_RA_REGNUM);
 
   /* Frame ID, since it's a frameless / stackless function, no stack
      space is allocated and SP on entry is the current SP.  */
@@ -1286,8 +2033,8 @@ nios2_stub_frame_cache (struct frame_info *this_frame, void **this_cache)
 /* Implement the this_id function for the stub unwinder.  */
 
 static void
-nios2_stub_frame_this_id (struct frame_info *this_frame, void **this_cache,
-                          struct frame_id *this_id)
+nios2_stub_frame_this_id (frame_info_ptr this_frame, void **this_cache,
+                         struct frame_id *this_id)
 {
   struct trad_frame_cache *this_trad_cache
     = nios2_stub_frame_cache (this_frame, this_cache);
@@ -1298,8 +2045,8 @@ nios2_stub_frame_this_id (struct frame_info *this_frame, void **this_cache,
 /* Implement the prev_register function for the stub unwinder.  */
 
 static struct value *
-nios2_stub_frame_prev_register (struct frame_info *this_frame,
-                               void **this_cache, int regnum)
+nios2_stub_frame_prev_register (frame_info_ptr this_frame,
+                               void **this_cache, int regnum)
 {
   struct trad_frame_cache *this_trad_cache
     = nios2_stub_frame_cache (this_frame, this_cache);
@@ -1314,10 +2061,9 @@ nios2_stub_frame_prev_register (struct frame_info *this_frame,
 
 static int
 nios2_stub_frame_sniffer (const struct frame_unwind *self,
-                         struct frame_info *this_frame, void **cache)
+                         frame_info_ptr this_frame, void **cache)
 {
   gdb_byte dummy[4];
-  struct obj_section *s;
   CORE_ADDR pc = get_frame_address_in_block (this_frame);
 
   /* Use the stub unwinder for unreadable code.  */
@@ -1330,22 +2076,11 @@ nios2_stub_frame_sniffer (const struct frame_unwind *self,
   return 0;
 }
 
-/* Implement the this_base, this_locals, and this_args hooks
-   for the stub unwinder.  */
-
-static CORE_ADDR
-nios2_stub_frame_base_address (struct frame_info *this_frame, void **this_cache)
-{
-  struct trad_frame_cache *this_trad_cache
-    = nios2_stub_frame_cache (this_frame, this_cache);
-
-  return trad_frame_get_this_base (this_trad_cache);
-}
-
 /* Define the data structures for the stub unwinder.  */
 
 static const struct frame_unwind nios2_stub_frame_unwind =
 {
+  "nios2 stub",
   NORMAL_FRAME,
   default_frame_unwind_stop_reason,
   nios2_stub_frame_this_id,
@@ -1354,138 +2089,139 @@ static const struct frame_unwind nios2_stub_frame_unwind =
   nios2_stub_frame_sniffer
 };
 
-static const struct frame_base nios2_stub_frame_base =
-{
-  &nios2_stub_frame_unwind,
-  nios2_stub_frame_base_address,
-  nios2_stub_frame_base_address,
-  nios2_stub_frame_base_address
-};
 
-/* Helper function to read an instruction at PC.  */
-
-static unsigned long
-nios2_fetch_instruction (struct gdbarch *gdbarch, CORE_ADDR pc)
-{
-  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-
-  return read_memory_unsigned_integer (pc, NIOS2_OPCODE_SIZE, byte_order);
-}
 
 /* Determine where to set a single step breakpoint while considering
    branch prediction.  */
 
 static CORE_ADDR
-nios2_get_next_pc (struct frame_info *frame, CORE_ADDR pc)
+nios2_get_next_pc (struct regcache *regcache, CORE_ADDR pc)
 {
-  struct gdbarch *gdbarch = get_frame_arch (frame);
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  unsigned long inst;
-  int op;
-  int imm16;
+  struct gdbarch *gdbarch = regcache->arch ();
+  nios2_gdbarch_tdep *tdep = gdbarch_tdep<nios2_gdbarch_tdep> (gdbarch);
+  unsigned long mach = gdbarch_bfd_arch_info (gdbarch)->mach;
+  unsigned int insn;
+  const struct nios2_opcode *op = nios2_fetch_insn (gdbarch, pc, &insn);
   int ra;
   int rb;
-  int ras;
-  int rbs;
-  unsigned int rau;
-  unsigned int rbu;
-
-  inst = nios2_fetch_instruction (gdbarch, pc);
-  pc += NIOS2_OPCODE_SIZE;
-
-  imm16 = (short) GET_IW_IMM16 (inst);
-  ra = GET_IW_A (inst);
-  rb = GET_IW_B (inst);
-  ras = get_frame_register_signed (frame, ra);
-  rbs = get_frame_register_signed (frame, rb);
-  rau = get_frame_register_unsigned (frame, ra);
-  rbu = get_frame_register_unsigned (frame, rb);
-
-  switch (GET_IW_OP (inst))
-    {
-    case OP_BEQ:
-      if (ras == rbs)
-       pc += imm16;
-      break;
-
-    case OP_BGE:
-      if (ras >= rbs)
-        pc += imm16;
-      break;
-
-    case OP_BGEU:
-      if (rau >= rbu)
-        pc += imm16;
-      break;
-
-    case OP_BLT:
-      if (ras < rbs)
-        pc += imm16;
-      break;
-
-    case OP_BLTU:
-      if (rau < rbu)
-        pc += imm16;
-      break;
-
-    case OP_BNE:
-      if (ras != rbs)
-        pc += imm16;
-      break;
-
-    case OP_BR:
-      pc += imm16;
-      break;
-
-    case OP_JMPI:
-    case OP_CALL:
-      pc = (pc & 0xf0000000) | (GET_IW_IMM26 (inst) << 2);
-      break;
-
-    case OP_OPX:
-      switch (GET_IW_OPX (inst))
+  int imm;
+  unsigned int uimm;
+  int wb, id, ret;
+  enum branch_condition cond;
+
+  /* Do something stupid if we can't disassemble the insn at pc.  */
+  if (op == NULL)
+    return pc + NIOS2_OPCODE_SIZE;
+    
+  if (nios2_match_branch (insn, op, mach, &ra, &rb, &imm, &cond))
+    {
+      int ras = regcache_raw_get_signed (regcache, ra);
+      int rbs = regcache_raw_get_signed (regcache, rb);
+      unsigned int rau = regcache_raw_get_unsigned (regcache, ra);
+      unsigned int rbu = regcache_raw_get_unsigned (regcache, rb);
+
+      pc += op->size;
+      switch (cond)
        {
-       case OPX_JMP:
-       case OPX_CALLR:
-       case OPX_RET:
-         pc = ras;
+       case branch_none:
+         pc += imm;
+         break;
+       case branch_eq:
+         if (ras == rbs)
+           pc += imm;
+         break;
+       case branch_ne:
+         if (ras != rbs)
+           pc += imm;
+         break;
+       case branch_ge:
+         if (ras >= rbs)
+           pc += imm;
+         break;
+       case branch_geu:
+         if (rau >= rbu)
+           pc += imm;
+         break;
+       case branch_lt:
+         if (ras < rbs)
+           pc += imm;
+         break;
+       case branch_ltu:
+         if (rau < rbu)
+           pc += imm;
          break;
-
-       case OPX_TRAP:
-         if (tdep->syscall_next_pc != NULL)
-           return tdep->syscall_next_pc (frame);
-
        default:
          break;
        }
-      break;
-    default:
-      break;
     }
+
+  else if (nios2_match_jmpi (insn, op, mach, &uimm))
+    pc = (pc & 0xf0000000) | uimm;
+  else if (nios2_match_calli (insn, op, mach, &uimm))
+    {
+      CORE_ADDR callto = (pc & 0xf0000000) | uimm;
+      if (tdep->is_kernel_helper != NULL
+         && tdep->is_kernel_helper (callto))
+       /* Step over call to kernel helper, which we cannot debug
+          from user space.  */
+       pc += op->size;
+      else
+       pc = callto;
+    }
+
+  else if (nios2_match_jmpr (insn, op, mach, &ra))
+    pc = regcache_raw_get_unsigned (regcache, ra);
+  else if (nios2_match_callr (insn, op, mach, &ra))
+    {
+      CORE_ADDR callto = regcache_raw_get_unsigned (regcache, ra);
+      if (tdep->is_kernel_helper != NULL
+         && tdep->is_kernel_helper (callto))
+       /* Step over call to kernel helper.  */
+       pc += op->size;
+      else
+       pc = callto;
+    }
+
+  else if (nios2_match_ldwm (insn, op, mach, &uimm, &ra, &imm, &wb, &id, &ret)
+          && ret)
+    {
+      /* If ra is in the reglist, we have to use the value saved in the
+        stack frame rather than the current value.  */
+      if (uimm & (1 << NIOS2_RA_REGNUM))
+       pc = nios2_unwind_pc (gdbarch, get_current_frame ());
+      else
+       pc = regcache_raw_get_unsigned (regcache, NIOS2_RA_REGNUM);
+    }
+
+  else if (nios2_match_trap (insn, op, mach, &uimm) && uimm == 0)
+    {
+      if (tdep->syscall_next_pc != NULL)
+       return tdep->syscall_next_pc (get_current_frame (), op);
+    }
+
+  else
+    pc += op->size;
+
   return pc;
 }
 
 /* Implement the software_single_step gdbarch method.  */
 
-static int
-nios2_software_single_step (struct frame_info *frame)
+static std::vector<CORE_ADDR>
+nios2_software_single_step (struct regcache *regcache)
 {
-  struct gdbarch *gdbarch = get_frame_arch (frame);
-  struct address_space *aspace = get_frame_address_space (frame);
-  CORE_ADDR next_pc = nios2_get_next_pc (frame, get_frame_pc (frame));
+  CORE_ADDR next_pc = nios2_get_next_pc (regcache, regcache_read_pc (regcache));
 
-  insert_single_step_breakpoint (gdbarch, aspace, next_pc);
-
-  return 1;
+  return {next_pc};
 }
 
 /* Implement the get_longjump_target gdbarch method.  */
 
 static int
-nios2_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
+nios2_get_longjmp_target (frame_info_ptr frame, CORE_ADDR *pc)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  nios2_gdbarch_tdep *tdep = gdbarch_tdep<nios2_gdbarch_tdep> (gdbarch);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   CORE_ADDR jb_addr = get_frame_register_unsigned (frame, NIOS2_R4_REGNUM);
   gdb_byte buf[4];
@@ -1497,15 +2233,49 @@ nios2_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
   return 1;
 }
 
+/* Implement the type_align gdbarch function.  */
+
+static ULONGEST
+nios2_type_align (struct gdbarch *gdbarch, struct type *type)
+{
+  switch (type->code ())
+    {
+    case TYPE_CODE_PTR:
+    case TYPE_CODE_FUNC:
+    case TYPE_CODE_FLAGS:
+    case TYPE_CODE_INT:
+    case TYPE_CODE_RANGE:
+    case TYPE_CODE_FLT:
+    case TYPE_CODE_ENUM:
+    case TYPE_CODE_REF:
+    case TYPE_CODE_RVALUE_REF:
+    case TYPE_CODE_CHAR:
+    case TYPE_CODE_BOOL:
+    case TYPE_CODE_DECFLOAT:
+    case TYPE_CODE_METHODPTR:
+    case TYPE_CODE_MEMBERPTR:
+      type = check_typedef (type);
+      return std::min<ULONGEST> (4, type->length ());
+    default:
+      return 0;
+    }
+}
+
+/* Implement the gcc_target_options gdbarch method.  */
+static std::string
+nios2_gcc_target_options (struct gdbarch *gdbarch)
+{
+  /* GCC doesn't know "-m32".  */
+  return {};
+}
+
 /* Initialize the Nios II gdbarch.  */
 
 static struct gdbarch *
 nios2_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 {
-  struct gdbarch *gdbarch;
-  struct gdbarch_tdep *tdep;
-  int register_bytes, i;
-  struct tdesc_arch_data *tdesc_data = NULL;
+  int i;
+  tdesc_arch_data_up tdesc_data;
   const struct target_desc *tdesc = info.target_desc;
 
   if (!tdesc_has_registers (tdesc))
@@ -1527,14 +2297,11 @@ nios2_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       valid_p = 1;
       
       for (i = 0; i < NIOS2_NUM_REGS; i++)
-       valid_p &= tdesc_numbered_register (feature, tdesc_data, i,
+       valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), i,
                                            nios2_reg_names[i]);
 
       if (!valid_p)
-       {
-         tdesc_data_cleanup (tdesc_data);
-         return NULL;
-       }
+       return NULL;
     }
 
   /* Find a candidate among the list of pre-declared architectures.  */
@@ -1544,8 +2311,9 @@ nios2_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   /* None found, create a new architecture from the information
      provided.  */
-  tdep = xcalloc (1, sizeof (struct gdbarch_tdep));
-  gdbarch = gdbarch_alloc (&info, tdep);
+  gdbarch *gdbarch
+    = gdbarch_alloc (&info, gdbarch_tdep_up (new nios2_gdbarch_tdep));
+  nios2_gdbarch_tdep *tdep = gdbarch_tdep<nios2_gdbarch_tdep> (gdbarch);
 
   /* longjmp support not enabled by default.  */
   tdep->jb_pc = -1;
@@ -1560,6 +2328,8 @@ nios2_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_float_bit (gdbarch, 32);
   set_gdbarch_double_bit (gdbarch, 64);
 
+  set_gdbarch_type_align (gdbarch, nios2_type_align);
+
   set_gdbarch_float_format (gdbarch, floatformats_ieee_single);
   set_gdbarch_double_format (gdbarch, floatformats_ieee_double);
 
@@ -1583,12 +2353,11 @@ nios2_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_return_value (gdbarch, nios2_return_value);
 
   set_gdbarch_skip_prologue (gdbarch, nios2_skip_prologue);
-  set_gdbarch_in_function_epilogue_p (gdbarch, nios2_in_function_epilogue_p);
-  set_gdbarch_breakpoint_from_pc (gdbarch, nios2_breakpoint_from_pc);
+  set_gdbarch_stack_frame_destroyed_p (gdbarch, nios2_stack_frame_destroyed_p);
+  set_gdbarch_breakpoint_kind_from_pc (gdbarch, nios2_breakpoint_kind_from_pc);
+  set_gdbarch_sw_breakpoint_from_kind (gdbarch, nios2_sw_breakpoint_from_kind);
 
-  set_gdbarch_dummy_id (gdbarch, nios2_dummy_id);
   set_gdbarch_unwind_pc (gdbarch, nios2_unwind_pc);
-  set_gdbarch_unwind_sp (gdbarch, nios2_unwind_sp);
 
   /* The dwarf2 unwinder will normally produce the best results if
      the debug information is available, so register it first.  */
@@ -1599,6 +2368,9 @@ nios2_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* Single stepping.  */
   set_gdbarch_software_single_step (gdbarch, nios2_software_single_step);
 
+  /* Target options for compile.  */
+  set_gdbarch_gcc_target_options (gdbarch, nios2_gcc_target_options);
+
   /* Hook in ABI-specific overrides, if they have been registered.  */
   gdbarch_init_osabi (info, gdbarch);
 
@@ -1607,21 +2379,18 @@ nios2_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   frame_base_set_default (gdbarch, &nios2_frame_base);
 
-  set_gdbarch_print_insn (gdbarch, nios2_print_insn);
-
   /* Enable inferior call support.  */
   set_gdbarch_push_dummy_call (gdbarch, nios2_push_dummy_call);
 
-  if (tdesc_data)
-    tdesc_use_registers (gdbarch, tdesc, tdesc_data);
+  if (tdesc_data != nullptr)
+    tdesc_use_registers (gdbarch, tdesc, std::move (tdesc_data));
 
   return gdbarch;
 }
 
-extern initialize_file_ftype _initialize_nios2_tdep; /* -Wmissing-prototypes */
-
+void _initialize_nios2_tdep ();
 void
-_initialize_nios2_tdep (void)
+_initialize_nios2_tdep ()
 {
   gdbarch_register (bfd_arch_nios2, nios2_gdbarch_init, NULL);
   initialize_tdesc_nios2 ();