gdb/doc: make use of group/end group in 'info pretty-printers' example
[binutils-gdb.git] / gdb / v850-tdep.c
index 285fe3fe864519314e11e52ac62000c529f66cac..a67310a2440ed5a8c916e04bb08a92bab8ab8ebd 100644 (file)
@@ -1,7 +1,6 @@
 /* Target-dependent code for the NEC V850 for GDB, the GNU debugger.
 
-   Copyright (C) 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007,
-   2008, 2009 Free Software Foundation, Inc.
+   Copyright (C) 1996-2022 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "frame-base.h"
 #include "trad-frame.h"
 #include "frame-unwind.h"
-#include "dwarf2-frame.h"
+#include "dwarf2/frame.h"
 #include "gdbtypes.h"
 #include "inferior.h"
-#include "gdb_string.h"
-#include "gdb_assert.h"
 #include "gdbcore.h"
 #include "arch-utils.h"
 #include "regcache.h"
 #include "dis-asm.h"
 #include "osabi.h"
+#include "elf-bfd.h"
+#include "elf/v850.h"
+#include "gdbarch.h"
 
 enum
   {
+    /* General purpose registers.  */
     E_R0_REGNUM,
     E_R1_REGNUM,
     E_R2_REGNUM,
@@ -68,6 +69,8 @@ enum
     E_R29_REGNUM, E_FP_REGNUM = E_R29_REGNUM,
     E_R30_REGNUM, E_EP_REGNUM = E_R30_REGNUM,
     E_R31_REGNUM, E_LP_REGNUM = E_R31_REGNUM,
+
+    /* System registers - main banks.  */
     E_R32_REGNUM, E_SR0_REGNUM = E_R32_REGNUM,
     E_R33_REGNUM,
     E_R34_REGNUM,
@@ -100,9 +103,134 @@ enum
     E_R61_REGNUM,
     E_R62_REGNUM,
     E_R63_REGNUM,
+
+    /* PC.  */
     E_R64_REGNUM, E_PC_REGNUM = E_R64_REGNUM,
     E_R65_REGNUM,
-    E_NUM_REGS
+    E_NUM_OF_V850_REGS,
+    E_NUM_OF_V850E_REGS = E_NUM_OF_V850_REGS,
+
+    /* System registers - MPV (PROT00) bank.  */
+    E_R66_REGNUM = E_NUM_OF_V850_REGS,
+    E_R67_REGNUM,
+    E_R68_REGNUM,
+    E_R69_REGNUM,
+    E_R70_REGNUM,
+    E_R71_REGNUM,
+    E_R72_REGNUM,
+    E_R73_REGNUM,
+    E_R74_REGNUM,
+    E_R75_REGNUM,
+    E_R76_REGNUM,
+    E_R77_REGNUM,
+    E_R78_REGNUM,
+    E_R79_REGNUM,
+    E_R80_REGNUM,
+    E_R81_REGNUM,
+    E_R82_REGNUM,
+    E_R83_REGNUM,
+    E_R84_REGNUM,
+    E_R85_REGNUM,
+    E_R86_REGNUM,
+    E_R87_REGNUM,
+    E_R88_REGNUM,
+    E_R89_REGNUM,
+    E_R90_REGNUM,
+    E_R91_REGNUM,
+    E_R92_REGNUM,
+    E_R93_REGNUM,
+
+    /* System registers - MPU (PROT01) bank.  */
+    E_R94_REGNUM,
+    E_R95_REGNUM,
+    E_R96_REGNUM,
+    E_R97_REGNUM,
+    E_R98_REGNUM,
+    E_R99_REGNUM,
+    E_R100_REGNUM,
+    E_R101_REGNUM,
+    E_R102_REGNUM,
+    E_R103_REGNUM,
+    E_R104_REGNUM,
+    E_R105_REGNUM,
+    E_R106_REGNUM,
+    E_R107_REGNUM,
+    E_R108_REGNUM,
+    E_R109_REGNUM,
+    E_R110_REGNUM,
+    E_R111_REGNUM,
+    E_R112_REGNUM,
+    E_R113_REGNUM,
+    E_R114_REGNUM,
+    E_R115_REGNUM,
+    E_R116_REGNUM,
+    E_R117_REGNUM,
+    E_R118_REGNUM,
+    E_R119_REGNUM,
+    E_R120_REGNUM,
+    E_R121_REGNUM,
+
+    /* FPU system registers.  */
+    E_R122_REGNUM,
+    E_R123_REGNUM,
+    E_R124_REGNUM,
+    E_R125_REGNUM,
+    E_R126_REGNUM,
+    E_R127_REGNUM,
+    E_R128_REGNUM, E_FPSR_REGNUM = E_R128_REGNUM,
+    E_R129_REGNUM, E_FPEPC_REGNUM = E_R129_REGNUM,
+    E_R130_REGNUM, E_FPST_REGNUM = E_R130_REGNUM,
+    E_R131_REGNUM, E_FPCC_REGNUM = E_R131_REGNUM,
+    E_R132_REGNUM, E_FPCFG_REGNUM = E_R132_REGNUM,
+    E_R133_REGNUM,
+    E_R134_REGNUM,
+    E_R135_REGNUM,
+    E_R136_REGNUM,
+    E_R137_REGNUM,
+    E_R138_REGNUM,
+    E_R139_REGNUM,
+    E_R140_REGNUM,
+    E_R141_REGNUM,
+    E_R142_REGNUM,
+    E_R143_REGNUM,
+    E_R144_REGNUM,
+    E_R145_REGNUM,
+    E_R146_REGNUM,
+    E_R147_REGNUM,
+    E_R148_REGNUM,
+    E_R149_REGNUM,
+    E_NUM_OF_V850E2_REGS,
+
+    /* v850e3v5 system registers, selID 1 thru 7.  */
+    E_SELID_1_R0_REGNUM = E_NUM_OF_V850E2_REGS,
+    E_SELID_1_R31_REGNUM = E_SELID_1_R0_REGNUM + 31,
+
+    E_SELID_2_R0_REGNUM,
+    E_SELID_2_R31_REGNUM = E_SELID_2_R0_REGNUM + 31,
+
+    E_SELID_3_R0_REGNUM,
+    E_SELID_3_R31_REGNUM = E_SELID_3_R0_REGNUM + 31,
+
+    E_SELID_4_R0_REGNUM,
+    E_SELID_4_R31_REGNUM = E_SELID_4_R0_REGNUM + 31,
+
+    E_SELID_5_R0_REGNUM,
+    E_SELID_5_R31_REGNUM = E_SELID_5_R0_REGNUM + 31,
+
+    E_SELID_6_R0_REGNUM,
+    E_SELID_6_R31_REGNUM = E_SELID_6_R0_REGNUM + 31,
+
+    E_SELID_7_R0_REGNUM,
+    E_SELID_7_R31_REGNUM = E_SELID_7_R0_REGNUM + 31,
+
+    /* v850e3v5 vector registers.  */
+    E_VR0_REGNUM,
+    E_VR31_REGNUM = E_VR0_REGNUM + 31,
+
+    E_NUM_OF_V850E3V5_REGS,
+
+    /* Total number of possible registers.  */
+    E_NUM_REGS = E_NUM_OF_V850E3V5_REGS
   };
 
 enum
