Automatic date update in version.in
[deliverable/binutils-gdb.git] / gdb / cris-tdep.c
index 4b812e2931ac17e9688eb4aa6064e7f17486c6a7..cb99b9288cd7e0da48ababd6da7593ad5164118e 100644 (file)
@@ -1,26 +1,31 @@
 /* Target dependent code for CRIS, for GDB, the GNU debugger.
-   Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+
+   Copyright (C) 2001-2019 Free Software Foundation, Inc.
+
    Contributed by Axis Communications AB.
    Written by Hendrik Ruijter, Stefan Andersson, and Orjan Friberg.
 
-This file is part of GDB.
+   This file is part of GDB.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "frame.h"
+#include "frame-unwind.h"
+#include "frame-base.h"
+#include "trad-frame.h"
+#include "dwarf2-frame.h"
 #include "symtab.h"
 #include "inferior.h"
 #include "gdbtypes.h"
@@ -29,16 +34,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "target.h"
 #include "value.h"
 #include "opcode/cris.h"
+#include "osabi.h"
 #include "arch-utils.h"
 #include "regcache.h"
 
-/* To get entry_point_address.  */
-#include "symfile.h"
+#include "objfiles.h"
 
-#include "solib.h"              /* Support for shared libraries. */
-#include "solib-svr4.h"         /* For struct link_map_offsets.  */
-#include "gdb_string.h"
+#include "solib.h"              /* Support for shared libraries.  */
+#include "solib-svr4.h"
+#include "dis-asm.h"
 
+#include "cris-tdep.h"
 
 enum cris_num_regs
 {
@@ -49,29 +55,33 @@ enum cris_num_regs
   NUM_GENREGS = 16,
   
   /* There are 16 special registers.  */
-  NUM_SPECREGS = 16
+  NUM_SPECREGS = 16,
+
+  /* CRISv32 has a pseudo PC register, not noted here.  */
+  
+  /* CRISv32 has 16 support registers.  */
+  NUM_SUPPREGS = 16
 };
 
 /* Register numbers of various important registers.
-   FP_REGNUM   Contains address of executing stack frame.
+   CRIS_FP_REGNUM   Contains address of executing stack frame.
    STR_REGNUM  Contains the address of structure return values.
    RET_REGNUM  Contains the return value when shorter than or equal to 32 bits
    ARG1_REGNUM Contains the first parameter to a function.
    ARG2_REGNUM Contains the second parameter to a function.
    ARG3_REGNUM Contains the third parameter to a function.
-   ARG4_REGNUM Contains the fourth parameter to a function. Rest on stack.
-   SP_REGNUM   Contains address of top of stack.
-   PC_REGNUM   Contains address of next instruction.
+   ARG4_REGNUM Contains the fourth parameter to a function.  Rest on stack.
+   gdbarch_sp_regnum Contains address of top of stack.
+   gdbarch_pc_regnum Contains address of next instruction.
    SRP_REGNUM  Subroutine return pointer register.
    BRP_REGNUM  Breakpoint return pointer register.  */
 
-/* FP_REGNUM = 8, SP_REGNUM = 14, and PC_REGNUM = 15 have been incorporated
-   into the multi-arch framework.  */
-
 enum cris_regnums
 {
   /* Enums with respect to the general registers, valid for all 
-     CRIS versions.  */
+     CRIS versions.  The frame pointer is always in R8.  */
+  CRIS_FP_REGNUM = 8,
+  /* ABI related registers.  */
   STR_REGNUM  = 9,
   RET_REGNUM  = 10,
   ARG1_REGNUM = 10,
@@ -79,111 +89,387 @@ enum cris_regnums
   ARG3_REGNUM = 12,
   ARG4_REGNUM = 13,
   
-  /* Enums with respect to the special registers, some of which may not be
-     applicable to all CRIS versions.  */
-  P0_REGNUM   = 16,
+  /* Registers which happen to be common.  */
   VR_REGNUM   = 17,
-  P2_REGNUM   = 18,
-  P3_REGNUM   = 19,
+  MOF_REGNUM  = 23,
+  SRP_REGNUM  = 27,
+
+  /* CRISv10 et al. specific registers.  */
+  P0_REGNUM   = 16,
   P4_REGNUM   = 20,
   CCR_REGNUM  = 21,
-  MOF_REGNUM  = 23,
   P8_REGNUM   = 24,
   IBR_REGNUM  = 25,
   IRP_REGNUM  = 26,
-  SRP_REGNUM  = 27,
   BAR_REGNUM  = 28,
   DCCR_REGNUM = 29,
   BRP_REGNUM  = 30,
-  USP_REGNUM  = 31
+  USP_REGNUM  = 31,
+
+  /* CRISv32 specific registers.  */
+  ACR_REGNUM  = 15,
+  BZ_REGNUM   = 16,
+  PID_REGNUM  = 18,
+  SRS_REGNUM  = 19,
+  WZ_REGNUM   = 20,
+  EXS_REGNUM  = 21,
+  EDA_REGNUM  = 22,
+  DZ_REGNUM   = 24,
+  EBP_REGNUM  = 25,
+  ERP_REGNUM  = 26,
+  NRP_REGNUM  = 28,
+  CCS_REGNUM  = 29,
+  CRISV32USP_REGNUM  = 30, /* Shares name but not number with CRISv10.  */
+  SPC_REGNUM  = 31,
+  CRISV32PC_REGNUM   = 32, /* Shares name but not number with CRISv10.  */
+
+  S0_REGNUM = 33,
+  S1_REGNUM = 34,
+  S2_REGNUM = 35,
+  S3_REGNUM = 36,
+  S4_REGNUM = 37,
+  S5_REGNUM = 38,
+  S6_REGNUM = 39,
+  S7_REGNUM = 40,
+  S8_REGNUM = 41,
+  S9_REGNUM = 42,
+  S10_REGNUM = 43,
+  S11_REGNUM = 44,
+  S12_REGNUM = 45,
+  S13_REGNUM = 46,
+  S14_REGNUM = 47,
+  S15_REGNUM = 48,
 };
 
 extern const struct cris_spec_reg cris_spec_regs[];
 
 /* CRIS version, set via the user command 'set cris-version'.  Affects
-   register names and sizes.*/
-static int usr_cmd_cris_version;
-
-/* Indicates whether to trust the above variable.  */
-static int usr_cmd_cris_version_valid = 0;
-
-/* CRIS mode, set via the user command 'set cris-mode'.  Affects availability
-   of some registers.  */
-static const char *usr_cmd_cris_mode;
+   register names and sizes.  */
+static unsigned int usr_cmd_cris_version;
 
 /* Indicates whether to trust the above variable.  */
-static int usr_cmd_cris_mode_valid = 0;
+static bool usr_cmd_cris_version_valid = false;
 
-static const char CRIS_MODE_USER[] = "CRIS_MODE_USER";
-static const char CRIS_MODE_SUPERVISOR[] = "CRIS_MODE_SUPERVISOR";
-static const char *cris_mode_enums[] = 
-{
-  CRIS_MODE_USER,
-  CRIS_MODE_SUPERVISOR,
+static const char cris_mode_normal[] = "normal";
+static const char cris_mode_guru[] = "guru";
+static const char *const cris_modes[] = {
+  cris_mode_normal,
+  cris_mode_guru,
   0
 };
 
-/* CRIS ABI, set via the user command 'set cris-abi'.  
-   There are two flavours:
-   1. Original ABI with 32-bit doubles, where arguments <= 4 bytes are 
-   passed by value.
-   2. New ABI with 64-bit doubles, where arguments <= 8 bytes are passed by 
-   value.  */
-static const char *usr_cmd_cris_abi;
+/* CRIS mode, set via the user command 'set cris-mode'.  Affects
+   type of break instruction among other things.  */
+static const char *usr_cmd_cris_mode = cris_mode_normal;
 
-/* Indicates whether to trust the above variable.  */
-static int usr_cmd_cris_abi_valid = 0;
-
-/* These variables are strings instead of enums to make them usable as 
-   parameters to add_set_enum_cmd.  */
-static const char CRIS_ABI_ORIGINAL[] = "CRIS_ABI_ORIGINAL";
-static const char CRIS_ABI_V2[] = "CRIS_ABI_V2";
-static const char CRIS_ABI_SYMBOL[] = ".$CRIS_ABI_V2";
-static const char *cris_abi_enums[] = 
+/* Whether to make use of Dwarf-2 CFI (default on).  */
+static bool usr_cmd_cris_dwarf2_cfi = true;
+
+/* Sigtramp identification code copied from i386-linux-tdep.c.  */
+
+#define SIGTRAMP_INSN0    0x9c5f  /* movu.w 0xXX, $r9 */
+#define SIGTRAMP_OFFSET0  0
+#define SIGTRAMP_INSN1    0xe93d  /* break 13 */
+#define SIGTRAMP_OFFSET1  4
+
+static const unsigned short sigtramp_code[] =
 {
-  CRIS_ABI_ORIGINAL,
-  CRIS_ABI_V2,
-  0
+  SIGTRAMP_INSN0, 0x0077,  /* movu.w $0x77, $r9 */
+  SIGTRAMP_INSN1           /* break 13 */
 };
 
-/* CRIS architecture specific information.  */
-struct gdbarch_tdep
+#define SIGTRAMP_LEN (sizeof sigtramp_code)
+
+/* Note: same length as normal sigtramp code.  */
+
+static const unsigned short rt_sigtramp_code[] =
 {
-  int cris_version;
-  const char *cris_mode;
-  const char *cris_abi;
+  SIGTRAMP_INSN0, 0x00ad,  /* movu.w $0xad, $r9 */
+  SIGTRAMP_INSN1           /* break 13 */
 };
 
-/* Functions for accessing target dependent data.  */
+/* If PC is in a sigtramp routine, return the address of the start of
+   the routine.  Otherwise, return 0.  */
 
-static int
-cris_version (void)
+static CORE_ADDR
+cris_sigtramp_start (struct frame_info *this_frame)
 {
-  return (gdbarch_tdep (current_gdbarch)->cris_version);
+  CORE_ADDR pc = get_frame_pc (this_frame);
+  gdb_byte buf[SIGTRAMP_LEN];
+
+  if (!safe_frame_unwind_memory (this_frame, pc, buf, SIGTRAMP_LEN))
+    return 0;
+
+  if (((buf[1] << 8) + buf[0]) != SIGTRAMP_INSN0)
+    {
+      if (((buf[1] << 8) + buf[0]) != SIGTRAMP_INSN1)
+       return 0;
+
+      pc -= SIGTRAMP_OFFSET1;
+      if (!safe_frame_unwind_memory (this_frame, pc, buf, SIGTRAMP_LEN))
+       return 0;
+    }
+
+  if (memcmp (buf, sigtramp_code, SIGTRAMP_LEN) != 0)
+    return 0;
+
+  return pc;
 }
 
-static const char *
-cris_mode (void)
+/* If PC is in a RT sigtramp routine, return the address of the start of
+   the routine.  Otherwise, return 0.  */
+
+static CORE_ADDR
+cris_rt_sigtramp_start (struct frame_info *this_frame)
 {
-  return (gdbarch_tdep (current_gdbarch)->cris_mode);
+  CORE_ADDR pc = get_frame_pc (this_frame);
+  gdb_byte buf[SIGTRAMP_LEN];
+
+  if (!safe_frame_unwind_memory (this_frame, pc, buf, SIGTRAMP_LEN))
+    return 0;
+
+  if (((buf[1] << 8) + buf[0]) != SIGTRAMP_INSN0)
+    {
+      if (((buf[1] << 8) + buf[0]) != SIGTRAMP_INSN1)
+       return 0;
+
+      pc -= SIGTRAMP_OFFSET1;
+      if (!safe_frame_unwind_memory (this_frame, pc, buf, SIGTRAMP_LEN))
+       return 0;
+    }
+
+  if (memcmp (buf, rt_sigtramp_code, SIGTRAMP_LEN) != 0)
+    return 0;
+
+  return pc;
 }
 
-static const char *
-cris_abi (void)
+/* Assuming THIS_FRAME is a frame for a GNU/Linux sigtramp routine,
+   return the address of the associated sigcontext structure.  */
+
+static CORE_ADDR
+cris_sigcontext_addr (struct frame_info *this_frame)
 {
-  return (gdbarch_tdep (current_gdbarch)->cris_abi);
-}
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  CORE_ADDR pc;
+  CORE_ADDR sp;
+  gdb_byte buf[4];
+
+  get_frame_register (this_frame, gdbarch_sp_regnum (gdbarch), buf);
+  sp = extract_unsigned_integer (buf, 4, byte_order);
 
-/* For saving call-clobbered contents in R9 when returning structs.  */
-static CORE_ADDR struct_return_address;
+  /* Look for normal sigtramp frame first.  */
+  pc = cris_sigtramp_start (this_frame);
+  if (pc)
+    {
+      /* struct signal_frame (arch/cris/kernel/signal.c) contains
+        struct sigcontext as its first member, meaning the SP points to
+        it already.  */
+      return sp;
+    }
 
-struct frame_extra_info
+  pc = cris_rt_sigtramp_start (this_frame);
+  if (pc)
+    {
+      /* struct rt_signal_frame (arch/cris/kernel/signal.c) contains
+        a struct ucontext, which in turn contains a struct sigcontext.
+        Magic digging:
+        4 + 4 + 128 to struct ucontext, then
+        4 + 4 + 12 to struct sigcontext.  */
+      return (sp + 156);
+    }
+
+  error (_("Couldn't recognize signal trampoline."));
+  return 0;
+}
+
+struct cris_unwind_cache
 {
+  /* The previous frame's inner most stack address.  Used as this
+     frame ID's stack_addr.  */
+  CORE_ADDR prev_sp;
+  /* The frame's base, optionally used by the high-level debug info.  */
+  CORE_ADDR base;
+  int size;
+  /* How far the SP and r8 (FP) have been offset from the start of
+     the stack frame (as defined by the previous frame's stack
+     pointer).  */
+  LONGEST sp_offset;
+  LONGEST r8_offset;
+  int uses_frame;
+
+  /* From old frame_extra_info struct.  */
   CORE_ADDR return_pc;
   int leaf_function;
+
+  /* Table indicating the location of each and every register.  */
+  struct trad_frame_saved_reg *saved_regs;
+};
+
+static struct cris_unwind_cache *
+cris_sigtramp_frame_unwind_cache (struct frame_info *this_frame,
+                                 void **this_cache)
+{
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  struct cris_unwind_cache *info;
+  CORE_ADDR addr;
+  gdb_byte buf[4];
+  int i;
+
+  if ((*this_cache))
+    return (struct cris_unwind_cache *) (*this_cache);
+
+  info = FRAME_OBSTACK_ZALLOC (struct cris_unwind_cache);
+  (*this_cache) = info;
+  info->saved_regs = trad_frame_alloc_saved_regs (this_frame);
+
+  /* Zero all fields.  */
+  info->prev_sp = 0;
+  info->base = 0;
+  info->size = 0;
+  info->sp_offset = 0;
+  info->r8_offset = 0;
+  info->uses_frame = 0;
+  info->return_pc = 0;
+  info->leaf_function = 0;
+
+  get_frame_register (this_frame, gdbarch_sp_regnum (gdbarch), buf);
+  info->base = extract_unsigned_integer (buf, 4, byte_order);
+
+  addr = cris_sigcontext_addr (this_frame);
+  
+  /* Layout of the sigcontext struct:
+     struct sigcontext {
+       struct pt_regs regs;
+       unsigned long oldmask;
+       unsigned long usp;
+     }; */
+  
+  if (tdep->cris_version == 10)
+    {
+      /* R0 to R13 are stored in reverse order at offset (2 * 4) in 
+        struct pt_regs.  */
+      for (i = 0; i <= 13; i++)
+       info->saved_regs[i].addr = addr + ((15 - i) * 4);
+
+      info->saved_regs[MOF_REGNUM].addr = addr + (16 * 4);
+      info->saved_regs[DCCR_REGNUM].addr = addr + (17 * 4);
+      info->saved_regs[SRP_REGNUM].addr = addr + (18 * 4);
+      /* Note: IRP is off by 2 at this point.  There's no point in correcting
+        it though since that will mean that the backtrace will show a PC 
+        different from what is shown when stopped.  */
+      info->saved_regs[IRP_REGNUM].addr = addr + (19 * 4);
+      info->saved_regs[gdbarch_pc_regnum (gdbarch)]
+       = info->saved_regs[IRP_REGNUM];
+      info->saved_regs[gdbarch_sp_regnum (gdbarch)].addr = addr + (24 * 4);
+    }
+  else
+    {
+      /* CRISv32.  */
+      /* R0 to R13 are stored in order at offset (1 * 4) in 
+        struct pt_regs.  */
+      for (i = 0; i <= 13; i++)
+       info->saved_regs[i].addr = addr + ((i + 1) * 4);
+
+      info->saved_regs[ACR_REGNUM].addr = addr + (15 * 4);
+      info->saved_regs[SRS_REGNUM].addr = addr + (16 * 4);
+      info->saved_regs[MOF_REGNUM].addr = addr + (17 * 4);
+      info->saved_regs[SPC_REGNUM].addr = addr + (18 * 4);
+      info->saved_regs[CCS_REGNUM].addr = addr + (19 * 4);
+      info->saved_regs[SRP_REGNUM].addr = addr + (20 * 4);
+      info->saved_regs[ERP_REGNUM].addr = addr + (21 * 4);
+      info->saved_regs[EXS_REGNUM].addr = addr + (22 * 4);
+      info->saved_regs[EDA_REGNUM].addr = addr + (23 * 4);
+
+      /* FIXME: If ERP is in a delay slot at this point then the PC will
+        be wrong at this point.  This problem manifests itself in the
+        sigaltstack.exp test case, which occasionally generates FAILs when
+        the signal is received while in a delay slot.
+        
+        This could be solved by a couple of read_memory_unsigned_integer and a
+        trad_frame_set_value.  */
+      info->saved_regs[gdbarch_pc_regnum (gdbarch)]
+       = info->saved_regs[ERP_REGNUM];
+
+      info->saved_regs[gdbarch_sp_regnum (gdbarch)].addr
+       = addr + (25 * 4);
+    }
+  
+  return info;
+}
+
+static void
+cris_sigtramp_frame_this_id (struct frame_info *this_frame, void **this_cache,
+                             struct frame_id *this_id)
+{
+  struct cris_unwind_cache *cache =
+    cris_sigtramp_frame_unwind_cache (this_frame, this_cache);
+  (*this_id) = frame_id_build (cache->base, get_frame_pc (this_frame));
+}
+
+/* Forward declaration.  */
+
+static struct value *cris_frame_prev_register (struct frame_info *this_frame,
+                                              void **this_cache, int regnum);
+static struct value *
+cris_sigtramp_frame_prev_register (struct frame_info *this_frame,
+                                   void **this_cache, int regnum)
+{
+  /* Make sure we've initialized the cache.  */
+  cris_sigtramp_frame_unwind_cache (this_frame, this_cache);
+  return cris_frame_prev_register (this_frame, this_cache, regnum);
+}
+
+static int
+cris_sigtramp_frame_sniffer (const struct frame_unwind *self,
+                            struct frame_info *this_frame,
+                            void **this_cache)
+{
+  if (cris_sigtramp_start (this_frame) 
+      || cris_rt_sigtramp_start (this_frame))
+    return 1;
+
+  return 0;
+}
+
+static const struct frame_unwind cris_sigtramp_frame_unwind =
+{
+  SIGTRAMP_FRAME,
+  default_frame_unwind_stop_reason,
+  cris_sigtramp_frame_this_id,
+  cris_sigtramp_frame_prev_register,
+  NULL,
+  cris_sigtramp_frame_sniffer
 };
 
+static int
+crisv32_single_step_through_delay (struct gdbarch *gdbarch,
+                                  struct frame_info *this_frame)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ULONGEST erp;
+  int ret = 0;
+
+  if (tdep->cris_mode == cris_mode_guru)
+    erp = get_frame_register_unsigned (this_frame, NRP_REGNUM);
+  else
+    erp = get_frame_register_unsigned (this_frame, ERP_REGNUM);
+
+  if (erp & 0x1)
+    {
+      /* In delay slot - check if there's a breakpoint at the preceding
+        instruction.  */
+      if (breakpoint_here_p (get_frame_address_space (this_frame), erp & ~0x1))
+       ret = 1;
+    }
+  return ret;
+}
+
 /* The instruction environment needed to find single-step breakpoints.  */
+
 typedef 
 struct instruction_environment
 {
@@ -199,17 +485,9 @@ struct instruction_environment
   int   delay_slot_pc_active;
   int   xflag_found;
   int   disable_interrupt;
+  enum bfd_endian byte_order;
 } inst_env_type;
 