@@ -116,6 +244,38 @@ enum
   E_MAX_RETTYPE_SIZE_IN_REGS = 2 * v850_reg_size
 };
 
+/* When v850 support was added to GCC in the late nineties, the intention
+   was to follow the Green Hills ABI for v850.  In fact, the authors of
+   that support at the time thought that they were doing so.  As far as
+   I can tell, the calling conventions are correct, but the return value
+   conventions were not quite right.  Over time, the return value code
+   in this file was modified to mostly reflect what GCC was actually
+   doing instead of to actually follow the Green Hills ABI as it did
+   when the code was first written.
+
+   Renesas defined the RH850 ABI which they use in their compiler.  It
+   is similar to the original Green Hills ABI with some minor
+   differences.  */
+
+enum v850_abi
+{
+  V850_ABI_GCC,
+  V850_ABI_RH850
+};
+
+/* Architecture specific data.  */
+
+struct v850_gdbarch_tdep : gdbarch_tdep
+{
+  /* Fields from the ELF header.  */
+  int e_flags = 0;
+  int e_machine = 0;
+
+  /* Which ABI are we using?  */
+  enum v850_abi abi {};
+  int eight_byte_align = 0;
+};
+
 struct v850_frame_cache
 { 
   /* Base address.  */
@@ -127,7 +287,7 @@ struct v850_frame_cache
   int uses_fp;
   
   /* Saved registers.  */
-  struct trad_frame_saved_reg *saved_regs;
+  trad_frame_saved_reg *saved_regs;
 };
 
 /* Info gleaned from scanning a function's prologue.  */
@@ -152,7 +312,7 @@ v850_register_name (struct gdbarch *gdbarch, int regnum)
     "sr24", "sr25", "sr26", "sr27", "sr28", "sr29", "sr30", "sr31",
     "pc", "fp"
   };
-  if (regnum < 0 || regnum >= E_NUM_REGS)
+  if (regnum < 0 || regnum > E_NUM_OF_V850_REGS)
     return NULL;
   return v850_reg_names[regnum];
 }
@@ -172,11 +332,158 @@ v850e_register_name (struct gdbarch *gdbarch, int regnum)
     "sr24", "sr25", "sr26", "sr27", "sr28", "sr29", "sr30", "sr31",
     "pc", "fp"
   };
-  if (regnum < 0 || regnum >= E_NUM_REGS)
+  if (regnum < 0 || regnum > E_NUM_OF_V850E_REGS)
     return NULL;
   return v850e_reg_names[regnum];
 }
 
+static const char *
+v850e2_register_name (struct gdbarch *gdbarch, int regnum)
+{
+  static const char *v850e2_reg_names[] =
+  {
+    /* General purpose registers.  */
+    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+    "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+    "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+    "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+
+    /* System registers - main banks.  */
+    "eipc", "eipsw", "fepc", "fepsw", "ecr", "psw", "pid", "cfg",
+    "", "", "", "sccfg", "scbp", "eiic", "feic", "dbic",
+    "ctpc", "ctpsw", "dbpc", "dbpsw", "ctbp", "dir", "", "",
+    "", "", "", "", "eiwr", "fewr", "dbwr", "bsel",
+
+
+    /* PC.  */
+    "pc", "",
+
+    /* System registers - MPV (PROT00) bank.  */
+    "vsecr", "vstid", "vsadr", "", "vmecr", "vmtid", "vmadr", "",
+    "vpecr", "vptid", "vpadr", "", "", "", "", "",
+    "", "", "", "", "", "", "", "",
+    "mca", "mcs", "mcc", "mcr",
+
+    /* System registers - MPU (PROT01) bank.  */
+    "mpm", "mpc", "tid", "", "", "", "ipa0l", "ipa0u",
+    "ipa1l", "ipa1u", "ipa2l", "ipa2u", "ipa3l", "ipa3u", "ipa4l", "ipa4u",
+    "dpa0l", "dpa0u", "dpa1l", "dpa1u", "dpa2l", "dpa2u", "dpa3l", "dpa3u",
+    "dpa4l", "dpa4u", "dpa5l", "dpa5u",
+
+    /* FPU system registers.  */
+    "", "", "", "", "", "", "fpsr", "fpepc",
+    "fpst", "fpcc", "fpcfg", "fpec", "", "", "", "",
+    "", "", "", "", "", "", "", "",
+    "", "", "", "fpspc"
+  };
+  if (regnum < 0 || regnum >= E_NUM_OF_V850E2_REGS)
+    return NULL;
+  return v850e2_reg_names[regnum];
+}
+
+/* Implement the "register_name" gdbarch method for v850e3v5.  */
+
+static const char *
+v850e3v5_register_name (struct gdbarch *gdbarch, int regnum)
+{
+  static const char *v850e3v5_reg_names[] =
+  {
+    /* General purpose registers.  */
+    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+    "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+    "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+    "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+
+    /* selID 0, not including FPU registers.  The FPU registers are
+       listed later on.  */
+    "eipc", "eipsw", "fepc", "fepsw",
+    "", "psw", "" /* fpsr */, "" /* fpepc */,
+    "" /* fpst */, "" /* fpcc */, "" /* fpcfg */, "" /* fpec */,
+    "sesr", "eiic", "feic", "",
+    "ctpc", "ctpsw", "", "", "ctbp", "", "", "",
+    "", "", "", "", "eiwr", "fewr", "", "bsel",
+
+
+    /* PC.  */
+    "pc", "",
+
+    /* v850e2 MPV bank.  */
+    "", "", "", "", "", "", "", "",
+    "", "", "", "", "", "", "", "",
+    "", "", "", "", "", "", "", "",
+    "", "", "", "",
+
+    /* Skip v850e2 MPU bank.  It's tempting to reuse these, but we need
+       32 entries for this bank.  */
+    "", "", "", "", "", "", "", "",
+    "", "", "", "", "", "", "", "",
+    "", "", "", "", "", "", "", "",
+    "", "", "", "",
+
+    /* FPU system registers.  These are actually in selID 0, but
+       are placed here to preserve register numbering compatibility
+       with previous architectures.  */
+    "", "", "", "", "", "", "fpsr", "fpepc",
+    "fpst", "fpcc", "fpcfg", "fpec", "", "", "", "",
+    "", "", "", "", "", "", "", "",
+    "", "", "", "",
+
+    /* selID 1.  */
+    "mcfg0", "mcfg1", "rbase", "ebase", "intbp", "mctl", "pid", "fpipr",
+    "", "", "tcsel", "sccfg", "scbp", "hvccfg", "hvcbp", "vsel",
+    "vmprt0", "vmprt1", "vmprt2", "", "", "", "", "vmscctl",
+    "vmsctbl0", "vmsctbl1", "vmsctbl2", "vmsctbl3", "", "", "", "",
+
+    /* selID 2.  */
+    "htcfg0", "", "", "", "", "htctl", "mea", "asid",
+    "mei", "ispr", "pmr", "icsr", "intcfg", "", "", "",
+    "tlbsch", "", "", "", "", "", "", "htscctl",
+    "htsctbl0", "htsctbl1", "htsctbl2", "htsctbl3",
+    "htsctbl4", "htsctbl5", "htsctbl6", "htsctbl7",
+
+    /* selID 3.  */
+    "", "", "", "", "", "", "", "",
+    "", "", "", "", "", "", "", "",
+    "", "", "", "", "", "", "", "",
+    "", "", "", "", "", "", "", "",
+
+    /* selID 4.  */
+    "tlbidx", "", "", "", "telo0", "telo1", "tehi0", "tehi1",
+    "", "", "tlbcfg", "", "bwerrl", "bwerrh", "brerrl", "brerrh",
+    "ictagl", "ictagh", "icdatl", "icdath",
+    "dctagl", "dctagh", "dcdatl", "dcdath",
+    "icctrl", "dcctrl", "iccfg", "dccfg", "icerr", "dcerr", "", "",
+
+    /* selID 5.  */
+    "mpm", "mprc", "", "", "mpbrgn", "mptrgn", "", "",
+    "mca", "mcs", "mcc", "mcr", "", "", "", "",
+    "", "", "", "", "mpprt0", "mpprt1", "mpprt2", "",
+    "", "", "", "", "", "", "", "",
+
+    /* selID 6.  */
+    "mpla0", "mpua0", "mpat0", "", "mpla1", "mpua1", "mpat1", "",
+    "mpla2", "mpua2", "mpat2", "", "mpla3", "mpua3", "mpat3", "",
+    "mpla4", "mpua4", "mpat4", "", "mpla5", "mpua5", "mpat5", "",
+    "mpla6", "mpua6", "mpat6", "", "mpla7", "mpua7", "mpat7", "",
+
+    /* selID 7.  */
+    "mpla8", "mpua8", "mpat8", "", "mpla9", "mpua9", "mpat9", "",
+    "mpla10", "mpua10", "mpat10", "", "mpla11", "mpua11", "mpat11", "",
+    "mpla12", "mpua12", "mpat12", "", "mpla13", "mpua13", "mpat13", "",
+    "mpla14", "mpua14", "mpat14", "", "mpla15", "mpua15", "mpat15", "",
+
+    /* Vector Registers */
+    "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7",
+    "vr8", "vr9", "vr10", "vr11", "vr12", "vr13", "vr14", "vr15",
+    "vr16", "vr17", "vr18", "vr19", "vr20", "vr21", "vr22", "vr23",
+    "vr24", "vr25", "vr26", "vr27", "vr28", "vr29", "vr30", "vr31",
+  };
+
+  if (regnum < 0 || regnum >= E_NUM_OF_V850E3V5_REGS)
+    return NULL;
+  return v850e3v5_reg_names[regnum];
+}
+
 /* Returns the default type for register N.  */
 
 static struct type *