-/* Save old breakpoints in order to restore the state before a single_step. 
-   At most, two breakpoints will have to be remembered.  */
-typedef 
-char binsn_quantum[BREAKPOINT_MAX];
-static binsn_quantum break_mem[2];
-static CORE_ADDR next_pc = 0;
-static CORE_ADDR branch_target_address = 0;
-static unsigned char branch_break_inserted = 0;
-
 /* Machine-dependencies in CRIS for opcodes.  */
 
 /* Instruction sizes.  */
@@ -291,18 +569,6 @@ cris_get_operand1 (unsigned short insn)
 
 /* Additional functions in order to handle opcodes.  */
 
-static int
-cris_get_wide_opcode (unsigned short insn)
-{
-  return ((insn & 0x03E0) >> 5);
-}
-
-static int
-cris_get_short_size (unsigned short insn)
-{
-  return ((insn & 0x0010) >> 4);
-}
-
 static int
 cris_get_quick_value (unsigned short insn)
 {
@@ -327,12 +593,6 @@ cris_get_asr_shift_steps (unsigned long value)
   return (value & 0x3F);
 }
 
-static int
-cris_get_asr_quick_shift_steps (unsigned short insn)
-{
-  return (insn & 0x1F);
-}
-
 static int
 cris_get_clear_size (unsigned short insn)
 {
@@ -366,27 +626,303 @@ cris_get_signed_offset (unsigned short insn)
 
 /* Calls an op function given the op-type, working on the insn and the
    inst_env.  */
-static void cris_gdb_func (enum cris_op_type, unsigned short, inst_env_type *);
-
-static CORE_ADDR cris_skip_prologue_main (CORE_ADDR pc, int frameless_p);
+static void cris_gdb_func (struct gdbarch *, enum cris_op_type, unsigned short,
+                          inst_env_type *);
 
 static struct gdbarch *cris_gdbarch_init (struct gdbarch_info,
                                           struct gdbarch_list *);
 
-static int cris_delayed_get_disassembler (bfd_vma, disassemble_info *);
-
 static void cris_dump_tdep (struct gdbarch *, struct ui_file *);
 
-static void cris_version_update (char *ignore_args, int from_tty, 
-                                 struct cmd_list_element *c);
+static void set_cris_version (const char *ignore_args, int from_tty, 
+                             struct cmd_list_element *c);
+
+static void set_cris_mode (const char *ignore_args, int from_tty, 
+                          struct cmd_list_element *c);
+
+static void set_cris_dwarf2_cfi (const char *ignore_args, int from_tty, 
+                                struct cmd_list_element *c);
+
+static CORE_ADDR cris_scan_prologue (CORE_ADDR pc, 
+                                    struct frame_info *this_frame,
+                                    struct cris_unwind_cache *info);
+
+static CORE_ADDR crisv32_scan_prologue (CORE_ADDR pc, 
+                                       struct frame_info *this_frame,
+                                       struct cris_unwind_cache *info);
+
+/* When arguments must be pushed onto the stack, they go on in reverse
+   order.  The below implements a FILO (stack) to do this.
+   Copied from d10v-tdep.c.  */
+
+struct stack_item
+{
+  int len;
+  struct stack_item *prev;
+  gdb_byte *data;
+};
+
+static struct stack_item *
+push_stack_item (struct stack_item *prev, const gdb_byte *contents, int len)
+{
+  struct stack_item *si = XNEW (struct stack_item);
+  si->data = (gdb_byte *) xmalloc (len);
+  si->len = len;
+  si->prev = prev;
+  memcpy (si->data, contents, len);
+  return si;
+}
+
+static struct stack_item *
+pop_stack_item (struct stack_item *si)
+{
+  struct stack_item *dead = si;
+  si = si->prev;
+  xfree (dead->data);
+  xfree (dead);
+  return si;
+}
+
+/* Put here the code to store, into fi->saved_regs, the addresses of
+   the saved registers of frame described by FRAME_INFO.  This
+   includes special registers such as pc and fp saved in special ways
+   in the stack frame.  sp is even more special: the address we return
+   for it IS the sp for the next frame.  */
+
+static struct cris_unwind_cache *
+cris_frame_unwind_cache (struct frame_info *this_frame,
+                        void **this_prologue_cache)
+{
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  struct cris_unwind_cache *info;
+
+  if ((*this_prologue_cache))
+    return (struct cris_unwind_cache *) (*this_prologue_cache);
+
+  info = FRAME_OBSTACK_ZALLOC (struct cris_unwind_cache);
+  (*this_prologue_cache) = info;
+  info->saved_regs = trad_frame_alloc_saved_regs (this_frame);
+
+  /* Zero all fields.  */
+  info->prev_sp = 0;
+  info->base = 0;
+  info->size = 0;
+  info->sp_offset = 0;
+  info->r8_offset = 0;
+  info->uses_frame = 0;
+  info->return_pc = 0;
+  info->leaf_function = 0;
+
+  /* Prologue analysis does the rest...  */
+  if (tdep->cris_version == 32)
+    crisv32_scan_prologue (get_frame_func (this_frame), this_frame, info);
+  else
+    cris_scan_prologue (get_frame_func (this_frame), this_frame, info);
+
+  return info;
+}
+
+/* Given a GDB frame, determine the address of the calling function's
+   frame.  This will be used to create a new GDB frame struct.  */
+
+static void
+cris_frame_this_id (struct frame_info *this_frame,
+                   void **this_prologue_cache,
+                   struct frame_id *this_id)
+{
+  struct cris_unwind_cache *info
+    = cris_frame_unwind_cache (this_frame, this_prologue_cache);
+  CORE_ADDR base;
+  CORE_ADDR func;
+  struct frame_id id;
+
+  /* The FUNC is easy.  */
+  func = get_frame_func (this_frame);
+
+  /* Hopefully the prologue analysis either correctly determined the
+     frame's base (which is the SP from the previous frame), or set
+     that base to "NULL".  */
+  base = info->prev_sp;
+  if (base == 0)
+    return;
+
+  id = frame_id_build (base, func);
+
+  (*this_id) = id;
+}
+
+static struct value *
+cris_frame_prev_register (struct frame_info *this_frame,
+                         void **this_prologue_cache, int regnum)
+{
+  struct cris_unwind_cache *info
+    = cris_frame_unwind_cache (this_frame, this_prologue_cache);
+  return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
+}
+
+static CORE_ADDR
+cris_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp)
+{
+  /* Align to the size of an instruction (so that they can safely be
+     pushed onto the stack).  */
+  return sp & ~3;
+}
+
+static CORE_ADDR
+cris_push_dummy_code (struct gdbarch *gdbarch,
+                      CORE_ADDR sp, CORE_ADDR funaddr,
+                      struct value **args, int nargs,
+                      struct type *value_type,
+                      CORE_ADDR *real_pc, CORE_ADDR *bp_addr,
+                     struct regcache *regcache)
+{
+  /* Allocate space sufficient for a breakpoint.  */
+  sp = (sp - 4) & ~3;
+  /* Store the address of that breakpoint */
+  *bp_addr = sp;
+  /* CRIS always starts the call at the callee's entry point.  */
+  *real_pc = funaddr;
+  return sp;
+}
+
+static CORE_ADDR
+cris_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
+                     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)
+{
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  int argreg;
+  int argnum;
+
+  struct stack_item *si = NULL;
+
+  /* Push the return address.  */
+  regcache_cooked_write_unsigned (regcache, SRP_REGNUM, bp_addr);
+
+  /* Are we returning a value using a structure return or a normal value
+     return?  struct_addr is the address of the reserved space for the return
+     structure to be written on the stack.  */
+  if (return_method == return_method_struct)
+    regcache_cooked_write_unsigned (regcache, STR_REGNUM, struct_addr);
+
+  /* Now load as many as possible of the first arguments into registers,
+     and push the rest onto the stack.  */
+  argreg = ARG1_REGNUM;
+
+  for (argnum = 0; argnum < nargs; argnum++)
+    {
+      int len;
+      const gdb_byte *val;
+      int reg_demand;
+      int i;
+      
+      len = TYPE_LENGTH (value_type (args[argnum]));
+      val = value_contents (args[argnum]);
+      
+      /* How may registers worth of storage do we need for this argument?  */
+      reg_demand = (len / 4) + (len % 4 != 0 ? 1 : 0);
+        
+      if (len <= (2 * 4) && (argreg + reg_demand - 1 <= ARG4_REGNUM))
+        {
+          /* Data passed by value.  Fits in available register(s).  */
+          for (i = 0; i < reg_demand; i++)
+            {
+              regcache->cooked_write (argreg, val);
+              argreg++;
+              val += 4;
+            }
+        }
+      else if (len <= (2 * 4) && argreg <= ARG4_REGNUM)
+        {
+          /* Data passed by value. Does not fit in available register(s).
+             Use the register(s) first, then the stack.  */
+          for (i = 0; i < reg_demand; i++)
+            {
+              if (argreg <= ARG4_REGNUM)
+                {
+                 regcache->cooked_write (argreg, val);
+                  argreg++;
+                  val += 4;
+                }
+              else
+                {
+                 /* Push item for later so that pushed arguments
+                    come in the right order.  */
+                 si = push_stack_item (si, val, 4);
+                  val += 4;
+                }
+            }
+        }
+      else if (len > (2 * 4))
+        {
+         /* Data passed by reference.  Push copy of data onto stack
+            and pass pointer to this copy as argument.  */
+         sp = (sp - len) & ~3;
+         write_memory (sp, val, len);
+
+         if (argreg <= ARG4_REGNUM)
+           {
+             regcache_cooked_write_unsigned (regcache, argreg, sp);
+             argreg++;
+           }
+         else
+           {
+             gdb_byte buf[4];
+             store_unsigned_integer (buf, 4, byte_order, sp);
+             si = push_stack_item (si, buf, 4);
+           }
+        }
+      else
+        {
+          /* Data passed by value.  No available registers.  Put it on
+             the stack.  */
+          si = push_stack_item (si, val, len);
+        }
+    }
 
-static void cris_mode_update (char *ignore_args, int from_tty, 
-                              struct cmd_list_element *c);
+  while (si)
+    {
+      /* fp_arg must be word-aligned (i.e., don't += len) to match
+        the function prologue.  */
+      sp = (sp - si->len) & ~3;
+      write_memory (sp, si->data, si->len);
+      si = pop_stack_item (si);
+    }
+
+  /* Finally, update the SP register.  */
+  regcache_cooked_write_unsigned (regcache, gdbarch_sp_regnum (gdbarch), sp);
 
-static void cris_abi_update (char *ignore_args, int from_tty, 
-                             struct cmd_list_element *c);
+  return sp;
+}
+
+static const struct frame_unwind cris_frame_unwind = 
+{
+  NORMAL_FRAME,
+  default_frame_unwind_stop_reason,
+  cris_frame_this_id,
+  cris_frame_prev_register,
+  NULL,
+  default_frame_sniffer
+};
 
-static CORE_ADDR bfd_lookup_symbol (bfd *, const char *);
+static CORE_ADDR
+cris_frame_base_address (struct frame_info *this_frame, void **this_cache)
+{
+  struct cris_unwind_cache *info
+    = cris_frame_unwind_cache (this_frame, this_cache);
+  return info->base;
+}
+
+static const struct frame_base cris_frame_base = 
+{
+  &cris_frame_unwind,
+  cris_frame_base_address,
+  cris_frame_base_address,
+  cris_frame_base_address
+};
 
 /* Frames information. The definition of the struct frame_info is
 
@@ -434,7 +970,7 @@ static CORE_ADDR bfd_lookup_symbol (bfd *, const char *);
    the subq-instruction will be present with X as the number of bytes
    needed for storage.  The reshuffle with respect to r8 may be performed
    with any size S (b, w, d) and any of the general registers Z={0..13}. 
-   The offset U should be representable by a signed 8-bit value in all cases. 
+   The offset U should be representable by a signed 8-bit value in all cases.
    Thus, the prefix word is assumed to be immediate byte offset mode followed
    by another word containing the instruction.
 
@@ -454,7 +990,7 @@ static CORE_ADDR bfd_lookup_symbol (bfd *, const char *);
    move.d r13,rV    ; P3
    move.S [r8+U],rZ ; P4
 
-   if any of the call parameters are stored. The host expects these 
+   if any of the call parameters are stored.  The host expects these 
    instructions to be executed in order to get the call parameters right.  */
 
 /* Examine the prologue of a function.  The variable ip is the address of 
@@ -464,10 +1000,13 @@ static CORE_ADDR bfd_lookup_symbol (bfd *, const char *);
    the entire prologue is examined (0) or just enough instructions to 
    determine that it is a prologue (1).  */
 