@@ -184,24 +491,36 @@ v850_register_type (struct gdbarch *gdbarch, int regnum)
 {
   if (regnum == E_PC_REGNUM)
     return builtin_type (gdbarch)->builtin_func_ptr;
-  return builtin_type_int32;
+  else if (E_VR0_REGNUM <= regnum && regnum <= E_VR31_REGNUM)
+    return builtin_type (gdbarch)->builtin_uint64;
+  return builtin_type (gdbarch)->builtin_int32;
 }
 
 static int
 v850_type_is_scalar (struct type *t)
 {
-  return (TYPE_CODE (t) != TYPE_CODE_STRUCT
-         && TYPE_CODE (t) != TYPE_CODE_UNION
-         && TYPE_CODE (t) != TYPE_CODE_ARRAY);
+  return (t->code () != TYPE_CODE_STRUCT
+         && t->code () != TYPE_CODE_UNION
+         && t->code () != TYPE_CODE_ARRAY);
 }
 
 /* Should call_function allocate stack space for a struct return?  */
+
 static int
-v850_use_struct_convention (struct type *type)
+v850_use_struct_convention (struct gdbarch *gdbarch, struct type *type)
 {
   int i;
   struct type *fld_type, *tgt_type;
+  v850_gdbarch_tdep *tdep = (v850_gdbarch_tdep *) gdbarch_tdep (gdbarch);
 
+  if (tdep->abi == V850_ABI_RH850)
+    {
+      if (v850_type_is_scalar (type) && TYPE_LENGTH(type) <= 8)
+       return 0;
+
+      /* Structs are never returned in registers for this ABI.  */
+      return 1;
+    }
   /* 1. The value is greater than 8 bytes -> returned by copying.  */
   if (TYPE_LENGTH (type) > 8)
     return 1;
@@ -213,16 +532,16 @@ v850_use_struct_convention (struct type *type)
   /* The value is a structure or union with a single element and that
      element is either a single basic type or an array of a single basic
      type whose size is greater than or equal to 4 -> returned in register.  */
-  if ((TYPE_CODE (type) == TYPE_CODE_STRUCT
-       || TYPE_CODE (type) == TYPE_CODE_UNION)
-       && TYPE_NFIELDS (type) == 1)
+  if ((type->code () == TYPE_CODE_STRUCT
+       || type->code () == TYPE_CODE_UNION)
+       && type->num_fields () == 1)
     {
-      fld_type = TYPE_FIELD_TYPE (type, 0);
+      fld_type = type->field (0).type ();
       if (v850_type_is_scalar (fld_type) && TYPE_LENGTH (fld_type) >= 4)
        return 0;
 
-      if (TYPE_CODE (fld_type) == TYPE_CODE_ARRAY)
-        {
+      if (fld_type->code () == TYPE_CODE_ARRAY)
+       {
          tgt_type = TYPE_TARGET_TYPE (fld_type);
          if (v850_type_is_scalar (tgt_type) && TYPE_LENGTH (tgt_type) >= 4)
            return 0;
@@ -232,17 +551,17 @@ v850_use_struct_convention (struct type *type)
   /* The value is a structure whose first element is an integer or a float,
      and which contains no arrays of more than two elements -> returned in
      register.  */
-  if (TYPE_CODE (type) == TYPE_CODE_STRUCT
-      && v850_type_is_scalar (TYPE_FIELD_TYPE (type, 0))
-      && TYPE_LENGTH (TYPE_FIELD_TYPE (type, 0)) == 4)
+  if (type->code () == TYPE_CODE_STRUCT
+      && v850_type_is_scalar (type->field (0).type ())
+      && TYPE_LENGTH (type->field (0).type ()) == 4)
     {
-      for (i = 1; i < TYPE_NFIELDS (type); ++i)
-        {
-         fld_type = TYPE_FIELD_TYPE (type, 0);
-         if (TYPE_CODE (fld_type) == TYPE_CODE_ARRAY)
+      for (i = 1; i < type->num_fields (); ++i)
+       {
+         fld_type = type->field (0).type ();
+         if (fld_type->code () == TYPE_CODE_ARRAY)
            {
              tgt_type = TYPE_TARGET_TYPE (fld_type);
-             if (TYPE_LENGTH (fld_type) >= 0 && TYPE_LENGTH (tgt_type) >= 0
+             if (TYPE_LENGTH (tgt_type) > 0
                  && TYPE_LENGTH (fld_type) / TYPE_LENGTH (tgt_type) > 2)
                return 1;
            }
@@ -250,14 +569,15 @@ v850_use_struct_convention (struct type *type)
       return 0;
     }
     
-  /* The value is a union which contains at least one field which would be
-     returned in registers according to these rules -> returned in register.  */
-  if (TYPE_CODE (type) == TYPE_CODE_UNION)
+  /* The value is a union which contains at least one field which
+     would be returned in registers according to these rules ->
+     returned in register.  */
+  if (type->code () == TYPE_CODE_UNION)
     {
-      for (i = 0; i < TYPE_NFIELDS (type); ++i)
-        {
-         fld_type = TYPE_FIELD_TYPE (type, 0);
-         if (!v850_use_struct_convention (fld_type))
+      for (i = 0; i < type->num_fields (); ++i)
+       {
+         fld_type = type->field (0).type ();
+         if (!v850_use_struct_convention (gdbarch, fld_type))
            return 0;
        }
     }
@@ -266,6 +586,7 @@ v850_use_struct_convention (struct type *type)
 }
 
 /* Structure for mapping bits in register lists to register numbers.  */
+
 struct reg_list
 {
   long mask;
@@ -400,7 +721,7 @@ v850_handle_pushm (int insn, int insn2, struct v850_frame_cache *pi,
   else
     reg_table = pushmh_reg_table;
 
-  /* Calculate the total size of the saved registers, and add it it to the
+  /* Calculate the total size of the saved registers, and add it to the
      immediate value used to adjust SP.  */
   for (i = 0; reg_table[i].mask != 0; i++)
     if (list12 & reg_table[i].mask)
@@ -438,7 +759,7 @@ v850_is_save_register (int reg)
 {
  /* The caller-save registers are R2, R20 - R29 and R31.  All other
     registers are either special purpose (PC, SP), argument registers,
-    or just considered free for use in the caller. */
+    or just considered free for use in the caller.  */
  return reg == E_R2_REGNUM
        || (reg >= E_R20_REGNUM && reg <= E_R29_REGNUM)
        || reg == E_R31_REGNUM;
@@ -453,13 +774,14 @@ v850_is_save_register (int reg)
    prologue.  */
 
 static CORE_ADDR
-v850_analyze_prologue (CORE_ADDR func_addr, CORE_ADDR pc,
+v850_analyze_prologue (struct gdbarch *gdbarch,
+                      CORE_ADDR func_addr, CORE_ADDR pc,
                       struct v850_frame_cache *pi, ULONGEST ctbp)
 {
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   CORE_ADDR prologue_end, current_pc;
   struct pifsr pifsrs[E_NUM_REGS + 1];
   struct pifsr *pifsr, *pifsr_tmp;
-  int fp_used;
   int ep_used;
   int reg;
   CORE_ADDR save_pc, save_end;
@@ -488,11 +810,11 @@ v850_analyze_prologue (CORE_ADDR func_addr, CORE_ADDR pc,
       int insn;
       int insn2 = -1; /* dummy value */
 
-      insn = read_memory_integer (current_pc, 2);
+      insn = read_memory_integer (current_pc, 2, byte_order);
       current_pc += 2;
-      if ((insn & 0x0780) >= 0x0600)   /* Four byte instruction? */
+      if ((insn & 0x0780) >= 0x0600)   /* Four byte instruction?  */
        {
-         insn2 = read_memory_integer (current_pc, 2);
+         insn2 = read_memory_integer (current_pc, 2, byte_order);
          current_pc += 2;
        }
 
@@ -520,7 +842,8 @@ v850_analyze_prologue (CORE_ADDR func_addr, CORE_ADDR pc,
          save_pc = current_pc;
          save_end = prologue_end;
          regsave_func_p = 1;
-         current_pc = ctbp + (read_memory_unsigned_integer (adr, 2) & 0xffff);
+         current_pc = ctbp + (read_memory_unsigned_integer (adr, 2, byte_order)
+                              & 0xffff);
          prologue_end = (current_pc
                          + (2 * 3)     /* prepare list2,imm5,sp/imm */
                          + 4           /* ctret */
@@ -555,32 +878,32 @@ v850_analyze_prologue (CORE_ADDR func_addr, CORE_ADDR pc,
               || (insn & 0xffe0) == 0x0060     /* jmp */
               || (insn & 0x0780) == 0x0580)    /* branch */
        {
-         break;                /* Ran into end of prologue */
+         break;                /* Ran into end of prologue */
        }
 
       else if ((insn & 0xffe0) == ((E_SP_REGNUM << 11) | 0x0240))
-        /* add <imm>,sp */
+       /* add <imm>,sp */
        pi->sp_offset += ((insn & 0x1f) ^ 0x10) - 0x10;
       else if (insn == ((E_SP_REGNUM << 11) | 0x0600 | E_SP_REGNUM))
-        /* addi <imm>,sp,sp */
+       /* addi <imm>,sp,sp */
        pi->sp_offset += insn2;
       else if (insn == ((E_FP_REGNUM << 11) | 0x0000 | E_SP_REGNUM))
-        /* mov sp,fp */
+       /* mov sp,fp */
        pi->uses_fp = 1;
       else if (insn == ((E_R12_REGNUM << 11) | 0x0640 | E_R0_REGNUM))
-        /* movhi hi(const),r0,r12 */
+       /* movhi hi(const),r0,r12 */
        r12_tmp = insn2 << 16;
       else if (insn == ((E_R12_REGNUM << 11) | 0x0620 | E_R12_REGNUM))
-        /* movea lo(const),r12,r12 */
+       /* movea lo(const),r12,r12 */
        r12_tmp += insn2;
       else if (insn == ((E_SP_REGNUM << 11) | 0x01c0 | E_R12_REGNUM) && r12_tmp)
-        /* add r12,sp */
+       /* add r12,sp */
        pi->sp_offset += r12_tmp;
       else if (insn == ((E_EP_REGNUM << 11) | 0x0000 | E_SP_REGNUM))
-        /* mov sp,ep */
+       /* mov sp,ep */
        ep_used = 1;
       else if (insn == ((E_EP_REGNUM << 11) | 0x0000 | E_R1_REGNUM))
-        /* mov r1,ep */
+       /* mov r1,ep */
        ep_used = 0;
       else if (((insn & 0x07ff) == (0x0760 | E_SP_REGNUM)      
                || (pi->uses_fp
@@ -612,7 +935,7 @@ v850_analyze_prologue (CORE_ADDR func_addr, CORE_ADDR pc,
   for (pifsr_tmp = pifsrs; pifsr_tmp != pifsr; pifsr_tmp++)
     {
       pifsr_tmp->offset -= pi->sp_offset - pifsr_tmp->cur_frameoffset;
-      pi->saved_regs[pifsr_tmp->reg].addr = pifsr_tmp->offset;
+      pi->saved_regs[pifsr_tmp->reg].set_addr (pifsr_tmp->offset);
     }
 
   return current_pc;
@@ -625,7 +948,7 @@ v850_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
   CORE_ADDR func_addr, func_end;
 
-  /* See what the symbol table says */
+  /* See what the symbol table says */
 
   if (find_pc_partial_function (pc, NULL, &func_addr, &func_end))
     {
@@ -641,10 +964,34 @@ v850_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
       return pc;
     }
 
-  /* We can't find the start of this function, so there's nothing we can do.  */
+  /* We can't find the start of this function, so there's nothing we
+     can do.  */
   return pc;
 }
 
+/* Return 1 if the data structure has any 8-byte fields that'll require
+   the entire data structure to be aligned.  Otherwise, return 0.  */
+
+static int
+v850_eight_byte_align_p (struct type *type)
+{
+  type = check_typedef (type);
+
+  if (v850_type_is_scalar (type))
+    return (TYPE_LENGTH (type) == 8);
+  else
+    {
+      int i;
+
+      for (i = 0; i < type->num_fields (); i++)
+       {
+         if (v850_eight_byte_align_p (type->field (i).type ()))
+           return 1;
+       }
+    }
+  return 0;
+}
+
 static CORE_ADDR
 v850_frame_align (struct gdbarch *ignore, CORE_ADDR sp)
 {
@@ -668,29 +1015,36 @@ v850_push_dummy_call (struct gdbarch *gdbarch,
                      int nargs,
                      struct value **args,
                      CORE_ADDR sp,
-                     int struct_return,
+                     function_call_return_method return_method,
                      CORE_ADDR struct_addr)
 {
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   int argreg;
   int argnum;
-  int len = 0;
+  int arg_space = 0;
   int stack_offset;
+  v850_gdbarch_tdep *tdep = (v850_gdbarch_tdep *) gdbarch_tdep (gdbarch);
 
-  /* The offset onto the stack at which we will start copying parameters
-     (after the registers are used up) begins at 16 rather than at zero.
-     That's how the ABI is defined, though there's no indication that these
-     16 bytes are used for anything, not even for saving incoming
-     argument registers.  */
-  stack_offset = 16;
+  if (tdep->abi == V850_ABI_RH850)
+    stack_offset = 0;
+  else
+    {
+      /* The offset onto the stack at which we will start copying parameters
+        (after the registers are used up) begins at 16 rather than at zero.
+        That's how the ABI is defined, though there's no indication that these
+        16 bytes are used for anything, not even for saving incoming
+        argument registers.  */
+      stack_offset = 16;
+    }
 
   /* Now make space on the stack for the args.  */
   for (argnum = 0; argnum < nargs; argnum++)
-    len += ((TYPE_LENGTH (value_type (args[argnum])) + 3) & ~3);
-  sp -= len + stack_offset;
+    arg_space += ((TYPE_LENGTH (value_type (args[argnum])) + 3) & ~3);
+  sp -= arg_space + stack_offset;
 
   argreg = E_ARG0_REGNUM;
   /* The struct_return pointer occupies the first parameter register.  */
-  if (struct_return)
+  if (return_method == return_method_struct)
     regcache_cooked_write_unsigned (regcache, argreg++, struct_addr);
 
   /* Now load as many as possible of the first arguments into
@@ -703,16 +1057,27 @@ v850_push_dummy_call (struct gdbarch *gdbarch,
       gdb_byte valbuf[v850_reg_size];
 
       if (!v850_type_is_scalar (value_type (*args))
+         && tdep->abi == V850_ABI_GCC
          && TYPE_LENGTH (value_type (*args)) > E_MAX_RETTYPE_SIZE_IN_REGS)
        {
-         store_unsigned_integer (valbuf, 4, value_address (*args));
+         store_unsigned_integer (valbuf, 4, byte_order,
+                                 value_address (*args));
          len = 4;
          val = valbuf;
        }
       else
        {
          len = TYPE_LENGTH (value_type (*args));
-         val = (gdb_byte *) value_contents (*args);
+         val = (gdb_byte *) value_contents (*args).data ();
+       }
+
+      if (tdep->eight_byte_align
+         && v850_eight_byte_align_p (value_type (*args)))
+       {
+         if (argreg <= E_ARGLAST_REGNUM && (argreg & 1))
+           argreg++;
+         else if (stack_offset & 0x4)
+           stack_offset += 4;
        }
 
       while (len > 0)
@@ -720,7 +1085,7 @@ v850_push_dummy_call (struct gdbarch *gdbarch,
          {
            CORE_ADDR regval;
 
-           regval = extract_unsigned_integer (val, v850_reg_size);
+           regval = extract_unsigned_integer (val, v850_reg_size, byte_order);
            regcache_cooked_write_unsigned (regcache, argreg, regval);
 
            len -= v850_reg_size;
@@ -751,6 +1116,8 @@ static void
 v850_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);
   int len = TYPE_LENGTH (type);
 
   if (len <= v850_reg_size)
@@ -758,7 +1125,7 @@ v850_extract_return_value (struct type *type, struct regcache *regcache,
       ULONGEST val;
 
       regcache_cooked_read_unsigned (regcache, E_V0_REGNUM, &val);
-      store_unsigned_integer (valbuf, len, val);
+      store_unsigned_integer (valbuf, len, byte_order, val);
     }
   else if (len <= 2 * v850_reg_size)
     {
@@ -766,7 +1133,7 @@ v850_extract_return_value (struct type *type, struct regcache *regcache,
       gdb_byte buf[v850_reg_size];
       for (i = 0; len > 0; i += 4, len -= 4)
        {
-         regcache_raw_read (regcache, regnum++, buf);
+         regcache->raw_read (regnum++, buf);
          memcpy (valbuf + i, buf, len > 4 ? 4 : len);
        }
     }
@@ -776,25 +1143,28 @@ static void
 v850_store_return_value (struct type *type, struct regcache *regcache,
                         const gdb_byte *valbuf)
 {
+  struct gdbarch *gdbarch = regcache->arch ();
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   int len = TYPE_LENGTH (type);
 
   if (len <= v850_reg_size)
-      regcache_cooked_write_unsigned (regcache, E_V0_REGNUM,
-                                     extract_unsigned_integer (valbuf, len));
+      regcache_cooked_write_unsigned
+       (regcache, E_V0_REGNUM,
+        extract_unsigned_integer (valbuf, len, byte_order));
   else if (len <= 2 * v850_reg_size)
     {
       int i, regnum = E_V0_REGNUM;
       for (i = 0; i < len; i += 4)
-       regcache_raw_write (regcache, regnum++, valbuf + i);
+       regcache->raw_write (regnum++, valbuf + i);
     }
 }
 
 static enum return_value_convention
-v850_return_value (struct gdbarch *gdbarch, struct type *func_type,
+v850_return_value (struct gdbarch *gdbarch, struct value *function,
                   struct type *type, struct regcache *regcache,
                   gdb_byte *readbuf, const gdb_byte *writebuf)
 {
-  if (v850_use_struct_convention (type))
+  if (v850_use_struct_convention (gdbarch, type))
     return RETURN_VALUE_STRUCT_CONVENTION;
   if (writebuf)
     v850_store_return_value (type, regcache, writebuf);
@@ -803,19 +1173,50 @@ v850_return_value (struct gdbarch *gdbarch, struct type *func_type,
   return RETURN_VALUE_REGISTER_CONVENTION;
 }
 
-const static unsigned char *
-v850_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr)
+/* Implement the breakpoint_kind_from_pc gdbarch method.  */
+
+static int
+v850_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
 {
-  static unsigned char breakpoint[] = { 0x85, 0x05 };
-  *lenptr = sizeof (breakpoint);
-  return breakpoint;
+  return 2;
+}
+
+/* Implement the sw_breakpoint_from_kind gdbarch method.  */
+
+static const gdb_byte *
+v850_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
+{
+  *size = kind;
+
+    switch (gdbarch_bfd_arch_info (gdbarch)->mach)
+    {
+    case bfd_mach_v850e2:
+    case bfd_mach_v850e2v3:
+    case bfd_mach_v850e3v5:
+      {
+       /* Implement software breakpoints by using the dbtrap instruction.
+          Older architectures had no such instruction.  For those, an
+          unconditional branch to self instruction is used.  */
+
+       static unsigned char dbtrap_breakpoint[] = { 0x40, 0xf8 };
+
+       return dbtrap_breakpoint;
+      }
+      break;
+    default:
+      {
+       static unsigned char breakpoint[] = { 0x85, 0x05 };
+
+       return breakpoint;
+      }
+      break;
+    }
 }
 
 static struct v850_frame_cache *
 v850_alloc_frame_cache (struct frame_info *this_frame)
 {
   struct v850_frame_cache *cache;
-  int i;
 
   cache = FRAME_OBSTACK_ZALLOC (struct v850_frame_cache);
   cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
@@ -834,12 +1235,13 @@ v850_alloc_frame_cache (struct frame_info *this_frame)
 static struct v850_frame_cache *
 v850_frame_cache (struct frame_info *this_frame, void **this_cache)
 {
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
   struct v850_frame_cache *cache;
   CORE_ADDR current_pc;
   int i;
 
   if (*this_cache)
-    return *this_cache;
+    return (struct v850_frame_cache *) *this_cache;
 
   cache = v850_alloc_frame_cache (this_frame);
   *this_cache = cache;
@@ -859,31 +1261,31 @@ v850_frame_cache (struct frame_info *this_frame, void **this_cache)
     {
       ULONGEST ctbp;
       ctbp = get_frame_register_unsigned (this_frame, E_CTBP_REGNUM);
-      v850_analyze_prologue (cache->pc, current_pc, cache, ctbp);
+      v850_analyze_prologue (gdbarch, cache->pc, current_pc, cache, ctbp);
     }
 
   if (!cache->uses_fp)
     {
       /* We didn't find a valid frame, which means that CACHE->base
-         currently holds the frame pointer for our calling frame.  If
-         we're at the start of a function, or somewhere half-way its
-         prologue, the function's frame probably hasn't been fully
-         setup yet.  Try to reconstruct the base address for the stack
-         frame by looking at the stack pointer.  For truly "frameless"
-         functions this might work too.  */
+        currently holds the frame pointer for our calling frame.  If
+        we're at the start of a function, or somewhere half-way its
+        prologue, the function's frame probably hasn't been fully
+        setup yet.  Try to reconstruct the base address for the stack
+        frame by looking at the stack pointer.  For truly "frameless"
+        functions this might work too.  */
       cache->base = get_frame_register_unsigned (this_frame, E_SP_REGNUM);
     }
 
   /* Now that we have the base address for the stack frame we can
      calculate the value of sp in the calling frame.  */
-  trad_frame_set_value (cache->saved_regs, E_SP_REGNUM,
-                       cache->base - cache->sp_offset);
+  cache->saved_regs[E_SP_REGNUM].set_value (cache->base - cache->sp_offset);
 
   /* Adjust all the saved registers such that they contain addresses
      instead of offsets.  */
-  for (i = 0; i < E_NUM_REGS; i++)
-    if (trad_frame_addr_p (cache->saved_regs, i))
-      cache->saved_regs[i].addr += cache->base;
+  for (i = 0; i < gdbarch_num_regs (gdbarch); i++)
+    if (cache->saved_regs[i].is_addr ())
+      cache->saved_regs[i].set_addr (cache->saved_regs[i].addr ()
+                                    + cache->base);
 
   /* The call instruction moves the caller's PC in the callee's LP.
      Since this is an unwind, do the reverse.  Copy the location of LP
@@ -917,39 +1319,19 @@ v850_frame_this_id (struct frame_info *this_frame, void **this_cache,
   if (cache->base == 0)
     return;
 
-  *this_id = frame_id_build (cache->saved_regs[E_SP_REGNUM].addr, cache->pc);
+  *this_id = frame_id_build (cache->saved_regs[E_SP_REGNUM].addr (), cache->pc);
 }
 
 static const struct frame_unwind v850_frame_unwind = {
+  "v850 prologue",
   NORMAL_FRAME,
+  default_frame_unwind_stop_reason,
   v850_frame_this_id,
   v850_frame_prev_register,
   NULL,
   default_frame_sniffer
 };
 
-static CORE_ADDR
-v850_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  return frame_unwind_register_unsigned (next_frame,
-                                        gdbarch_sp_regnum (gdbarch));
-} 
-
-static CORE_ADDR
-v850_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  return frame_unwind_register_unsigned (next_frame,
-                                        gdbarch_pc_regnum (gdbarch));
-}
-
-static struct frame_id
-v850_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
-{
-  CORE_ADDR sp = get_frame_register_unsigned (this_frame,
-                                             gdbarch_sp_regnum (gdbarch));
-  return frame_id_build (sp, get_frame_pc (this_frame));
-}
-  
 static CORE_ADDR
 v850_frame_base_address (struct frame_info *this_frame, void **this_cache)
 {
@@ -969,25 +1351,76 @@ static struct gdbarch *
 v850_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 {
   struct gdbarch *gdbarch;
+  int e_flags, e_machine;
 
-  /* Change the register names based on the current machine type.  */
-  if (info.bfd_arch_info->arch != bfd_arch_v850)
-    return NULL;
+  /* Extract the elf_flags if available.  */
+  if (info.abfd != NULL
+      && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour)
+    {
+      e_flags = elf_elfheader (info.abfd)->e_flags;
+      e_machine = elf_elfheader (info.abfd)->e_machine;
+    }
+  else
+    {
+      e_flags = 0;
+      e_machine = 0;
+    }
+
+
+  /* Try to find the architecture in the list of already defined
+     architectures.  */
+  for (arches = gdbarch_list_lookup_by_info (arches, &info);
+       arches != NULL;
+       arches = gdbarch_list_lookup_by_info (arches->next, &info))
+    {
+      v850_gdbarch_tdep *tdep
+       = (v850_gdbarch_tdep *) gdbarch_tdep (arches->gdbarch);
+
+      if (tdep->e_flags != e_flags || tdep->e_machine != e_machine)
+       continue;
+
+      return arches->gdbarch;
+    }
+
+  v850_gdbarch_tdep *tdep = new v850_gdbarch_tdep;
+  tdep->e_flags = e_flags;
+  tdep->e_machine = e_machine;
+
+  switch (tdep->e_machine)
+    {
+    case EM_V800:
+      tdep->abi = V850_ABI_RH850;
+      break;
+    default:
+      tdep->abi = V850_ABI_GCC;
+      break;
+    }
 
-  gdbarch = gdbarch_alloc (&info, NULL);
+  tdep->eight_byte_align = (tdep->e_flags & EF_RH850_DATA_ALIGN8) ? 1 : 0;
+  gdbarch = gdbarch_alloc (&info, tdep);
 
   switch (info.bfd_arch_info->mach)
     {
     case bfd_mach_v850:
       set_gdbarch_register_name (gdbarch, v850_register_name);
+      set_gdbarch_num_regs (gdbarch, E_NUM_OF_V850_REGS);
       break;
     case bfd_mach_v850e:
     case bfd_mach_v850e1:
       set_gdbarch_register_name (gdbarch, v850e_register_name);
+      set_gdbarch_num_regs (gdbarch, E_NUM_OF_V850E_REGS);
+      break;
+    case bfd_mach_v850e2:
+    case bfd_mach_v850e2v3:
+      set_gdbarch_register_name (gdbarch, v850e2_register_name);
+      set_gdbarch_num_regs (gdbarch, E_NUM_REGS);
+      break;
+    case bfd_mach_v850e3v5:
+      set_gdbarch_register_name (gdbarch, v850e3v5_register_name);
+      set_gdbarch_num_regs (gdbarch, E_NUM_OF_V850E3V5_REGS);
       break;
     }
 
-  set_gdbarch_num_regs (gdbarch, E_NUM_REGS);
   set_gdbarch_num_pseudo_regs (gdbarch, 0);
   set_gdbarch_sp_regnum (gdbarch, E_SP_REGNUM);
   set_gdbarch_pc_regnum (gdbarch, E_PC_REGNUM);
@@ -995,7 +1428,7 @@ v850_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   set_gdbarch_register_type (gdbarch, v850_register_type);
 
-  set_gdbarch_char_signed (gdbarch, 0);
+  set_gdbarch_char_signed (gdbarch, 1);
   set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT);
   set_gdbarch_int_bit (gdbarch, 4 * TARGET_CHAR_BIT);
   set_gdbarch_long_bit (gdbarch, 4 * TARGET_CHAR_BIT);
@@ -1009,18 +1442,14 @@ v850_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_addr_bit (gdbarch, 4 * TARGET_CHAR_BIT);
 
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
-  set_gdbarch_breakpoint_from_pc (gdbarch, v850_breakpoint_from_pc);
 
+  set_gdbarch_breakpoint_kind_from_pc (gdbarch, v850_breakpoint_kind_from_pc);
+  set_gdbarch_sw_breakpoint_from_kind (gdbarch, v850_sw_breakpoint_from_kind);
   set_gdbarch_return_value (gdbarch, v850_return_value);
   set_gdbarch_push_dummy_call (gdbarch, v850_push_dummy_call);
   set_gdbarch_skip_prologue (gdbarch, v850_skip_prologue);
 
-  set_gdbarch_print_insn (gdbarch, print_insn_v850);
-
   set_gdbarch_frame_align (gdbarch, v850_frame_align);
-  set_gdbarch_unwind_sp (gdbarch, v850_unwind_sp);
-  set_gdbarch_unwind_pc (gdbarch, v850_unwind_pc);
-  set_gdbarch_dummy_id (gdbarch, v850_dummy_id);
   frame_base_set_default (gdbarch, &v850_frame_base);
 
   /* Hook in ABI-specific overrides, if they have been registered.  */
@@ -1032,10 +1461,10 @@ v850_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   return gdbarch;
 }
 
-extern initialize_file_ftype _initialize_v850_tdep; /* -Wmissing-prototypes */
-
+void _initialize_v850_tdep ();
 void
-_initialize_v850_tdep (void)
+_initialize_v850_tdep ()
 {
   register_gdbarch_init (bfd_arch_v850, v850_gdbarch_init);
+  register_gdbarch_init (bfd_arch_v850_rh850, v850_gdbarch_init);
 }