-CORE_ADDR 
-cris_examine (CORE_ADDR ip, CORE_ADDR limit, struct frame_info *fi, 
-              int frameless_p)
+static CORE_ADDR 
+cris_scan_prologue (CORE_ADDR pc, struct frame_info *this_frame,
+                   struct cris_unwind_cache *info)
 {
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+
   /* Present instruction.  */
   unsigned short insn;
 
@@ -475,9 +1014,6 @@ cris_examine (CORE_ADDR ip, CORE_ADDR limit, struct frame_info *fi,
   unsigned short insn_next; 
   int regno;
 
-  /* Is there a push fp?  */
-  int have_fp; 
-
   /* Number of byte on stack used for local variables and movem.  */
   int val; 
 
@@ -487,82 +1023,86 @@ cris_examine (CORE_ADDR ip, CORE_ADDR limit, struct frame_info *fi,
   /* move.d r<source_register>,rS */
   short source_register; 
 
-  /* This frame is with respect to a leaf until a push srp is found.  */
-  get_frame_extra_info (fi)->leaf_function = 1;
+  /* Scan limit.  */
+  int limit;
 
-  /* This frame is without the FP until a push fp is found.  */
-  have_fp = 0;
+  /* This frame is with respect to a leaf until a push srp is found.  */
+  if (info)
+    {
+      info->leaf_function = 1;
+    }
 
   /* Assume nothing on stack.  */
   val = 0;
   regsave = -1;
 
-  /* No information about register contents so far.  */
+  /* If we were called without a this_frame, that means we were called
+     from cris_skip_prologue which already tried to find the end of the
+     prologue through the symbol information.  64 instructions past current
+     pc is arbitrarily chosen, but at least it means we'll stop eventually.  */
+  limit = this_frame ? get_frame_pc (this_frame) : pc + 64;
 
-  /* We only want to know the end of the prologue when fi->saved_regs == 0.
-     When the saved registers are allocated full information is required.  */
-  if (get_frame_saved_regs (fi))
-    {
-      for (regno = 0; regno < NUM_REGS; regno++)
-        get_frame_saved_regs (fi)[regno] = 0;
-    }
   /* Find the prologue instructions.  */
-  do
+  while (pc > 0 && pc < limit)
     {
-      insn = read_memory_unsigned_integer (ip, sizeof (short));
-      ip += sizeof (short);
+      insn = read_memory_unsigned_integer (pc, 2, byte_order);
+      pc += 2;
       if (insn == 0xE1FC)
         {
-          /* push <reg> 32 bit instruction */
-          insn_next = read_memory_unsigned_integer (ip, sizeof (short));
-          ip += sizeof (short);
+          /* push <reg> 32 bit instruction */
+          insn_next = read_memory_unsigned_integer (pc, 2, byte_order);
+          pc += 2;
           regno = cris_get_operand2 (insn_next);
-
+         if (info)
+           {
+             info->sp_offset += 4;
+           }
           /* This check, meant to recognize srp, used to be regno == 
              (SRP_REGNUM - NUM_GENREGS), but that covers r11 also.  */
           if (insn_next == 0xBE7E)
             {
-              if (frameless_p)
-                {
-                  return ip;
-                }
-              get_frame_extra_info (fi)->leaf_function = 0;
+             if (info)
+               {
+                 info->leaf_function = 0;
+               }
             }
-          else if (regno == FP_REGNUM)
+         else if (insn_next == 0x8FEE)
             {
-              have_fp = 1;
+             /* push $r8 */
+             if (info)
+               {
+                 info->r8_offset = info->sp_offset;
+               }
             }
         }
       else if (insn == 0x866E)
         {
           /* move.d sp,r8 */
-          if (frameless_p)
-            {
-              return ip;
-            }
+         if (info)
+           {
+             info->uses_frame = 1;
+           }
           continue;
         }
-      else if (cris_get_operand2 (insn) == SP_REGNUM 
+      else if (cris_get_operand2 (insn) == gdbarch_sp_regnum (gdbarch)
                && cris_get_mode (insn) == 0x0000
                && cris_get_opcode (insn) == 0x000A)
         {
           /* subq <val>,sp */
-          val = cris_get_quick_value (insn);
+         if (info)
+           {
+             info->sp_offset += cris_get_quick_value (insn);
+           }
         }
       else if (cris_get_mode (insn) == 0x0002 
                && cris_get_opcode (insn) == 0x000F
                && cris_get_size (insn) == 0x0003
-               && cris_get_operand1 (insn) == SP_REGNUM)
+               && cris_get_operand1 (insn) == gdbarch_sp_regnum (gdbarch))
         {
           /* movem r<regsave>,[sp] */
-          if (frameless_p)
-            {
-              return ip;
-            }
           regsave = cris_get_operand2 (insn);
         }
-      else if (cris_get_operand2 (insn) == SP_REGNUM
+      else if (cris_get_operand2 (insn) == gdbarch_sp_regnum (gdbarch)
                && ((insn & 0x0F00) >> 8) == 0x0001
                && (cris_get_signed_offset (insn) < 0))
         {
@@ -570,24 +1110,24 @@ cris_examine (CORE_ADDR ip, CORE_ADDR limit, struct frame_info *fi,
              register.  Used for CRIS v8 i.e. ETRAX 100 and newer if <val> 
              is between 64 and 128. 
              movem r<regsave>,[sp=sp-<val>] */
-          val = -cris_get_signed_offset (insn);
-          insn_next = read_memory_unsigned_integer (ip, sizeof (short));
-          ip += sizeof (short);
+         if (info)
+           {
+             info->sp_offset += -cris_get_signed_offset (insn);
+           }
+         insn_next = read_memory_unsigned_integer (pc, 2, byte_order);
+          pc += 2;
           if (cris_get_mode (insn_next) == PREFIX_ASSIGN_MODE
               && cris_get_opcode (insn_next) == 0x000F
               && cris_get_size (insn_next) == 0x0003
-              && cris_get_operand1 (insn_next) == SP_REGNUM)
+              && cris_get_operand1 (insn_next) == gdbarch_sp_regnum
+                                                 (gdbarch))
             {
-              if (frameless_p)
-                {
-                  return ip;
-                }
               regsave = cris_get_operand2 (insn_next);
             }
           else
             {
               /* The prologue ended before the limit was reached.  */
-              ip -= 2 * sizeof (short);
+              pc -= 4;
               break;
             }
         }
@@ -596,10 +1136,6 @@ cris_examine (CORE_ADDR ip, CORE_ADDR limit, struct frame_info *fi,
                && cris_get_size (insn) == 0x0002)
         {
           /* move.d r<10..13>,r<0..15> */
-          if (frameless_p)
-            {
-              return ip;
-            }
           source_register = cris_get_operand1 (insn);
 
           /* FIXME?  In the glibc solibs, the prologue might contain something
@@ -612,21 +1148,21 @@ cris_examine (CORE_ADDR ip, CORE_ADDR limit, struct frame_info *fi,
           if (source_register < ARG1_REGNUM || source_register > ARG4_REGNUM)
             {
               /* The prologue ended before the limit was reached.  */
-              ip -= sizeof (short);
+              pc -= 2;
               break;
             }
         }
-      else if (cris_get_operand2 (insn) == FP_REGNUM 
+      else if (cris_get_operand2 (insn) == CRIS_FP_REGNUM 
                /* The size is a fixed-size.  */
                && ((insn & 0x0F00) >> 8) == 0x0001 
                /* A negative offset.  */
                && (cris_get_signed_offset (insn) < 0))  
         {
           /* move.S rZ,[r8-U] (?) */
-          insn_next = read_memory_unsigned_integer (ip, sizeof (short));
-          ip += sizeof (short);
+          insn_next = read_memory_unsigned_integer (pc, 2, byte_order);
+          pc += 2;
           regno = cris_get_operand2 (insn_next);
-          if ((regno >= 0 && regno < SP_REGNUM)
+          if ((regno >= 0 && regno < gdbarch_sp_regnum (gdbarch))
               && cris_get_mode (insn_next) == PREFIX_OFFSET_MODE
               && cris_get_opcode (insn_next) == 0x000F)
             {
@@ -636,21 +1172,21 @@ cris_examine (CORE_ADDR ip, CORE_ADDR limit, struct frame_info *fi,
           else
             {
               /* The prologue ended before the limit was reached.  */
-              ip -= 2 * sizeof (short);
+              pc -= 4;
               break;
             }
         }
-      else if (cris_get_operand2 (insn) == FP_REGNUM 
+      else if (cris_get_operand2 (insn) == CRIS_FP_REGNUM 
                /* The size is a fixed-size.  */
                && ((insn & 0x0F00) >> 8) == 0x0001 
                /* A positive offset.  */
                && (cris_get_signed_offset (insn) > 0))  
         {
           /* move.S [r8+U],rZ (?) */
-          insn_next = read_memory_unsigned_integer (ip, sizeof (short));
-          ip += sizeof (short);
+         insn_next = read_memory_unsigned_integer (pc, 2, byte_order);
+          pc += 2;
           regno = cris_get_operand2 (insn_next);
-          if ((regno >= 0 && regno < SP_REGNUM)
+          if ((regno >= 0 && regno < gdbarch_sp_regnum (gdbarch))
               && cris_get_mode (insn_next) == PREFIX_OFFSET_MODE
               && cris_get_opcode (insn_next) == 0x0009
               && cris_get_operand1 (insn_next) == regno)
@@ -661,133 +1197,197 @@ cris_examine (CORE_ADDR ip, CORE_ADDR limit, struct frame_info *fi,
           else
             {
               /* The prologue ended before the limit was reached.  */
-              ip -= 2 * sizeof (short);
+              pc -= 4;
               break;
             }
         }
       else
         {
           /* The prologue ended before the limit was reached.  */
-          ip -= sizeof (short);
+          pc -= 2;
           break;
         }
     }
-  while (ip < limit);
 
-  /* We only want to know the end of the prologue when
-     fi->saved_regs == 0.  */ 
-  if (!get_frame_saved_regs (fi))
-    return ip;
+  /* We only want to know the end of the prologue when this_frame and info
+     are NULL (called from cris_skip_prologue i.e.).  */
+  if (this_frame == NULL && info == NULL)
+    {
+      return pc;
+    }
+
+  info->size = info->sp_offset;
 
-  if (have_fp)
+  /* Compute the previous frame's stack pointer (which is also the
+     frame's ID's stack address), and this frame's base pointer.  */
+  if (info->uses_frame)
+    {
+      ULONGEST this_base;
+      /* The SP was moved to the FP.  This indicates that a new frame
+         was created.  Get THIS frame's FP value by unwinding it from
+         the next frame.  */
+      this_base = get_frame_register_unsigned (this_frame, CRIS_FP_REGNUM);
+      info->base = this_base;
+      info->saved_regs[CRIS_FP_REGNUM].addr = info->base;
+  
+      /* The FP points at the last saved register.  Adjust the FP back
+         to before the first saved register giving the SP.  */
+      info->prev_sp = info->base + info->r8_offset;
+    }
+  else
     {
-      get_frame_saved_regs (fi)[FP_REGNUM] = get_frame_base (fi);
+      ULONGEST this_base;      
+      /* Assume that the FP is this frame's SP but with that pushed
+         stack space added back.  */
+      this_base = get_frame_register_unsigned (this_frame,
+                                              gdbarch_sp_regnum (gdbarch));
+      info->base = this_base;
+      info->prev_sp = info->base + info->size;
+    }
       
-      /* Calculate the addresses.  */
-      for (regno = regsave; regno >= 0; regno--)
-        {
-          get_frame_saved_regs (fi)[regno] = get_frame_base (fi) - val;
-          val -= 4;
-        }
-      if (get_frame_extra_info (fi)->leaf_function)
-        {
-          /* Set the register SP to contain the stack pointer of 
-             the caller.  */
-          get_frame_saved_regs (fi)[SP_REGNUM] = get_frame_base (fi) + 4;
-        }
+  /* Calculate the addresses for the saved registers on the stack.  */
+  /* FIXME: The address calculation should really be done on the fly while
+     we're analyzing the prologue (we only hold one regsave value as it is 
+     now).  */
+  val = info->sp_offset;
+
+  for (regno = regsave; regno >= 0; regno--)
+    {
+      info->saved_regs[regno].addr = info->base + info->r8_offset - val;
+      val -= 4;
+    }
+
+  /* The previous frame's SP needed to be computed.  Save the computed
+     value.  */
+  trad_frame_set_value (info->saved_regs,
+                       gdbarch_sp_regnum (gdbarch), info->prev_sp);
+
+  if (!info->leaf_function)
+    {
+      /* SRP saved on the stack.  But where?  */
+      if (info->r8_offset == 0)
+       {
+         /* R8 not pushed yet.  */
+         info->saved_regs[SRP_REGNUM].addr = info->base;
+       }
       else
-        {
-          /* Set the register SP to contain the stack pointer of 
-             the caller.  */
-          get_frame_saved_regs (fi)[SP_REGNUM] = get_frame_base (fi) + 8;
-      
-          /* Set the register SRP to contain the return address of 
-             the caller.  */
-          get_frame_saved_regs (fi)[SRP_REGNUM] = get_frame_base (fi) + 4;
-        }
+       {
+         /* R8 pushed, but SP may or may not be moved to R8 yet.  */
+         info->saved_regs[SRP_REGNUM].addr = info->base + 4;
+       }
     }
-  return ip;
-}
 
-/* Advance pc beyond any function entry prologue instructions at pc
-   to reach some "real" code.  */
+  /* The PC is found in SRP (the actual register or located on the stack).  */
+  info->saved_regs[gdbarch_pc_regnum (gdbarch)]
+    = info->saved_regs[SRP_REGNUM];
 
-CORE_ADDR
-cris_skip_prologue (CORE_ADDR pc)
-{
-  return cris_skip_prologue_main (pc, 0);
+  return pc;
 }
 
-/* As cris_skip_prologue, but stops as soon as it knows that the function 
-   has a frame.  Its result is equal to its input pc if the function is 
-   frameless, unequal otherwise.  */
-
-CORE_ADDR
-cris_skip_prologue_frameless_p (CORE_ADDR pc)
+static CORE_ADDR 
+crisv32_scan_prologue (CORE_ADDR pc, struct frame_info *this_frame,
+                   struct cris_unwind_cache *info)
 {
-  return cris_skip_prologue_main (pc, 1);
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  ULONGEST this_base;
+
+  /* Unlike the CRISv10 prologue scanner (cris_scan_prologue), this is not
+     meant to be a full-fledged prologue scanner.  It is only needed for 
+     the cases where we end up in code always lacking DWARF-2 CFI, notably:
+
+       * PLT stubs (library calls)
+       * call dummys
+       * signal trampolines
+
+     For those cases, it is assumed that there is no actual prologue; that 
+     the stack pointer is not adjusted, and (as a consequence) the return
+     address is not pushed onto the stack.  */
+
+  /* We only want to know the end of the prologue when this_frame and info
+     are NULL (called from cris_skip_prologue i.e.).  */
+  if (this_frame == NULL && info == NULL)
+    {
+      return pc;
+    }
+
+  /* The SP is assumed to be unaltered.  */
+  this_base = get_frame_register_unsigned (this_frame,
+                                          gdbarch_sp_regnum (gdbarch));
+  info->base = this_base;
+  info->prev_sp = this_base;
+      
+  /* The PC is assumed to be found in SRP.  */
+  info->saved_regs[gdbarch_pc_regnum (gdbarch)]
+    = info->saved_regs[SRP_REGNUM];
+
+  return pc;
 }
 
+/* Advance pc beyond any function entry prologue instructions at pc
+   to reach some "real" code.  */
+
 /* Given a PC value corresponding to the start of a function, return the PC
    of the first instruction after the function prologue.  */
 
-CORE_ADDR
-cris_skip_prologue_main (CORE_ADDR pc, int frameless_p)
+static CORE_ADDR
+cris_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
-  struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
-  struct frame_info *fi;
-  struct symtab_and_line sal = find_pc_line (pc, 0);
-  int best_limit;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  CORE_ADDR func_addr, func_end;
+  struct symtab_and_line sal;
   CORE_ADDR pc_after_prologue;
   
-  /* frame_info now contains dynamic memory.  Since fi is a dummy
-     here, I don't bother allocating memory for saved_regs.  */
-  fi = deprecated_frame_xmalloc_with_cleanup (0, sizeof (struct frame_extra_info));
-
-  /* If there is no symbol information then sal.end == 0, and we end up
-     examining only the first instruction in the function prologue. 
-     Exaggerating the limit seems to be harmless.  */
-  if (sal.end > 0)
-    best_limit = sal.end;
+  /* If we have line debugging information, then the end of the prologue
+     should the first assembly instruction of the first source line.  */
+  if (find_pc_partial_function (pc, NULL, &func_addr, &func_end))
+    {
+      sal = find_pc_line (func_addr, 0);
+      if (sal.end > 0 && sal.end < func_end)
+       return sal.end;
+    }
+
+  if (tdep->cris_version == 32)
+    pc_after_prologue = crisv32_scan_prologue (pc, NULL, NULL);
   else
-    best_limit = pc + 100; 
+    pc_after_prologue = cris_scan_prologue (pc, NULL, NULL);
 
-  pc_after_prologue = cris_examine (pc, best_limit, fi, frameless_p);
-  do_cleanups (old_chain);
   return pc_after_prologue;
 }
 
-/* Use the program counter to determine the contents and size of a breakpoint
-   instruction.  It returns a pointer to a string of bytes that encode a
-   breakpoint instruction, stores the length of the string to *lenptr, and
-   adjusts pcptr (if necessary) to point to the actual memory location where
-   the breakpoint should be inserted.  */
+/* Implement the breakpoint_kind_from_pc gdbarch method.  */
 
-const unsigned char *
-cris_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
+static int
+cris_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
 {
-  static unsigned char break_insn[] = {0x38, 0xe9};
-  *lenptr = 2;
-
-  return break_insn;
+  return 2;
 }
 
-/* Returns the register SRP (subroutine return pointer) which must contain 
-   the content of the register PC after a function call.  */
+/* Implement the sw_breakpoint_from_kind gdbarch method.  */
 
-static CORE_ADDR
-cris_saved_pc_after_call (struct frame_info *frame)
+static const gdb_byte *
+cris_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
 {
-  return read_register (SRP_REGNUM);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  static unsigned char break8_insn[] = {0x38, 0xe9};
+  static unsigned char break15_insn[] = {0x3f, 0xe9};
+
+  *size = kind;
+
+  if (tdep->cris_mode == cris_mode_guru)
+    return break15_insn;
+  else
+    return break8_insn;
 }
 
 /* Returns 1 if spec_reg is applicable to the current gdbarch's CRIS version,
    0 otherwise.  */
 
-int
-cris_spec_reg_applicable (struct cris_spec_reg spec_reg)
+static int
+cris_spec_reg_applicable (struct gdbarch *gdbarch,
+                         struct cris_spec_reg spec_reg)
 {
-  int version = cris_version ();
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  unsigned int version = tdep->cris_version;
   
   switch (spec_reg.applicable_version)
     {
@@ -796,19 +1396,26 @@ cris_spec_reg_applicable (struct cris_spec_reg spec_reg)
     case cris_ver_warning:
       /* Indeterminate/obsolete.  */
       return 0;
-    case cris_ver_sim:
-      /* Simulator only.  */
-      return 0;
     case cris_ver_v0_3:
-      return (version >= 0 && version <= 3);
+      return in_inclusive_range (version, 0U, 3U);
     case cris_ver_v3p:
       return (version >= 3);
     case cris_ver_v8:
-      return (version == 8 || version == 9);
+      return in_inclusive_range (version, 8U, 9U);
     case cris_ver_v8p:
       return (version >= 8);
+    case cris_ver_v0_10:
+      return in_inclusive_range (version, 0U, 10U);
+    case cris_ver_v3_10:
+      return in_inclusive_range (version, 3U, 10U);
+    case cris_ver_v8_10:
+      return in_inclusive_range (version, 8U, 10U);
+    case cris_ver_v10:
+      return (version == 10);
     case cris_ver_v10p:
       return (version >= 10);
+    case cris_ver_v32p:
+      return (version >= 32);
     default:
       /* Invalid cris version.  */
       return 0;
@@ -818,8 +1425,8 @@ cris_spec_reg_applicable (struct cris_spec_reg spec_reg)
 /* Returns the register size in unit byte.  Returns 0 for an unimplemented
    register, -1 for an invalid register.  */
 
-int
-cris_register_size (int regno)
+static int
+cris_register_size (struct gdbarch *gdbarch, int regno)
 {
   int i;
   int spec_regno;
@@ -829,763 +1436,400 @@ cris_register_size (int regno)
       /* General registers (R0 - R15) are 32 bits.  */
       return 4;
     }
-  else if (regno >= NUM_GENREGS && regno < NUM_REGS)
+  else if (regno >= NUM_GENREGS && regno < (NUM_GENREGS + NUM_SPECREGS))
     {
       /* Special register (R16 - R31).  cris_spec_regs is zero-based. 
          Adjust regno accordingly.  */
       spec_regno = regno - NUM_GENREGS;
       
-      /* The entries in cris_spec_regs are stored in register number order,
-         which means we can shortcut into the array when searching it.  */
-      for (i = spec_regno; cris_spec_regs[i].name != NULL; i++)
+      for (i = 0; cris_spec_regs[i].name != NULL; i++)
         {
           if (cris_spec_regs[i].number == spec_regno 
-              && cris_spec_reg_applicable (cris_spec_regs[i]))
+              && cris_spec_reg_applicable (gdbarch, cris_spec_regs[i]))
             /* Go with the first applicable register.  */
             return cris_spec_regs[i].reg_size;
         }
       /* Special register not applicable to this CRIS version.  */
       return 0;
     }
-  else
+  else if (regno >= gdbarch_pc_regnum (gdbarch)
+          && regno < gdbarch_num_regs (gdbarch))
     {
-      /* Invalid register.  */
-      return -1;
-    }
-}
-
-/* Nonzero if regno should not be fetched from the target.  This is the case
-   for unimplemented (size 0) and non-existant registers.  */
-
-int
-cris_cannot_fetch_register (int regno)
-{
-  return ((regno < 0 || regno >= NUM_REGS) 
-          || (cris_register_size (regno) == 0));
-}
-
-/* Nonzero if regno should not be written to the target, for various 
-   reasons.  */
-
-int
-cris_cannot_store_register (int regno)
-{
-  /* There are three kinds of registers we refuse to write to.
-     1. Those that not implemented.
-     2. Those that are read-only (depends on the processor mode).
-     3. Those registers to which a write has no effect.
-  */
-
-  if (regno < 0 || regno >= NUM_REGS || cris_register_size (regno) == 0)
-    /* Not implemented.  */
-    return 1;
-
-  else if  (regno == VR_REGNUM)
-    /* Read-only.  */
-    return 1;
-
-  else if  (regno == P0_REGNUM || regno == P4_REGNUM || regno == P8_REGNUM)
-    /* Writing has no effect.  */
-    return 1;
-
-  else if (cris_mode () == CRIS_MODE_USER)
-    {
-      if (regno == IBR_REGNUM || regno == BAR_REGNUM || regno == BRP_REGNUM 
-          || regno == IRP_REGNUM)
-        /* Read-only in user mode.  */
-        return 1;
-    }
-  
-  return 0;
-}
-
-/* Returns the register offset for the first byte of register regno's space 
-   in the saved register state.  Returns -1 for an invalid or unimplemented
-   register.  */
-
-int
-cris_register_offset (int regno)
-{
-  int i;
-  int reg_size;
-  int offset = 0;
-  
-  if (regno >= 0 && regno < NUM_REGS)
-    {
-      /* FIXME: The offsets should be cached and calculated only once,
-         when the architecture being debugged has changed.  */
-      for (i = 0; i < regno; i++)
-        offset += cris_register_size (i);
-      
-      return offset;
-    }
-  else
-    {
-      /* Invalid register. */
-      return -1;
-    }
-}
-
-/* Return the GDB type (defined in gdbtypes.c) for the "standard" data type
-   of data in register regno.  */
-
-struct type *
-cris_register_virtual_type (int regno)
-{
-  if (regno == SP_REGNUM || regno == PC_REGNUM
-      || (regno > P8_REGNUM && regno < USP_REGNUM))
-    {
-      /* SP, PC, IBR, IRP, SRP, BAR, DCCR, BRP */
-      return lookup_pointer_type (builtin_type_void);
-    }
-  else if (regno == P8_REGNUM || regno == USP_REGNUM
-           || (regno >= 0 && regno < SP_REGNUM))
-    {
-      /* R0 - R13, P8, P15 */
-      return builtin_type_unsigned_long;
-    }
-  else if (regno > P3_REGNUM && regno < P8_REGNUM)
-    {
-      /* P4, CCR, DCR0, DCR1 */
-      return builtin_type_unsigned_short;
-    }
-  else if (regno > PC_REGNUM && regno < P4_REGNUM)
-    {
-      /* P0, P1, P2, P3 */
-      return builtin_type_unsigned_char;
-    }
-  else
-    {
-      /* Invalid register.  */
-      return builtin_type_void;
-    }
-}
-
-/* Stores a function return value of type type, where valbuf is the address 
-   of the value to be stored.  */
-
-/* In the original CRIS ABI, R10 is used to store return values.  */
-
-void
-cris_abi_original_store_return_value (struct type *type, char *valbuf)
-{
-  int len = TYPE_LENGTH (type);
-  
-  if (len <= REGISTER_SIZE) 
-    deprecated_write_register_bytes (REGISTER_BYTE (RET_REGNUM), valbuf, len);
-  else
-    internal_error (__FILE__, __LINE__, "cris_abi_original_store_return_value: type length too large.");
-}
-
-/* In the CRIS ABI V2, R10 and R11 are used to store return values.  */
-
-void
-cris_abi_v2_store_return_value (struct type *type, char *valbuf)
-{
-  int len = TYPE_LENGTH (type);
-  
-  if (len <= 2 * REGISTER_SIZE)
-    {
-      /* Note that this works since R10 and R11 are consecutive registers.  */
-      deprecated_write_register_bytes (REGISTER_BYTE (RET_REGNUM), valbuf,
-                                      len);
-    }
-  else
-    internal_error (__FILE__, __LINE__, "cris_abi_v2_store_return_value: type length too large.");
-}
-
-/* Return the name of register regno as a string. Return NULL for an invalid or
-   unimplemented register.  */
-
-const char *
-cris_register_name (int regno)
-{
-  static char *cris_genreg_names[] =
-  { "r0",  "r1",  "r2",  "r3", \
-    "r4",  "r5",  "r6",  "r7", \
-    "r8",  "r9",  "r10", "r11", \
-    "r12", "r13", "sp",  "pc" };
-
-  int i;
-  int spec_regno;
-
-  if (regno >= 0 && regno < NUM_GENREGS)
-    {
-      /* General register.  */
-      return cris_genreg_names[regno];
-    }
-  else if (regno >= NUM_GENREGS && regno < NUM_REGS)
-    {
-      /* Special register (R16 - R31).  cris_spec_regs is zero-based. 
-         Adjust regno accordingly.  */
-      spec_regno = regno - NUM_GENREGS;
-      
-      /* The entries in cris_spec_regs are stored in register number order,
-         which means we can shortcut into the array when searching it.  */
-      for (i = spec_regno; cris_spec_regs[i].name != NULL; i++)
-        {
-          if (cris_spec_regs[i].number == spec_regno 
-              && cris_spec_reg_applicable (cris_spec_regs[i]))
-            /* Go with the first applicable register.  */
-            return cris_spec_regs[i].name;
-        }
-      /* Special register not applicable to this CRIS version.  */
-      return NULL;
-    }
-  else
-    {
-      /* Invalid register.  */
-      return NULL;
+      /* This will apply to CRISv32 only where there are additional registers
+        after the special registers (pseudo PC and support registers).  */
+      return 4;
     }
-}
-
-int
-cris_register_bytes_ok (long bytes)
-{
-  return (bytes == REGISTER_BYTES);
-}
-
-/* Extract from an array regbuf containing the raw register state a function
-   return value of type type, and copy that, in virtual format, into 
-   valbuf.  */
-
-/* In the original CRIS ABI, R10 is used to return values.  */
-
-void
-cris_abi_original_extract_return_value (struct type *type, char *regbuf, 
-                                        char *valbuf)
-{
-  int len = TYPE_LENGTH (type);
+
   
-  if (len <= REGISTER_SIZE)
-    memcpy (valbuf, regbuf + REGISTER_BYTE (RET_REGNUM), len);
-  else
-    internal_error (__FILE__, __LINE__, "cris_abi_original_extract_return_value: type length too large");
+  return -1;
 }
 
-/* In the CRIS ABI V2, R10 and R11 are used to store return values.  */
+/* Nonzero if regno should not be fetched from the target.  This is the case
+   for unimplemented (size 0) and non-existant registers.  */
 
-void
-cris_abi_v2_extract_return_value (struct type *type, char *regbuf, 
-                                  char *valbuf)
+static int
+cris_cannot_fetch_register (struct gdbarch *gdbarch, int regno)
 {
-  int len = TYPE_LENGTH (type);
-  
-  if (len <= 2 * REGISTER_SIZE)
-    memcpy (valbuf, regbuf + REGISTER_BYTE (RET_REGNUM), len);
-  else
-    internal_error (__FILE__, __LINE__, "cris_abi_v2_extract_return_value: type length too large");
+  return ((regno < 0 || regno >= gdbarch_num_regs (gdbarch))
+          || (cris_register_size (gdbarch, regno) == 0));
 }
 
-/* Store the address of the place in which to copy the structure the
-   subroutine will return.  In the CRIS ABI, R9 is used in order to pass 
-   the address of the allocated area where a structure return value must 
-   be stored.  R9 is call-clobbered, which means we must save it here for
-   later use.  */
+/* Nonzero if regno should not be written to the target, for various 
+   reasons.  */
 
-void
-cris_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
+static int
+cris_cannot_store_register (struct gdbarch *gdbarch, int regno)
 {
-  write_register (STR_REGNUM, addr);
-  struct_return_address = addr;
+  /* There are three kinds of registers we refuse to write to.
+     1. Those that not implemented.
+     2. Those that are read-only (depends on the processor mode).
+     3. Those registers to which a write has no effect.  */
+
+  if (regno < 0
+      || regno >= gdbarch_num_regs (gdbarch)
+      || cris_register_size (gdbarch, regno) == 0)
+    /* Not implemented.  */
+    return 1;
+
+  else if  (regno == VR_REGNUM)
+    /* Read-only.  */
+    return 1;
+
+  else if  (regno == P0_REGNUM || regno == P4_REGNUM || regno == P8_REGNUM)
+    /* Writing has no effect.  */
+    return 1;
+
+  /* IBR, BAR, BRP and IRP are read-only in user mode.  Let the debug
+     agent decide whether they are writable.  */
+  
+  return 0;
 }
 
-/* Extract from regbuf the address where a function should return a 
-   structure value.  It's not there in the CRIS ABI, so we must do it another
-   way.  */
+/* Nonzero if regno should not be fetched from the target.  This is the case
+   for unimplemented (size 0) and non-existant registers.  */
 
-CORE_ADDR
-cris_extract_struct_value_address (char *regbuf)
+static int
+crisv32_cannot_fetch_register (struct gdbarch *gdbarch, int regno)
 {
-  return struct_return_address;
+  return ((regno < 0 || regno >= gdbarch_num_regs (gdbarch))
+          || (cris_register_size (gdbarch, regno) == 0));
 }
 
-/* Returns 1 if a value of the given type being returned from a function 
-   must have space allocated for it on the stack.  gcc_p is true if the 
-   function being considered is known to have been compiled by GCC. 
-   In the CRIS ABI, structure return values are passed to the called 
-   function by reference in register R9 to a caller-allocated area, so
-   this is always true.  */
+/* Nonzero if regno should not be written to the target, for various 
+   reasons.  */
 
-int
-cris_use_struct_convention (int gcc_p, struct type *type)
+static int
+crisv32_cannot_store_register (struct gdbarch *gdbarch, int regno)
 {
-  return 1;
-}
+  /* There are three kinds of registers we refuse to write to.
+     1. Those that not implemented.
+     2. Those that are read-only (depends on the processor mode).
+     3. Those registers to which a write has no effect.  */
 
-/* Returns 1 if the given type will be passed by pointer rather than 
-   directly.  */
+  if (regno < 0
+      || regno >= gdbarch_num_regs (gdbarch)
+      || cris_register_size (gdbarch, regno) == 0)
+    /* Not implemented.  */
+    return 1;
+
+  else if  (regno == VR_REGNUM)
+    /* Read-only.  */
+    return 1;
 
-/* In the original CRIS ABI, arguments shorter than or equal to 32 bits are 
-   passed by value.  */
+  else if  (regno == BZ_REGNUM || regno == WZ_REGNUM || regno == DZ_REGNUM)
+    /* Writing has no effect.  */
+    return 1;
 
-int 
-cris_abi_original_reg_struct_has_addr (int gcc_p, struct type *type)
-{ 
-  return (TYPE_LENGTH (type) > 4);
+  /* Many special registers are read-only in user mode.  Let the debug
+     agent decide whether they are writable.  */
+  
+  return 0;
 }
 
-/* In the CRIS ABI V2, arguments shorter than or equal to 64 bits are passed
-   by value.  */
+/* Return the GDB type (defined in gdbtypes.c) for the "standard" data type
+   of data in register regno.  */
 
-int 
-cris_abi_v2_reg_struct_has_addr (int gcc_p, struct type *type)
-{ 
-  return (TYPE_LENGTH (type) > 8);
+static struct type *
+cris_register_type (struct gdbarch *gdbarch, int regno)
+{
+  if (regno == gdbarch_pc_regnum (gdbarch))
+    return builtin_type (gdbarch)->builtin_func_ptr;
+  else if (regno == gdbarch_sp_regnum (gdbarch)
+          || regno == CRIS_FP_REGNUM)
+    return builtin_type (gdbarch)->builtin_data_ptr;
+  else if ((regno >= 0 && regno < gdbarch_sp_regnum (gdbarch))
+          || (regno >= MOF_REGNUM && regno <= USP_REGNUM))
+    /* Note: R8 taken care of previous clause.  */
+    return builtin_type (gdbarch)->builtin_uint32;
+  else if (regno >= P4_REGNUM && regno <= CCR_REGNUM)
+      return builtin_type (gdbarch)->builtin_uint16;
+  else if (regno >= P0_REGNUM && regno <= VR_REGNUM)
+      return builtin_type (gdbarch)->builtin_uint8;
+  else
+      /* Invalid (unimplemented) register.  */
+      return builtin_type (gdbarch)->builtin_int0;
+}
+
+static struct type *
+crisv32_register_type (struct gdbarch *gdbarch, int regno)
+{
+  if (regno == gdbarch_pc_regnum (gdbarch))
+    return builtin_type (gdbarch)->builtin_func_ptr;
+  else if (regno == gdbarch_sp_regnum (gdbarch)
+          || regno == CRIS_FP_REGNUM)
+    return builtin_type (gdbarch)->builtin_data_ptr;
+  else if ((regno >= 0 && regno <= ACR_REGNUM)
+          || (regno >= EXS_REGNUM && regno <= SPC_REGNUM)
+          || (regno == PID_REGNUM)
+          || (regno >= S0_REGNUM && regno <= S15_REGNUM))
+    /* Note: R8 and SP taken care of by previous clause.  */
+    return builtin_type (gdbarch)->builtin_uint32;
+  else if (regno == WZ_REGNUM)
+      return builtin_type (gdbarch)->builtin_uint16;
+  else if (regno == BZ_REGNUM || regno == VR_REGNUM || regno == SRS_REGNUM)
+      return builtin_type (gdbarch)->builtin_uint8;
+  else
+    {
+      /* Invalid (unimplemented) register.  Should not happen as there are
+        no unimplemented CRISv32 registers.  */
+      warning (_("crisv32_register_type: unknown regno %d"), regno);
+      return builtin_type (gdbarch)->builtin_int0;
+    }
 }
 
-/* Returns 1 if the function invocation represented by fi does not have a 
-   stack frame associated with it.  Otherwise return 0.  */
+/* Stores a function return value of type type, where valbuf is the address 
+   of the value to be stored.  */
 
-int
-cris_frameless_function_invocation (struct frame_info *fi)
+/* In the CRIS ABI, R10 and R11 are used to store return values.  */
+
+static void
+cris_store_return_value (struct type *type, struct regcache *regcache,
+                        const gdb_byte *valbuf)
 {
-  if ((get_frame_type (fi) == SIGTRAMP_FRAME))
-    return 0;
+  struct gdbarch *gdbarch = regcache->arch ();
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  ULONGEST val;
+  int len = TYPE_LENGTH (type);
+  
+  if (len <= 4)
+    {
+      /* Put the return value in R10.  */
+      val = extract_unsigned_integer (valbuf, len, byte_order);
+      regcache_cooked_write_unsigned (regcache, ARG1_REGNUM, val);
+    }
+  else if (len <= 8)
+    {
+      /* Put the return value in R10 and R11.  */
+      val = extract_unsigned_integer (valbuf, 4, byte_order);
+      regcache_cooked_write_unsigned (regcache, ARG1_REGNUM, val);
+      val = extract_unsigned_integer (valbuf + 4, len - 4, byte_order);
+      regcache_cooked_write_unsigned (regcache, ARG2_REGNUM, val);
+    }
   else
-    return frameless_look_for_prologue (fi);
+    error (_("cris_store_return_value: type length too large."));
 }
 
-/* See frame.h.  Determines the address of all registers in the
-   current stack frame storing each in frame->saved_regs.  Space for
-   frame->saved_regs shall be allocated by
-   DEPRECATED_FRAME_INIT_SAVED_REGS using frame_saved_regs_zalloc.  */
+/* Return the name of register regno as a string.  Return NULL for an
+   invalid or unimplemented register.  */
 
-void
-cris_frame_init_saved_regs (struct frame_info *fi)
+static const char *
+cris_special_register_name (struct gdbarch *gdbarch, int regno)
 {
-  CORE_ADDR ip;
-  struct symtab_and_line sal;
-  int best_limit;
-  char *dummy_regs = deprecated_generic_find_dummy_frame (get_frame_pc (fi),
-                                                         get_frame_base (fi));
-  
-  /* Examine the entire prologue.  */
-  register int frameless_p = 0; 
-
-  /* Has this frame's registers already been initialized?  */
-  if (get_frame_saved_regs (fi))
-    return;
+  int spec_regno;
+  int i;
 
-  frame_saved_regs_zalloc (fi);
+  /* Special register (R16 - R31).  cris_spec_regs is zero-based. 
+     Adjust regno accordingly.  */
+  spec_regno = regno - NUM_GENREGS;
   
-  if (dummy_regs)
+  /* Assume nothing about the layout of the cris_spec_regs struct
+     when searching.  */
+  for (i = 0; cris_spec_regs[i].name != NULL; i++)
     {
-      /* I don't see this ever happening, considering the context in which
-         cris_frame_init_saved_regs is called (always when we're not in
-         a dummy frame).  */
-      memcpy (get_frame_saved_regs (fi), dummy_regs, SIZEOF_FRAME_SAVED_REGS);
-    }
-  else
-    {    
-      ip = get_pc_function_start (get_frame_pc (fi));
-      sal = find_pc_line (ip, 0);
-
-      /* If there is no symbol information then sal.end == 0, and we end up
-         examining only the first instruction in the function prologue. 
-         Exaggerating the limit seems to be harmless.  */
-      if (sal.end > 0)
-        best_limit = sal.end;
-      else
-        best_limit = ip + 100;
-
-      cris_examine (ip, best_limit, fi, frameless_p);
+      if (cris_spec_regs[i].number == spec_regno 
+         && cris_spec_reg_applicable (gdbarch, cris_spec_regs[i]))
+       /* Go with the first applicable register.  */
+       return cris_spec_regs[i].name;
     }
+  /* Special register not applicable to this CRIS version.  */
+  return NULL;
 }
 
-/* Initialises the extra frame information at the creation of a new frame. 
-   The inparameter fromleaf is 0 when the call is from create_new_frame. 
-   When the call is from get_prev_frame_info, fromleaf is determined by
-   cris_frameless_function_invocation.  */
-
-void
-cris_init_extra_frame_info (int fromleaf, struct frame_info *fi)
+static const char *
+cris_register_name (struct gdbarch *gdbarch, int regno)
 {
-  if (get_next_frame (fi))
+  static const char *cris_genreg_names[] =
+  { "r0",  "r1",  "r2",  "r3", \
+    "r4",  "r5",  "r6",  "r7", \
+    "r8",  "r9",  "r10", "r11", \
+    "r12", "r13", "sp",  "pc" };
+
+  if (regno >= 0 && regno < NUM_GENREGS)
     {
-      /* Called from get_prev_frame.  */
-      deprecated_update_frame_pc_hack (fi, DEPRECATED_FRAME_SAVED_PC (get_next_frame (fi)));
+      /* General register.  */
+      return cris_genreg_names[regno];
     }
-  frame_extra_info_zalloc (fi, sizeof (struct frame_extra_info));
-  get_frame_extra_info (fi)->return_pc = 0;
-  get_frame_extra_info (fi)->leaf_function = 0;
-
-  if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi),
-                                  get_frame_base (fi),
-                                  get_frame_base (fi)))
-    {    
-      /* We need to setup fi->frame here because run_stack_dummy gets it wrong
-         by assuming it's always FP.  */
-      deprecated_update_frame_base_hack (fi, deprecated_read_register_dummy (get_frame_pc (fi), get_frame_base (fi), SP_REGNUM));
-      get_frame_extra_info (fi)->return_pc = 
-        deprecated_read_register_dummy (get_frame_pc (fi),
-                                       get_frame_base (fi), PC_REGNUM);
-
-      /* FIXME: Is this necessarily true?  */
-      get_frame_extra_info (fi)->leaf_function = 0;
+  else if (regno >= NUM_GENREGS && regno < gdbarch_num_regs (gdbarch))
+    {
+      return cris_special_register_name (gdbarch, regno);
     }
   else
     {
-      cris_frame_init_saved_regs (fi);
-
-      /* Check fromleaf/frameless_function_invocation.  (FIXME)  */
-
-      if (get_frame_saved_regs (fi)[SRP_REGNUM] != 0)
-        {
-          /* SRP was saved on the stack; non-leaf function.  */
-          get_frame_extra_info (fi)->return_pc =
-            read_memory_integer (get_frame_saved_regs (fi)[SRP_REGNUM], 
-                                 REGISTER_RAW_SIZE (SRP_REGNUM));
-        }
-      else
-        {
-          /* SRP is still in a register; leaf function.  */
-          get_frame_extra_info (fi)->return_pc = read_register (SRP_REGNUM);
-          /* FIXME: Should leaf_function be set to 1 here?  */
-          get_frame_extra_info (fi)->leaf_function = 1;
-        }
+      /* Invalid register.  */
+      return NULL;
     }
 }
 
-/* Return the content of the frame pointer in the present frame.  In other
-   words, determine the address of the calling function's frame.  */
+static const char *
+crisv32_register_name (struct gdbarch *gdbarch, int regno)
+{
+  static const char *crisv32_genreg_names[] =
+    { "r0",  "r1",  "r2",  "r3", \
+      "r4",  "r5",  "r6",  "r7", \
+      "r8",  "r9",  "r10", "r11", \
+      "r12", "r13", "sp",  "acr"
+    };
+
+  static const char *crisv32_sreg_names[] =
+    { "s0",  "s1",  "s2",  "s3", \
+      "s4",  "s5",  "s6",  "s7", \
+      "s8",  "s9",  "s10", "s11", \
+      "s12", "s13", "s14",  "s15"
+    };
 
-CORE_ADDR
-cris_frame_chain (struct frame_info *fi)
-{
-  if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi),
-                                  get_frame_base (fi),
-                                  get_frame_base (fi)))
+  if (regno >= 0 && regno < NUM_GENREGS)
+    {
+      /* General register.  */
+      return crisv32_genreg_names[regno];
+    }
+  else if (regno >= NUM_GENREGS && regno < (NUM_GENREGS + NUM_SPECREGS))
     {
-      return get_frame_base (fi);
+      return cris_special_register_name (gdbarch, regno);
     }
-  else if (!inside_entry_file (get_frame_pc (fi)))
+  else if (regno == gdbarch_pc_regnum (gdbarch))
     {
-      return read_memory_unsigned_integer (get_frame_base (fi), 4);
+      return "pc";
+    }
+  else if (regno >= S0_REGNUM && regno <= S15_REGNUM)
+    {
+      return crisv32_sreg_names[regno - S0_REGNUM];
     }
   else
     {
-      return 0;
+      /* Invalid register.  */
+      return NULL;
     }
 }
 
-/* Return the saved PC (which equals the return address) of this frame.  */
-
-CORE_ADDR
-cris_frame_saved_pc (struct frame_info *fi)
-{
-  return get_frame_extra_info (fi)->return_pc;
-}
-
-/* Setup the function arguments for calling a function in the inferior.  */
+/* Convert DWARF register number REG to the appropriate register
+   number used by GDB.  */
 
-CORE_ADDR 
-cris_abi_original_push_arguments (int nargs, struct value **args, 
-                                  CORE_ADDR sp, int struct_return, 
-                                  CORE_ADDR struct_addr)
+static int
+cris_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, int reg)
 {
-  int stack_alloc;
-  int stack_offset;
-  int argreg;
-  int argnum;
-  struct type *type;
-  int len;
-  CORE_ADDR regval;
-  char *val;
-
-  /* Data and parameters reside in different areas on the stack. 
-     Both frame pointers grow toward higher addresses.  */  
-  CORE_ADDR fp_params;
-  CORE_ADDR fp_data;
-  
-  /* Are we returning a value using a structure return or a normal value 
-     return?  struct_addr is the address of the reserved space for the return 
-     structure to be written on the stack.  */
-  if (struct_return)
-    {
-      write_register (STR_REGNUM, struct_addr);
-    }
+  /* We need to re-map a couple of registers (SRP is 16 in Dwarf-2 register
+     numbering, MOF is 18).
+     Adapted from gcc/config/cris/cris.h.  */
+  static int cris_dwarf_regmap[] = {
+    0,  1,  2,  3,
+    4,  5,  6,  7,
+    8,  9,  10, 11,
+    12, 13, 14, 15,
+    27, -1, -1, -1,
+    -1, -1, -1, 23,
+    -1, -1, -1, 27,
+    -1, -1, -1, -1
+  };
+  int regnum = -1;
 
-  /* Make sure there's space on the stack.  Allocate space for data and a 
-     parameter to refer to that data.  */
-  for (argnum = 0, stack_alloc = 0; argnum < nargs; argnum++)
-    stack_alloc += (TYPE_LENGTH (VALUE_TYPE (args[argnum])) + REGISTER_SIZE);
-  sp -= stack_alloc;
-  /* We may over-allocate a little here, but that won't hurt anything.  */
+  if (reg >= 0 && reg < ARRAY_SIZE (cris_dwarf_regmap))
+    regnum = cris_dwarf_regmap[reg];
 
-  /* Initialize stack frame pointers.  */
-  fp_params = sp;
-  fp_data = sp + (nargs * REGISTER_SIZE);
+  return regnum;
+}
 
-  /* Now load as many as possible of the first arguments into
-     registers, and push the rest onto the stack.  */
-  argreg = ARG1_REGNUM; 
-  stack_offset = 0;
+/* DWARF-2 frame support.  */
 
-  for (argnum = 0; argnum < nargs; argnum++)
-    {
-      type = VALUE_TYPE (args[argnum]);
-      len = TYPE_LENGTH (type);
-      val = (char *) VALUE_CONTENTS (args[argnum]);
-    
-      if (len <= REGISTER_SIZE && argreg <= ARG4_REGNUM)
-        {
-          /* Data fits in a register; put it in the first available 
-             register.  */
-          write_register (argreg, *(unsigned long *) val);
-          argreg++;
-        }
-      else if (len > REGISTER_SIZE && argreg <= ARG4_REGNUM)
-        {
-          /* Data does not fit in register; pass it on the stack and
-             put its address in the first available register.  */
-          write_memory (fp_data, val, len);
-          write_register (argreg, fp_data);
-          fp_data += len;
-          argreg++;      
-        }
-      else if (len > REGISTER_SIZE)
-        {
-          /* Data does not fit in register; put both data and 
-             parameter on the stack.  */
-          write_memory (fp_data, val, len);
-          write_memory (fp_params, (char *) (&fp_data), REGISTER_SIZE);
-          fp_data += len;
-          fp_params += REGISTER_SIZE;
-        }
-      else
-        {
-          /* Data fits in a register, but we are out of registers;
-             put the parameter on the stack.  */
-          write_memory (fp_params, val, REGISTER_SIZE);
-          fp_params += REGISTER_SIZE;
-        }
-    }
+static void
+cris_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
+                            struct dwarf2_frame_state_reg *reg,
+                           struct frame_info *this_frame)
+{
+  /* The return address column.  */
+  if (regnum == gdbarch_pc_regnum (gdbarch))
+    reg->how = DWARF2_FRAME_REG_RA;
 
-  return sp;
+  /* The call frame address.  */
+  else if (regnum == gdbarch_sp_regnum (gdbarch))
+    reg->how = DWARF2_FRAME_REG_CFA;
 }
 
-CORE_ADDR 
-cris_abi_v2_push_arguments (int nargs, struct value **args, CORE_ADDR sp, 
-                     int struct_return, CORE_ADDR struct_addr)
-{
-  int stack_alloc;
-  int stack_offset;
-  int argreg;
-  int argnum;
+/* Extract from an array regbuf containing the raw register state a function
+   return value of type type, and copy that, in virtual format, into 
+   valbuf.  */
 
-  CORE_ADDR regval;
+/* In the CRIS ABI, R10 and R11 are used to store return values.  */
 
-  /* The function's arguments and memory allocated by gdb for the arguments to
-     point at reside in separate areas on the stack.
-     Both frame pointers grow toward higher addresses.  */
-  CORE_ADDR fp_arg;
-  CORE_ADDR fp_mem;
+static void
+cris_extract_return_value (struct type *type, struct regcache *regcache,
+                          gdb_byte *valbuf)
+{
+  struct gdbarch *gdbarch = regcache->arch ();
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  ULONGEST val;
+  int len = TYPE_LENGTH (type);
   
-  /* Are we returning a value using a structure return or a normal value 
-     return?  struct_addr is the address of the reserved space for the return 
-     structure to be written on the stack.  */
-  if (struct_return)
-    {
-      write_register (STR_REGNUM, struct_addr);
-    }
-
-  /* Allocate enough to keep things word-aligned on both parts of the 
-     stack.  */
-  stack_alloc = 0;
-  for (argnum = 0; argnum < nargs; argnum++)
+  if (len <= 4)
     {
-      int len;
-      int reg_demand;
-      
-      len = TYPE_LENGTH (VALUE_TYPE (args[argnum]));
-      reg_demand = (len / REGISTER_SIZE) + (len % REGISTER_SIZE != 0 ? 1 : 0);
-
-      /* reg_demand * REGISTER_SIZE is the amount of memory we might need to
-         allocate for this argument.  2 * REGISTER_SIZE is the amount of stack
-         space we might need to pass the argument itself (either by value or by
-         reference).  */
-      stack_alloc += (reg_demand * REGISTER_SIZE + 2 * REGISTER_SIZE);
+      /* Get the return value from R10.  */
+      regcache_cooked_read_unsigned (regcache, ARG1_REGNUM, &val);
+      store_unsigned_integer (valbuf, len, byte_order, val);
     }
-  sp -= stack_alloc;
-  /* We may over-allocate a little here, but that won't hurt anything.  */
-
-  /* Initialize frame pointers.  */
-  fp_arg = sp;
-  fp_mem = sp + (nargs * (2 * REGISTER_SIZE));
-
-  /* Now load as many as possible of the first arguments into registers,
-     and push the rest onto the stack.  */
-  argreg = ARG1_REGNUM; 
-  stack_offset = 0;
-
-  for (argnum = 0; argnum < nargs; argnum++)
+  else if (len <= 8)
     {
-      int len;
-      char *val;
-      int reg_demand;
-      int i;
-      
-      len = TYPE_LENGTH (VALUE_TYPE (args[argnum]));
-      val = (char *) VALUE_CONTENTS (args[argnum]);
-      
-      /* How may registers worth of storage do we need for this argument?  */
-      reg_demand = (len / REGISTER_SIZE) + (len % REGISTER_SIZE != 0 ? 1 : 0);
-        
-      if (len <= (2 * REGISTER_SIZE)
-          && (argreg + reg_demand - 1 <= ARG4_REGNUM)) 
-        {
-          /* Data passed by value.  Fits in available register(s).  */
-          for (i = 0; i < reg_demand; i++)
-            {
-              write_register (argreg, *(unsigned long *) val);
-              argreg++;
-              val += REGISTER_SIZE;
-            }
-        }
-      else if (len <= (2 * REGISTER_SIZE) && argreg <= ARG4_REGNUM)
-        {
-          /* Data passed by value. Does not fit in available register(s).  
-             Use the register(s) first, then the stack.  */
-          for (i = 0; i < reg_demand; i++)
-            {
-              if (argreg <= ARG4_REGNUM)
-                {
-                  write_register (argreg, *(unsigned long *) val);
-                  argreg++;
-                  val += REGISTER_SIZE;
-                }
-              else
-                {
-                  /* I guess this memory write could write the remaining data
-                     all at once instead of in REGISTER_SIZE chunks.  */
-                  write_memory (fp_arg, val, REGISTER_SIZE);
-                  fp_arg += REGISTER_SIZE;
-                  val += REGISTER_SIZE;              
-                }
-            }    
-        }
-      else if (len > (2 * REGISTER_SIZE))
-        {
-          /* Data passed by reference.  Put it on the stack.  */
-          write_memory (fp_mem, val, len);
-          write_memory (fp_arg, (char *) (&fp_mem), REGISTER_SIZE);
-
-          /* fp_mem need not be word-aligned since it's just a chunk of
-             memory being pointed at.  That is, += len would do.  */
-          fp_mem += reg_demand * REGISTER_SIZE;
-          fp_arg += REGISTER_SIZE;
-        }
-      else
-        {
-          /* Data passed by value.  No available registers.  Put it on 
-             the stack.  */
-          write_memory (fp_arg, val, len);
-
-          /* fp_arg must be word-aligned (i.e., don't += len) to match
-             the function prologue.  */
-          fp_arg += reg_demand * REGISTER_SIZE;
-        }
+      /* Get the return value from R10 and R11.  */
+      regcache_cooked_read_unsigned (regcache, ARG1_REGNUM, &val);
+      store_unsigned_integer (valbuf, 4, byte_order, val);
+      regcache_cooked_read_unsigned (regcache, ARG2_REGNUM, &val);
+      store_unsigned_integer (valbuf + 4, len - 4, byte_order, val);
     }
-
-  return sp;
+  else
+    error (_("cris_extract_return_value: type length too large"));
 }
 
-/* Never put the return address on the stack.  The register SRP is pushed
-   by the called function unless it is a leaf-function.  Due to the BRP
-   register the PC will change when continue is sent.  */
+/* Handle the CRIS return value convention.  */
 
-CORE_ADDR
-cris_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
+static enum return_value_convention
+cris_return_value (struct gdbarch *gdbarch, struct value *function,
+                  struct type *type, struct regcache *regcache,
+                  gdb_byte *readbuf, const gdb_byte *writebuf)
 {
-  write_register (SRP_REGNUM, CALL_DUMMY_ADDRESS ());
-  return sp;
-}
+  if (TYPE_CODE (type) == TYPE_CODE_STRUCT 
+      || TYPE_CODE (type) == TYPE_CODE_UNION
+      || TYPE_LENGTH (type) > 8)
+    /* Structs, unions, and anything larger than 8 bytes (2 registers)
+       goes on the stack.  */
+    return RETURN_VALUE_STRUCT_CONVENTION;
 
-/* Restore the machine to the state it had before the current frame 
-   was created.  Discard the innermost frame from the stack and restore 
-   all saved registers.  */
+  if (readbuf)
+    cris_extract_return_value (type, regcache, readbuf);
+  if (writebuf)
+    cris_store_return_value (type, regcache, writebuf);
 
-void 
-cris_pop_frame (void)
-{
-  register struct frame_info *fi = get_current_frame ();
-  register int regno;
-  register int stack_offset = 0;
-  
-  if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi),
-                                  get_frame_base (fi),
-                                  get_frame_base (fi)))
-    {
-      /* This happens when we hit a breakpoint set at the entry point,
-         when returning from a dummy frame.  */
-      generic_pop_dummy_frame ();
-    }
-  else
-    {
-      cris_frame_init_saved_regs (fi);
-
-      /* For each register, the address of where it was saved on entry to
-         the frame now lies in fi->saved_regs[regno], or zero if it was not 
-         saved.  This includes special registers such as PC and FP saved in
-         special ways in the stack frame.  The SP_REGNUM is even more
-         special, the address here is the SP for the next frame, not the
-         address where the SP was saved.  */
-                                                     
-      /* Restore general registers R0 - R7.  They were pushed on the stack 
-         after SP was saved.  */
-      for (regno = 0; regno < FP_REGNUM; regno++)
-        {
-          if (get_frame_saved_regs (fi)[regno])
-            {
-              write_register (regno, 
-                              read_memory_integer (get_frame_saved_regs (fi)[regno], 4));
-            }
-        }
-     
-      if (get_frame_saved_regs (fi)[FP_REGNUM])
-        {
-          /* Pop the frame pointer (R8).  It was pushed before SP 
-             was saved.  */
-          write_register (FP_REGNUM, 
-                          read_memory_integer (get_frame_saved_regs (fi)[FP_REGNUM], 4));
-          stack_offset += 4;
-
-          /* Not a leaf function.  */
-          if (get_frame_saved_regs (fi)[SRP_REGNUM])
-            {     
-              /* SRP was pushed before SP was saved.  */
-              stack_offset += 4;
-            }
-      
-          /* Restore the SP and adjust for R8 and (possibly) SRP.  */
-          write_register (SP_REGNUM, get_frame_saved_regs (fi)[FP_REGNUM] + stack_offset);
-        } 
-      else
-        {
-          /* Currently, we can't get the correct info into fi->saved_regs 
-             without a frame pointer.  */
-        }
-    
-      /* Restore the PC.  */
-      write_register (PC_REGNUM, get_frame_extra_info (fi)->return_pc);
-    }
-  flush_cached_frames ();
+  return RETURN_VALUE_REGISTER_CONVENTION;
 }
 
 /* Calculates a value that measures how good inst_args constraints an 
    instruction.  It stems from cris_constraint, found in cris-dis.c.  */
 
 static int
-constraint (unsigned int insn, const signed char *inst_args, 
+constraint (unsigned int insn, const char *inst_args,
             inst_env_type *inst_env)
 {
   int retval = 0;
   int tmp, i;
 
-  const char *s = inst_args;
+  const gdb_byte *s = (const gdb_byte *) inst_args;
 
   for (; *s; s++)
     switch (*s) 
@@ -1679,7 +1923,9 @@ find_cris_op (unsigned short insn, inst_env_type *inst_env)
   for (i = 0; cris_opcodes[i].name != NULL; i++)
     {
       if (((cris_opcodes[i].match & insn) == cris_opcodes[i].match) 
-          && ((cris_opcodes[i].lose & insn) == 0))
+          && ((cris_opcodes[i].lose & insn) == 0)
+         /* Only CRISv10 instructions, please.  */
+         && (cris_opcodes[i].applicable_version != cris_ver_v32p))
         {
           level_of_match = constraint (insn, cris_opcodes[i].args, inst_env);
           if (level_of_match >= 0)
@@ -1706,21 +1952,25 @@ find_cris_op (unsigned short insn, inst_env_type *inst_env)
    actually an internal error.  */
 
 static int
-find_step_target (inst_env_type *inst_env)
+find_step_target (struct regcache *regcache, inst_env_type *inst_env)
 {
   int i;
   int offset;
   unsigned short insn;
+  struct gdbarch *gdbarch = regcache->arch ();
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
 
   /* Create a local register image and set the initial state.  */
   for (i = 0; i < NUM_GENREGS; i++)
     {
-      inst_env->reg[i] = (unsigned long) read_register (i);
+      inst_env->reg[i] = 
+       (unsigned long) regcache_raw_get_unsigned (regcache, i);
     }
   offset = NUM_GENREGS;
   for (i = 0; i < NUM_SPECREGS; i++)
     {
-      inst_env->preg[i] = (unsigned long) read_register (offset + i);
+      inst_env->preg[i] = 
+       (unsigned long) regcache_raw_get_unsigned (regcache, offset + i);
     }
   inst_env->branch_found = 0;
   inst_env->slot_needed = 0;
@@ -1729,12 +1979,14 @@ find_step_target (inst_env_type *inst_env)
   inst_env->invalid = 0;
   inst_env->xflag_found = 0;
   inst_env->disable_interrupt = 0;
+  inst_env->byte_order = byte_order;
 
   /* Look for a step target.  */
   do
     {
       /* Read an instruction from the client.  */
-      insn = read_memory_unsigned_integer (inst_env->reg[PC_REGNUM], 2);
+      insn = read_memory_unsigned_integer
+            (inst_env->reg[gdbarch_pc_regnum (gdbarch)], 2, byte_order);
 
       /* If the instruction is not in a delay slot the new content of the
          PC is [PC] + 2.  If the instruction is in a delay slot it is not
@@ -1743,12 +1995,13 @@ find_step_target (inst_env_type *inst_env)
          Just make sure it is a valid instruction.  */
       if (!inst_env->delay_slot_pc_active)
         {
-          inst_env->reg[PC_REGNUM] += 2;
+          inst_env->reg[gdbarch_pc_regnum (gdbarch)] += 2;
         }
       else
         {
           inst_env->delay_slot_pc_active = 0;
-          inst_env->reg[PC_REGNUM] = inst_env->delay_slot_pc;
+          inst_env->reg[gdbarch_pc_regnum (gdbarch)]
+           = inst_env->delay_slot_pc;
         }
       /* Analyse the present instruction.  */
       i = find_cris_op (insn, inst_env);
@@ -1758,7 +2011,7 @@ find_step_target (inst_env_type *inst_env)
         }
       else
         {
-          cris_gdb_func (cris_opcodes[i].op, insn, inst_env);
+          cris_gdb_func (gdbarch, cris_opcodes[i].op, insn, inst_env);
         }
     } while (!inst_env->invalid 
              && (inst_env->prefix_found || inst_env->xflag_found 
@@ -1767,54 +2020,49 @@ find_step_target (inst_env_type *inst_env)
 }
 
 /* There is no hardware single-step support.  The function find_step_target
-   digs through the opcodes in order to find all possible targets. 
+   digs through the opcodes in order to find all possible targets.
    Either one ordinary target or two targets for branches may be found.  */
 
-void
-cris_software_single_step (enum target_signal ignore, int insert_breakpoints)
+static std::vector<CORE_ADDR>
+cris_software_single_step (struct regcache *regcache)
 {
+  struct gdbarch *gdbarch = regcache->arch ();
   inst_env_type inst_env;
-  
-  if (insert_breakpoints)
+  std::vector<CORE_ADDR> next_pcs;
+
+  /* Analyse the present instruction environment and insert 
+     breakpoints.  */
+  int status = find_step_target (regcache, &inst_env);
+  if (status == -1)
     {
-      /* Analyse the present instruction environment and insert 
-         breakpoints.  */
-      int status = find_step_target (&inst_env);
-      if (status == -1)
-        {
-          /* Could not find a target.  FIXME: Should do something.  */
-        }
-      else
-        {
-          /* Insert at most two breakpoints.  One for the next PC content
-             and possibly another one for a branch, jump, etc.  */
-          next_pc = (CORE_ADDR) inst_env.reg[PC_REGNUM];
-          target_insert_breakpoint (next_pc, break_mem[0]);
-          if (inst_env.branch_found 
-              && (CORE_ADDR) inst_env.branch_break_address != next_pc)
-            {
-              branch_target_address = 
-                (CORE_ADDR) inst_env.branch_break_address;
-              target_insert_breakpoint (branch_target_address, break_mem[1]);
-              branch_break_inserted = 1;
-            }
-        }
+      /* Could not find a target.  Things are likely to go downhill 
+        from here.  */
+      warning (_("CRIS software single step could not find a step target."));
     }
   else
     {
-      /* Remove breakpoints.  */
-      target_remove_breakpoint (next_pc, break_mem[0]);
-      if (branch_break_inserted)
-        {
-          target_remove_breakpoint (branch_target_address, break_mem[1]);
-          branch_break_inserted = 0;
-        }
+      /* Insert at most two breakpoints.  One for the next PC content
+         and possibly another one for a branch, jump, etc.  */
+      CORE_ADDR next_pc
+       = (CORE_ADDR) inst_env.reg[gdbarch_pc_regnum (gdbarch)];
+
+      next_pcs.push_back (next_pc);
+      if (inst_env.branch_found 
+         && (CORE_ADDR) inst_env.branch_break_address != next_pc)
+       {
+         CORE_ADDR branch_target_address
+               = (CORE_ADDR) inst_env.branch_break_address;
+
+         next_pcs.push_back (branch_target_address);
+       }
     }
+
+  return next_pcs;
 }
 
 /* Calculates the prefix value for quick offset addressing mode.  */
 
-void
+static void
 quick_mode_bdap_prefix (unsigned short inst, inst_env_type *inst_env)
 {
   /* It's invalid to be in a delay slot.  You can't have a prefix to this
@@ -1838,7 +2086,7 @@ quick_mode_bdap_prefix (unsigned short inst, inst_env_type *inst_env)
    from the size of the operation.  The PC is always kept aligned on even
    word addresses.  */
 
-void 
+static void 
 process_autoincrement (int size, unsigned short inst, inst_env_type *inst_env)
 {
   if (size == INST_BYTE_SIZE)
@@ -1869,17 +2117,16 @@ process_autoincrement (int size, unsigned short inst, inst_env_type *inst_env)
 
 /* Just a forward declaration.  */
 
-unsigned long get_data_from_address (unsigned short *inst, CORE_ADDR address);
+static unsigned long get_data_from_address (unsigned short *inst,
+                                           CORE_ADDR address,
+                                           enum bfd_endian byte_order);
 
 /* Calculates the prefix value for the general case of offset addressing 
    mode.  */
 
-void
+static void
 bdap_prefix (unsigned short inst, inst_env_type *inst_env)
 {
-
-  long offset;
-
   /* It's invalid to be in a delay slot.  */
   if (inst_env->slot_needed || inst_env->prefix_found)
     {
@@ -1895,7 +2142,8 @@ bdap_prefix (unsigned short inst, inst_env_type *inst_env)
 
   /* The offset is an indirection of the contents of the operand1 register.  */
   inst_env->prefix_value += 
-    get_data_from_address (&inst, inst_env->reg[cris_get_operand1 (inst)]);
+    get_data_from_address (&inst, inst_env->reg[cris_get_operand1 (inst)],
+                          inst_env->byte_order);
   
   if (cris_get_mode (inst) == AUTOINC_MODE)
     {
@@ -1910,7 +2158,7 @@ bdap_prefix (unsigned short inst, inst_env_type *inst_env)
 
 /* Calculates the prefix value for the index addressing mode.  */
 
-void
+static void
 biap_prefix (unsigned short inst, inst_env_type *inst_env)
 {
   /* It's invalid to be in a delay slot.  I can't see that it's possible to
@@ -1945,7 +2193,7 @@ biap_prefix (unsigned short inst, inst_env_type *inst_env)
 
 /* Calculates the prefix value for the double indirect addressing mode.  */
 
-void 
+static void 
 dip_prefix (unsigned short inst, inst_env_type *inst_env)
 {
 
@@ -1961,7 +2209,8 @@ dip_prefix (unsigned short inst, inst_env_type *inst_env)
   /* The prefix value is one dereference of the contents of the operand1
      register.  */
   address = (CORE_ADDR) inst_env->reg[cris_get_operand1 (inst)];
-  inst_env->prefix_value = read_memory_unsigned_integer (address, 4);
+  inst_env->prefix_value
+    = read_memory_unsigned_integer (address, 4, inst_env->byte_order);
     
   /* Check if the mode is autoincrement.  */
   if (cris_get_mode (inst) == AUTOINC_MODE)
@@ -1978,7 +2227,7 @@ dip_prefix (unsigned short inst, inst_env_type *inst_env)
 
 /* Finds the destination for a branch with 8-bits offset.  */
 
-void
+static void
 eight_bit_offset_branch_op (unsigned short inst, inst_env_type *inst_env)
 {
 
@@ -2015,7 +2264,7 @@ eight_bit_offset_branch_op (unsigned short inst, inst_env_type *inst_env)
 
 /* Finds the destination for a branch with 16-bits offset.  */
 
-void 
+static void 
 sixteen_bit_offset_branch_op (unsigned short inst, inst_env_type *inst_env)
 {
   short offset;
@@ -2028,7 +2277,8 @@ sixteen_bit_offset_branch_op (unsigned short inst, inst_env_type *inst_env)
     }
 
   /* We have a branch, find out the offset for the branch.  */
-  offset = read_memory_integer (inst_env->reg[REG_PC], 2);
+  offset = read_memory_integer (inst_env->reg[REG_PC], 2,
+                               inst_env->byte_order);
 
   /* The instruction is one word longer than normal, so add one word
      to the PC.  */
@@ -2046,7 +2296,7 @@ sixteen_bit_offset_branch_op (unsigned short inst, inst_env_type *inst_env)
 
 /* Handles the ABS instruction.  */
 
-void 
+static void 
 abs_op (unsigned short inst, inst_env_type *inst_env)
 {
 
@@ -2088,7 +2338,7 @@ abs_op (unsigned short inst, inst_env_type *inst_env)
 
 /* Handles the ADDI instruction.  */
 
-void 
+static void 
 addi_op (unsigned short inst, inst_env_type *inst_env)
 {
   /* It's invalid to have the PC as base register.  And ADDI can't have
@@ -2107,7 +2357,7 @@ addi_op (unsigned short inst, inst_env_type *inst_env)
 
 /* Handles the ASR instruction.  */
 
-void 
+static void 
 asr_op (unsigned short inst, inst_env_type *inst_env)
 {
   int shift_steps;
@@ -2131,7 +2381,8 @@ asr_op (unsigned short inst, inst_env_type *inst_env)
           return;
         }
       /* Get the number of bits to shift.  */
-      shift_steps = cris_get_asr_shift_steps (inst_env->reg[cris_get_operand1 (inst)]);
+      shift_steps
+       = cris_get_asr_shift_steps (inst_env->reg[cris_get_operand1 (inst)]);
       value = inst_env->reg[REG_PC];
 
       /* Find out how many bits the operation should apply to.  */
@@ -2184,7 +2435,7 @@ asr_op (unsigned short inst, inst_env_type *inst_env)
 
 /* Handles the ASRQ instruction.  */
 
-void 
+static void 
 asrq_op (unsigned short inst, inst_env_type *inst_env)
 {
 
@@ -2210,7 +2461,7 @@ asrq_op (unsigned short inst, inst_env_type *inst_env)
           return;
         }
       /* The shift size is given as a 5 bit quick value, i.e. we don't
-         want the the sign bit of the quick value.  */
+         want the sign bit of the quick value.  */
       shift_steps = cris_get_asr_shift_steps (inst);
       value = inst_env->reg[REG_PC];
       if (value & SIGNED_DWORD_MASK)
@@ -2231,7 +2482,7 @@ asrq_op (unsigned short inst, inst_env_type *inst_env)
 
 /* Handles the AX, EI and SETF instruction.  */
 
-void 
+static void 
 ax_ei_setf_op (unsigned short inst, inst_env_type *inst_env)
 {
   if (inst_env->prefix_found)
@@ -2257,7 +2508,7 @@ ax_ei_setf_op (unsigned short inst, inst_env_type *inst_env)
    register.  Note that check_assign assumes that the caller has checked that
    there is a prefix to this instruction.  The mode check depends on this.  */
 
-void 
+static void 
 check_assign (unsigned short inst, inst_env_type *inst_env)
 {
   /* Check if it's an assign addressing mode.  */
@@ -2270,7 +2521,7 @@ check_assign (unsigned short inst, inst_env_type *inst_env)
 
 /* Handles the 2-operand BOUND instruction.  */
 
-void 
+static void 
 two_operand_bound_op (unsigned short inst, inst_env_type *inst_env)
 {
   /* It's invalid to have the PC as the index operand.  */
@@ -2303,7 +2554,7 @@ two_operand_bound_op (unsigned short inst, inst_env_type *inst_env)
 
 /* Handles the 3-operand BOUND instruction.  */
 
-void 
+static void 
 three_operand_bound_op (unsigned short inst, inst_env_type *inst_env)
 {
   /* It's an error if we haven't got a prefix.  And it's also an error
@@ -2321,7 +2572,7 @@ three_operand_bound_op (unsigned short inst, inst_env_type *inst_env)
 
 /* Clears the status flags in inst_env.  */
 
-void 
+static void 
 btst_nop_op (unsigned short inst, inst_env_type *inst_env)
 {
   /* It's an error if we have got a prefix.  */
@@ -2339,7 +2590,7 @@ btst_nop_op (unsigned short inst, inst_env_type *inst_env)
 
 /* Clears the status flags in inst_env.  */
 
-void 
+static void 
 clearf_di_op (unsigned short inst, inst_env_type *inst_env)
 {
   /* It's an error if we have got a prefix.  */
@@ -2357,7 +2608,7 @@ clearf_di_op (unsigned short inst, inst_env_type *inst_env)
 
 /* Handles the CLEAR instruction if it's in register mode.  */
 
-void 
+static void 
 reg_mode_clear_op (unsigned short inst, inst_env_type *inst_env)
 {
   /* Check if the target is the PC.  */
@@ -2394,7 +2645,7 @@ reg_mode_clear_op (unsigned short inst, inst_env_type *inst_env)
 
 /* Handles the TEST instruction if it's in register mode.  */
 
-void
+static void
 reg_mode_test_op (unsigned short inst, inst_env_type *inst_env)
 {
   /* It's an error if we have got a prefix.  */
@@ -2413,7 +2664,7 @@ reg_mode_test_op (unsigned short inst, inst_env_type *inst_env)
 /* Handles the CLEAR and TEST instruction if the instruction isn't 
    in register mode.  */
 
-void 
+static void 
 none_reg_mode_clear_test_op (unsigned short inst, inst_env_type *inst_env)
 {
   /* Check if we are in a prefix mode.  */
@@ -2438,7 +2689,7 @@ none_reg_mode_clear_test_op (unsigned short inst, inst_env_type *inst_env)
 /* Checks that the PC isn't the destination register or the instructions has
    a prefix.  */
 
-void 
+static void 
 dstep_logshift_mstep_neg_not_op (unsigned short inst, inst_env_type *inst_env)
 {
   /* It's invalid to have the PC as the destination.  The instruction can't
@@ -2457,7 +2708,7 @@ dstep_logshift_mstep_neg_not_op (unsigned short inst, inst_env_type *inst_env)
 
 /* Checks that the instruction doesn't have a prefix.  */
 
-void
+static void
 break_op (unsigned short inst, inst_env_type *inst_env)
 {
   /* The instruction can't have a prefix.  */
@@ -2476,7 +2727,7 @@ break_op (unsigned short inst, inst_env_type *inst_env)
 /* Checks that the PC isn't the destination register and that the instruction
    doesn't have a prefix.  */
 
-void
+static void
 scc_op (unsigned short inst, inst_env_type *inst_env)
 {
   /* It's invalid to have the PC as the destination.  The instruction can't
@@ -2495,7 +2746,7 @@ scc_op (unsigned short inst, inst_env_type *inst_env)
 
 /* Handles the register mode JUMP instruction.  */
 
-void 
+static void 
 reg_mode_jump_op (unsigned short inst, inst_env_type *inst_env)
 {
   /* It's invalid to do a JUMP in a delay slot.  The mode is register, so 
@@ -2516,7 +2767,8 @@ reg_mode_jump_op (unsigned short inst, inst_env_type *inst_env)
 
 /* Handles the JUMP instruction for all modes except register.  */
 
-void none_reg_mode_jump_op (unsigned short inst, inst_env_type *inst_env)
+static void
+none_reg_mode_jump_op (unsigned short inst, inst_env_type *inst_env)
 {
   unsigned long newpc;
   CORE_ADDR address;
@@ -2533,16 +2785,17 @@ void none_reg_mode_jump_op (unsigned short inst, inst_env_type *inst_env)
         {
           check_assign (inst, inst_env);
 
-          /* Get the new value for the the PC.  */
+          /* Get the new value for the PC.  */
           newpc = 
             read_memory_unsigned_integer ((CORE_ADDR) inst_env->prefix_value,
-                                          4);
+                                          4, inst_env->byte_order);
         }
       else
         {
           /* Get the new value for the PC.  */
           address = (CORE_ADDR) inst_env->reg[cris_get_operand1 (inst)];
-          newpc = read_memory_unsigned_integer (address, 4);
+          newpc = read_memory_unsigned_integer (address,
+                                               4, inst_env->byte_order);
 
           /* Check if we should increment a register.  */
           if (cris_get_mode (inst) == AUTOINC_MODE)
@@ -2560,8 +2813,9 @@ void none_reg_mode_jump_op (unsigned short inst, inst_env_type *inst_env)
 
 /* Handles moves to special registers (aka P-register) for all modes.  */
 
-void 
-move_to_preg_op (unsigned short inst, inst_env_type *inst_env)
+static void 
+move_to_preg_op (struct gdbarch *gdbarch, unsigned short inst,
+                inst_env_type *inst_env)
 {
   if (inst_env->prefix_found)
     {
@@ -2592,11 +2846,11 @@ move_to_preg_op (unsigned short inst, inst_env_type *inst_env)
             }
 
           /* The increment depends on the size of the special register.  */
-          if (cris_register_size (cris_get_operand2 (inst)) == 1)
+          if (cris_register_size (gdbarch, cris_get_operand2 (inst)) == 1)
             {
               process_autoincrement (INST_BYTE_SIZE, inst, inst_env);
             }
-          else if (cris_register_size (cris_get_operand2 (inst)) == 2)
+          else if (cris_register_size (gdbarch, cris_get_operand2 (inst)) == 2)
             {
               process_autoincrement (INST_WORD_SIZE, inst, inst_env);
             }
@@ -2615,8 +2869,9 @@ move_to_preg_op (unsigned short inst, inst_env_type *inst_env)
 /* Handles moves from special registers (aka P-register) for all modes
    except register.  */
 
-void 
-none_reg_mode_move_from_preg_op (unsigned short inst, inst_env_type *inst_env)
+static void 
+none_reg_mode_move_from_preg_op (struct gdbarch *gdbarch, unsigned short inst,
+                                inst_env_type *inst_env)
 {
   if (inst_env->prefix_found)
     {
@@ -2647,11 +2902,11 @@ none_reg_mode_move_from_preg_op (unsigned short inst, inst_env_type *inst_env)
             }
           
           /* The increment depends on the size of the special register.  */
-          if (cris_register_size (cris_get_operand2 (inst)) == 1)
+          if (cris_register_size (gdbarch, cris_get_operand2 (inst)) == 1)
             {
               process_autoincrement (INST_BYTE_SIZE, inst, inst_env);
             }
-          else if (cris_register_size (cris_get_operand2 (inst)) == 2)
+          else if (cris_register_size (gdbarch, cris_get_operand2 (inst)) == 2)
             {
               process_autoincrement (INST_WORD_SIZE, inst, inst_env);
             }
@@ -2670,7 +2925,7 @@ none_reg_mode_move_from_preg_op (unsigned short inst, inst_env_type *inst_env)
 /* Handles moves from special registers (aka P-register) when the mode
    is register.  */
 
-void 
+static void 
 reg_mode_move_from_preg_op (unsigned short inst, inst_env_type *inst_env)
 {
   /* Register mode move from special register can't have a prefix.  */
@@ -2705,7 +2960,7 @@ reg_mode_move_from_preg_op (unsigned short inst, inst_env_type *inst_env)
 
 /* Handles the MOVEM from memory to general register instruction.  */
 
-void 
+static void 
 move_mem_to_reg_movem_op (unsigned short inst, inst_env_type *inst_env)
 {
   if (inst_env->prefix_found)
@@ -2715,7 +2970,8 @@ move_mem_to_reg_movem_op (unsigned short inst, inst_env_type *inst_env)
       if (cris_get_operand2 (inst) >= REG_PC)
         {
           inst_env->reg[REG_PC] = 
-            read_memory_unsigned_integer (inst_env->prefix_value, 4);
+            read_memory_unsigned_integer (inst_env->prefix_value,
+                                         4, inst_env->byte_order);
         }
       /* The assign value is the value after the increment.  Normally, the   
          assign value is the value before the increment.  */
@@ -2739,11 +2995,12 @@ move_mem_to_reg_movem_op (unsigned short inst, inst_env_type *inst_env)
             }
           inst_env->reg[REG_PC] =
             read_memory_unsigned_integer (inst_env->reg[cris_get_operand1 (inst)], 
-                                          4);
+                                          4, inst_env->byte_order);
         }
       /* The increment is not depending on the size, instead it's depending
          on the number of registers loaded from memory.  */
-      if ((cris_get_operand1 (inst) == REG_PC) && (cris_get_mode (inst) == AUTOINC_MODE))
+      if ((cris_get_operand1 (inst) == REG_PC)
+         && (cris_get_mode (inst) == AUTOINC_MODE))
         {
           /* It's invalid to change the PC in a delay slot.  */
           if (inst_env->slot_needed)
@@ -2762,15 +3019,15 @@ move_mem_to_reg_movem_op (unsigned short inst, inst_env_type *inst_env)
 
 /* Handles the MOVEM to memory from general register instruction.  */
 
-void 
+static void 
 move_reg_to_mem_movem_op (unsigned short inst, inst_env_type *inst_env)
 {
   if (inst_env->prefix_found)
     {
       /* The assign value is the value after the increment.  Normally, the
          assign value is the value before the increment.  */
-      if ((cris_get_operand1 (inst) == REG_PC) &&
-          (cris_get_mode (inst) == PREFIX_ASSIGN_MODE))
+      if ((cris_get_operand1 (inst) == REG_PC)
+          && (cris_get_mode (inst) == PREFIX_ASSIGN_MODE))
         {
           /* The prefix handles the problem if we are in a delay slot.  */
           inst_env->reg[REG_PC] = inst_env->prefix_value;
@@ -2781,7 +3038,8 @@ move_reg_to_mem_movem_op (unsigned short inst, inst_env_type *inst_env)
     {
       /* The increment is not depending on the size, instead it's depending
          on the number of registers loaded to memory.  */
-      if ((cris_get_operand1 (inst) == REG_PC) && (cris_get_mode (inst) == AUTOINC_MODE))
+      if ((cris_get_operand1 (inst) == REG_PC)
+         && (cris_get_mode (inst) == AUTOINC_MODE))
         {
           /* It's invalid to change the PC in a delay slot.  */
           if (inst_env->slot_needed)
@@ -2798,67 +3056,10 @@ move_reg_to_mem_movem_op (unsigned short inst, inst_env_type *inst_env)
   inst_env->disable_interrupt = 0;
 }
 
-/* Handles the pop instruction to a general register. 
-   POP is a assembler macro for MOVE.D [SP+], Rd.  */
-
-void 
-reg_pop_op (unsigned short inst, inst_env_type *inst_env)
-{
-  /* POP can't have a prefix.  */
-  if (inst_env->prefix_found)
-    {
-      inst_env->invalid = 1;
-      return;
-    }
-  if (cris_get_operand2 (inst) == REG_PC)
-    {
-      /* It's invalid to change the PC in a delay slot.  */
-      if (inst_env->slot_needed)
-        {
-          inst_env->invalid = 1;
-          return;
-        }
-      inst_env->reg[REG_PC] = 
-        read_memory_unsigned_integer (inst_env->reg[REG_SP], 4);
-    }
-  inst_env->slot_needed = 0;
-  inst_env->prefix_found = 0;
-  inst_env->xflag_found = 0;
-  inst_env->disable_interrupt = 0;
-}
-
-/* Handles moves from register to memory.  */
-
-void 
-move_reg_to_mem_index_inc_op (unsigned short inst, inst_env_type *inst_env)
-{
-  /* Check if we have a prefix.  */
-  if (inst_env->prefix_found)
-    {
-      /* The only thing that can change the PC is an assign.  */
-      check_assign (inst, inst_env);
-    }
-  else if ((cris_get_operand1 (inst) == REG_PC) 
-           && (cris_get_mode (inst) == AUTOINC_MODE))
-    {
-      /* It's invalid to change the PC in a delay slot.  */
-      if (inst_env->slot_needed)
-        {
-          inst_env->invalid = 1;
-          return;
-        }
-      process_autoincrement (cris_get_size (inst), inst, inst_env);
-    }
-  inst_env->slot_needed = 0;
-  inst_env->prefix_found = 0;
-  inst_env->xflag_found = 0;
-  inst_env->disable_interrupt = 0;
-}
-
-/* Handles the intructions that's not yet implemented, by setting 
+/* Handles the instructions that's not yet implemented, by setting
    inst_env->invalid to true.  */
 
-void 
+static void 
 not_implemented_op (unsigned short inst, inst_env_type *inst_env)
 {
   inst_env->invalid = 1;
@@ -2866,7 +3067,7 @@ not_implemented_op (unsigned short inst, inst_env_type *inst_env)
 
 /* Handles the XOR instruction.  */
 
-void 
+static void 
 xor_op (unsigned short inst, inst_env_type *inst_env)
 {
   /* XOR can't have a prefix.  */
@@ -2895,7 +3096,7 @@ xor_op (unsigned short inst, inst_env_type *inst_env)
 
 /* Handles the MULS instruction.  */
 
-void 
+static void 
 muls_op (unsigned short inst, inst_env_type *inst_env)
 {
   /* MULS/U can't have a prefix.  */
@@ -2919,7 +3120,7 @@ muls_op (unsigned short inst, inst_env_type *inst_env)
 
 /* Handles the MULU instruction.  */
 
-void 
+static void 
 mulu_op (unsigned short inst, inst_env_type *inst_env)
 {
   /* MULS/U can't have a prefix.  */
@@ -2941,10 +3142,10 @@ mulu_op (unsigned short inst, inst_env_type *inst_env)
   inst_env->disable_interrupt = 0;
 }
 
-/* Calculate the result of the instruction for ADD, SUB, CMP AND, OR and MOVE. 
+/* Calculate the result of the instruction for ADD, SUB, CMP AND, OR and MOVE.
    The MOVE instruction is the move from source to register.  */
 
-void 
+static void 
 add_sub_cmp_and_or_move_action (unsigned short inst, inst_env_type *inst_env, 
                                 unsigned long source1, unsigned long source2)
 {
@@ -3026,7 +3227,7 @@ add_sub_cmp_and_or_move_action (unsigned short inst, inst_env_type *inst_env,
    is zero extend then the value is extended with zero.  If instead the mode
    is signed extend the sign bit of the value is taken into consideration.  */
 
-unsigned long 
+static unsigned long 
 do_sign_or_zero_extend (unsigned long value, unsigned short *inst)
 {
   /* The size can be either byte or word, check which one it is. 
@@ -3064,7 +3265,7 @@ do_sign_or_zero_extend (unsigned long value, unsigned short *inst)
 /* Handles the register mode for the ADD, SUB, CMP, AND, OR and MOVE
    instruction.  The MOVE instruction is the move from source to register.  */
 
-void 
+static void 
 reg_mode_add_sub_cmp_and_or_move_op (unsigned short inst,
                                      inst_env_type *inst_env)
 {
@@ -3109,8 +3310,9 @@ reg_mode_add_sub_cmp_and_or_move_op (unsigned short inst,
    the size of the operation.  If the instruction is a zero or signed
    extend instruction, the size field is changed in instruction.  */
 
-unsigned long 
-get_data_from_address (unsigned short *inst, CORE_ADDR address)
+static unsigned long 
+get_data_from_address (unsigned short *inst, CORE_ADDR address,
+                      enum bfd_endian byte_order)
 {
   int size = cris_get_size (*inst);
   unsigned long value;
@@ -3124,7 +3326,7 @@ get_data_from_address (unsigned short *inst, CORE_ADDR address)
   /* Is there a need for checking the size?  Size should contain the number of
      bytes to read.  */
   size = 1 << size;
-  value = read_memory_unsigned_integer (address, size);
+  value = read_memory_unsigned_integer (address, size, byte_order);
 
   /* Check if it's an extend, signed or zero instruction.  */
   if (cris_get_opcode (*inst) < 4)
@@ -3137,7 +3339,7 @@ get_data_from_address (unsigned short *inst, CORE_ADDR address)
 /* Handles the assign addresing mode for the ADD, SUB, CMP, AND, OR and MOVE 
    instructions.  The MOVE instruction is the move from source to register.  */
 
-void 
+static void 
 handle_prefix_assign_mode_for_aritm_op (unsigned short inst, 
                                         inst_env_type *inst_env)
 {
@@ -3150,7 +3352,8 @@ handle_prefix_assign_mode_for_aritm_op (unsigned short inst,
       operand2 = inst_env->reg[REG_PC];
 
       /* Get the value of the third operand.  */
-      operand3 = get_data_from_address (&inst, inst_env->prefix_value);
+      operand3 = get_data_from_address (&inst, inst_env->prefix_value,
+                                       inst_env->byte_order);
 
       /* Calculate the PC value after the instruction, i.e. where the
          breakpoint should be.  The order of the udw_operands is vital.  */
@@ -3166,7 +3369,7 @@ handle_prefix_assign_mode_for_aritm_op (unsigned short inst,
    OR instructions.  Note that for this to work as expected, the calling
    function must have made sure that there is a prefix to this instruction.  */
 
-void 
+static void 
 three_operand_add_sub_cmp_and_or_op (unsigned short inst, 
                                      inst_env_type *inst_env)
 {
@@ -3179,7 +3382,8 @@ three_operand_add_sub_cmp_and_or_op (unsigned short inst,
       operand2 = inst_env->reg[cris_get_operand2 (inst)];
 
       /* Get the value of the third operand.  */
-      operand3 = get_data_from_address (&inst, inst_env->prefix_value);
+      operand3 = get_data_from_address (&inst, inst_env->prefix_value,
+                                       inst_env->byte_order);
 
       /* Calculate the PC value after the instruction, i.e. where the
          breakpoint should be.  */
@@ -3194,7 +3398,7 @@ three_operand_add_sub_cmp_and_or_op (unsigned short inst,
 /* Handles the index addresing mode for the ADD, SUB, CMP, AND, OR and MOVE
    instructions.  The MOVE instruction is the move from source to register.  */
 
-void 
+static void 
 handle_prefix_index_mode_for_aritm_op (unsigned short inst, 
                                        inst_env_type *inst_env)
 {
@@ -3222,7 +3426,7 @@ handle_prefix_index_mode_for_aritm_op (unsigned short inst,
    CMP, AND OR and MOVE instruction.  The MOVE instruction is the move from
    source to register.  */
 
-void 
+static void 
 handle_inc_and_index_mode_for_aritm_op (unsigned short inst, 
                                         inst_env_type *inst_env)
 {
@@ -3231,7 +3435,7 @@ handle_inc_and_index_mode_for_aritm_op (unsigned short inst,
   unsigned long operand3;
   int size;
 
-  /* The instruction is either an indirect or autoincrement addressing mode. 
+  /* The instruction is either an indirect or autoincrement addressing mode.
      Check if the destination register is the PC.  */
   if (cris_get_operand2 (inst) == REG_PC)
     {
@@ -3242,7 +3446,7 @@ handle_inc_and_index_mode_for_aritm_op (unsigned short inst,
 
       /* Get the value of the third operand, i.e. the indirect operand.  */
       operand1 = inst_env->reg[cris_get_operand1 (inst)];
-      operand3 = get_data_from_address (&inst, operand1);
+      operand3 = get_data_from_address (&inst, operand1, inst_env->byte_order);
 
       /* Calculate the PC value after the instruction, i.e. where the
          breakpoint should be.  The order of the udw_operands is vital.  */
@@ -3250,7 +3454,8 @@ handle_inc_and_index_mode_for_aritm_op (unsigned short inst,
     }
   /* If this is an autoincrement addressing mode, check if the increment
      changes the PC.  */
-  if ((cris_get_operand1 (inst) == REG_PC) && (cris_get_mode (inst) == AUTOINC_MODE))
+  if ((cris_get_operand1 (inst) == REG_PC)
+      && (cris_get_mode (inst) == AUTOINC_MODE))
     {
       /* Get the size field.  */
       size = cris_get_size (inst);
@@ -3272,7 +3477,7 @@ handle_inc_and_index_mode_for_aritm_op (unsigned short inst,
 /* Handles the two-operand addressing mode, all modes except register, for
    the ADD, SUB CMP, AND and OR instruction.  */
 
-void 
+static void 
 none_reg_mode_add_sub_cmp_and_or_move_op (unsigned short inst, 
                                           inst_env_type *inst_env)
 {
@@ -3301,7 +3506,7 @@ none_reg_mode_add_sub_cmp_and_or_move_op (unsigned short inst,
 
 /* Handles the quick addressing mode for the ADD and SUB instruction.  */
 
-void 
+static void 
 quick_mode_add_sub_op (unsigned short inst, inst_env_type *inst_env)
 {
   unsigned long operand1;
@@ -3341,7 +3546,7 @@ quick_mode_add_sub_op (unsigned short inst, inst_env_type *inst_env)
 
 /* Handles the quick addressing mode for the CMP, AND and OR instruction.  */
 
-void 
+static void 
 quick_mode_and_cmp_move_or_op (unsigned short inst, inst_env_type *inst_env)
 {
   unsigned long operand1;
@@ -3387,8 +3592,9 @@ quick_mode_and_cmp_move_or_op (unsigned short inst, inst_env_type *inst_env)
 
 /* Translate op_type to a function and call it.  */
 
-static void cris_gdb_func (enum cris_op_type op_type, unsigned short inst, 
-                           inst_env_type *inst_env)
+static void
+cris_gdb_func (struct gdbarch *gdbarch, enum cris_op_type op_type,
+              unsigned short inst, inst_env_type *inst_env)
 {
   switch (op_type)
     {
@@ -3457,7 +3663,7 @@ static void cris_gdb_func (enum cris_op_type op_type, unsigned short inst,
       break;
 
     case cris_move_to_preg_op:
-      move_to_preg_op (inst, inst_env);
+      move_to_preg_op (gdbarch, inst, inst_env);
       break;
 
     case cris_muls_op:
@@ -3481,7 +3687,7 @@ static void cris_gdb_func (enum cris_op_type op_type, unsigned short inst,
       break;
 
     case cris_none_reg_mode_move_from_preg_op:
-      none_reg_mode_move_from_preg_op (inst, inst_env);
+      none_reg_mode_move_from_preg_op (gdbarch, inst, inst_env);
       break;
 
     case cris_quick_mode_add_sub_op:
@@ -3542,36 +3748,43 @@ static void cris_gdb_func (enum cris_op_type op_type, unsigned short inst,
     }
 }
 
-/* This wrapper is to avoid cris_get_assembler being called before 
-   exec_bfd has been set.  */
-
-static int
-cris_delayed_get_disassembler (bfd_vma addr, disassemble_info *info)
-{
-  tm_print_insn = cris_get_disassembler (exec_bfd);
-  return TARGET_PRINT_INSN (addr, info);
-}
-
-/* Copied from <asm/elf.h>.  */
-typedef unsigned long elf_greg_t;
+/* Originally from <asm/elf.h>.  */
+typedef unsigned char cris_elf_greg_t[4];
 
 /* Same as user_regs_struct struct in <asm/user.h>.  */
-typedef elf_greg_t elf_gregset_t[35];
+#define CRISV10_ELF_NGREG 35
+typedef cris_elf_greg_t cris_elf_gregset_t[CRISV10_ELF_NGREG];
 
-/* Unpack an elf_gregset_t into GDB's register cache.  */
+#define CRISV32_ELF_NGREG 32
+typedef cris_elf_greg_t crisv32_elf_gregset_t[CRISV32_ELF_NGREG];
 
-void 
-supply_gregset (elf_gregset_t *gregsetp)
+/* Unpack a cris_elf_gregset_t into GDB's register cache.  */
+
+static void 
+cris_supply_gregset (struct regcache *regcache, cris_elf_gregset_t *gregsetp)
 {
+  struct gdbarch *gdbarch = regcache->arch ();
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   int i;
-  elf_greg_t *regp = *gregsetp;
-  static char zerobuf[4] = {0};
+  cris_elf_greg_t *regp = *gregsetp;
 
   /* The kernel dumps all 32 registers as unsigned longs, but supply_register
      knows about the actual size of each register so that's no problem.  */
   for (i = 0; i < NUM_GENREGS + NUM_SPECREGS; i++)
     {
-      supply_register (i, (char *)&regp[i]);
+      regcache->raw_supply (i, (char *)&regp[i]);
+    }
+
+  if (tdep->cris_version == 32)
+    {
+      /* Needed to set pseudo-register PC for CRISv32.  */
+      /* FIXME: If ERP is in a delay slot at this point then the PC will
+        be wrong.  Issue a warning to alert the user.  */
+      regcache->raw_supply (gdbarch_pc_regnum (gdbarch),
+                           (char *)&regp[ERP_REGNUM]);
+
+      if (*(char *)&regp[ERP_REGNUM] & 0x1)
+       fprintf_unfiltered (gdb_stderr, "Warning: PC in delay slot\n");
     }
 }
 
@@ -3579,22 +3792,24 @@ supply_gregset (elf_gregset_t *gregsetp)
     regsets, until multi-arch core support is ready.  */
 
 static void
-fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
+fetch_core_registers (struct regcache *regcache,
+                     char *core_reg_sect, unsigned core_reg_size,
                       int which, CORE_ADDR reg_addr)
 {
-  elf_gregset_t gregset;
+  cris_elf_gregset_t gregset;
 
   switch (which)
     {
     case 0:
-      if (core_reg_size != sizeof (gregset))
+      if (core_reg_size != sizeof (cris_elf_gregset_t)
+         && core_reg_size != sizeof (crisv32_elf_gregset_t))
         {
-          warning ("wrong size gregset struct in core file");
+          warning (_("wrong size gregset struct in core file"));
         }
       else
         {
           memcpy (&gregset, core_reg_sect, sizeof (gregset));
-          supply_gregset (&gregset);
+          cris_supply_gregset (regcache, &gregset);
         }
 
     default:
@@ -3614,281 +3829,46 @@ static struct core_fns cris_elf_core_fns =
   NULL                                  /* next */
 };
 
-/* Fetch (and possibly build) an appropriate link_map_offsets
-   structure for native GNU/Linux CRIS targets using the struct
-   offsets defined in link.h (but without actual reference to that
-   file).
-
-   This makes it possible to access GNU/Linux CRIS shared libraries
-   from a GDB that was not built on an GNU/Linux CRIS host (for cross
-   debugging).
-
-   See gdb/solib-svr4.h for an explanation of these fields.  */
-
-struct link_map_offsets *
-cris_linux_svr4_fetch_link_map_offsets (void)
-{ 
-  static struct link_map_offsets lmo;
-  static struct link_map_offsets *lmp = NULL;
-
-  if (lmp == NULL)
-    { 
-      lmp = &lmo;
-
-      lmo.r_debug_size = 8;    /* The actual size is 20 bytes, but
-                                  this is all we need.  */
-      lmo.r_map_offset = 4;
-      lmo.r_map_size   = 4;
-
-      lmo.link_map_size = 20;
-
-      lmo.l_addr_offset = 0;
-      lmo.l_addr_size   = 4;
-
-      lmo.l_name_offset = 4;
-      lmo.l_name_size   = 4;
-
-      lmo.l_next_offset = 12;
-      lmo.l_next_size   = 4;
-
-      lmo.l_prev_offset = 16;
-      lmo.l_prev_size   = 4;
-    }
-
-  return lmp;
-}
-
-static void
-cris_fpless_backtrace (char *noargs, int from_tty)
-{
-  /* Points at the instruction after the jsr (except when in innermost frame
-     where it points at the original pc).  */
-  CORE_ADDR pc = 0;
-
-  /* Temporary variable, used for parsing from the start of the function that
-     the pc is in, up to the pc.  */
-  CORE_ADDR tmp_pc = 0;
-  CORE_ADDR sp = 0;
-
-  /* Information about current frame.  */
-  struct symtab_and_line sal;
-  char* func_name;
-
-  /* Present instruction.  */
-  unsigned short insn;
-  
-  /* Next instruction, lookahead.  */
-  unsigned short insn_next; 
-
-  /* This is to store the offset between sp at start of function and until we
-     reach push srp (if any).  */
-  int sp_add_later = 0;
-  int push_srp_found = 0;
-
-  int val = 0;
-
-  /* Frame counter.  */
-  int frame = 0;
-
-  /* For the innermost frame, we want to look at srp in case it's a leaf
-     function (since there's no push srp in that case).  */
-  int innermost_frame = 1;
-  
-  deprecated_read_register_gen (PC_REGNUM, (char *) &pc);
-  deprecated_read_register_gen (SP_REGNUM, (char *) &sp);
-  
-  /* We make an explicit return when we can't find an outer frame.  */
-  while (1)
-    {
-      /* Get file name and line number.  */
-      sal = find_pc_line (pc, 0);
-
-      /* Get function name.  */
-      find_pc_partial_function (pc, &func_name, (CORE_ADDR *) NULL,
-                                (CORE_ADDR *) NULL);
-
-      /* Print information about current frame.  */
-      printf_unfiltered ("#%i  0x%08lx in %s", frame++, pc, func_name);
-      if (sal.symtab)
-        {    
-          printf_unfiltered (" at %s:%i", sal.symtab->filename, sal.line);
-        }
-      printf_unfiltered ("\n");
-      
-      /* Get the start address of this function.  */
-      tmp_pc = get_pc_function_start (pc);
-  
-      /* Mini parser, only meant to find push sp and sub ...,sp from the start
-         of the function, up to the pc.  */
-      while (tmp_pc < pc)
-        {
-          insn = read_memory_unsigned_integer (tmp_pc, sizeof (short));
-          tmp_pc += sizeof (short);
-          if (insn == 0xE1FC)
-            {
-              /* push <reg> 32 bit instruction */
-              insn_next = read_memory_unsigned_integer (tmp_pc, 
-                                                        sizeof (short));
-              tmp_pc += sizeof (short);
-
-              /* Recognize srp.  */
-              if (insn_next == 0xBE7E)
-                {
-                  /* For subsequent (not this one though) push or sub which
-                     affects sp, adjust sp immediately.  */
-                  push_srp_found = 1;
-
-                  /* Note: this will break if we ever encounter a 
-                     push vr (1 byte) or push ccr (2 bytes).  */
-                  sp_add_later += 4;
-                }
-              else
-                {
-                  /* Some other register was pushed.  */
-                  if (push_srp_found)
-                    {    
-                      sp += 4;
-                    }
-                  else
-                    {
-                      sp_add_later += 4;
-                    }
-                }
-            }
-          else if (cris_get_operand2 (insn) == SP_REGNUM 
-                   && cris_get_mode (insn) == 0x0000
-                   && cris_get_opcode (insn) == 0x000A)
-            {
-              /* subq <val>,sp */
-              val = cris_get_quick_value (insn);
-
-              if (push_srp_found)
-                {
-                  sp += val;
-                }
-              else
-                {
-                  sp_add_later += val;
-                }
-              
-            }
-          else if (cris_get_operand2 (insn) == SP_REGNUM
-                   /* Autoincrement addressing mode.  */
-                   && cris_get_mode (insn) == 0x0003
-                   /* Opcode.  */
-                   && ((insn) & 0x03E0) >> 5 == 0x0004)
-            {
-              /* subu <val>,sp */
-              val = get_data_from_address (&insn, tmp_pc);
-
-              if (push_srp_found)
-                {
-                  sp += val;
-                }
-              else
-                {
-                  sp_add_later += val;
-                }
-            }
-          else if (cris_get_operand2 (insn) == SP_REGNUM
-                   && ((insn & 0x0F00) >> 8) == 0x0001
-                   && (cris_get_signed_offset (insn) < 0))
-            {
-              /* Immediate byte offset addressing prefix word with sp as base 
-                 register.  Used for CRIS v8 i.e. ETRAX 100 and newer if <val> 
-                 is between 64 and 128. 
-                 movem r<regsave>,[sp=sp-<val>] */
-              val = -cris_get_signed_offset (insn);
-              insn_next = read_memory_unsigned_integer (tmp_pc, 
-                                                        sizeof (short));
-              tmp_pc += sizeof (short);
-              
-              if (cris_get_mode (insn_next) == PREFIX_ASSIGN_MODE
-                  && cris_get_opcode (insn_next) == 0x000F
-                  && cris_get_size (insn_next) == 0x0003
-                  && cris_get_operand1 (insn_next) == SP_REGNUM)
-                {             
-                  if (push_srp_found)
-                    {
-                      sp += val;
-                    }
-                  else
-                    {
-                      sp_add_later += val;
-                    }
-                }
-            }
-        }
-      
-      if (push_srp_found)
-        {
-          /* Reset flag.  */
-          push_srp_found = 0;
-
-          /* sp should now point at where srp is stored on the stack.  Update
-             the pc to the srp.  */
-          pc = read_memory_unsigned_integer (sp, 4);
-        }
-      else if (innermost_frame)
-        {
-          /* We couldn't find a push srp in the prologue, so this must be
-             a leaf function, and thus we use the srp register directly.
-             This should happen at most once, for the innermost function.  */
-          deprecated_read_register_gen (SRP_REGNUM, (char *) &pc);
-        }
-      else
-        {
-          /* Couldn't find an outer frame.  */
-          return;
-        }
-
-      /* Reset flag.  (In case the innermost frame wasn't a leaf, we don't
-         want to look at the srp register later either).  */
-      innermost_frame = 0;
-
-      /* Now, add the offset for everything up to, and including push srp,
-         that was held back during the prologue parsing.  */ 
-      sp += sp_add_later;
-      sp_add_later = 0;
-    }
-}
-
 void
 _initialize_cris_tdep (void)
 {
-  struct cmd_list_element *c;
-
   gdbarch_register (bfd_arch_cris, cris_gdbarch_init, cris_dump_tdep);
   
-  /* Used in disassembly.  */
-  tm_print_insn = cris_delayed_get_disassembler;
-
   /* CRIS-specific user-commands.  */
-  c = add_set_cmd ("cris-version", class_support, var_integer, 
-                   (char *) &usr_cmd_cris_version, 
-                   "Set the current CRIS version.", &setlist);
-  set_cmd_sfunc (c, cris_version_update);
-  add_show_from_set (c, &showlist);
-  
-  c = add_set_enum_cmd ("cris-mode", class_support, cris_mode_enums, 
-                        &usr_cmd_cris_mode, 
-                        "Set the current CRIS mode.", &setlist);
-  set_cmd_sfunc (c, cris_mode_update);
-  add_show_from_set (c, &showlist);
-
-  c = add_set_enum_cmd ("cris-abi", class_support, cris_abi_enums, 
-                        &usr_cmd_cris_abi, 
-                        "Set the current CRIS ABI version.", &setlist);
-  set_cmd_sfunc (c, cris_abi_update);
-  add_show_from_set (c, &showlist);
-
-  c = add_cmd ("cris-fpless-backtrace", class_support, cris_fpless_backtrace, 
-               "Display call chain using the subroutine return pointer.\n"
-               "Note that this displays the address after the jump to the "
-               "subroutine.", &cmdlist);
-  
-  add_core_fns (&cris_elf_core_fns);
-  
+  add_setshow_zuinteger_cmd ("cris-version", class_support,
+                            &usr_cmd_cris_version,
+                            _("Set the current CRIS version."),
+                            _("Show the current CRIS version."),
+                            _("\
+Set to 10 for CRISv10 or 32 for CRISv32 if autodetection fails.\n\
+Defaults to 10. "),
+                            set_cris_version,
+                            NULL, /* FIXME: i18n: Current CRIS version
+                                     is %s.  */
+                            &setlist, &showlist);
+
+  add_setshow_enum_cmd ("cris-mode", class_support, 
+                       cris_modes, &usr_cmd_cris_mode, 
+                       _("Set the current CRIS mode."),
+                       _("Show the current CRIS mode."),
+                       _("\
+Set to CRIS_MODE_GURU when debugging in guru mode.\n\
+Makes GDB use the NRP register instead of the ERP register in certain cases."),
+                       set_cris_mode,
+                       NULL, /* FIXME: i18n: Current CRIS version is %s.  */
+                       &setlist, &showlist);
+  
+  add_setshow_boolean_cmd ("cris-dwarf2-cfi", class_support,
+                          &usr_cmd_cris_dwarf2_cfi,
+                          _("Set the usage of Dwarf-2 CFI for CRIS."),
+                          _("Show the usage of Dwarf-2 CFI for CRIS."),
+                          _("Set this to \"off\" if using gcc-cris < R59."),
+                          set_cris_dwarf2_cfi,
+                          NULL, /* FIXME: i18n: Usage of Dwarf-2 CFI
+                                   for CRIS is %d.  */
+                          &setlist, &showlist);
+
+  deprecated_add_core_fns (&cris_elf_core_fns);
 }
 
 /* Prints out all target specific values.  */
@@ -3896,134 +3876,57 @@ _initialize_cris_tdep (void)
 static void
 cris_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   if (tdep != NULL)
     {
       fprintf_unfiltered (file, "cris_dump_tdep: tdep->cris_version = %i\n",
                           tdep->cris_version);
       fprintf_unfiltered (file, "cris_dump_tdep: tdep->cris_mode = %s\n",
                           tdep->cris_mode);
-      fprintf_unfiltered (file, "cris_dump_tdep: tdep->cris_abi = %s\n",
-                          tdep->cris_abi);
-
+      fprintf_unfiltered (file, "cris_dump_tdep: tdep->cris_dwarf2_cfi = %i\n",
+                          tdep->cris_dwarf2_cfi);
     }
 }
 
 static void
-cris_version_update (char *ignore_args, int from_tty, 
-                     struct cmd_list_element *c)
+set_cris_version (const char *ignore_args, int from_tty, 
+                 struct cmd_list_element *c)
 {
   struct gdbarch_info info;
 
-  /* NOTE: cagney/2002-03-17: The add_show_from_set() function clones
-     the set command passed as a parameter.  The clone operation will
-     include (BUG?) any ``set'' command callback, if present.
-     Commands like ``info set'' call all the ``show'' command
-     callbacks.  Unfortunatly, for ``show'' commands cloned from
-     ``set'', this includes callbacks belonging to ``set'' commands.
-     Making this worse, this only occures if add_show_from_set() is
-     called after add_cmd_sfunc() (BUG?).  */
-
-  /* From here on, trust the user's CRIS version setting.  */
-  if (cmd_type (c) == set_cmd)
-    {
-      usr_cmd_cris_version_valid = 1;
+  usr_cmd_cris_version_valid = 1;
   
-      /* Update the current architecture, if needed.  */
-      gdbarch_info_init (&info);
-      if (!gdbarch_update_p (info))
-        internal_error (__FILE__, __LINE__, "cris_gdbarch_update: failed to update architecture.");
-    }  
+  /* Update the current architecture, if needed.  */
+  gdbarch_info_init (&info);
+  if (!gdbarch_update_p (info))
+    internal_error (__FILE__, __LINE__, 
+                   _("cris_gdbarch_update: failed to update architecture."));
 }
 
 static void
-cris_mode_update (char *ignore_args, int from_tty, 
-                 struct cmd_list_element *c)
+set_cris_mode (const char *ignore_args, int from_tty, 
+              struct cmd_list_element *c)
 {
   struct gdbarch_info info;
-  
-  /* NOTE: cagney/2002-03-17: The add_show_from_set() function clones
-     the set command passed as a parameter.  The clone operation will
-     include (BUG?) any ``set'' command callback, if present.
-     Commands like ``info set'' call all the ``show'' command
-     callbacks.  Unfortunatly, for ``show'' commands cloned from
-     ``set'', this includes callbacks belonging to ``set'' commands.
-     Making this worse, this only occures if add_show_from_set() is
-     called after add_cmd_sfunc() (BUG?).  */
-
-  /* From here on, trust the user's CRIS mode setting.  */
-  if (cmd_type (c) == set_cmd)
-    {
-      usr_cmd_cris_mode_valid = 1;
-  
-      /* Update the current architecture, if needed.  */
-      gdbarch_info_init (&info);
-      if (!gdbarch_update_p (info))
-        internal_error (__FILE__, __LINE__, "cris_gdbarch_update: failed to update architecture.");
-    }
+
+  /* Update the current architecture, if needed.  */
+  gdbarch_info_init (&info);
+  if (!gdbarch_update_p (info))
+    internal_error (__FILE__, __LINE__, 
+                   "cris_gdbarch_update: failed to update architecture.");
 }
 
 static void
-cris_abi_update (char *ignore_args, int from_tty, 
-                 struct cmd_list_element *c)
+set_cris_dwarf2_cfi (const char *ignore_args, int from_tty, 
+                    struct cmd_list_element *c)
 {
   struct gdbarch_info info;
-  
-  /* NOTE: cagney/2002-03-17: The add_show_from_set() function clones
-     the set command passed as a parameter.  The clone operation will
-     include (BUG?) any ``set'' command callback, if present.
-     Commands like ``info set'' call all the ``show'' command
-     callbacks.  Unfortunatly, for ``show'' commands cloned from
-     ``set'', this includes callbacks belonging to ``set'' commands.
-     Making this worse, this only occures if add_show_from_set() is
-     called after add_cmd_sfunc() (BUG?).  */
-
-  /* From here on, trust the user's CRIS ABI setting.  */
-  if (cmd_type (c) == set_cmd)
-    {
-      usr_cmd_cris_abi_valid = 1;
-  
-      /* Update the current architecture, if needed.  */
-      gdbarch_info_init (&info);
-      if (!gdbarch_update_p (info))
-        internal_error (__FILE__, __LINE__, "cris_gdbarch_update: failed to update architecture.");
-    }
-}
-
-/* Copied from pa64solib.c, with a couple of minor changes.  */
-
-static CORE_ADDR
-bfd_lookup_symbol (bfd *abfd, const char *symname)
-{
-  unsigned int storage_needed;
-  asymbol *sym;
-  asymbol **symbol_table;
-  unsigned int number_of_symbols;
-  unsigned int i;
-  struct cleanup *back_to;
-  CORE_ADDR symaddr = 0;
 
-  storage_needed = bfd_get_symtab_upper_bound (abfd);
-
-  if (storage_needed > 0)
-    {
-      symbol_table = (asymbol **) xmalloc (storage_needed);
-      back_to = make_cleanup (free, symbol_table);
-      number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
-
-      for (i = 0; i < number_of_symbols; i++)
-       {
-         sym = *symbol_table++;
-         if (!strcmp (sym->name, symname))
-           {
-             /* Bfd symbols are section relative.  */
-             symaddr = sym->value + sym->section->vma;
-             break;
-           }
-       }
-      do_cleanups (back_to);
-    }
-  return (symaddr);
+  /* Update the current architecture, if needed.  */
+  gdbarch_info_init (&info);
+  if (!gdbarch_update_p (info))
+    internal_error (__FILE__, __LINE__, 
+                   _("cris_gdbarch_update: failed to update architecture."));
 }
 
 static struct gdbarch *
@@ -4031,178 +3934,64 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 {
   struct gdbarch *gdbarch;
   struct gdbarch_tdep *tdep;
-  int cris_version;
-  const char *cris_mode;
-  const char *cris_abi;
-  CORE_ADDR cris_abi_sym = 0;
-  int register_bytes;
+  unsigned int cris_version;
 
   if (usr_cmd_cris_version_valid)
     {
       /* Trust the user's CRIS version setting.  */ 
       cris_version = usr_cmd_cris_version;
     }
-  else
-    {
-      /* Assume it's CRIS version 10.  */
-      cris_version = 10;
-    }
-
-  if (usr_cmd_cris_mode_valid)
-    {
-      /* Trust the user's CRIS mode setting.  */ 
-      cris_mode = usr_cmd_cris_mode;
-    }
-  else if (cris_version == 10)
-    {
-      /* Assume CRIS version 10 is in user mode.  */
-      cris_mode = CRIS_MODE_USER;
-    }
-  else
-    {
-      /* Strictly speaking, older CRIS version don't have a supervisor mode,
-         but we regard its only mode as supervisor mode.  */
-      cris_mode = CRIS_MODE_SUPERVISOR;
-    }
-
-  if (usr_cmd_cris_abi_valid)
-    {
-      /* Trust the user's ABI setting.  */
-      cris_abi = usr_cmd_cris_abi;
-    }
-  else if (info.abfd)
+  else if (info.abfd && bfd_get_mach (info.abfd) == bfd_mach_cris_v32)
     {
-      if (bfd_get_flavour (info.abfd) == bfd_target_elf_flavour)
-        {
-          /* An elf target uses the new ABI.  */
-          cris_abi = CRIS_ABI_V2;
-        }
-      else if (bfd_get_flavour (info.abfd) == bfd_target_aout_flavour)
-        {
-          /* An a.out target may use either ABI.  Look for hints in the
-             symbol table.  */
-          cris_abi_sym = bfd_lookup_symbol (info.abfd, CRIS_ABI_SYMBOL);
-          cris_abi = cris_abi_sym ? CRIS_ABI_V2 : CRIS_ABI_ORIGINAL;
-        }
-      else
-        {
-          /* Unknown bfd flavour.  Assume it's the new ABI.  */
-          cris_abi = CRIS_ABI_V2;
-        }
-    }
-  else if (arches != NULL)
-    {
-      /* No bfd available.  Stick with the ABI from the most recently
-         selected architecture of this same family (the head of arches
-         always points to this).  (This is to avoid changing the ABI
-         when the user updates the architecture with the 'set
-         cris-version' command.)  */
-      cris_abi = gdbarch_tdep (arches->gdbarch)->cris_abi;
+      cris_version = 32;
     }
   else
     {
-      /* No bfd, and no previously selected architecture available.
-         Assume it's the new ABI.  */
-      cris_abi = CRIS_ABI_V2;
+      /* Assume it's CRIS version 10.  */
+      cris_version = 10;
     }
 
   /* Make the current settings visible to the user.  */
   usr_cmd_cris_version = cris_version;
-  usr_cmd_cris_mode = cris_mode;
-  usr_cmd_cris_abi = cris_abi;
   
-  /* Find a candidate among the list of pre-declared architectures.  Both
-     CRIS version and ABI must match.  */
+  /* Find a candidate among the list of pre-declared architectures.  */
   for (arches = gdbarch_list_lookup_by_info (arches, &info); 
        arches != NULL;
        arches = gdbarch_list_lookup_by_info (arches->next, &info))
     {
-      if ((gdbarch_tdep (arches->gdbarch)->cris_version == cris_version)
-          && (gdbarch_tdep (arches->gdbarch)->cris_mode == cris_mode)
-          && (gdbarch_tdep (arches->gdbarch)->cris_abi == cris_abi))
+      if ((gdbarch_tdep (arches->gdbarch)->cris_version 
+          == usr_cmd_cris_version)
+         && (gdbarch_tdep (arches->gdbarch)->cris_mode 
+          == usr_cmd_cris_mode)
+         && (gdbarch_tdep (arches->gdbarch)->cris_dwarf2_cfi 
+             == usr_cmd_cris_dwarf2_cfi))
         return arches->gdbarch;
     }
 
   /* No matching architecture was found.  Create a new one.  */
-  tdep = (struct gdbarch_tdep *) xmalloc (sizeof (struct gdbarch_tdep));
+  tdep = XCNEW (struct gdbarch_tdep);
+  info.byte_order = BFD_ENDIAN_LITTLE;
   gdbarch = gdbarch_alloc (&info, tdep);
 
-  /* NOTE: cagney/2002-12-06: This can be deleted when this arch is
-     ready to unwind the PC first (see frame.c:get_prev_frame()).  */
-  set_gdbarch_deprecated_init_frame_pc (gdbarch, init_frame_pc_default);
-
-  tdep->cris_version = cris_version;
-  tdep->cris_mode = cris_mode;
-  tdep->cris_abi = cris_abi;
-
-  /* INIT shall ensure that the INFO.BYTE_ORDER is non-zero.  */
-  switch (info.byte_order)
-    {
-    case BFD_ENDIAN_LITTLE:
-      /* Ok.  */
-      break;
-
-    case BFD_ENDIAN_BIG:
-      internal_error (__FILE__, __LINE__, "cris_gdbarch_init: big endian byte order in info");
-      break;
-    
-    default:
-      internal_error (__FILE__, __LINE__, "cris_gdbarch_init: unknown byte order in info");
-    }
-
-  /* Initialize the ABI dependent things.  */
-  if (tdep->cris_abi == CRIS_ABI_ORIGINAL)
-    {
-      set_gdbarch_double_bit (gdbarch, 32);
-      set_gdbarch_deprecated_push_arguments (gdbarch, cris_abi_original_push_arguments);
-      set_gdbarch_deprecated_store_return_value (gdbarch, 
-                                      cris_abi_original_store_return_value);
-      set_gdbarch_deprecated_extract_return_value 
-        (gdbarch, cris_abi_original_extract_return_value);
-      set_gdbarch_reg_struct_has_addr 
-        (gdbarch, cris_abi_original_reg_struct_has_addr);
-    }
-  else if (tdep->cris_abi == CRIS_ABI_V2)
-    {
-      set_gdbarch_double_bit (gdbarch, 64);
-      set_gdbarch_deprecated_push_arguments (gdbarch, cris_abi_v2_push_arguments);
-      set_gdbarch_deprecated_store_return_value (gdbarch, cris_abi_v2_store_return_value);
-      set_gdbarch_deprecated_extract_return_value
-       (gdbarch, cris_abi_v2_extract_return_value);
-      set_gdbarch_reg_struct_has_addr (gdbarch, 
-                                       cris_abi_v2_reg_struct_has_addr);
-    }
-  else
-    internal_error (__FILE__, __LINE__, "cris_gdbarch_init: unknown CRIS ABI");
+  tdep->cris_version = usr_cmd_cris_version;
+  tdep->cris_mode = usr_cmd_cris_mode;
+  tdep->cris_dwarf2_cfi = usr_cmd_cris_dwarf2_cfi;
 
-  /* The default definition of a long double is 2 * TARGET_DOUBLE_BIT,
-     which means we have to set this explicitly.  */
-  set_gdbarch_long_double_bit (gdbarch, 64);
-    
-  /* There are 32 registers (some of which may not be implemented).  */
-  set_gdbarch_num_regs (gdbarch, 32);
+  set_gdbarch_return_value (gdbarch, cris_return_value);
   set_gdbarch_sp_regnum (gdbarch, 14);
-  set_gdbarch_fp_regnum (gdbarch, 8);
-  set_gdbarch_pc_regnum (gdbarch, 15);
-
-  set_gdbarch_register_name (gdbarch, cris_register_name);
-  
-  /* Length of ordinary registers used in push_word and a few other places. 
-     REGISTER_RAW_SIZE is the real way to know how big a register is.  */
-  set_gdbarch_register_size (gdbarch, 4);
-  
-  /* NEW */
-  set_gdbarch_register_bytes_ok (gdbarch, cris_register_bytes_ok);
-  set_gdbarch_software_single_step (gdbarch, cris_software_single_step);
-
   
-  set_gdbarch_cannot_store_register (gdbarch, cris_cannot_store_register);
-  set_gdbarch_cannot_fetch_register (gdbarch, cris_cannot_fetch_register);
+  /* Length of ordinary registers used in push_word and a few other
+     places.  register_size() is the real way to know how big a
+     register is.  */
 
+  set_gdbarch_double_bit (gdbarch, 64);
+  /* The default definition of a long double is 2 * gdbarch_double_bit,
+     which means we have to set this explicitly.  */
+  set_gdbarch_long_double_bit (gdbarch, 64);
 
   /* The total amount of space needed to store (in an array called registers)
      GDB's copy of the machine's register state.  Note: We can not use
-     cris_register_size at this point, since it relies on current_gdbarch
+     cris_register_size at this point, since it relies on gdbarch
      being set.  */
   switch (tdep->cris_version)
     {
@@ -4210,118 +3999,84 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     case 1:
     case 2:
     case 3:
-      /* Support for these may be added later.  */
-      internal_error (__FILE__, __LINE__, "cris_gdbarch_init: unsupported CRIS version");
-      break;
-      
     case 8:
     case 9:
-      /* CRIS v8 and v9, a.k.a. ETRAX 100.  General registers R0 - R15 
-         (32 bits), special registers P0 - P1 (8 bits), P4 - P5 (16 bits), 
-         and P8 - P14 (32 bits).  */
-      register_bytes = (16 * 4) + (2 * 1) + (2 * 2) + (7 * 4);
-      break;
+      /* Old versions; not supported.  */
+      return 0;
 
     case 10:
     case 11: 
       /* CRIS v10 and v11, a.k.a. ETRAX 100LX.  In addition to ETRAX 100, 
          P7 (32 bits), and P15 (32 bits) have been implemented.  */
-      register_bytes = (16 * 4) + (2 * 1) + (2 * 2) + (9 * 4);
+      set_gdbarch_pc_regnum (gdbarch, 15);
+      set_gdbarch_register_type (gdbarch, cris_register_type);
+      /* There are 32 registers (some of which may not be implemented).  */
+      set_gdbarch_num_regs (gdbarch, 32);
+      set_gdbarch_register_name (gdbarch, cris_register_name);
+      set_gdbarch_cannot_store_register (gdbarch, cris_cannot_store_register);
+      set_gdbarch_cannot_fetch_register (gdbarch, cris_cannot_fetch_register);
+
+      set_gdbarch_software_single_step (gdbarch, cris_software_single_step);
       break;
 
-    default:
-      internal_error (__FILE__, __LINE__, "cris_gdbarch_init: unknown CRIS version");
-    }
+    case 32:
+      /* CRIS v32.  General registers R0 - R15 (32 bits), special registers 
+        P0 - P15 (32 bits) except P0, P1, P3 (8 bits) and P4 (16 bits)
+        and pseudo-register PC (32 bits).  */
+      set_gdbarch_pc_regnum (gdbarch, 32);
+      set_gdbarch_register_type (gdbarch, crisv32_register_type);
+      /* 32 registers + pseudo-register PC + 16 support registers.  */
+      set_gdbarch_num_regs (gdbarch, 32 + 1 + 16);
+      set_gdbarch_register_name (gdbarch, crisv32_register_name);
 
-  set_gdbarch_register_bytes (gdbarch, register_bytes);
+      set_gdbarch_cannot_store_register 
+       (gdbarch, crisv32_cannot_store_register);
+      set_gdbarch_cannot_fetch_register
+       (gdbarch, crisv32_cannot_fetch_register);
 
-  /* Returns the register offset for the first byte of register regno's space 
-     in the saved register state.  */
-  set_gdbarch_register_byte (gdbarch, cris_register_offset);
-  
-  /* The length of the registers in the actual machine representation.  */
-  set_gdbarch_register_raw_size (gdbarch, cris_register_size);
-  
-  /* The largest value REGISTER_RAW_SIZE can have.  */
-  set_gdbarch_deprecated_max_register_raw_size (gdbarch, 32);
-  
-  /* The length of the registers in the program's representation.  */
-  set_gdbarch_register_virtual_size (gdbarch, cris_register_size);
-  
-  /* The largest value REGISTER_VIRTUAL_SIZE can have.  */
-  set_gdbarch_deprecated_max_register_virtual_size (gdbarch, 32);
+      set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
 
-  set_gdbarch_register_virtual_type (gdbarch, cris_register_virtual_type);
-  
-  /* Use generic dummy frames.  */
-  
-  /* Start execution at the beginning of dummy.  */
-  set_gdbarch_call_dummy_start_offset (gdbarch, 0);
-  set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0);
-  
-  /* Set to 1 since call_dummy_breakpoint_offset was defined.  */
-  set_gdbarch_call_dummy_breakpoint_offset_p (gdbarch, 1);
-  
-  /* Read all about dummy frames in blockframe.c.  */
-  set_gdbarch_call_dummy_length (gdbarch, 0);
-  set_gdbarch_deprecated_pc_in_call_dummy (gdbarch, deprecated_pc_in_call_dummy_at_entry_point);
-  
-  /* Defined to 1 to indicate that the target supports inferior function 
-     calls.  */
-  set_gdbarch_call_dummy_words (gdbarch, 0);
-  set_gdbarch_sizeof_call_dummy_words (gdbarch, 0);
-  
-  set_gdbarch_deprecated_get_saved_register (gdbarch, deprecated_generic_get_saved_register);
-  
-  /* No register requires conversion from raw format to virtual format.  */
-  set_gdbarch_register_convertible (gdbarch, generic_register_convertible_not);
+      set_gdbarch_single_step_through_delay 
+       (gdbarch, crisv32_single_step_through_delay);
 
-  set_gdbarch_deprecated_push_return_address (gdbarch, cris_push_return_address);
-  set_gdbarch_deprecated_pop_frame (gdbarch, cris_pop_frame);
+      break;
 
-  set_gdbarch_deprecated_store_struct_return (gdbarch, cris_store_struct_return);
-  set_gdbarch_deprecated_extract_struct_value_address
-    (gdbarch, cris_extract_struct_value_address);
-  set_gdbarch_use_struct_convention (gdbarch, cris_use_struct_convention);
+    default:
+      /* Unknown version.  */
+      return 0;
+    }
 
-  set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, cris_frame_init_saved_regs);
-  set_gdbarch_deprecated_init_extra_frame_info (gdbarch, cris_init_extra_frame_info);
+  /* Dummy frame functions (shared between CRISv10 and CRISv32 since they
+     have the same ABI).  */
+  set_gdbarch_push_dummy_code (gdbarch, cris_push_dummy_code);
+  set_gdbarch_push_dummy_call (gdbarch, cris_push_dummy_call);
+  set_gdbarch_frame_align (gdbarch, cris_frame_align);
   set_gdbarch_skip_prologue (gdbarch, cris_skip_prologue);
-  set_gdbarch_prologue_frameless_p (gdbarch, generic_prologue_frameless_p);
   
   /* The stack grows downward.  */
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
 
-  set_gdbarch_breakpoint_from_pc (gdbarch, cris_breakpoint_from_pc);
+  set_gdbarch_breakpoint_kind_from_pc (gdbarch, cris_breakpoint_kind_from_pc);
+  set_gdbarch_sw_breakpoint_from_kind (gdbarch, cris_sw_breakpoint_from_kind);
   
-  /* The PC must not be decremented after a breakpoint.  (The breakpoint
-     handler takes care of that.)  */
-  set_gdbarch_decr_pc_after_break (gdbarch, 0);
-  
-  /* Offset from address of function to start of its code.  */
-  set_gdbarch_function_start_offset (gdbarch, 0);  
-  
-  /* The number of bytes at the start of arglist that are not really args,
-     0 in the CRIS ABI.  */
-  set_gdbarch_frame_args_skip (gdbarch, 0);
-  set_gdbarch_frameless_function_invocation 
-    (gdbarch, cris_frameless_function_invocation);
-  set_gdbarch_deprecated_frame_chain (gdbarch, cris_frame_chain);
+  if (tdep->cris_dwarf2_cfi == 1)
+    {
+      /* Hook in the Dwarf-2 frame sniffer.  */
+      set_gdbarch_dwarf2_reg_to_regnum (gdbarch, cris_dwarf2_reg_to_regnum);
+      dwarf2_frame_set_init_reg (gdbarch, cris_dwarf2_frame_init_reg);
+      dwarf2_append_unwinders (gdbarch);
+    }
 
-  set_gdbarch_deprecated_frame_saved_pc (gdbarch, cris_frame_saved_pc);
-  set_gdbarch_saved_pc_after_call (gdbarch, cris_saved_pc_after_call);
+  if (tdep->cris_mode != cris_mode_guru)
+    {
+      frame_unwind_append_unwinder (gdbarch, &cris_sigtramp_frame_unwind);
+    }
 
-  set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
-  
-  /* Helpful for backtracing and returning in a call dummy.  */
-  set_gdbarch_save_dummy_frame_tos (gdbarch, generic_save_dummy_frame_tos);
+  frame_unwind_append_unwinder (gdbarch, &cris_frame_unwind);
+  frame_base_set_default (gdbarch, &cris_frame_base);
 
-  /* Should be using push_dummy_call.  */
-  set_gdbarch_deprecated_dummy_write_sp (gdbarch, generic_target_write_sp);
+  /* Hook in ABI-specific overrides, if they have been registered.  */
+  gdbarch_init_osabi (info, gdbarch);
 
-  /* Use target_specific function to define link map offsets.  */
-  set_solib_svr4_fetch_link_map_offsets 
-    (gdbarch, cris_linux_svr4_fetch_link_map_offsets);
-  
   return gdbarch;
 }
This page took 0.068738 seconds and 4 git commands to generate.