public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 06/24]     mips-linux-nat: pick fp64 target description when appropriate
  2016-06-27 14:50 [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size Bhushan Attarde
  2016-06-27 14:50 ` [PATCH 10/24] MIPS: override fscr/fir types and print control registers specially Bhushan Attarde
  2016-06-27 14:50 ` [PATCH 08/24] MIPS: Convert FP mode to enum and put fp registers into fp reggroup Bhushan Attarde
@ 2016-06-27 14:50 ` Bhushan Attarde
  2016-06-27 14:50 ` [PATCH 03/24] regcache: handle invalidated regcache Bhushan Attarde
                   ` (18 subsequent siblings)
  21 siblings, 0 replies; 37+ messages in thread
From: Bhushan Attarde @ 2016-06-27 14:50 UTC (permalink / raw)
  To: gdb-patches
  Cc: Maciej.Rozycki, Matthew.Fortune, James.Hogan, Andrew.Bennett,
	Jaydeep.Patil, Bhushan Attarde

    This is decided by reading MIPS FIR register using prace and checking it's
    F64 bit.

    gdb/ChangeLog:

    * mips-linux-nat.c: Include "features/mips-fpu64-linux.c" and
    "features/mips-fpu64-dsp-linux.c".
    (FIR_F64): New definaition for F64 bit of FIR register.
    (supply_fpregset, fill_fpregset): Use 64-bit functions.
    (mips_linux_read_description): New have_fpu64 variable to indicate 64-bit
    FPU target.
    (initialize_tdesc_mips_fpu64_linux, initialize_tdesc_mips_fpu64_dsp_linux):
    Add initializer functions for fpu64 and fpu64_dsp targets.
---
 gdb/mips-linux-nat.c | 55 +++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 44 insertions(+), 11 deletions(-)

diff --git a/gdb/mips-linux-nat.c b/gdb/mips-linux-nat.c
index 627c652..543cc36 100644
--- a/gdb/mips-linux-nat.c
+++ b/gdb/mips-linux-nat.c
@@ -40,6 +40,8 @@
 
 #include "features/mips-linux.c"
 #include "features/mips-dsp-linux.c"
+#include "features/mips-fpu64-linux.c"
+#include "features/mips-fpu64-dsp-linux.c"
 #include "features/mips64-linux.c"
 #include "features/mips64-dsp-linux.c"
 
@@ -55,6 +57,8 @@
 #define PTRACE_SETREGSET	0x4205
 #endif
 
+#define FIR_F64	  (1 << 22)
+
 /* Assume that we have PTRACE_GETREGS et al. support.  If we do not,
    we'll clear this and use PTRACE_PEEKUSER instead.  */
 static int have_ptrace_regsets = 1;
@@ -203,22 +207,16 @@ fill_gregset (const struct regcache *regcache,
 void
 supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
 {
-  if (mips_isa_regsize (get_regcache_arch (regcache)) == 4)
-    mips_supply_fpregset (regcache, (const mips_elf_fpregset_t *) fpregsetp);
-  else
-    mips64_supply_fpregset (regcache,
-			    (const mips64_elf_fpregset_t *) fpregsetp);
+  mips64_supply_fpregset (regcache,
+			  (const mips64_elf_fpregset_t *) fpregsetp);
 }
 
 void
 fill_fpregset (const struct regcache *regcache,
 	       gdb_fpregset_t *fpregsetp, int regno)
 {
-  if (mips_isa_regsize (get_regcache_arch (regcache)) == 4)
-    mips_fill_fpregset (regcache, (mips_elf_fpregset_t *) fpregsetp, regno);
-  else
-    mips64_fill_fpregset (regcache,
-			  (mips64_elf_fpregset_t *) fpregsetp, regno);
+  mips64_fill_fpregset (regcache,
+			(mips64_elf_fpregset_t *) fpregsetp, regno);
 }
 
 
@@ -604,8 +602,41 @@ mips_linux_register_u_offset (struct gdbarch *gdbarch, int regno, int store_p)
 static const struct target_desc *
 mips_linux_read_description (struct target_ops *ops)
 {
+  const struct target_desc *tdescs[2][2] =
+    {
+	/* have_fpu64 = 0	have_fpu64 = 1 */
+	{ tdesc_mips_linux,	tdesc_mips_fpu64_linux },     /* have_dsp = 0 */
+	{ tdesc_mips_dsp_linux,	tdesc_mips_fpu64_dsp_linux }, /* have_dsp = 1 */
+    };
+
   static int have_dsp = -1;
+  static int have_fpu64 = -1;
 
+  if (have_fpu64 < 0)
+    {
+      int tid;
+      long fir;
+
+      tid = ptid_get_lwp (inferior_ptid);
+      if (tid == 0)
+	tid = ptid_get_pid (inferior_ptid);
+
+      /* Try peeking at FIR.F64 bit */
+      errno = 0;
+      fir = ptrace (PTRACE_PEEKUSER, tid, FPC_EIR, 0);
+      switch (errno)
+	{
+	case 0:
+	  have_fpu64 = !!(fir & FIR_F64);
+	  break;
+	case EIO:
+	  have_fpu64 = 0;
+	  break;
+	default:
+	  perror_with_name ("ptrace");
+	  break;
+	}
+    }
   if (have_dsp < 0)
     {
       int tid;
@@ -633,7 +664,7 @@ mips_linux_read_description (struct target_ops *ops)
   /* Report that target registers are a size we know for sure
      that we can get from ptrace.  */
   if (_MIPS_SIM == _ABIO32)
-    return have_dsp ? tdesc_mips_dsp_linux : tdesc_mips_linux;
+    return tdescs[have_dsp][have_fpu64];
   else
     return have_dsp ? tdesc_mips64_dsp_linux : tdesc_mips64_linux;
 }
@@ -990,6 +1021,8 @@ triggers a breakpoint or watchpoint."),
   /* Initialize the standard target descriptions.  */
   initialize_tdesc_mips_linux ();
   initialize_tdesc_mips_dsp_linux ();
+  initialize_tdesc_mips_fpu64_linux ();
+  initialize_tdesc_mips_fpu64_dsp_linux ();
   initialize_tdesc_mips64_linux ();
   initialize_tdesc_mips64_dsp_linux ();
 }
-- 
1.9-rc2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 11/24]     MIPS: Add support for hybrid fp32/fp64 mode
  2016-06-27 14:50 [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size Bhushan Attarde
                   ` (3 preceding siblings ...)
  2016-06-27 14:50 ` [PATCH 03/24] regcache: handle invalidated regcache Bhushan Attarde
@ 2016-06-27 14:50 ` Bhushan Attarde
  2016-06-27 14:51 ` [PATCH 04/24] Add MIPS Config5 register related support Bhushan Attarde
                   ` (16 subsequent siblings)
  21 siblings, 0 replies; 37+ messages in thread
From: Bhushan Attarde @ 2016-06-27 14:50 UTC (permalink / raw)
  To: gdb-patches
  Cc: Maciej.Rozycki, Matthew.Fortune, James.Hogan, Andrew.Bennett,
	Jaydeep.Patil, Bhushan Attarde

    Add support for the new hybrid fp32/fp64 mode, which is intended to allow
    fp32 (which requires FR=0) and MSA code (which requires FR=1) to coexist
    in the same process. It is determined by the FRE bit in the Config5
    register, which causes single-precision instructions to trap so that the
    kernel can emulate them using the FR=0 aliasing of singles in even
    doubles.

    When FR=1 and FRE=1:
    - Even FP registers can be interpreted as a double, or a single (aliasing
      the least significant half of the double).
    - Odd FP registers can be interpreted as a double, or a single (aliasing
      the most significant half of the even double).

    The even registers can use the existing fp64 type, however a new type is
    required for the odd FP registers when FRE=1, since the single and double
    interpretations don't alias. It is equivalent to this C definition:
      struct fp96 {
         union {
             double f64;
             int64  i64;
         };
         union {
             float  f32;
             int32  i32;
         };
      };

    For example:
      (gdb) info float
      ...
      f30: 0x41f8000041f00000 flt: 30                dbl: 6442451998.9999998
      f31: 0x403f000000000000 flt: 31                dbl: 31
      (gdb) p $f30
      $1 = {f32 = 30, f64 = 6442451998.9999998,
            i32 = 1106247680, i64 = 4753549407795806208}
      (gdb) p $f31
      $2 = {f32 = 31, f64 = 31,
            i32 = 1106771968, i64 = 4629418941960159232}

    gdb/ChangeLog:

        * mips-linux-tdep.c (mips_linux_init_abi): Drop fixed register
        mode.
    	* mips-tdep.c (CONF5_FRE): New define.
    	(mips_set_float_regsize): Detect MIPS_FPU_HYBRID from Config5.FRE.
    	(mips_float_regsize, mips_get_fp_single_location): Handle
    	MIPS_FPU_HYBRID.
    	(mips_get_fp_multi_location, mips_pseudo_register_read,
    	mips_pseudo_register_write, mips_convert_register_p,
    	mips_register_to_value, mips_value_to_register, mips_fp_type,
    	mips_read_fp_register_single): Handle fp96.
    	(mips_float_hybrid, mips_convert_register_float_fre_case_p,
    	mips_fp96_type): New function.
    	(mips_gdbarch_init): Initialise tdep->fp96_type.
        (mips_register_type, mips_print_fp_register): Use
        mips_float_regsize to decide size of fp registers.
    	* mips-tdep.h (enum mips_fpu_mode): Add MIPS_FPU_HYBRID.
    	(struct gdbarch_tdep): Update fp_mode comment, add fp96_type.
---
 gdb/mips-linux-tdep.c |   1 -
 gdb/mips-tdep.c       | 182 +++++++++++++++++++++++++++++++++++++++++---------
 gdb/mips-tdep.h       |   7 +-
 3 files changed, 157 insertions(+), 33 deletions(-)

diff --git a/gdb/mips-linux-tdep.c b/gdb/mips-linux-tdep.c
index da5ccc0..d337a5b 100644
--- a/gdb/mips-linux-tdep.c
+++ b/gdb/mips-linux-tdep.c
@@ -1725,7 +1725,6 @@ mips_linux_init_abi (struct gdbarch_info info,
 				    mips_gdb_signal_to_target);
 
   tdep->syscall_next_pc = mips_linux_syscall_next_pc;
-  tdep->fp_register_mode_fixed_p = 1;
 
   if (((struct gdbarch_tdep_info*)(info.tdep_info))->tdesc_data)
     {
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index 2cc49aa..13c1532 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -78,6 +78,10 @@ static void mips_print_float_info (struct gdbarch *, struct ui_file *,
 /* This bit is set if we are emulating 32-bit FPRs on a 64-bit chip.  */
 #define ST0_FR (1 << 26)
 
+/* A useful bit in the CP0 Config5 register.
+   This bit is set in hybrid 64-bit FPR mode.  */
+#define CONF5_FRE (1 << 8)
+
 /* The sizes of floating point registers.  */
 
 enum
@@ -307,29 +311,36 @@ mips_set_float_regsize (struct gdbarch *gdbarch, struct regcache *regcache)
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   struct gdbarch_tdep_info tdep_info = { NULL };
   struct gdbarch_info info;
-  int fpsize;
   enum mips_fpu_mode fp_mode;
+  enum register_status status;
+  ULONGEST sr, config5;
 
   if (tdep->fp_register_mode_fixed_p)
     return 0;
 
-  fpsize = mips_isa_regsize (gdbarch);
-  fp_mode = fpsize == 8 ? MIPS_FPU_64 : MIPS_FPU_32;
-  if (fpsize == 8)
-    {
-      enum register_status status;
-      ULONGEST sr;
+  status = regcache_raw_read_unsigned (regcache, MIPS_PS_REGNUM, &sr);
+  if (status == REG_VALID)
+    fp_mode = (sr & ST0_FR) ? MIPS_FPU_64 : MIPS_FPU_32;
+  else
+    fp_mode = mips_isa_regsize (gdbarch) == 8 ? MIPS_FPU_64 : MIPS_FPU_32;
 
-      status = regcache_raw_read_unsigned (regcache, MIPS_PS_REGNUM, &sr);
-      if (status == REG_VALID)
-	fp_mode = (sr & ST0_FR) ? MIPS_FPU_64 : MIPS_FPU_32;
+  if (fp_mode == MIPS_FPU_64 && mips_regnum (gdbarch)->config5 >= 0)
+    {
+      /* Find out if FRE is set */
+      status = regcache_raw_read_unsigned (regcache,
+					   mips_regnum (gdbarch)->config5,
+					   &config5);
+      if (status == REG_VALID && config5 & CONF5_FRE)
+	fp_mode = MIPS_FPU_HYBRID;
     }
 
   if (fp_mode == tdep->fp_mode)
     return 0;
 
-  /* Need a new gdbarch, go get one.  */
+  /* Need a new gdbarch, go get one.
+     Be careful to preserve target description. */
   gdbarch_info_init (&info);
+  info.target_desc = target_current_description ();
   info.tdep_info = &tdep_info;
   ((struct gdbarch_tdep_info*)(info.tdep_info))->fp_mode = fp_mode;
   gdbarch_update_p (info);
@@ -347,12 +358,22 @@ mips_float_regsize (struct gdbarch *gdbarch)
     case MIPS_FPU_32:
       return 4;
     case MIPS_FPU_64:
+    case MIPS_FPU_HYBRID:
       return 8;
     default:
       return 0;
     }
 }
 
+/* Return whether the FPU is currently in hybrid 64-bit mode (where odd singles
+   are found in the top half of the 64-bit even FP registers.  */
+
+static int
+mips_float_hybrid (struct gdbarch *gdbarch)
+{
+  return gdbarch_tdep (gdbarch)->fp_mode == MIPS_FPU_HYBRID;
+}
+
 /* MIPS16/microMIPS function addresses are odd (bit 0 is set).  Here
    are some functions to handle addresses associated with compressed
    code including but not limited to testing, setting, or clearing
@@ -835,6 +856,7 @@ mips_get_fp_single_location (struct gdbarch *gdbarch,
   switch (fp_mode)
     {
     case MIPS_FPU_32:
+    case MIPS_FPU_HYBRID:
       loc->regnum = raw_num + (idx & ~1);
       loc->offset = 4 * (big_endian ^ (idx & 1));
       return 1;
@@ -892,7 +914,7 @@ mips_get_fp_double_location (struct gdbarch *gdbarch,
 }
 
 /* Get the raw register part(s) composing a cooked float register.
-   Returns the number of parts (maximum 2) written through loc.	 */
+   Returns the number of parts (maximum 3) written through loc.	 */
 
 static unsigned int
 mips_get_fp_multi_location (struct gdbarch *gdbarch,
@@ -904,8 +926,9 @@ mips_get_fp_multi_location (struct gdbarch *gdbarch,
 
   /* The cooked formats supported are:
      fp32 (len=4):  just a single.
-     fp64 (len=8):  double (with aliased single).  */
-  if (cooked_len > 8 || cooked_len < 4 || cooked_len & 0x3)
+     fp64 (len=8):  double (with aliased single).
+     fp96 (len=12): consecutive double and single.  */
+  if (cooked_len > 12 || cooked_len < 4 || cooked_len & 0x3)
     internal_error (__FILE__, __LINE__, _("bad cooked register size"));
 
   /* Formats containing a distinct double.  */
@@ -988,7 +1011,7 @@ mips_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 
   if (mips_float_register_p (gdbarch, rawnum))
     {
-      struct mips_reg_part loc[2];
+      struct mips_reg_part loc[3];
       unsigned int parts;
 
       fpnum = rawnum - mips_regnum (gdbarch)->fp0;
@@ -1034,7 +1057,7 @@ mips_pseudo_register_write (struct gdbarch *gdbarch,
 
   if (mips_float_register_p (gdbarch, rawnum))
     {
-      struct mips_reg_part loc[2];
+      struct mips_reg_part loc[3];
       unsigned int parts;
 
       fpnum = rawnum - mips_regnum (gdbarch)->fp0;
@@ -1149,6 +1172,20 @@ mips_convert_register_float_case_p (struct gdbarch *gdbarch, int regnum,
 	  && TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) == 4);
 }
 
+/* This predicate tests for the case of a 4 or 8 byte floating point
+   value that is being transferred to or from a floating point
+   register which is 12 bytes wide (containing both single and double).  */
+
+static int
+mips_convert_register_float_fre_case_p (struct gdbarch *gdbarch,
+					int regnum, struct type *type)
+{
+  return (register_size (gdbarch, regnum) == 12
+	  && mips_float_register_p (gdbarch, regnum)
+	  && TYPE_CODE (type) == TYPE_CODE_FLT
+          && (TYPE_LENGTH (type) == 4 || TYPE_LENGTH (type) == 8));
+}
+
 /* This predicate tests for the case of a value of less than 8
    bytes in width that is being transfered to or from an 8 byte
    general purpose register.  */
@@ -1168,6 +1205,7 @@ mips_convert_register_p (struct gdbarch *gdbarch,
 			 int regnum, struct type *type)
 {
   return (mips_convert_register_float_case_p (gdbarch, regnum, type)
+	  || mips_convert_register_float_fre_case_p (gdbarch, regnum, type)
 	  || mips_convert_register_gpreg_case_p (gdbarch, regnum, type));
 }
 
@@ -1196,6 +1234,26 @@ mips_register_to_value (struct frame_info *frame, int regnum,
       *optimizedp = *unavailablep = 0;
       return 1;
     }
+  else if (mips_convert_register_float_fre_case_p (gdbarch, regnum, type))
+    {
+      int len = TYPE_LENGTH (type);
+      if (len == 8)
+	{
+	  /* double comes first */
+	  if (!get_frame_register_bytes (frame, regnum, 0, 8, to,
+					 optimizedp, unavailablep))
+	    return 0;
+	}
+      else
+	{
+	  /* followed by single */
+	  if (!get_frame_register_bytes (frame, regnum, 8, 4, to,
+					 optimizedp, unavailablep))
+	    return 0;
+	}
+      *optimizedp = *unavailablep = 0;
+      return 1;
+    }
   else if (mips_convert_register_gpreg_case_p (gdbarch, regnum, type))
     {
       int len = TYPE_LENGTH (type);
@@ -1314,6 +1372,56 @@ mips_fp64_type (struct gdbarch *gdbarch)
   return tdep->fp64_type;
 }
 
+/* Get FRE odd floating point type, which can contains separate single and
+   double precision floats, or a separate 32-bit or 64-bit signed integer.
+   This is used for odd fp registers when FR=1 and FRE=1 (the odd single comes
+   from the upper half of the even double, so odd singles and odd doubles do not
+   overlap).  */
+
+static struct type *
+mips_fp96_type (struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (tdep->fp96_type == NULL)
+    {
+      const struct builtin_type *bt = builtin_type (gdbarch);
+      struct type *t;
+      struct field *f;
+
+      /* The type we're building is roughly this:
+
+      struct __gdb_builtin_mips_fp96 {
+	  union {
+	      double f64;
+	      int64  i64;
+	  };
+	  union {
+	      float  f32;
+	      int32  i32;
+	  };
+      }; */
+
+
+      t = arch_composite_type (gdbarch, "__gdb_builtin_type_mips_fp96",
+			       TYPE_CODE_STRUCT);
+      f = append_composite_type_field_raw (t, "f32", bt->builtin_float);
+      SET_FIELD_BITPOS (*f, 64);
+      f = append_composite_type_field_raw (t, "f64", bt->builtin_double);
+      SET_FIELD_BITPOS (*f, 0);
+      f = append_composite_type_field_raw (t, "i32", bt->builtin_int32);
+      SET_FIELD_BITPOS (*f, 64);
+      f = append_composite_type_field_raw (t, "i64", bt->builtin_int64);
+      SET_FIELD_BITPOS (*f, 0);
+
+      TYPE_LENGTH (t) = 12;
+      TYPE_NAME (t) = "fp96";
+      tdep->fp96_type = t;
+    }
+
+  return tdep->fp96_type;
+}
+
 /* Get the floating point type for an arbitrary FP register. This returns the
    appropriate type depending on the possible types and overlaps of the
    register.  */
@@ -1321,9 +1429,12 @@ mips_fp64_type (struct gdbarch *gdbarch)
 static struct type *
 mips_fp_type (struct gdbarch *gdbarch, int fpnum)
 {
-  if ((fpnum & 1) == 0 || mips_float_regsize (gdbarch) == 8)
+  if ((fpnum & 1) == 1 && mips_float_hybrid (gdbarch) )
+    /* 64-bit hybrid registers: odd singles and doubles don't overlap.  */
+    return mips_fp96_type (gdbarch);
+  else if ((fpnum & 1) == 0 || mips_float_regsize (gdbarch) == 8)
     /* Even singles and doubles always overlap, as do odd singles and
-       doubles when FR=1.  */
+       doubles when FR=1 (and FRE=0).  */
     return mips_fp64_type (gdbarch);
   else
     /* 32-bit odd singles (there are no odd doubles).  */
@@ -1517,6 +1628,16 @@ mips_value_to_register (struct frame_info *frame, int regnum,
       else
 	put_frame_register_bytes (frame, regnum, 0, 4, from);
     }
+  else if (mips_convert_register_float_fre_case_p (gdbarch, regnum, type))
+    {
+      int len = TYPE_LENGTH (type);
+      if (len == 8)
+	  /* double goes first */
+	  put_frame_register_bytes (frame, regnum, 0, 8, from);
+      else
+	  /* followed by single */
+	  put_frame_register_bytes (frame, regnum, 8, 4, from);
+    }
   else if (mips_convert_register_gpreg_case_p (gdbarch, regnum, type))
     {
       gdb_byte fill[8];
@@ -1564,11 +1685,12 @@ mips_register_type (struct gdbarch *gdbarch, int regnum)
   if (regnum < gdbarch_num_regs (gdbarch))
     {
       /* The raw or ISA registers.  These are all sized according to
-	 the ISA regsize.  */
+	 the ISA regsize, except FP registers which may be double
+	 even on MIPS32 since rev 2 of the architecture.  */
       int regsize = mips_isa_regsize (gdbarch);
 
       if (mips_float_register_p (gdbarch, regnum))
-	return (regsize == 4
+	return (mips_float_regsize (gdbarch) == 4
 		? builtin_type (gdbarch)->builtin_float
 		: builtin_type (gdbarch)->builtin_double);
       else
@@ -6776,8 +6898,12 @@ mips_read_fp_register_single (struct frame_info *frame, int regno,
   if (!deprecated_frame_register_read (frame, regno, raw_buffer))
     return 0;
 
-  if (cooked_size == 8)
-    /* FR=1
+  if (cooked_size == 12)
+    /* FR=1, FRE=1
+       Single is after double. */
+    memcpy(rare_buffer, raw_buffer+8, 8);
+  else if (cooked_size == 8)
+    /* FR=1, FRE=0
        Single is overlapping double. */
     memcpy(rare_buffer, raw_buffer + 4*big_endian, 4);
   else
@@ -6814,7 +6940,7 @@ mips_print_fp_register (struct ui_file *file, struct frame_info *frame,
 			int regnum)
 {				/* Do values for FP (float) regs.  */
   struct gdbarch *gdbarch = get_frame_arch (frame);
-  int fpsize = register_size (gdbarch, regnum);
+  int fpsize = mips_float_regsize (gdbarch);
   gdb_byte *raw_buffer;
   double doub, flt1;	/* Doubles extracted from raw hex data.  */
   int res1, res2, inv1, inv2;
@@ -8910,7 +9036,6 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       const struct tdesc_feature *feature;
       int valid_p;
       int fpsize;
-      enum mips_fpu_mode fpmode;
 
       feature = tdesc_find_feature (info.target_desc,
 				    "org.gnu.gdb.mips.cpu");
@@ -8983,12 +9108,11 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
          supplied the description got the current setting right wrt
          CP0 Status register's bit FR if applicable.  */
       fpsize = tdesc_register_size (feature, mips_fprs[0]) / 8;
-      fpmode = (fpsize == 8) ? MIPS_FPU_64 : MIPS_FPU_32;
 
       /* Only accept a description whose floating-point register size
          matches the requested size or if none was specified.  */
-      valid_p = (info.tdep_info->fp_mode == MIPS_FPU_UNKNOWN
-		 || info.tdep_info->fp_mode == fpmode);
+      valid_p = 1;
+
       for (i = 0; i < 32; i++)
 	valid_p &= tdesc_numbered_register (feature, tdesc_data,
 					    i + mips_regnum.fp0, mips_fprs[i]);
@@ -9043,9 +9167,6 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 	    }
 	}
 
-      /* Fix the floating-point register mode found.  */
-      info.tdep_info->fp_mode = fpmode;
-
       /* It would be nice to detect an attempt to use a 64-bit ABI
 	 when only 32-bit registers are provided.  */
       reg_names = NULL;
@@ -9287,6 +9408,7 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->fp_ir_type = NULL;
   tdep->fp32_type = NULL;
   tdep->fp64_type = NULL;
+  tdep->fp96_type = NULL;
 
   if (info.target_desc)
     {
diff --git a/gdb/mips-tdep.h b/gdb/mips-tdep.h
index ad5cba3..110eb6c 100644
--- a/gdb/mips-tdep.h
+++ b/gdb/mips-tdep.h
@@ -89,6 +89,8 @@ enum mips_fpu_mode
   MIPS_FPU_UNKNOWN = 0,
   MIPS_FPU_32,		/* FR=0, 32bit FP regs, doubles in pairs.  */
   MIPS_FPU_64,		/* FR=1, 64bit FP regs.  */
+  MIPS_FPU_HYBRID,	/* FR=1, FRE=1, 64bit FP regs, odd singles in upper half
+			   of even doubles.  */
 };
 
 /* MIPS specific per-architecture information.  */
@@ -123,8 +125,8 @@ struct gdbarch_tdep
   int register_size;
 
   /* The floating-point register mode determined at run time.
-     This corresponds to CP0 Status register's FR bit unless fixed_p is
-     set.  */
+     This corresponds to CP0 Status register's FR bit and Config5's FRE bit
+     unless fixed_p is set.  */
   int fp_register_mode_fixed_p;
   enum mips_fpu_mode fp_mode;
 
@@ -136,6 +138,7 @@ struct gdbarch_tdep
   struct type *fp_ir_type;
   struct type *fp32_type;
   struct type *fp64_type;
+  struct type *fp96_type;
 
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
-- 
1.9-rc2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 08/24]     MIPS: Convert FP mode to enum and put fp registers into fp reggroup
  2016-06-27 14:50 [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size Bhushan Attarde
  2016-06-27 14:50 ` [PATCH 10/24] MIPS: override fscr/fir types and print control registers specially Bhushan Attarde
@ 2016-06-27 14:50 ` Bhushan Attarde
  2016-06-27 14:50 ` [PATCH 06/24] mips-linux-nat: pick fp64 target description when appropriate Bhushan Attarde
                   ` (19 subsequent siblings)
  21 siblings, 0 replies; 37+ messages in thread
From: Bhushan Attarde @ 2016-06-27 14:50 UTC (permalink / raw)
  To: gdb-patches
  Cc: Maciej.Rozycki, Matthew.Fortune, James.Hogan, Andrew.Bennett,
	Jaydeep.Patil, Bhushan Attarde

    Convert FP mode representation from a register size to an enum, in order
    to allow for more FP modes with the same register size, namely FR=1 &&
    FRE=1, where FP registers are 64-bits, but odd singles reside in the upper
    half of even doubles.

    gdb/ChangeLog:

    	* mips-linux-tdep.c (mips_linux_init_abi): Rename
    	fp_register_size_fixed_p to fp_register_mode_fixed_p.
    	* mips-tdep.c (mips_set_float_regsize, mips_float_regsize,
    	mips_gdbarch_init): Rename fp_register_size_fixed_p to
    	fp_register_mode_fixed_p and convert fp_register_size to fp_mode
    	enum.
        (mips_register_reggroup_p): Put fp registers into fp reggroup.
    	* mips-tdep.h (enum mips_fpu_mode): New definition.
    	(struct gdbarch_tdep): Rename fp_register_size_fixed_p to
    	fp_register_mode_fixed_p and convert fp_register_size to fp_mode
    	enum.
    	(struct gdbarch_tdep_info): Convert fp_register_size to fp_mode
    	enum.
---
 gdb/mips-linux-tdep.c |  2 +-
 gdb/mips-tdep.c       | 50 ++++++++++++++++++++++++++++++++------------------
 gdb/mips-tdep.h       | 21 ++++++++++++++-------
 3 files changed, 47 insertions(+), 26 deletions(-)

diff --git a/gdb/mips-linux-tdep.c b/gdb/mips-linux-tdep.c
index 82b8127..da5ccc0 100644
--- a/gdb/mips-linux-tdep.c
+++ b/gdb/mips-linux-tdep.c
@@ -1725,7 +1725,7 @@ mips_linux_init_abi (struct gdbarch_info info,
 				    mips_gdb_signal_to_target);
 
   tdep->syscall_next_pc = mips_linux_syscall_next_pc;
-  tdep->fp_register_size_fixed_p = 1;
+  tdep->fp_register_mode_fixed_p = 1;
 
   if (((struct gdbarch_tdep_info*)(info.tdep_info))->tdesc_data)
     {
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index 61b560c..47ddef4 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -298,7 +298,7 @@ mips_abi_regsize (struct gdbarch *gdbarch)
    As the CP0 Status register's bit FR cannot be modified on processors
    that do not implement an FPU, backends for operating systems that
    can emulate the FPU in software should set the size according to the
-   ABI in use and then set fp_register_size_fixed_p to 1 to prevent
+   ABI in use and then set fp_register_mode_fixed_p to 1 to prevent
    further updates.  */
 
 static int
@@ -308,11 +308,13 @@ mips_set_float_regsize (struct gdbarch *gdbarch, struct regcache *regcache)
   struct gdbarch_tdep_info tdep_info = { NULL };
   struct gdbarch_info info;
   int fpsize;
+  enum mips_fpu_mode fp_mode;
 
-  if (tdep->fp_register_size_fixed_p)
+  if (tdep->fp_register_mode_fixed_p)
     return 0;
 
   fpsize = mips_isa_regsize (gdbarch);
+  fp_mode = fpsize == 8 ? MIPS_FPU_64 : MIPS_FPU_32;
   if (fpsize == 8)
     {
       enum register_status status;
@@ -320,16 +322,16 @@ mips_set_float_regsize (struct gdbarch *gdbarch, struct regcache *regcache)
 
       status = regcache_raw_read_unsigned (regcache, MIPS_PS_REGNUM, &sr);
       if (status == REG_VALID)
-	fpsize = (sr & ST0_FR) ? 8 : 4;
+	fp_mode = (sr & ST0_FR) ? MIPS_FPU_64 : MIPS_FPU_32;
     }
 
-  if (fpsize == tdep->fp_register_size)
+  if (fp_mode == tdep->fp_mode)
     return 0;
 
   /* Need a new gdbarch, go get one.  */
   gdbarch_info_init (&info);
   info.tdep_info = &tdep_info;
-  info.tdep_info->fp_register_size = fpsize;
+  ((struct gdbarch_tdep_info*)(info.tdep_info))->fp_mode = fp_mode;
   gdbarch_update_p (info);
 
   return 1;
@@ -340,7 +342,15 @@ mips_set_float_regsize (struct gdbarch *gdbarch, struct regcache *regcache)
 static int
 mips_float_regsize (struct gdbarch *gdbarch)
 {
-  return gdbarch_tdep (gdbarch)->fp_register_size;
+  switch (gdbarch_tdep (gdbarch)->fp_mode)
+    {
+    case MIPS_FPU_32:
+      return 4;
+    case MIPS_FPU_64:
+      return 8;
+    default:
+      return 0;
+    }
 }
 
 /* MIPS16/microMIPS function addresses are odd (bit 0 is set).  Here
@@ -724,7 +734,9 @@ mips_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
   if (reggroup == all_reggroup)
     return pseudo;
   vector_p = TYPE_VECTOR (register_type (gdbarch, regnum));
-  float_p = TYPE_CODE (register_type (gdbarch, regnum)) == TYPE_CODE_FLT;
+  float_p = (mips_float_register_p (gdbarch, rawnum) ||
+	     rawnum == mips_regnum (gdbarch)->fp_control_status ||
+	     rawnum == mips_regnum (gdbarch)->fp_implementation_revision);
   /* FIXME: cagney/2003-04-13: Can't yet use gdbarch_num_regs
      (gdbarch), as not all architectures are multi-arch.  */
   raw_p = rawnum < gdbarch_num_regs (gdbarch);
@@ -8333,6 +8345,7 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       const struct tdesc_feature *feature;
       int valid_p;
       int fpsize;
+      enum mips_fpu_mode fpmode;
 
       feature = tdesc_find_feature (info.target_desc,
 				    "org.gnu.gdb.mips.cpu");
@@ -8405,11 +8418,12 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
          supplied the description got the current setting right wrt
          CP0 Status register's bit FR if applicable.  */
       fpsize = tdesc_register_size (feature, mips_fprs[0]) / 8;
+      fpmode = (fpsize == 8) ? MIPS_FPU_64 : MIPS_FPU_32;
 
       /* Only accept a description whose floating-point register size
          matches the requested size or if none was specified.  */
-      valid_p = (info.tdep_info->fp_register_size == 0
-		 || info.tdep_info->fp_register_size == fpsize);
+      valid_p = (info.tdep_info->fp_mode == MIPS_FPU_UNKNOWN
+		 || info.tdep_info->fp_mode == fpmode);
       for (i = 0; i < 32; i++)
 	valid_p &= tdesc_numbered_register (feature, tdesc_data,
 					    i + mips_regnum.fp0, mips_fprs[i]);
@@ -8464,8 +8478,8 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 	    }
 	}
 
-      /* Fix the floating-point register size found.  */
-      info.tdep_info->fp_register_size = fpsize;
+      /* Fix the floating-point register mode found.  */
+      info.tdep_info->fp_mode = fpmode;
 
       /* It would be nice to detect an attempt to use a 64-bit ABI
 	 when only 32-bit registers are provided.  */
@@ -8678,9 +8692,9 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       if (gdbarch_tdep (arches->gdbarch)->mips_fpu_type != fpu_type)
 	continue;
       /* Ditto the requested floating-point register size if any.  */
-      if (info.tdep_info->fp_register_size != 0
-	  && (gdbarch_tdep (arches->gdbarch)->fp_register_size)
-	      != info.tdep_info->fp_register_size)
+      if (((struct gdbarch_tdep_info*)(info.tdep_info))->fp_mode != MIPS_FPU_UNKNOWN
+	  && (gdbarch_tdep (arches->gdbarch)->fp_mode)
+	      != ((struct gdbarch_tdep_info*)(info.tdep_info))->fp_mode)
 	continue;
 
       if (tdesc_data != NULL)
@@ -8699,8 +8713,8 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->mips_fpu_type = fpu_type;
   tdep->register_size_valid_p = 0;
   tdep->register_size = 0;
-  tdep->fp_register_size = info.tdep_info->fp_register_size;
-  tdep->fp_register_size_fixed_p = 0;
+  tdep->fp_mode = ((struct gdbarch_tdep_info*)(info.tdep_info))->fp_mode;
+  tdep->fp_register_mode_fixed_p = 0;
   tdep->config5_type = NULL;
 
   if (info.target_desc)
@@ -8721,8 +8735,8 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* If we haven't figured out the size of floating-point registers
      by now yet, then assume it is the same as for general-purpose
      registers.  */
-  if (tdep->fp_register_size == 0)
-    tdep->fp_register_size = mips_isa_regsize (gdbarch);
+  if (tdep->fp_mode == MIPS_FPU_UNKNOWN)
+    tdep->fp_mode = mips_isa_regsize (gdbarch) == 8 ? MIPS_FPU_64 : MIPS_FPU_32;
 
   /* Initially set everything according to the default ABI/ISA.  */
   set_gdbarch_short_bit (gdbarch, 16);
diff --git a/gdb/mips-tdep.h b/gdb/mips-tdep.h
index 97bfab3..b6f99f2 100644
--- a/gdb/mips-tdep.h
+++ b/gdb/mips-tdep.h
@@ -84,6 +84,13 @@ enum mips_fpu_type
   MIPS_FPU_NONE			/* No floating point.  */
 };
 
+enum mips_fpu_mode
+{
+  MIPS_FPU_UNKNOWN = 0,
+  MIPS_FPU_32,		/* FR=0, 32bit FP regs, doubles in pairs.  */
+  MIPS_FPU_64,		/* FR=1, 64bit FP regs.  */
+};
+
 /* MIPS specific per-architecture information.  */
 struct gdbarch_tdep
 {
@@ -115,11 +122,11 @@ struct gdbarch_tdep
   int register_size_valid_p;
   int register_size;
 
-  /* The size of floating-point registers determined at the run time.
-     This corresponds to CP0 Status register's bit FR setting if
-     implemented unless fixed_p is set.  */
-  int fp_register_size_fixed_p;
-  int fp_register_size;
+  /* The floating-point register mode determined at run time.
+     This corresponds to CP0 Status register's FR bit unless fixed_p is
+     set.  */
+  int fp_register_mode_fixed_p;
+  enum mips_fpu_mode fp_mode;
 
   /* ISA-specific data types.  */
   struct type *config5_type;
@@ -135,8 +142,8 @@ struct gdbarch_tdep_info
   /* Target description data.  */
   struct tdesc_arch_data *tdesc_data;
 
-  /* The size of floating-point registers determined at the run time.  */
-  int fp_register_size;
+  /* The floating-point register mode determined at run time.  */
+  enum mips_fpu_mode fp_mode;
 };
 
 /* Register numbers of various important registers.  */
-- 
1.9-rc2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 10/24]     MIPS: override fscr/fir types and print control registers specially
  2016-06-27 14:50 [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size Bhushan Attarde
@ 2016-06-27 14:50 ` Bhushan Attarde
  2016-06-27 14:50 ` [PATCH 08/24] MIPS: Convert FP mode to enum and put fp registers into fp reggroup Bhushan Attarde
                   ` (20 subsequent siblings)
  21 siblings, 0 replies; 37+ messages in thread
From: Bhushan Attarde @ 2016-06-27 14:50 UTC (permalink / raw)
  To: gdb-patches
  Cc: Maciej.Rozycki, Matthew.Fortune, James.Hogan, Andrew.Bennett,
	Jaydeep.Patil, Bhushan Attarde

    Define types for the MIPS floating point status and control register and
    implementation register, allowing the fields to be decoded.

    gdb/ChangeLog:

        * mips-tdep.c (mips_frm_type, mips_fcflags_type, mips_fcsr_type,
        mips_fir_type): New functions.
        (mips_value_to_register): Return appropriat type for FP control
        and implementation revision register.
        (print_control_register): New function.
        (mips_print_register): Use print_control_register to print
        control registers.
        (print_control_register_row): New function.
        (mips_print_registers_info): Use print_control_register_row to
        print a single complex control register row.
        (mips_gdbarch_init): Initialize fp_rm_type, fp_cflags_type,
        fp_csr_type and fp_ir_type types.
        * mips-tdep.h (gdbarch_tdep): Add fp_rm_type, fp_cflags_type,
        fp_csr_type and fp_ir_type fields.
---
 gdb/mips-tdep.c | 262 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 gdb/mips-tdep.h |   4 +
 2 files changed, 261 insertions(+), 5 deletions(-)

diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index 0024edf..2cc49aa 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -1330,6 +1330,179 @@ mips_fp_type (struct gdbarch *gdbarch, int fpnum)
     return mips_fp32_type (gdbarch);
 }
 
+/* Get floating point rounding mode enumeration type */
+
+static struct type *
+mips_frm_type (struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (tdep->fp_rm_type == NULL)
+    {
+      const struct builtin_type *bt = builtin_type (gdbarch);
+      struct type *t;
+      struct field *f;
+
+      t = arch_type (gdbarch, TYPE_CODE_ENUM, 1, "__gdb_builtin_type_fp_rm");
+      TYPE_UNSIGNED (t) = 1;
+      f = append_composite_type_field_raw (t, "NEAREST", bt->builtin_uint8);
+      SET_FIELD_ENUMVAL (*f, 0);
+      f = append_composite_type_field_raw (t, "ZERO", bt->builtin_uint8);
+      SET_FIELD_ENUMVAL (*f, 1);
+      f = append_composite_type_field_raw (t, "INF", bt->builtin_uint8);
+      SET_FIELD_ENUMVAL (*f, 2);
+      f = append_composite_type_field_raw (t, "NINF", bt->builtin_uint8);
+      SET_FIELD_ENUMVAL (*f, 3);
+
+      tdep->fp_rm_type = t;
+    }
+  return tdep->fp_rm_type;
+}
+
+/* Get floating point condition flags type */
+
+static struct type *
+mips_fcflags_type (struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (tdep->fp_cflags_type == NULL)
+    {
+      struct type *t;
+
+      /* Flags, Enables, Cause have common set of condition flags */
+      t = arch_flags_type (gdbarch, "__gdb_builtin_type_fp_cflags", 1);
+      append_flags_type_flag (t, 0, "I");
+      append_flags_type_flag (t, 1, "U");
+      append_flags_type_flag (t, 2, "O");
+      append_flags_type_flag (t, 3, "Z");
+      append_flags_type_flag (t, 4, "V");
+      append_flags_type_flag (t, 5, "E"); /* Cause field only */
+
+      tdep->fp_cflags_type = t;
+    }
+  return tdep->fp_cflags_type;
+}
+
+static struct type *
+mips_fcsr_type (struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (tdep->fp_csr_type == NULL)
+    {
+      const struct builtin_type *bt = builtin_type (gdbarch);
+      struct type *t, *cflags, *flags;
+      struct field *f;
+
+      /* Flags, Enables, Cause have common set of condition flags */
+      cflags = mips_fcflags_type (gdbarch);
+
+      /* Various bits at top end */
+      flags = arch_flags_type (gdbarch, "__gdb_builtin_type_fp_csr_flags", 2);
+      append_flags_type_flag (flags, 0, "NAN2008");
+      append_flags_type_flag (flags, 1, "ABS2008");
+      append_flags_type_flag (flags, 2, "MAC2008");
+      append_flags_type_flag (flags, 3, "IMPL0");
+      append_flags_type_flag (flags, 4, "IMPL1");
+      append_flags_type_flag (flags, 5, "FCC0");
+      append_flags_type_flag (flags, 6, "FS");
+      append_flags_type_flag (flags, 7, "FCC1");
+      append_flags_type_flag (flags, 8, "FCC2");
+      append_flags_type_flag (flags, 9, "FCC3");
+      append_flags_type_flag (flags, 10, "FCC4");
+      append_flags_type_flag (flags, 11, "FCC5");
+      append_flags_type_flag (flags, 12, "FCC6");
+      append_flags_type_flag (flags, 13, "FCC7");
+
+      t = arch_composite_type (gdbarch, "__gdb_builtin_type_fp_csr",
+			       TYPE_CODE_STRUCT);
+
+      /* rounding mode */
+      f = append_composite_type_field_raw (t, "rm", mips_frm_type (gdbarch));
+      SET_FIELD_BITPOS (*f, 0);
+      FIELD_BITSIZE (*f) = 2;
+
+      f = append_composite_type_field_raw (t, "flags", cflags);
+      SET_FIELD_BITPOS (*f, 2);
+      FIELD_BITSIZE (*f) = 5;
+
+      f = append_composite_type_field_raw (t, "enables", cflags);
+      SET_FIELD_BITPOS (*f, 7);
+      FIELD_BITSIZE (*f) = 5;
+
+      f = append_composite_type_field_raw (t, "cause", cflags);
+      SET_FIELD_BITPOS (*f, 12);
+      FIELD_BITSIZE (*f) = 6;
+
+      f = append_composite_type_field_raw (t, "", flags);
+      SET_FIELD_BITPOS (*f, 18);
+      FIELD_BITSIZE (*f) = 14;
+
+      TYPE_LENGTH (t) = 4;
+      TYPE_NAME (t) = "fp_csr";
+      tdep->fp_csr_type = t;
+    }
+
+  return tdep->fp_csr_type;
+}
+
+static struct type *
+mips_fir_type (struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (tdep->fp_ir_type == NULL)
+    {
+      const struct builtin_type *bt = builtin_type (gdbarch);
+      struct type *t, *flags;
+      /* top half has flags */
+      flags = arch_flags_type (gdbarch, "__gdb_builtin_type_fp_ir_flags", 2);
+      append_flags_type_flag (flags, 0, "S");
+      append_flags_type_flag (flags, 1, "D");
+      append_flags_type_flag (flags, 2, "PS");
+      append_flags_type_flag (flags, 3, "3D");
+      append_flags_type_flag (flags, 4, "W");
+      append_flags_type_flag (flags, 5, "L");
+      append_flags_type_flag (flags, 6, "F64");
+      append_flags_type_flag (flags, 7, "HAS2008");
+      append_flags_type_flag (flags, 8, "IMPL0");
+      append_flags_type_flag (flags, 9, "IMPL1");
+      append_flags_type_flag (flags, 10, "IMPL2");
+      append_flags_type_flag (flags, 11, "IMPL3");
+      append_flags_type_flag (flags, 12, "UFRP");
+      append_flags_type_flag (flags, 13, "FREP");
+
+      t = arch_composite_type (gdbarch, "__gdb_builtin_type_fp_ir",
+			       TYPE_CODE_STRUCT);
+
+      if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE)
+	{
+	  /* bottom half has revision & processor id */
+	  append_composite_type_field (t, "rev", bt->builtin_uint8);
+	  append_composite_type_field (t, "prid", bt->builtin_uint8);
+
+	  /* top half has flags */
+	  append_composite_type_field (t, "", flags);
+	}
+      else
+	{
+	  /* top half has flags */
+	  append_composite_type_field (t, "", flags);
+
+	  /* bottom half has revision & processor id */
+	  append_composite_type_field (t, "prid", bt->builtin_uint8);
+	  append_composite_type_field (t, "rev", bt->builtin_uint8);
+	}
+
+      TYPE_LENGTH (t) = 4;
+      TYPE_NAME (t) = "fp_ir";
+      tdep->fp_ir_type = t;
+    }
+
+  return tdep->fp_ir_type;
+}
+
 static void
 mips_value_to_register (struct frame_info *frame, int regnum,
 			struct type *type, const gdb_byte *from)
@@ -1415,9 +1588,10 @@ mips_register_type (struct gdbarch *gdbarch, int regnum)
          Use the current setting for cooked registers.  */
       if (mips_float_register_p (gdbarch, regnum))
 	return mips_fp_type (gdbarch, rawnum - mips_regnum (gdbarch)->fp0);
-      else if (rawnum == mips_regnum (gdbarch)->fp_control_status
-	  || rawnum == mips_regnum (gdbarch)->fp_implementation_revision)
-	return builtin_type (gdbarch)->builtin_int32;
+      else if (rawnum == mips_regnum (gdbarch)->fp_control_status)
+	return mips_fcsr_type (gdbarch);
+      else if (rawnum == mips_regnum (gdbarch)->fp_implementation_revision)
+	return mips_fir_type (gdbarch);
       else if (rawnum == mips_regnum (gdbarch)->config5)
 	return mips_config5_type (gdbarch);
       else if (gdbarch_osabi (gdbarch) != GDB_OSABI_IRIX
@@ -1492,6 +1666,12 @@ mips_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
 	      && rawnum < mips_regnum (gdbarch)->dspacc + 6)))
     return builtin_type (gdbarch)->builtin_int32;
 
+  if (rawnum == mips_regnum (gdbarch)->fp_control_status)
+    return mips_fcsr_type (gdbarch);
+
+  if (rawnum == mips_regnum (gdbarch)->fp_implementation_revision)
+    return mips_fir_type (gdbarch);
+
   if (rawnum == mips_regnum (gdbarch)->config5)
     return mips_config5_type (gdbarch);
 
@@ -6741,9 +6921,52 @@ mips_print_fp_register (struct ui_file *file, struct frame_info *frame,
     }
 }
 
+/* Print a single complex control register */
+
 static void
-mips_print_register (struct ui_file *file, struct frame_info *frame,
-		     int regnum)
+print_control_register (struct ui_file *file, struct frame_info *frame,
+			int regnum)
+{
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  const char *name = gdbarch_register_name (gdbarch, regnum);
+  struct value *val = value_of_register (regnum, frame);
+  struct type *regtype = value_type (val);
+  enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (regtype));
+  struct value_print_options opts;
+  const gdb_byte *valaddr;
+
+  fputs_filtered (name, file);
+  print_spaces_filtered (15 - strlen (name), file);
+
+  if (!value_entirely_available (val))
+    {
+      fprintf_filtered (file, "*value not available*\n");
+      return;
+    }
+  else if (value_optimized_out (val))
+    {
+      val_print_optimized_out (val, file);
+      fprintf_filtered (file, "\n");
+      return;
+    }
+
+  valaddr = value_contents_for_printing (val);
+
+  /* Print raw value */
+  fprintf_filtered (file, "\t");
+  print_hex_chars (file, valaddr, TYPE_LENGTH (regtype), byte_order);
+
+  /* Print it according to its natural format. */
+  get_user_print_options (&opts);
+  opts.deref_ref = 1;
+  fprintf_filtered (file, "\t");
+  val_print (regtype, valaddr,
+	     value_embedded_offset (val), 0,
+	     file, 0, val, &opts, current_language);
+}
+
+static void
+mips_print_register (struct ui_file *file, struct frame_info *frame, int regnum)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
   struct value_print_options opts;
@@ -6755,6 +6978,14 @@ mips_print_register (struct ui_file *file, struct frame_info *frame,
       return;
     }
 
+  if (mips_register_reggroup_p (gdbarch, regnum, float_reggroup) ||
+      mips_register_reggroup_p (gdbarch, regnum, vector_reggroup))
+    {
+      /* FP & MSA control registers */
+      print_control_register (file, frame, regnum);
+      return;
+    }
+
   val = get_frame_register_value (frame, regnum);
 
   fputs_filtered (gdbarch_register_name (gdbarch, regnum), file);
@@ -6972,6 +7203,19 @@ print_gp_register_row (struct ui_file *file, struct frame_info *frame,
   return regnum;
 }
 
+/* Print a single complex control register row */
+
+static int
+print_control_register_row (struct ui_file *file, struct frame_info *frame,
+			    int regnum)
+{
+  print_control_register (file, frame, regnum);
+
+  fprintf_filtered (file, "\n");
+  ++regnum;
+  return regnum;
+}
+
 /* MIPS_DO_REGISTERS_INFO(): called by "info register" command.  */
 
 static void
@@ -7001,6 +7245,10 @@ mips_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file,
 	      else
 		regnum += MIPS_NUMREGS;	/* Skip floating point regs.  */
 	    }
+	  else if (mips_register_reggroup_p (gdbarch, regnum, float_reggroup) ||
+		   mips_register_reggroup_p (gdbarch, regnum, vector_reggroup))
+	    /* FP & MSA control registers */
+	    regnum = print_control_register_row (file, frame, regnum);
 	  else
 	    regnum = print_gp_register_row (file, frame, regnum);
 	}
@@ -9033,6 +9281,10 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->fp_mode = ((struct gdbarch_tdep_info*)(info.tdep_info))->fp_mode;
   tdep->fp_register_mode_fixed_p = 0;
   tdep->config5_type = NULL;
+  tdep->fp_rm_type = NULL;
+  tdep->fp_cflags_type = NULL;
+  tdep->fp_csr_type = NULL;
+  tdep->fp_ir_type = NULL;
   tdep->fp32_type = NULL;
   tdep->fp64_type = NULL;
 
diff --git a/gdb/mips-tdep.h b/gdb/mips-tdep.h
index 11353be..ad5cba3 100644
--- a/gdb/mips-tdep.h
+++ b/gdb/mips-tdep.h
@@ -130,6 +130,10 @@ struct gdbarch_tdep
 
   /* ISA-specific data types.  */
   struct type *config5_type;
+  struct type *fp_rm_type;
+  struct type *fp_cflags_type;
+  struct type *fp_csr_type;
+  struct type *fp_ir_type;
   struct type *fp32_type;
   struct type *fp64_type;
 
-- 
1.9-rc2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 01/24]     MIPS: Handle run-time reconfigurable FPR size
@ 2016-06-27 14:50 Bhushan Attarde
  2016-06-27 14:50 ` [PATCH 10/24] MIPS: override fscr/fir types and print control registers specially Bhushan Attarde
                   ` (21 more replies)
  0 siblings, 22 replies; 37+ messages in thread
From: Bhushan Attarde @ 2016-06-27 14:50 UTC (permalink / raw)
  To: gdb-patches
  Cc: Maciej.Rozycki, Matthew.Fortune, James.Hogan, Andrew.Bennett,
	Jaydeep.Patil, Bhushan Attarde

    Many MIPS architecture processors can reconfigure the size of their
    floating-point registers at the run time.  The file comprising 32
    registers can be either 32-bit or 64-bit wide depending on whether CP0
    Status register's bit FR is zero or one, respectively.  Fortunately access
    to Status is available on all targets.

    Here's a change to handle this property.  It requires the generic register
    access code to raise the target backend's attention whenever a new
    register set has been retrieved so that it can examine the state of
    CP0.Status.FR and act accordingly.  I have added this hook to
    get_thread_regcache, the backend has then an opportunity to switch gdbarch
    as necessary and let the caller know if it did so.  If that indeed
    happened, then the register cache originally retrieved is then discarded
    and another one obtained using the newly-selected gdbarch.  This new
    register cache is not revalidated.

    This has been regression-tested successfully, using o32 and n64 multilibs
    on mips-sde-elf and mips-linux-gnu targets.  The ability to flip
    CP0.Status.FR is not however covered by any test suite, and was therefore
    tested manually.  An example session with a bare-iron MIPS64 target looks
    like this (I've stripped out some noise):

    (gdb) info all-registers
                      zero               at               v0               v1
     R0   0000000000000000 0000000000000000 0000000000000000 0000000020000000
                        a0               a1               a2               a3
     R4   0000000000000000 0000000000000000 0000000000000000 0000000000000000
                        a4               a5               a6               a7
     R8   0000000000000000 0000000000000000 0000000000000000 0000000000000000
                        t0               t1               t2               t3
     R12  0000000000000000 0000000000000000 0000000000000000 0000000000000000
                        s0               s1               s2               s3
     R16  0000000000000000 0000000000000000 0000000000000000 0000000000000000
                        s4               s5               s6               s7
     R20  0000000000000000 0000000000000000 0000000000000000 0000000000000000
                        t8               t9               k0               k1
     R24  0000000000000000 0000000000000000 0000000000000000 0000000000000000
                        gp               sp               s8               ra
     R28  0000000000000000 0000000000000000 0000000000000000 0000000000000000
                        sr               lo               hi              bad
          0000000024000000 0000000000000000 0000000000000000 0000000000000000
                     cause               pc
          0000000000000000 ffffffff80000000
     f0:  0x0000000000000000 flt: 0                 dbl: 0
     f1:  0x000000003f800000 flt: 1                 dbl: 5.2635442471208903e-315
     f2:  0x0000000000000000 flt: 0                 dbl: 0
     f3:  0x0000000040000000 flt: 2                 dbl: 5.3049894774131808e-315
     f4:  0x0000000000000000 flt: 0                 dbl: 0
     f5:  0x0000000040400000 flt: 3                 dbl: 5.325712092559326e-315
     f6:  0x0000000000000000 flt: 0                 dbl: 0
     f7:  0x0000000040800000 flt: 4                 dbl: 5.3464347077054713e-315
     f8:  0x0000000000000000 flt: 0                 dbl: 0
     f9:  0x0000000040a00000 flt: 5                 dbl: 5.3567960152785439e-315
     f10: 0x0000000000000000 flt: 0                 dbl: 0
     f11: 0x0000000040c00000 flt: 6                 dbl: 5.3671573228516165e-315
     f12: 0x0000000000000000 flt: 0                 dbl: 0
     f13: 0x0000000040e00000 flt: 7                 dbl: 5.3775186304246891e-315
     f14: 0x0000000000000000 flt: 0                 dbl: 0
     f15: 0x0000000041000000 flt: 8                 dbl: 5.3878799379977617e-315
     f16: 0x0000000000000000 flt: 0                 dbl: 0
     f17: 0x0000000041100000 flt: 9                 dbl: 5.393060591784298e-315
     f18: 0x0000000000000000 flt: 0                 dbl: 0
     f19: 0x0000000041200000 flt: 10                dbl: 5.3982412455708344e-315
     f20: 0x0000000000000000 flt: 0                 dbl: 0
     f21: 0x0000000041300000 flt: 11                dbl: 5.4034218993573707e-315
     f22: 0x0000000000000000 flt: 0                 dbl: 0
     f23: 0x0000000041400000 flt: 12                dbl: 5.408602553143907e-315
     f24: 0x0000000000000000 flt: 0                 dbl: 0
     f25: 0x0000000041500000 flt: 13                dbl: 5.4137832069304433e-315
     f26: 0x0000000000000000 flt: 0                 dbl: 0
     f27: 0x0000000041600000 flt: 14                dbl: 5.4189638607169796e-315
     f28: 0x0000000000000000 flt: 0                 dbl: 0
     f29: 0x0000000041700000 flt: 15                dbl: 5.4241445145035159e-315
     f30: 0x0000000000000000 flt: 0                 dbl: 0
     f31: 0x0000000041800000 flt: 16                dbl: 5.4293251682900522e-315
                       fsr              fir
                  00000000         00738900
    (gdb) x /i $pc
    => 0xffffffff80000000:	mtc0	v1,c0_status
    (gdb) stepi
    0xffffffff80000004 in ?? ()
    (gdb) info all-registers
                      zero               at               v0               v1
     R0   0000000000000000 0000000000000000 0000000000000000 0000000020000000
                        a0               a1               a2               a3
     R4   0000000000000000 0000000000000000 0000000000000000 0000000000000000
                        a4               a5               a6               a7
     R8   0000000000000000 0000000000000000 0000000000000000 0000000000000000
                        t0               t1               t2               t3
     R12  0000000000000000 0000000000000000 0000000000000000 0000000000000000
                        s0               s1               s2               s3
     R16  0000000000000000 0000000000000000 0000000000000000 0000000000000000
                        s4               s5               s6               s7
     R20  0000000000000000 0000000000000000 0000000000000000 0000000000000000
                        t8               t9               k0               k1
     R24  0000000000000000 0000000000000000 0000000000000000 0000000000000000
                        gp               sp               s8               ra
     R28  0000000000000000 0000000000000000 0000000000000000 0000000000000000
                        sr               lo               hi              bad
          0000000020000000 0000000000000000 0000000000000000 0000000000000000
                     cause               pc
          0000000000000000 ffffffff80000004
     f0:  0x00000000 flt: 0                 dbl: 0.0078125
     f1:  0x3f800000 flt: 1
     f2:  0x00000000 flt: 0                 dbl: 2
     f3:  0x40000000 flt: 2
     f4:  0x00000000 flt: 0                 dbl: 32
     f5:  0x40400000 flt: 3
     f6:  0x00000000 flt: 0                 dbl: 512
     f7:  0x40800000 flt: 4
     f8:  0x00000000 flt: 0                 dbl: 2048
     f9:  0x40a00000 flt: 5
     f10: 0x00000000 flt: 0                 dbl: 8192
     f11: 0x40c00000 flt: 6
     f12: 0x00000000 flt: 0                 dbl: 32768
     f13: 0x40e00000 flt: 7
     f14: 0x00000000 flt: 0                 dbl: 131072
     f15: 0x41000000 flt: 8
     f16: 0x00000000 flt: 0                 dbl: 262144
     f17: 0x41100000 flt: 9
     f18: 0x00000000 flt: 0                 dbl: 524288
     f19: 0x41200000 flt: 10
     f20: 0x00000000 flt: 0                 dbl: 1048576
     f21: 0x41300000 flt: 11
     f22: 0x00000000 flt: 0                 dbl: 2097152
     f23: 0x41400000 flt: 12
     f24: 0x00000000 flt: 0                 dbl: 4194304
     f25: 0x41500000 flt: 13
     f26: 0x00000000 flt: 0                 dbl: 8388608
     f27: 0x41600000 flt: 14
     f28: 0x00000000 flt: 0                 dbl: 16777216
     f29: 0x41700000 flt: 15
     f30: 0x00000000 flt: 0                 dbl: 33554432
     f31: 0x41800000 flt: 16
                       fsr              fir
                  00000000         00738900
    (gdb) set $sr ^= 1 << 26
    (gdb) info all-registers
                      zero               at               v0               v1
     R0   0000000000000000 0000000000000000 0000000000000000 0000000020000000
                        a0               a1               a2               a3
     R4   0000000000000000 0000000000000000 0000000000000000 0000000000000000
                        a4               a5               a6               a7
     R8   0000000000000000 0000000000000000 0000000000000000 0000000000000000
                        t0               t1               t2               t3
     R12  0000000000000000 0000000000000000 0000000000000000 0000000000000000
                        s0               s1               s2               s3
     R16  0000000000000000 0000000000000000 0000000000000000 0000000000000000
                        s4               s5               s6               s7
     R20  0000000000000000 0000000000000000 0000000000000000 0000000000000000
                        t8               t9               k0               k1
     R24  0000000000000000 0000000000000000 0000000000000000 0000000000000000
                        gp               sp               s8               ra
     R28  0000000000000000 0000000000000000 0000000000000000 0000000000000000
                        sr               lo               hi              bad
          0000000024000000 0000000000000000 0000000000000000 0000000000000000
                     cause               pc
          0000000000000000 ffffffff80000004
     f0:  0x0000000000000000 flt: 0                 dbl: 0
     f1:  0x000000003f800000 flt: 1                 dbl: 5.2635442471208903e-315
     f2:  0x0000000000000000 flt: 0                 dbl: 0
     f3:  0x0000000040000000 flt: 2                 dbl: 5.3049894774131808e-315
     f4:  0x0000000000000000 flt: 0                 dbl: 0
     f5:  0x0000000040400000 flt: 3                 dbl: 5.325712092559326e-315
     f6:  0x0000000000000000 flt: 0                 dbl: 0
     f7:  0x0000000040800000 flt: 4                 dbl: 5.3464347077054713e-315
     f8:  0x0000000000000000 flt: 0                 dbl: 0
     f9:  0x0000000040a00000 flt: 5                 dbl: 5.3567960152785439e-315
     f10: 0x0000000000000000 flt: 0                 dbl: 0
     f11: 0x0000000040c00000 flt: 6                 dbl: 5.3671573228516165e-315
     f12: 0x0000000000000000 flt: 0                 dbl: 0
     f13: 0x0000000040e00000 flt: 7                 dbl: 5.3775186304246891e-315
     f14: 0x0000000000000000 flt: 0                 dbl: 0
     f15: 0x0000000041000000 flt: 8                 dbl: 5.3878799379977617e-315
     f16: 0x0000000000000000 flt: 0                 dbl: 0
     f17: 0x0000000041100000 flt: 9                 dbl: 5.393060591784298e-315
     f18: 0x0000000000000000 flt: 0                 dbl: 0
     f19: 0x0000000041200000 flt: 10                dbl: 5.3982412455708344e-315
     f20: 0x0000000000000000 flt: 0                 dbl: 0
     f21: 0x0000000041300000 flt: 11                dbl: 5.4034218993573707e-315
     f22: 0x0000000000000000 flt: 0                 dbl: 0
     f23: 0x0000000041400000 flt: 12                dbl: 5.408602553143907e-315
     f24: 0x0000000000000000 flt: 0                 dbl: 0
     f25: 0x0000000041500000 flt: 13                dbl: 5.4137832069304433e-315
     f26: 0x0000000000000000 flt: 0                 dbl: 0
     f27: 0x0000000041600000 flt: 14                dbl: 5.4189638607169796e-315
     f28: 0x0000000000000000 flt: 0                 dbl: 0
     f29: 0x0000000041700000 flt: 15                dbl: 5.4241445145035159e-315
     f30: 0x0000000000000000 flt: 0                 dbl: 0
     f31: 0x0000000041800000 flt: 16                dbl: 5.4293251682900522e-315
                       fsr              fir
                  00000000         00738900
    (gdb)

    This is implemented by retaining the raw register size for the FPRs at its
    native size (64-bits; this is required for remote packet offsets to work
    out correctly) and then truncating the cooked register size or not as
    required.  I have skipped `maintenance print registers' dumps here for
    brevity, the types flip between "double" and "float" as expected.

     This change supports bare-iron, Linux and IRIX targets.  For Linux and
    IRIX the width of the floating-point registers is set by the ABI of the
    program being run by the OS kernel and the kernel is responsible for
    setting CP0.Status.FR correctly; the image of Status accessible via
    ptrace(2) is read-only.  Therefore the respective backends mark the width
    as fixed and cause the run-time check to be skipped for efficiency.  I
    have verified that the Linux target does that correctly; the change for
    IRIX is the same and is expected to be all right, but I have no access to
    such a system (I will appreciate anyone verifying that).

     The change currently supports 64-bit processors only as GDB has no way to
    access upper halves of floating-point registers on 32-bit processors that
    have a 64-bit FPU (i.e. MIPS32r2 and newer processors); this is mentioned
    in the explanatory notes included with the change itself.

     The change also supports both XML and non-XML targets, but currently
    bare-iron targets for which this update has any significant meaning do not
    really support XML.  Any XML target is supposed to always provide an FPU
    description that matches the current setting of CP0.Status.FR, the new
    code verifies this is always the case and rejects the description as
    invalid otherwise.

     Generic parts require a general maintainer's approval, would whoever
    finds themselves most familiar with regcache internals please have a look
    at these bits?  Thanks.

     This addresses the CP0.Status.FR part of PR gdb/7518 (former GNATS PR
    gdb/413) and is based on work started by Nigel and David (neither at MIPS
    Technologies anymore).

    2012-06-06  Maciej W. Rozycki  <macro@codesourcery.com>
                Nigel Stephens  <nigel@mips.com>
                David Ung  <davidu@mips.com>

        PR gdb/7518

        gdb/
        * gdbarch.sh (regcache_changed): New function.
        * regcache.c (set_current_thread_ptid_arch): New function,
        factored out from...
        (get_thread_regcache): ... here.  Call gdbarch_regcache_changed
        as necessary.
        * mips-tdep.h (gdbarch_tdep): Add fp_register_size_fixed_p and
        fp_register_size members.
        (gdbarch_tdep_info): New structure.
        * mips-tdep.c (mips_register_type): Remove forward declaration.
        (mips_set_float_regsize, mips_float_regsize): New functions.
        (mips2_fp_compat): Remove function.
        (mips_register_type): Use mips_float_regsize to handle cooked
        floating-point registers.  Fold floating-point cases into common
        code.
        (mips_pseudo_register_type): Update comment on floating-point
        registers.
        (mips_read_fp_register_single): Rename raw_size local variable
        to fpsize.
        (mips_read_fp_register_double): Likewise.  Remove call to
        mips2_fp_compat.
        (mips_print_fp_register): Check the size of the register
        requested rather than $f0 and use fpsize local variable to hold
        it.  Remove call to mips2_fp_compat.
        (mips_print_float_info): Use mips_float_regsize.
        (mips_gdbarch_init): Use a proper tdep_info structure.  Match
        gdbarch against fp_register_size requested if any.  Initialize
        fp_register_size and fp_register_size_fixed_p in gdbarch target
        data.  Install mips_set_float_regsize as gdbarch regcache_changed
        routine.
        * mips-irix-tdep.c (mips_irix_init_abi): Set
        fp_register_size_fixed_p in gdbarch target data.
        * mips-linux-tdep.c (mips_linux_init_abi): Likewise.  Adjust for
        tdep_info update.
        * gdbarch.h: Regenerate.
        * gdbarch.c: Regenerate.
---
 gdb/gdbarch.c         |  32 +++++++++
 gdb/gdbarch.h         |  11 +++
 gdb/gdbarch.sh        |   5 ++
 gdb/mips-linux-tdep.c |   7 +-
 gdb/mips-tdep.c       | 194 +++++++++++++++++++++++++++++++++++---------------
 gdb/mips-tdep.h       |  16 +++++
 gdb/regcache.c        |  25 ++++++-
 7 files changed, 227 insertions(+), 63 deletions(-)

diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 4143744..0673fc1 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -199,6 +199,7 @@ struct gdbarch
   gdbarch_dwarf2_reg_to_regnum_ftype *dwarf2_reg_to_regnum;
   gdbarch_register_name_ftype *register_name;
   gdbarch_register_type_ftype *register_type;
+  gdbarch_regcache_changed_ftype *regcache_changed;
   gdbarch_dummy_id_ftype *dummy_id;
   int deprecated_fp_regnum;
   gdbarch_push_dummy_call_ftype *push_dummy_call;
@@ -543,6 +544,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   if (gdbarch->register_name == 0)
     fprintf_unfiltered (log, "\n\tregister_name");
   /* Skip verify of register_type, has predicate.  */
+  /* Skip verify of regcache_changed, has predicate.  */
   /* Skip verify of dummy_id, has predicate.  */
   /* Skip verify of deprecated_fp_regnum, invalid_p == 0 */
   /* Skip verify of push_dummy_call, has predicate.  */
@@ -1225,6 +1227,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
                       "gdbarch_dump: record_special_symbol = <%s>\n",
                       host_address_to_string (gdbarch->record_special_symbol));
   fprintf_unfiltered (file,
+                      "gdbarch_dump: gdbarch_regcache_changed_p() = %d\n",
+                      gdbarch_regcache_changed_p (gdbarch));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: regcache_changed = <%s>\n",
+                      host_address_to_string (gdbarch->regcache_changed));
+  fprintf_unfiltered (file,
                       "gdbarch_dump: register_name = <%s>\n",
                       host_address_to_string (gdbarch->register_name));
   fprintf_unfiltered (file,
@@ -2171,6 +2179,30 @@ set_gdbarch_register_type (struct gdbarch *gdbarch,
 }
 
 int
+gdbarch_regcache_changed_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->regcache_changed != NULL;
+}
+
+int
+gdbarch_regcache_changed (struct gdbarch *gdbarch, struct regcache *regcache)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->regcache_changed != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_regcache_changed called\n");
+  return gdbarch->regcache_changed (gdbarch, regcache);
+}
+
+void
+set_gdbarch_regcache_changed (struct gdbarch *gdbarch,
+                              gdbarch_regcache_changed_ftype regcache_changed)
+{
+  gdbarch->regcache_changed = regcache_changed;
+}
+
+int
 gdbarch_dummy_id_p (struct gdbarch *gdbarch)
 {
   gdb_assert (gdbarch != NULL);
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 3fadcd1..22b02a3 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -356,6 +356,17 @@ typedef struct type * (gdbarch_register_type_ftype) (struct gdbarch *gdbarch, in
 extern struct type * gdbarch_register_type (struct gdbarch *gdbarch, int reg_nr);
 extern void set_gdbarch_register_type (struct gdbarch *gdbarch, gdbarch_register_type_ftype *register_type);
 
+/* Notify the architecture that the registers have changed and we now have
+   a new regcache to examine.  Return one if a new architecture has been
+   selected that changed the layout of the regcache and it has to be
+   discarded and a new one initialised, zero otherwise. */
+
+extern int gdbarch_regcache_changed_p (struct gdbarch *gdbarch);
+
+typedef int (gdbarch_regcache_changed_ftype) (struct gdbarch *gdbarch, struct regcache *regcache);
+extern int gdbarch_regcache_changed (struct gdbarch *gdbarch, struct regcache *regcache);
+extern void set_gdbarch_regcache_changed (struct gdbarch *gdbarch, gdbarch_regcache_changed_ftype *regcache_changed);
+
 extern int gdbarch_dummy_id_p (struct gdbarch *gdbarch);
 
 typedef struct frame_id (gdbarch_dummy_id_ftype) (struct gdbarch *gdbarch, struct frame_info *this_frame);
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index 4ac6b90..2c09371 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -469,6 +469,11 @@ m:const char *:register_name:int regnr:regnr::0
 # the register cache should call this function directly; others should
 # use "register_type".
 M:struct type *:register_type:int reg_nr:reg_nr
+# Notify the architecture that the registers have changed and we now have
+# a new regcache to examine.  Return one if a new architecture has been
+# selected that changed the layout of the regcache and it has to be
+# discarded and a new one initialised, zero otherwise.
+M:int:regcache_changed:struct regcache *regcache:regcache
 
 M:struct frame_id:dummy_id:struct frame_info *this_frame:this_frame
 # Implement DUMMY_ID and PUSH_DUMMY_CALL, then delete
diff --git a/gdb/mips-linux-tdep.c b/gdb/mips-linux-tdep.c
index 8dc0566..6b9743b 100644
--- a/gdb/mips-linux-tdep.c
+++ b/gdb/mips-linux-tdep.c
@@ -1737,8 +1737,9 @@ mips_linux_init_abi (struct gdbarch_info info,
 				    mips_gdb_signal_to_target);
 
   tdep->syscall_next_pc = mips_linux_syscall_next_pc;
+  tdep->fp_register_size_fixed_p = 1;
 
-  if (tdesc_data)
+  if (((struct gdbarch_tdep_info*)(info.tdep_info))->tdesc_data)
     {
       const struct tdesc_feature *feature;
 
@@ -1753,8 +1754,8 @@ mips_linux_init_abi (struct gdbarch_info info,
       feature = tdesc_find_feature (info.target_desc,
 				    "org.gnu.gdb.mips.linux");
       if (feature != NULL)
-	tdesc_numbered_register (feature, tdesc_data, MIPS_RESTART_REGNUM,
-				 "restart");
+	tdesc_numbered_register (feature, (((struct gdbarch_tdep_info*)(info.tdep_info))->tdesc_data),
+				 MIPS_RESTART_REGNUM, "restart");
     }
 }
 
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index 63c1560..ae4dc2e 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -58,8 +58,6 @@
 
 static const struct objfile_data *mips_pdr_data;
 
-static struct type *mips_register_type (struct gdbarch *gdbarch, int regnum);
-
 static int mips32_instruction_has_delay_slot (struct gdbarch *gdbarch,
 					      ULONGEST inst);
 static int micromips_instruction_has_delay_slot (ULONGEST insn, int mustbe32);
@@ -274,6 +272,77 @@ mips_abi_regsize (struct gdbarch *gdbarch)
     }
 }
 
+/* Determine the current floating-point register size and update our
+   architecture data accordingly.  Return one if the size has changed
+   and a new architecture has been selected, zero otherwise.
+
+   For MIPS1, MIPS2 and MIPS32 rev. 1 processors the size is hardwired
+   to 32 bits.  For MIPS3 and other 64-bit processors up to the MIPS64
+   rev. 1 ISA the size is determined by the CP0 Status register's bit
+   FR.  If this bit is 1, then the size is 64 bits.  If it is 0, then
+   the FPU operates in the compatibility mode and the size is 32 bits.
+
+   From MIPS32 and MIPS64 rev. 2 ISAs up the size is implementation
+   specific and reported by the CP1 FIR register's bit F64.  If this
+   bit is 0, then the size is hardwired to 32 bits.  If this bit is 1,
+   then the size is determined by the CP0 Status register's bit FR as
+   described above.  Unfortunately we may not have access to the CP0
+   registers needed to determine whether the ISA implemented is MIPS32
+   or MIPS64 rev. 2 or higher.
+
+   We currently cannot handle the 64-bit floating-point register size
+   on MIPS32 rev. 2 and higher ISA processors though as no target
+   provides access to upper halves of such registers.  Therefore we
+   hardcode the size to 32 bits for any 32-bit processors.
+
+   As the CP0 Status register's bit FR cannot be modified on processors
+   that do not implement an FPU, backends for operating systems that
+   can emulate the FPU in software should set the size according to the
+   ABI in use and then set fp_register_size_fixed_p to 1 to prevent
+   further updates.  */
+
+static int
+mips_set_float_regsize (struct gdbarch *gdbarch, struct regcache *regcache)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  struct gdbarch_tdep_info tdep_info = { NULL };
+  struct gdbarch_info info;
+  int fpsize;
+
+  if (tdep->fp_register_size_fixed_p)
+    return 0;
+
+  fpsize = mips_isa_regsize (gdbarch);
+  if (fpsize == 8)
+    {
+      enum register_status status;
+      ULONGEST sr;
+
+      status = regcache_raw_read_unsigned (regcache, MIPS_PS_REGNUM, &sr);
+      if (status == REG_VALID)
+	fpsize = (sr & ST0_FR) ? 8 : 4;
+    }
+
+  if (fpsize == tdep->fp_register_size)
+    return 0;
+
+  /* Need a new gdbarch, go get one.  */
+  gdbarch_info_init (&info);
+  info.tdep_info = &tdep_info;
+  info.tdep_info->fp_register_size = fpsize;
+  gdbarch_update_p (info);
+
+  return 1;
+}
+
+/* Return the currently configured floating-point register size.  */
+
+static int
+mips_float_regsize (struct gdbarch *gdbarch)
+{
+  return gdbarch_tdep (gdbarch)->fp_register_size;
+}
+
 /* MIPS16/microMIPS function addresses are odd (bit 0 is set).  Here
    are some functions to handle addresses associated with compressed
    code including but not limited to testing, setting, or clearing
@@ -504,32 +573,6 @@ mips_xfer_register (struct gdbarch *gdbarch, struct regcache *regcache,
     fprintf_unfiltered (gdb_stdlog, "\n");
 }
 
-/* Determine if a MIPS3 or later cpu is operating in MIPS{1,2} FPU
-   compatiblity mode.  A return value of 1 means that we have
-   physical 64-bit registers, but should treat them as 32-bit registers.  */
-
-static int
-mips2_fp_compat (struct frame_info *frame)
-{
-  struct gdbarch *gdbarch = get_frame_arch (frame);
-  /* MIPS1 and MIPS2 have only 32 bit FPRs, and the FR bit is not
-     meaningful.  */
-  if (register_size (gdbarch, mips_regnum (gdbarch)->fp0) == 4)
-    return 0;
-
-#if 0
-  /* FIXME drow 2002-03-10: This is disabled until we can do it consistently,
-     in all the places we deal with FP registers.  PR gdb/413.  */
-  /* Otherwise check the FR bit in the status register - it controls
-     the FP compatiblity mode.  If it is clear we are in compatibility
-     mode.  */
-  if ((get_frame_register_unsigned (frame, MIPS_PS_REGNUM) & ST0_FR) == 0)
-    return 1;
-#endif
-
-  return 0;
-}
-
 #define VM_MIN_ADDRESS (CORE_ADDR)0x400000
 
 static CORE_ADDR heuristic_proc_start (struct gdbarch *, CORE_ADDR);
@@ -1005,31 +1048,36 @@ static struct type *
 mips_register_type (struct gdbarch *gdbarch, int regnum)
 {
   gdb_assert (regnum >= 0 && regnum < 2 * gdbarch_num_regs (gdbarch));
-  if (mips_float_register_p (gdbarch, regnum))
-    {
-      /* The floating-point registers raw, or cooked, always match
-         mips_isa_regsize(), and also map 1:1, byte for byte.  */
-      if (mips_isa_regsize (gdbarch) == 4)
-	return builtin_type (gdbarch)->builtin_float;
-      else
-	return builtin_type (gdbarch)->builtin_double;
-    }
-  else if (regnum < gdbarch_num_regs (gdbarch))
+  if (regnum < gdbarch_num_regs (gdbarch))
     {
       /* The raw or ISA registers.  These are all sized according to
 	 the ISA regsize.  */
-      if (mips_isa_regsize (gdbarch) == 4)
-	return builtin_type (gdbarch)->builtin_int32;
+      int regsize = mips_isa_regsize (gdbarch);
+
+      if (mips_float_register_p (gdbarch, regnum))
+	return (regsize == 4
+		? builtin_type (gdbarch)->builtin_float
+		: builtin_type (gdbarch)->builtin_double);
       else
-	return builtin_type (gdbarch)->builtin_int64;
+	return (regsize == 4
+		? builtin_type (gdbarch)->builtin_int32
+		: builtin_type (gdbarch)->builtin_int64);
     }
   else
     {
-      int rawnum = regnum - gdbarch_num_regs (gdbarch);
-
       /* The cooked or ABI registers.  These are sized according to
 	 the ABI (with a few complications).  */
-      if (rawnum == mips_regnum (gdbarch)->fp_control_status
+      int rawnum = regnum - gdbarch_num_regs (gdbarch);
+
+      /* Floating-point registers of most 64-bit and some 32-bit MIPS
+         processors can be reconfigured dynamically at the run time as
+         either 64-bit or 32-bit via the CP0 Status register's FR bit.
+         Use the current setting for cooked registers.  */
+      if (mips_float_register_p (gdbarch, regnum))
+	return (mips_float_regsize (gdbarch) == 4
+		? builtin_type (gdbarch)->builtin_float
+		: builtin_type (gdbarch)->builtin_double);
+      else if (rawnum == mips_regnum (gdbarch)->fp_control_status
 	  || rawnum == mips_regnum (gdbarch)->fp_implementation_revision)
 	return builtin_type (gdbarch)->builtin_int32;
       else if (gdbarch_osabi (gdbarch) != GDB_OSABI_IRIX
@@ -1074,8 +1122,10 @@ mips_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
     return rawtype;
 
   if (mips_float_register_p (gdbarch, rawnum))
-    /* Present the floating point registers however the hardware did;
-       do not try to convert between FPU layouts.  */
+    /* Present the floating point registers however the hardware did; do
+       not try to convert between FPU layouts.  A target description is
+       expected to have taken the CP0 Status register's FR bit into account
+       as necessary, this has been already verified in mips_gdbarch_init.  */
     return rawtype;
 
   /* Use pointer types for registers if we can.  For n32 we can not,
@@ -6187,13 +6237,13 @@ mips_read_fp_register_single (struct frame_info *frame, int regno,
 			      gdb_byte *rare_buffer)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
-  int raw_size = register_size (gdbarch, regno);
-  gdb_byte *raw_buffer = (gdb_byte *) alloca (raw_size);
+  int fpsize = register_size (gdbarch, regno);
+  gdb_byte *raw_buffer = alloca (fpsize);
 
   if (!deprecated_frame_register_read (frame, regno, raw_buffer))
     error (_("can't read register %d (%s)"),
 	   regno, gdbarch_register_name (gdbarch, regno));
-  if (raw_size == 8)
+  if (fpsize == 8)
     {
       /* We have a 64-bit value for this register.  Find the low-order
          32 bits.  */
@@ -6221,9 +6271,9 @@ mips_read_fp_register_double (struct frame_info *frame, int regno,
 			      gdb_byte *rare_buffer)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
-  int raw_size = register_size (gdbarch, regno);
+  int fpsize = register_size (gdbarch, regno);
 
-  if (raw_size == 8 && !mips2_fp_compat (frame))
+  if (fpsize == 8)
     {
       /* We have a 64-bit value for this register, and we should use
          all 64 bits.  */
@@ -6260,20 +6310,19 @@ mips_print_fp_register (struct ui_file *file, struct frame_info *frame,
 			int regnum)
 {				/* Do values for FP (float) regs.  */
   struct gdbarch *gdbarch = get_frame_arch (frame);
+  int fpsize = register_size (gdbarch, regnum);
   gdb_byte *raw_buffer;
   double doub, flt1;	/* Doubles extracted from raw hex data.  */
   int inv1, inv2;
 
-  raw_buffer
-    = ((gdb_byte *)
-       alloca (2 * register_size (gdbarch, mips_regnum (gdbarch)->fp0)));
+  raw_buffer = alloca (2 * fpsize);
 
   fprintf_filtered (file, "%s:", gdbarch_register_name (gdbarch, regnum));
   fprintf_filtered (file, "%*s",
 		    4 - (int) strlen (gdbarch_register_name (gdbarch, regnum)),
 		    "");
 
-  if (register_size (gdbarch, regnum) == 4 || mips2_fp_compat (frame))
+  if (fpsize == 4)
     {
       struct value_print_options opts;
 
@@ -8167,6 +8216,7 @@ value_of_mips_user_reg (struct frame_info *frame, const void *baton)
 static struct gdbarch *
 mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 {
+  struct gdbarch_tdep_info tdep_info = { NULL };
   struct gdbarch *gdbarch;
   struct gdbarch_tdep *tdep;
   int elf_flags;
@@ -8181,6 +8231,10 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   int dspacc;
   int dspctl;
 
+  /* Wire in an empty template tdep_info if one hasn't been supplied.  */
+  if (info.tdep_info == NULL)
+    info.tdep_info = &tdep_info;
+
   /* Fill in the OS dependent register numbers and names.  */
   if (info.osabi == GDB_OSABI_IRIX)
     {
@@ -8252,6 +8306,7 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
       const struct tdesc_feature *feature;
       int valid_p;
+      int fpsize;
 
       feature = tdesc_find_feature (info.target_desc,
 				    "org.gnu.gdb.mips.cpu");
@@ -8311,7 +8366,15 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 	  return NULL;
 	}
 
-      valid_p = 1;
+      /* Set the floating-point register size, assuming that whoever
+         supplied the description got the current setting right wrt
+         CP0 Status register's bit FR if applicable.  */
+      fpsize = tdesc_register_size (feature, mips_fprs[0]) / 8;
+
+      /* Only accept a description whose floating-point register size
+         matches the requested size or if none was specified.  */
+      valid_p = (info.tdep_info->fp_register_size == 0
+		 || info.tdep_info->fp_register_size == fpsize);
       for (i = 0; i < 32; i++)
 	valid_p &= tdesc_numbered_register (feature, tdesc_data,
 					    i + mips_regnum.fp0, mips_fprs[i]);
@@ -8366,6 +8429,9 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 	    }
 	}
 
+      /* Fix the floating-point register size found.  */
+      info.tdep_info->fp_register_size = fpsize;
+
       /* It would be nice to detect an attempt to use a 64-bit ABI
 	 when only 32-bit registers are provided.  */
       reg_names = NULL;
@@ -8576,6 +8642,11 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       /* Be pedantic about which FPU is selected.  */
       if (gdbarch_tdep (arches->gdbarch)->mips_fpu_type != fpu_type)
 	continue;
+      /* Ditto the requested floating-point register size if any.  */
+      if (info.tdep_info->fp_register_size != 0
+	  && (gdbarch_tdep (arches->gdbarch)->fp_register_size)
+	      != info.tdep_info->fp_register_size)
+	continue;
 
       if (tdesc_data != NULL)
 	tdesc_data_cleanup (tdesc_data);
@@ -8593,6 +8664,8 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->mips_fpu_type = fpu_type;
   tdep->register_size_valid_p = 0;
   tdep->register_size = 0;
+  tdep->fp_register_size = info.tdep_info->fp_register_size;
+  tdep->fp_register_size_fixed_p = 0;
 
   if (info.target_desc)
     {
@@ -8609,6 +8682,12 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 	}
     }
 
+  /* If we haven't figured out the size of floating-point registers
+     by now yet, then assume it is the same as for general-purpose
+     registers.  */
+  if (tdep->fp_register_size == 0)
+    tdep->fp_register_size = mips_isa_regsize (gdbarch);
+
   /* Initially set everything according to the default ABI/ISA.  */
   set_gdbarch_short_bit (gdbarch, 16);
   set_gdbarch_int_bit (gdbarch, 32);
@@ -8830,6 +8909,7 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_integer_to_address (gdbarch, mips_integer_to_address);
 
   set_gdbarch_register_type (gdbarch, mips_register_type);
+  set_gdbarch_regcache_changed (gdbarch, mips_set_float_regsize);
 
   set_gdbarch_print_registers_info (gdbarch, mips_print_registers_info);
 
@@ -8869,7 +8949,7 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   mips_register_g_packet_guesses (gdbarch);
 
   /* Hook in OS ABI-specific overrides, if they have been registered.  */
-  info.tdep_info = tdesc_data;
+  ((struct gdbarch_tdep_info*)(info.tdep_info))->tdesc_data = tdesc_data;
   gdbarch_init_osabi (info, gdbarch);
 
   /* The hook may have adjusted num_regs, fetch the final value and
diff --git a/gdb/mips-tdep.h b/gdb/mips-tdep.h
index 2e4d194..6c1d9ca 100644
--- a/gdb/mips-tdep.h
+++ b/gdb/mips-tdep.h
@@ -113,11 +113,27 @@ struct gdbarch_tdep
   int register_size_valid_p;
   int register_size;
 
+  /* The size of floating-point registers determined at the run time.
+     This corresponds to CP0 Status register's bit FR setting if
+     implemented unless fixed_p is set.  */
+  int fp_register_size_fixed_p;
+  int fp_register_size;
+
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
 };
 
+/* MIPS specific per-architecture initialization information.  */
+struct gdbarch_tdep_info
+{
+  /* Target description data.  */
+  struct tdesc_arch_data *tdesc_data;
+
+  /* The size of floating-point registers determined at the run time.  */
+  int fp_register_size;
+};
+
 /* Register numbers of various important registers.  */
 
 enum
diff --git a/gdb/regcache.c b/gdb/regcache.c
index f0ba0cf..c3405b6 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -534,16 +534,35 @@ get_thread_arch_regcache (ptid_t ptid, struct gdbarch *gdbarch)
 static ptid_t current_thread_ptid;
 static struct gdbarch *current_thread_arch;
 
-struct regcache *
-get_thread_regcache (ptid_t ptid)
+static void
+set_current_thread_ptid_arch (ptid_t ptid)
 {
   if (!current_thread_arch || !ptid_equal (current_thread_ptid, ptid))
     {
       current_thread_ptid = ptid;
       current_thread_arch = target_thread_architecture (ptid);
     }
+}
+
+struct regcache *
+get_thread_regcache (ptid_t ptid)
+{
+  int registers_changed_p = current_regcache == NULL;
+  struct regcache *new_regcache;
+
+  set_current_thread_ptid_arch (ptid);
+  new_regcache = get_thread_arch_regcache (ptid, current_thread_arch);
+
+  if (registers_changed_p
+      && gdbarch_regcache_changed_p (current_thread_arch)
+      && gdbarch_regcache_changed (current_thread_arch, new_regcache))
+    {
+      registers_changed ();
+      set_current_thread_ptid_arch (ptid);
+      new_regcache = get_thread_arch_regcache (ptid, current_thread_arch);
+    }
 
-  return get_thread_arch_regcache (ptid, current_thread_arch);
+  return new_regcache;
 }
 
 struct regcache *
-- 
1.9-rc2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 03/24]     regcache: handle invalidated regcache
  2016-06-27 14:50 [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size Bhushan Attarde
                   ` (2 preceding siblings ...)
  2016-06-27 14:50 ` [PATCH 06/24] mips-linux-nat: pick fp64 target description when appropriate Bhushan Attarde
@ 2016-06-27 14:50 ` Bhushan Attarde
  2016-10-21 22:42   ` Maciej W. Rozycki
  2016-06-27 14:50 ` [PATCH 11/24] MIPS: Add support for hybrid fp32/fp64 mode Bhushan Attarde
                   ` (17 subsequent siblings)
  21 siblings, 1 reply; 37+ messages in thread
From: Bhushan Attarde @ 2016-06-27 14:50 UTC (permalink / raw)
  To: gdb-patches
  Cc: Maciej.Rozycki, Matthew.Fortune, James.Hogan, Andrew.Bennett,
	Jaydeep.Patil, Bhushan Attarde

    When registers are marked as change, set a new regcache_invalidated
    variable which is used by get_thread_regcache to decide whether to
    recreate the gdbarch.

	gdb/ChangeLog:
		* regcache.c (regcache_invalidated): New variable.
		(set_current_thread_ptid_arch): Use regcache_invalidated to
		set registers_changed_p.
		(get_thread_regcache): Reset regcache_invalidated to 0.
		(registers_changed_ptid): Set regcache_invalidated to 1.
---
 gdb/regcache.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/gdb/regcache.c b/gdb/regcache.c
index c3405b6..3cbec6e 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -489,6 +489,7 @@ struct regcache_list
 };
 
 static struct regcache_list *current_regcache;
+static int regcache_invalidated = 1;
 
 struct regcache *
 get_thread_arch_aspace_regcache (ptid_t ptid, struct gdbarch *gdbarch,
@@ -547,7 +548,7 @@ set_current_thread_ptid_arch (ptid_t ptid)
 struct regcache *
 get_thread_regcache (ptid_t ptid)
 {
-  int registers_changed_p = current_regcache == NULL;
+  int registers_changed_p = current_regcache == NULL || regcache_invalidated;
   struct regcache *new_regcache;
 
   set_current_thread_ptid_arch (ptid);
@@ -560,6 +561,7 @@ get_thread_regcache (ptid_t ptid)
       registers_changed ();
       set_current_thread_ptid_arch (ptid);
       new_regcache = get_thread_arch_regcache (ptid, current_thread_arch);
+      regcache_invalidated = 0;
     }
 
   return new_regcache;
@@ -646,6 +648,7 @@ registers_changed_ptid (ptid_t ptid)
 	 forget about any frames we have cached, too.  */
       reinit_frame_cache ();
     }
+  regcache_invalidated = 1;
 }
 
 void
-- 
1.9-rc2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 09/24]     MIPS: Enhance cooked FP format
  2016-06-27 14:50 [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size Bhushan Attarde
                   ` (7 preceding siblings ...)
  2016-06-27 14:51 ` [PATCH 24/24] MIPS R6 forbidden slot support Bhushan Attarde
@ 2016-06-27 14:51 ` Bhushan Attarde
  2016-06-27 14:51 ` [PATCH 20/24] Drop FP and MSA control registers from default info registers Bhushan Attarde
                   ` (12 subsequent siblings)
  21 siblings, 0 replies; 37+ messages in thread
From: Bhushan Attarde @ 2016-06-27 14:51 UTC (permalink / raw)
  To: gdb-patches
  Cc: Maciej.Rozycki, Matthew.Fortune, James.Hogan, Andrew.Bennett,
	Jaydeep.Patil, Bhushan Attarde

    Define cooked FP types as unions representing the possible interpretations
    of the registers.

    Previously the type of the cooked floating point registers depended
    directly on the raw type, so for MIPS32 targets they were single
    precision, and for MIPS64 targets they were single or double precision
    depending on the FP mode.

    However in both cases it is possible for the FP registers to be
    interpreted as either single or double precision values depending on the
    instruction executed, and in a different way depending on the FP mode.

    When FR=0:
    - Even FP registers can be interpreted as a double (aliasing both odd and
      even singles), or a single (aliasing the least significant half of the
      double).
    - Odd FP registers can be interpreted only as a single (aliasing the most
      significant half of the even double).

    When FR=1:
    - All FP registers can be interpreted as a double, or a single (aliasing
      the least significant half of the double).

    Some instructions can also treat them as 32-bit or 64-bit integers for the
    purposes of converting between formats.

    Therefore define two cooked fp types, as follows.

    The first type, fp32, is used for odd FP registers when FR=0, which can
    only be interpreted as singles or 32-bit integers. It is equivalent to
    this C definition:
      union fp32 {
        float f32;
        int32_t i32;
      };

    The second type, fp64, is used for even FP registers when FR=0, and all FP
    registers when FR=1, which can be interpreted as either singles or
    doubles, with the single always in the least significant half of the
    double. It is roughly equivalent to this C definition (when interpreted as
    little endian):
      union fp64 {
        float  f32;
        double f64;
        int32  i32;
        int64  i64;
      };

    Since multiple bits of code need to handle the different raw register
    layouts and these new cooked types for different modes, the details are
    abstracted with the following functions:
    - mips_get_fp_single_location: Gets the raw register and offset containing
      a single precision register value.
    - mips_get_fp_double_location: Gets the raw register(s) and offset(s)
      composing a double precision register value.
    - mips_get_fp_multi_location: Gets the raw register(s) and offset(s)
      composing a cooked register value.

    These abstractions are used by the code which reads and writes the cooked
    (pseudo) FP registers, and the code which prints out the FP registers
    ("info float").

    Now that the cooked type may be composed of multiple raw registers (where
    only single precision raw values are provided), there is no need to
    provide conversion functions from the 32-bit cooked value to double.
    Instead the opposite is required for extracting a single out of the 64-bit
    cooked value.

    For example, with FR=0:
      (gdb) info float
      ...
      f30: 0x41f00000 flt: 30                dbl: 6442451998.9999998
      f31: 0x41f80000 flt: 31
      (gdb) p $f30
      $1 = {f32 = 30, f64 = 6442451998.9999998,
            i32 = 1106247680, i64 = 4753549407795806208}
      (gdb) p $f31
      $2 = {f32 = 31, i32 = 1106771968}

    And with FR=1:
      (gdb) info float
      ...
      f30: 0x403e000041f00000 flt: 30                dbl: 30.000003930181265
      f31: 0x403f000041f80000 flt: 31                dbl: 31.00000393204391
      (gdb) p $f30
      $1 = {f32 = 30, f64 = 30.000003930181265,
            i32 = 1106247680, i64 = 4629137468089696256}
      (gdb) p $f31
      $2 = {f32 = 31, f64 = 31.00000393204391,
            i32 = 1106771968, i64 = 4629418943066931200}

    gdb/ChangeLog:

    	* mips-tdep.c (mips_register_reggroup_p): Match FP registers with
    	mips_float_register_p rather than TYPE_CODE_FLT.
    	(struct mips_reg_part, mips_get_fp_single_location,
    	mips_get_fp_double_location, mips_get_fp_multi_location,
    	mips_regcache_raw_read_parts, mips_regcache_raw_write_parts,
    	mips_fp32_type, mips_fp64_type, mips_fp_type): New definitions.
    	(mips_pseudo_register_read, mips_pseudo_register_write,
    	mips_convert_register_float_case_p, mips_register_to_value,
    	mips_value_to_register, mips_register_type,
    	mips_pseudo_register_type, mips_read_fp_register_single,
    	mips_read_fp_register_double, mips_print_fp_register): Convert to
    	handle new cooked FP format.
    	(mips_gdbarch_init): Initialise tdep->fp32_type and
    	tdep->fp64_type.
    	mips-tdep.h (struct gdbarch_tdep): Add fp32_type and fp64_type.
---
 gdb/mips-tdep.c | 537 ++++++++++++++++++++++++++++++++++++++++++++------------
 gdb/mips-tdep.h |   2 +
 2 files changed, 430 insertions(+), 109 deletions(-)

diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index 47ddef4..0024edf 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -789,6 +789,185 @@ mips_tdesc_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
   return mips_register_reggroup_p (gdbarch, regnum, reggroup);
 }
 
+/* Describes a part of a raw register, used for constructing cooked registers.
+   */
+
+struct mips_reg_part
+{
+  unsigned int regnum;
+  unsigned char offset;
+  unsigned char size;
+};
+
+/* Get the raw register containing a single precision float.
+   Returns the number of parts (maximum 1) written through loc.	 */
+
+static unsigned int
+mips_get_fp_single_location (struct gdbarch *gdbarch,
+			     unsigned int idx,
+			     struct mips_reg_part *loc)
+{
+  int raw_num = mips_regnum (gdbarch)->fp0;
+  int raw_len = register_size (gdbarch, raw_num);
+  enum mips_fpu_mode fp_mode = gdbarch_tdep (gdbarch)->fp_mode;
+  int big_endian;
+
+  /* Only even doubles provided, in pairs of 32-bit registers.  */
+  if (raw_len == 4)
+    {
+      /* In 64-bit FP mode, odd singles don't alias even doubles.  */
+      if (fp_mode == MIPS_FPU_64 && idx & 1)
+	return 0;
+
+      loc->regnum = raw_num + idx;
+      loc->offset = 0;
+      loc->size = 4;
+      return 1;
+    }
+
+  if (raw_len != 8)
+    return 0;
+
+  /* All doubles provided.  */
+  big_endian = (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG);
+
+  loc->size = 4;
+  switch (fp_mode)
+    {
+    case MIPS_FPU_32:
+      loc->regnum = raw_num + (idx & ~1);
+      loc->offset = 4 * (big_endian ^ (idx & 1));
+      return 1;
+    case MIPS_FPU_64:
+      loc->regnum = raw_num + idx;
+      loc->offset = 4 * big_endian;
+      return 1;
+    default:
+      return 0;
+    }
+}
+
+/* Get the raw register part(s) containing a double precision float.
+   Returns the number of parts (maximum 2) written through loc.	 */
+
+static unsigned int
+mips_get_fp_double_location (struct gdbarch *gdbarch,
+			     unsigned int idx,
+			     struct mips_reg_part *loc)
+{
+  int raw_num = mips_regnum (gdbarch)->fp0;
+  int raw_len = register_size (gdbarch, raw_num);
+  enum mips_fpu_mode fp_mode = gdbarch_tdep (gdbarch)->fp_mode;
+  int big_endian = (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG);
+
+  /* Only even doubles provided, in pairs of 32-bit registers.  */
+  if (raw_len == 4)
+    {
+      /* No odd doubles.  */
+      if (idx & 1)
+	return 0;
+
+      /* Even register contains even single, least significant end of double */
+      loc[big_endian].regnum = raw_num + idx;
+      loc[big_endian].offset = 0;
+      loc[big_endian].size = 4;
+      loc[!big_endian].regnum = raw_num + idx + 1;
+      loc[!big_endian].offset = 0;
+      loc[!big_endian].size = 4;
+      return 2;
+    }
+
+  if (raw_len != 8)
+    return 0;
+
+  /* FPU32 doesn't have odd doubles */
+  if (fp_mode == MIPS_FPU_32 && idx & 1)
+    return 0;
+
+  /* All doubles provided.  */
+  loc->regnum = raw_num + idx;
+  loc->offset = 0;
+  loc->size = 8;
+  return 1;
+}
+
+/* Get the raw register part(s) composing a cooked float register.
+   Returns the number of parts (maximum 2) written through loc.	 */
+
+static unsigned int
+mips_get_fp_multi_location (struct gdbarch *gdbarch,
+			    unsigned int idx,
+			    unsigned int cooked_len,
+			    struct mips_reg_part *loc)
+{
+  unsigned int parts, total_parts = 0;
+
+  /* The cooked formats supported are:
+     fp32 (len=4):  just a single.
+     fp64 (len=8):  double (with aliased single).  */
+  if (cooked_len > 8 || cooked_len < 4 || cooked_len & 0x3)
+    internal_error (__FILE__, __LINE__, _("bad cooked register size"));
+
+  /* Formats containing a distinct double.  */
+  if (cooked_len & 8)
+    {
+      parts = mips_get_fp_double_location (gdbarch, idx, loc);
+      if (!parts)
+	return 0;
+      total_parts += parts;
+      loc += parts;
+    }
+
+  /* Formats containing a distinct single.  */
+  if (cooked_len & 4)
+    {
+      parts = mips_get_fp_single_location (gdbarch, idx, loc);
+      if (!parts)
+	return 0;
+      total_parts += parts;
+    }
+
+  return total_parts;
+}
+
+/* Read multiple register parts from the register cache into a buffer.	*/
+
+static enum register_status
+mips_regcache_raw_read_parts (struct regcache *regcache,
+			      struct mips_reg_part *loc,
+			      unsigned int parts,
+			      gdb_byte **buf)
+{
+  enum register_status ret = REG_UNAVAILABLE;
+
+  for (; parts; --parts, ++loc)
+    {
+      ret = regcache_raw_read_part (regcache, loc->regnum, loc->offset,
+				    loc->size, *buf);
+      if (ret != REG_VALID)
+	return ret;
+      *buf += loc->size;
+    }
+
+  return ret;
+}
+
+/* Write multiple register parts of the register cache from a buffer.  */
+
+static void
+mips_regcache_raw_write_parts (struct regcache *regcache,
+			       struct mips_reg_part *loc,
+			       unsigned int parts,
+			       const gdb_byte **buf)
+{
+  for (; parts; --parts, ++loc)
+    {
+      regcache_raw_write_part (regcache, loc->regnum, loc->offset, loc->size,
+			       *buf);
+      *buf += loc->size;
+    }
+}
+
 /* Map the symbol table registers which live in the range [1 *
    gdbarch_num_regs .. 2 * gdbarch_num_regs) back onto the corresponding raw
    registers.  Take care of alignment and size problems.  */
@@ -798,12 +977,27 @@ mips_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 			   int cookednum, gdb_byte *buf)
 {
   int rawnum = cookednum % gdbarch_num_regs (gdbarch);
+  int fpnum;
+  int raw_len, cooked_len;
+
   gdb_assert (cookednum >= gdbarch_num_regs (gdbarch)
 	      && cookednum < 2 * gdbarch_num_regs (gdbarch));
-  if (register_size (gdbarch, rawnum) == register_size (gdbarch, cookednum))
+
+  raw_len = register_size (gdbarch, rawnum);
+  cooked_len = register_size (gdbarch, cookednum);
+
+  if (mips_float_register_p (gdbarch, rawnum))
+    {
+      struct mips_reg_part loc[2];
+      unsigned int parts;
+
+      fpnum = rawnum - mips_regnum (gdbarch)->fp0;
+      parts = mips_get_fp_multi_location (gdbarch, fpnum, cooked_len, loc);
+      return mips_regcache_raw_read_parts (regcache, loc, parts, &buf);
+    }
+  else if (raw_len == cooked_len)
     return regcache_raw_read (regcache, rawnum, buf);
-  else if (register_size (gdbarch, rawnum) >
-	   register_size (gdbarch, cookednum))
+  else if (raw_len > cooked_len)
     {
       if (gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p)
 	return regcache_raw_read_part (regcache, rawnum, 0, 4, buf);
@@ -829,12 +1023,27 @@ mips_pseudo_register_write (struct gdbarch *gdbarch,
 			    const gdb_byte *buf)
 {
   int rawnum = cookednum % gdbarch_num_regs (gdbarch);
+  int fpnum;
+  int raw_len, cooked_len;
+
   gdb_assert (cookednum >= gdbarch_num_regs (gdbarch)
 	      && cookednum < 2 * gdbarch_num_regs (gdbarch));
-  if (register_size (gdbarch, rawnum) == register_size (gdbarch, cookednum))
+
+  raw_len = register_size (gdbarch, rawnum);
+  cooked_len = register_size (gdbarch, cookednum);
+
+  if (mips_float_register_p (gdbarch, rawnum))
+    {
+      struct mips_reg_part loc[2];
+      unsigned int parts;
+
+      fpnum = rawnum - mips_regnum (gdbarch)->fp0;
+      parts = mips_get_fp_multi_location (gdbarch, fpnum, cooked_len, loc);
+      mips_regcache_raw_write_parts (regcache, loc, parts, &buf);
+    }
+  else if (raw_len == cooked_len)
     regcache_raw_write (regcache, rawnum, buf);
-  else if (register_size (gdbarch, rawnum) >
-	   register_size (gdbarch, cookednum))
+  else if (raw_len > cooked_len)
     {
       if (gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p)
 	regcache_raw_write_part (regcache, rawnum, 0, 4, buf);
@@ -927,18 +1136,17 @@ set_mips64_transfers_32bit_regs (char *args, int from_tty,
 
 /* Convert to/from a register and the corresponding memory value.  */
 
-/* This predicate tests for the case of an 8 byte floating point
-   value that is being transferred to or from a pair of floating point
-   registers each of which are (or are considered to be) only 4 bytes
-   wide.  */
+/* This predicate tests for the case of a 4 byte floating point
+   value that is being transferred to or from a floating point
+   register which is 8 bytes wide.  */
+
 static int
 mips_convert_register_float_case_p (struct gdbarch *gdbarch, int regnum,
 				    struct type *type)
 {
-  return (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG
-	  && register_size (gdbarch, regnum) == 4
+  return (register_size (gdbarch, regnum) == 8
 	  && mips_float_register_p (gdbarch, regnum)
-	  && TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8);
+	  && TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) == 4);
 }
 
 /* This predicate tests for the case of a value of less than 8
@@ -972,16 +1180,19 @@ mips_register_to_value (struct frame_info *frame, int regnum,
 
   if (mips_convert_register_float_case_p (gdbarch, regnum, type))
     {
-      get_frame_register (frame, regnum + 0, to + 4);
-      get_frame_register (frame, regnum + 1, to + 0);
-
-      if (!get_frame_register_bytes (frame, regnum + 0, 0, 4, to + 4,
-				     optimizedp, unavailablep))
-	return 0;
-
-      if (!get_frame_register_bytes (frame, regnum + 1, 0, 4, to + 0,
-				     optimizedp, unavailablep))
-	return 0;
+      /* single comes from low half of 64-bit register */
+      if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+	{
+	  if (!get_frame_register_bytes (frame, regnum, 4, 4, to,
+					 optimizedp, unavailablep))
+	    return 0;
+	}
+      else
+	{
+	  if (!get_frame_register_bytes (frame, regnum, 0, 4, to,
+					 optimizedp, unavailablep))
+	    return 0;
+	}
       *optimizedp = *unavailablep = 0;
       return 1;
     }
@@ -1024,6 +1235,101 @@ mips_config5_type (struct gdbarch *gdbarch)
   return tdep->config5_type;
 }
 
+/* Get 32-bit only floating point type, which can be interpreted as either a
+   single precision float or a 32-bit signed integer.
+   This is used for odd fp registers when FR=0. In this case there are no odd
+   doubles.  */
+
+static struct type *
+mips_fp32_type (struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (tdep->fp32_type == NULL)
+    {
+      const struct builtin_type *bt = builtin_type (gdbarch);
+      struct type *t;
+
+      /* The type we're building is this:
+      union __gdb_builtin_mips_fp32 {
+	  float f32;
+	  int32_t i32;
+      }; */
+
+      t = arch_composite_type (gdbarch, "__gdb_builtin_type_mips_fp32",
+			       TYPE_CODE_UNION);
+      append_composite_type_field (t, "f32", bt->builtin_float);
+      append_composite_type_field (t, "i32", bt->builtin_int32);
+
+      TYPE_NAME (t) = "fp32";
+      tdep->fp32_type = t;
+    }
+
+  return tdep->fp32_type;
+}
+
+/* Get general floating point type, which can be interpreted as either a
+   single or double precision float, or a 32-bit or 64-bit signed integer.
+   This is used for even fp registers when FR=0 (doubles are constructed from
+   even/odd pairs of fp registers so only even registers can be interpreted as
+   double precision flaots) and for all fp registers when FR=1.  */
+
+static struct type *
+mips_fp64_type (struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (tdep->fp64_type == NULL)
+    {
+      const struct builtin_type *bt = builtin_type (gdbarch);
+      int big_endian = (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG);
+      struct type *t;
+      struct field *f;
+
+      /* The type we're building is roughly this (little endian):
+
+      union __gdb_builtin_mips_fp64 {
+	  float  f32;
+	  double f64;
+	  int32  i32;
+	  int64  i64;
+      }; */
+
+      t = arch_composite_type (gdbarch, "__gdb_builtin_type_mips_fp64",
+			       TYPE_CODE_UNION);
+      f = append_composite_type_field_raw (t, "f32", bt->builtin_float);
+      SET_FIELD_BITPOS (*f, 32*big_endian);
+      f = append_composite_type_field_raw (t, "f64", bt->builtin_double);
+      SET_FIELD_BITPOS (*f, 0);
+      f = append_composite_type_field_raw (t, "i32", bt->builtin_int32);
+      SET_FIELD_BITPOS (*f, 32*big_endian);
+      f = append_composite_type_field_raw (t, "i64", bt->builtin_int64);
+      SET_FIELD_BITPOS (*f, 0);
+
+      TYPE_LENGTH (t) = 8;
+      TYPE_NAME (t) = "fp64";
+      tdep->fp64_type = t;
+    }
+
+  return tdep->fp64_type;
+}
+
+/* Get the floating point type for an arbitrary FP register. This returns the
+   appropriate type depending on the possible types and overlaps of the
+   register.  */
+
+static struct type *
+mips_fp_type (struct gdbarch *gdbarch, int fpnum)
+{
+  if ((fpnum & 1) == 0 || mips_float_regsize (gdbarch) == 8)
+    /* Even singles and doubles always overlap, as do odd singles and
+       doubles when FR=1.  */
+    return mips_fp64_type (gdbarch);
+  else
+    /* 32-bit odd singles (there are no odd doubles).  */
+    return mips_fp32_type (gdbarch);
+}
+
 static void
 mips_value_to_register (struct frame_info *frame, int regnum,
 			struct type *type, const gdb_byte *from)
@@ -1032,8 +1338,11 @@ mips_value_to_register (struct frame_info *frame, int regnum,
 
   if (mips_convert_register_float_case_p (gdbarch, regnum, type))
     {
-      put_frame_register (frame, regnum + 0, from + 4);
-      put_frame_register (frame, regnum + 1, from + 0);
+      /* single goes in low half of 64-bit register */
+      if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+	put_frame_register_bytes (frame, regnum, 4, 4, from);
+      else
+	put_frame_register_bytes (frame, regnum, 0, 4, from);
     }
   else if (mips_convert_register_gpreg_case_p (gdbarch, regnum, type))
     {
@@ -1105,9 +1414,7 @@ mips_register_type (struct gdbarch *gdbarch, int regnum)
          either 64-bit or 32-bit via the CP0 Status register's FR bit.
          Use the current setting for cooked registers.  */
       if (mips_float_register_p (gdbarch, regnum))
-	return (mips_float_regsize (gdbarch) == 4
-		? builtin_type (gdbarch)->builtin_float
-		: builtin_type (gdbarch)->builtin_double);
+	return mips_fp_type (gdbarch, rawnum - mips_regnum (gdbarch)->fp0);
       else if (rawnum == mips_regnum (gdbarch)->fp_control_status
 	  || rawnum == mips_regnum (gdbarch)->fp_implementation_revision)
 	return builtin_type (gdbarch)->builtin_int32;
@@ -1145,7 +1452,7 @@ mips_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
 {
   const int num_regs = gdbarch_num_regs (gdbarch);
   int rawnum = regnum % num_regs;
-  struct type *rawtype;
+  struct type *rawtype, *fp_rawtype;
 
   gdb_assert (regnum >= num_regs && regnum < 2 * num_regs);
 
@@ -1159,7 +1466,7 @@ mips_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
        not try to convert between FPU layouts.  A target description is
        expected to have taken the CP0 Status register's FR bit into account
        as necessary, this has been already verified in mips_gdbarch_init.  */
-    return rawtype;
+    return mips_fp_type (gdbarch, rawnum - mips_regnum (gdbarch)->fp0);
 
   /* Use pointer types for registers if we can.  For n32 we can not,
      since we do not have a 64-bit pointer type.  */
@@ -6266,79 +6573,60 @@ mips_o64_return_value (struct gdbarch *gdbarch, struct value *function,
    and below).  */
 
 /* Copy a 32-bit single-precision value from the current frame
-   into rare_buffer.  */
+   into rare_buffer. This is done by reading the pseudo register and extracting
+   the relevant part so as not to duplicate code.
+   Returns 0 on failure. */
 
-static void
+static int
 mips_read_fp_register_single (struct frame_info *frame, int regno,
 			      gdb_byte *rare_buffer)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
-  int fpsize = register_size (gdbarch, regno);
-  gdb_byte *raw_buffer = alloca (fpsize);
+  int cooked_size = register_size (gdbarch, regno);
+  gdb_byte *raw_buffer = alloca (cooked_size);
+  int big_endian = (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG);
 
-  if (!deprecated_frame_register_read (frame, regno, raw_buffer))
-    error (_("can't read register %d (%s)"),
-	   regno, gdbarch_register_name (gdbarch, regno));
-  if (fpsize == 8)
-    {
-      /* We have a 64-bit value for this register.  Find the low-order
-         32 bits.  */
-      int offset;
+  if (cooked_size < 4)
+    return 0;
 
-      if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
-	offset = 4;
-      else
-	offset = 0;
+  if (cooked_size == 4)
+    /* FR=0 odd */
+    return deprecated_frame_register_read (frame, regno, rare_buffer);
 
-      memcpy (rare_buffer, raw_buffer + offset, 4);
-    }
+  if (!deprecated_frame_register_read (frame, regno, raw_buffer))
+    return 0;
+
+  if (cooked_size == 8)
+    /* FR=1
+       Single is overlapping double. */
+    memcpy(rare_buffer, raw_buffer + 4*big_endian, 4);
   else
-    {
-      memcpy (rare_buffer, raw_buffer, 4);
-    }
+    return 0;
+  return 1;
 }
 
 /* Copy a 64-bit double-precision value from the current frame into
-   rare_buffer.  This may include getting half of it from the next
-   register.  */
+   rare_buffer. This is done by reading the pseudo register and extracting the
+   relevant part so as not to duplicate code.
+   Returns 0 on failure. */
 
-static void
+static int
 mips_read_fp_register_double (struct frame_info *frame, int regno,
 			      gdb_byte *rare_buffer)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
-  int fpsize = register_size (gdbarch, regno);
+  int cooked_size = register_size (gdbarch, regno);
+  gdb_byte *raw_buffer = alloca (cooked_size);
 
-  if (fpsize == 8)
-    {
-      /* We have a 64-bit value for this register, and we should use
-         all 64 bits.  */
-      if (!deprecated_frame_register_read (frame, regno, rare_buffer))
-	error (_("can't read register %d (%s)"),
-	       regno, gdbarch_register_name (gdbarch, regno));
-    }
-  else
-    {
-      int rawnum = regno % gdbarch_num_regs (gdbarch);
+  if (cooked_size < 8)
+    /* FR=0 odd */
+    return 0;
 
-      if ((rawnum - mips_regnum (gdbarch)->fp0) & 1)
-	internal_error (__FILE__, __LINE__,
-			_("mips_read_fp_register_double: bad access to "
-			"odd-numbered FP register"));
+  if (!deprecated_frame_register_read (frame, regno, raw_buffer))
+    return 0;
 
-      /* mips_read_fp_register_single will find the correct 32 bits from
-         each register.  */
-      if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
-	{
-	  mips_read_fp_register_single (frame, regno, rare_buffer + 4);
-	  mips_read_fp_register_single (frame, regno + 1, rare_buffer);
-	}
-      else
-	{
-	  mips_read_fp_register_single (frame, regno, rare_buffer);
-	  mips_read_fp_register_single (frame, regno + 1, rare_buffer + 4);
-	}
-    }
+  memcpy(rare_buffer, raw_buffer, 8);
+  return 1;
 }
 
 static void
@@ -6349,7 +6637,7 @@ mips_print_fp_register (struct ui_file *file, struct frame_info *frame,
   int fpsize = register_size (gdbarch, regnum);
   gdb_byte *raw_buffer;
   double doub, flt1;	/* Doubles extracted from raw hex data.  */
-  int inv1, inv2;
+  int res1, res2, inv1, inv2;
 
   raw_buffer = alloca (2 * fpsize);
 
@@ -6364,29 +6652,39 @@ mips_print_fp_register (struct ui_file *file, struct frame_info *frame,
 
       /* 4-byte registers: Print hex and floating.  Also print even
          numbered registers as doubles.  */
-      mips_read_fp_register_single (frame, regnum, raw_buffer);
-      flt1 = unpack_double (builtin_type (gdbarch)->builtin_float,
-			    raw_buffer, &inv1);
+      res1 = mips_read_fp_register_single (frame, regnum, raw_buffer);
+      if (res1)
+	{
+	  flt1 = unpack_double (builtin_type (gdbarch)->builtin_float,
+				raw_buffer, &inv1);
 
-      get_formatted_print_options (&opts, 'x');
-      print_scalar_formatted (raw_buffer,
-			      builtin_type (gdbarch)->builtin_uint32,
-			      &opts, 'w', file);
+	  get_formatted_print_options (&opts, 'x');
+	  print_scalar_formatted (raw_buffer,
+				  builtin_type (gdbarch)->builtin_uint32,
+				  &opts, 'w', file);
+	}
+      else
+	fprintf_filtered (file, "0x????????");
 
       fprintf_filtered (file, " flt: ");
-      if (inv1)
+      if (!res1)
+	fprintf_filtered (file, " <unavailable>   ");
+      else if (inv1)
 	fprintf_filtered (file, " <invalid float> ");
       else
 	fprintf_filtered (file, "%-17.9g", flt1);
 
       if ((regnum - gdbarch_num_regs (gdbarch)) % 2 == 0)
 	{
-	  mips_read_fp_register_double (frame, regnum, raw_buffer);
-	  doub = unpack_double (builtin_type (gdbarch)->builtin_double,
-				raw_buffer, &inv2);
+	  res2 = mips_read_fp_register_double (frame, regnum, raw_buffer);
+	  if (res2)
+	      doub = unpack_double (builtin_type (gdbarch)->builtin_double,
+				    raw_buffer, &inv2);
 
 	  fprintf_filtered (file, " dbl: ");
-	  if (inv2)
+	  if (!res2)
+	    fprintf_filtered (file, "<unavailable>");
+	  else if (inv2)
 	    fprintf_filtered (file, "<invalid double>");
 	  else
 	    fprintf_filtered (file, "%-24.17g", doub);
@@ -6395,29 +6693,48 @@ mips_print_fp_register (struct ui_file *file, struct frame_info *frame,
   else
     {
       struct value_print_options opts;
+      int no_odd;
+
+      /* if top half isn't provided we can't access odd floats or doubles */
+      if ((regnum - gdbarch_num_regs (gdbarch)) & 1 &&
+	  register_size (gdbarch, regnum % gdbarch_num_regs (gdbarch)) < 8)
+	{
+	  fprintf_filtered (file, "<unavailable>");
+	  return;
+	}
 
       /* Eight byte registers: print each one as hex, float and double.  */
-      mips_read_fp_register_single (frame, regnum, raw_buffer);
-      flt1 = unpack_double (builtin_type (gdbarch)->builtin_float,
-			    raw_buffer, &inv1);
+      res1 = mips_read_fp_register_single (frame, regnum, raw_buffer);
+      if (res1)
+	flt1 = unpack_double (builtin_type (gdbarch)->builtin_float,
+			      raw_buffer, &inv1);
 
-      mips_read_fp_register_double (frame, regnum, raw_buffer);
-      doub = unpack_double (builtin_type (gdbarch)->builtin_double,
-			    raw_buffer, &inv2);
+      res2 = mips_read_fp_register_double (frame, regnum, raw_buffer);
+      if (res2)
+	{
+	  doub = unpack_double (builtin_type (gdbarch)->builtin_double,
+				raw_buffer, &inv2);
 
-      get_formatted_print_options (&opts, 'x');
-      print_scalar_formatted (raw_buffer,
-			      builtin_type (gdbarch)->builtin_uint64,
-			      &opts, 'g', file);
+	  get_formatted_print_options (&opts, 'x');
+	  print_scalar_formatted (raw_buffer,
+				  builtin_type (gdbarch)->builtin_uint64,
+				  &opts, 'g', file);
+	}
+      else
+	fprintf_filtered (file, "0x????????????????");
 
       fprintf_filtered (file, " flt: ");
-      if (inv1)
-	fprintf_filtered (file, "<invalid float>");
+      if (!res1)
+	fprintf_filtered (file, " <unavailable>  ");
+      else if (inv1)
+	fprintf_filtered (file, " <invalid float>");
       else
 	fprintf_filtered (file, "%-17.9g", flt1);
 
       fprintf_filtered (file, " dbl: ");
-      if (inv2)
+      if (!res2)
+	fprintf_filtered (file, "<unavailable>   ");
+      else if (inv2)
 	fprintf_filtered (file, "<invalid double>");
       else
 	fprintf_filtered (file, "%-24.17g", doub);
@@ -8716,6 +9033,8 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->fp_mode = ((struct gdbarch_tdep_info*)(info.tdep_info))->fp_mode;
   tdep->fp_register_mode_fixed_p = 0;
   tdep->config5_type = NULL;
+  tdep->fp32_type = NULL;
+  tdep->fp64_type = NULL;
 
   if (info.target_desc)
     {
diff --git a/gdb/mips-tdep.h b/gdb/mips-tdep.h
index b6f99f2..11353be 100644
--- a/gdb/mips-tdep.h
+++ b/gdb/mips-tdep.h
@@ -130,6 +130,8 @@ struct gdbarch_tdep
 
   /* ISA-specific data types.  */
   struct type *config5_type;
+  struct type *fp32_type;
+  struct type *fp64_type;
 
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
-- 
1.9-rc2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 02/24]     Add MIPS32 FPU64 GDB target descriptions
  2016-06-27 14:50 [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size Bhushan Attarde
                   ` (10 preceding siblings ...)
  2016-06-27 14:51 ` [PATCH 23/24] MIPS R6 opcode table shuffle for LDC2/SDC2 Bhushan Attarde
@ 2016-06-27 14:51 ` Bhushan Attarde
  2016-10-12 12:42   ` Maciej W. Rozycki
  2016-06-27 14:51 ` [PATCH 21/24] MIPSR6 support for GDB Bhushan Attarde
                   ` (9 subsequent siblings)
  21 siblings, 1 reply; 37+ messages in thread
From: Bhushan Attarde @ 2016-06-27 14:51 UTC (permalink / raw)
  To: gdb-patches
  Cc: Maciej.Rozycki, Matthew.Fortune, James.Hogan, Andrew.Bennett,
	Jaydeep.Patil, Bhushan Attarde

    Add a couple of new target descriptions for MIPS32 targets with 64-bit
    floating point registers, with and without DSP.

    These are identical to their 32-bit FPU counterparts except that the FP
    registers are 64-bits long to allow for debugging of F64=1 MIPS32 targets
    such as MIPS32r2 compatible cores, and they include the Config5 CP0
    register which has an FRE bit.

    F64 targets have an FR bit in the status register to specify the effective
    register size, and the FRE bit is used with FR=1 to enable a compatibility
    mode which is similar to FR=0 but with usable odd doubles which don't
    alias with any other FP registers.

    gdb/ChangeLog:

    	* features/Makefile (WHICH): Add mips-fpu64-linux and
    	mips-fpu64-dsp-linux and Sort microblaze out of the way
        of mips/mips64
    	(mips-fpu64-expedite): Set.
    	(mips-fpu64-dsp-expedite): Set.
    	* features/mips-fpu64-dsp-linux.xml: New file.
    	* features/mips-fpu64-linux.xml: New file.
    	* features/mips-fpu64.xml: New file.
    	* features/mips-fpu64-dsp-linux.c: New generated file.
    	* features/mips-fpu64-linux.c: New generated file.
    	* regformats/mips-fpu64-dsp-linux.dat: New generated file.
    	* regformats/mips-fpu64-linux.dat: New generated file.

    gdb/gdbserver/ChangeLog:

    	* Makefile.in (clean): Delete mips-fpu64-linux.c and
    	mips-fpu64-dsp-linux.c.
    	(mips-fpu64-linux.c): New rule.
    	(mips-fpu64-dsp-linux.c): New rule.
    	* configure.srv (srv_regobj): Add mips-fpu64-linux.o and
    	mips-fpu64-dsp-linux.o.
    	(srv_xmlfiles): Add mips-fpu64-linux.xml,
    	mips-fpu64-dsp-linux.xml, mips-cp0-fpu64.xml and mips-fpu64.xml.
---
 gdb/features/Makefile                   |   6 +-
 gdb/features/mips-fpu64-dsp-linux.c     | 111 ++++++++++++++++++++++++++++++++
 gdb/features/mips-fpu64-dsp-linux.xml   |  20 ++++++
 gdb/features/mips-fpu64-linux.c         | 102 +++++++++++++++++++++++++++++
 gdb/features/mips-fpu64-linux.xml       |  19 ++++++
 gdb/features/mips-fpu64.xml             |  45 +++++++++++++
 gdb/gdbserver/Makefile.in               |   7 +-
 gdb/gdbserver/configure.srv             |   5 ++
 gdb/regformats/mips-fpu64-dsp-linux.dat |  85 ++++++++++++++++++++++++
 gdb/regformats/mips-fpu64-linux.dat     |  78 ++++++++++++++++++++++
 10 files changed, 475 insertions(+), 3 deletions(-)
 create mode 100644 gdb/features/mips-fpu64-dsp-linux.c
 create mode 100644 gdb/features/mips-fpu64-dsp-linux.xml
 create mode 100644 gdb/features/mips-fpu64-linux.c
 create mode 100644 gdb/features/mips-fpu64-linux.xml
 create mode 100644 gdb/features/mips-fpu64.xml
 create mode 100644 gdb/regformats/mips-fpu64-dsp-linux.dat
 create mode 100644 gdb/regformats/mips-fpu64-linux.dat

diff --git a/gdb/features/Makefile b/gdb/features/Makefile
index 10173cf..b6baaf66 100644
--- a/gdb/features/Makefile
+++ b/gdb/features/Makefile
@@ -57,8 +57,8 @@ WHICH = aarch64 \
 	i386/x32 i386/x32-linux \
 	i386/x32-avx i386/x32-avx-linux \
 	i386/x32-avx512 i386/x32-avx512-linux \
-	mips-linux mips-dsp-linux \
 	microblaze-with-stack-protect \
+	mips-linux mips-dsp-linux mips-fpu64-linux mips-fpu64-dsp-linux \
 	mips64-linux mips64-dsp-linux \
 	nios2-linux \
 	rs6000/powerpc-32 \
@@ -100,11 +100,13 @@ i386/x32-avx-expedite = rbp,rsp,rip
 i386/x32-avx-linux-expedite = rbp,rsp,rip
 i386/x32-avx512-expedite = rbp,rsp,rip
 i386/x32-avx512-linux-expedite = rbp,rsp,rip
+microblaze-expedite = r1,rpc
 mips-expedite = r29,pc
 mips-dsp-expedite = r29,pc
+mips-fpu64-expedite = r29,pc
+mips-fpu64-dsp-expedite = r29,pc
 mips64-expedite = r29,pc
 mips64-dsp-expedite = r29,pc
-microblaze-expedite = r1,rpc
 nios2-linux-expedite = sp,pc
 powerpc-expedite = r1,pc
 rs6000/powerpc-cell32l-expedite = r1,pc,r0,orig_r3,r4
diff --git a/gdb/features/mips-fpu64-dsp-linux.c b/gdb/features/mips-fpu64-dsp-linux.c
new file mode 100644
index 0000000..c6dd7d0
--- /dev/null
+++ b/gdb/features/mips-fpu64-dsp-linux.c
@@ -0,0 +1,111 @@
+/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
+  Original: mips-fpu64-dsp-linux.xml */
+
+#include "defs.h"
+#include "osabi.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_mips_fpu64_dsp_linux;
+static void
+initialize_tdesc_mips_fpu64_dsp_linux (void)
+{
+  struct target_desc *result = allocate_target_description ();
+  struct tdesc_feature *feature;
+
+  set_tdesc_architecture (result, bfd_scan_arch ("mips"));
+
+  set_tdesc_osabi (result, osabi_from_tdesc_string ("GNU/Linux"));
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cpu");
+  tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r13", 13, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r14", 14, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r15", 15, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r16", 16, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r17", 17, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r18", 18, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r19", 19, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r20", 20, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r21", 21, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r22", 22, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r23", 23, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r24", 24, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r25", 25, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r26", 26, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r27", 27, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r28", 28, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r29", 29, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r30", 30, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r31", 31, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lo", 33, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hi", 34, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pc", 37, 1, NULL, 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cp0");
+  tdesc_create_reg (feature, "status", 32, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "badvaddr", 35, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "cause", 36, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "config5", 38, 1, NULL, 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.fpu");
+  tdesc_create_reg (feature, "f0", 39, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f1", 40, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f2", 41, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f3", 42, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f4", 43, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f5", 44, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f6", 45, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f7", 46, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f8", 47, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f9", 48, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f10", 49, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f11", 50, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f12", 51, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f13", 52, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f14", 53, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f15", 54, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f16", 55, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f17", 56, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f18", 57, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f19", 58, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f20", 59, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f21", 60, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f22", 61, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f23", 62, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f24", 63, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f25", 64, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f26", 65, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f27", 66, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f28", 67, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f29", 68, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f30", 69, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f31", 70, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "fcsr", 71, 1, "float", 32, "int");
+  tdesc_create_reg (feature, "fir", 72, 1, "float", 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.dsp");
+  tdesc_create_reg (feature, "hi1", 73, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lo1", 74, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hi2", 75, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lo2", 76, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hi3", 77, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lo3", 78, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "dspctl", 79, 1, NULL, 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.linux");
+  tdesc_create_reg (feature, "restart", 80, 1, "system", 32, "int");
+
+  tdesc_mips_fpu64_dsp_linux = result;
+}
diff --git a/gdb/features/mips-fpu64-dsp-linux.xml b/gdb/features/mips-fpu64-dsp-linux.xml
new file mode 100644
index 0000000..f0de5ce
--- /dev/null
+++ b/gdb/features/mips-fpu64-dsp-linux.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <architecture>mips</architecture>
+  <osabi>GNU/Linux</osabi>
+  <xi:include href="mips-cpu.xml"/>
+  <xi:include href="mips-cp0.xml"/>
+  <xi:include href="mips-fpu64.xml"/>
+  <xi:include href="mips-dsp.xml"/>
+
+  <feature name="org.gnu.gdb.mips.linux">
+    <reg name="restart" bitsize="32" group="system"/>
+  </feature>
+</target>
diff --git a/gdb/features/mips-fpu64-linux.c b/gdb/features/mips-fpu64-linux.c
new file mode 100644
index 0000000..3fe4497
--- /dev/null
+++ b/gdb/features/mips-fpu64-linux.c
@@ -0,0 +1,102 @@
+/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
+  Original: mips-fpu64-linux.xml */
+
+#include "defs.h"
+#include "osabi.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_mips_fpu64_linux;
+static void
+initialize_tdesc_mips_fpu64_linux (void)
+{
+  struct target_desc *result = allocate_target_description ();
+  struct tdesc_feature *feature;
+
+  set_tdesc_architecture (result, bfd_scan_arch ("mips"));
+
+  set_tdesc_osabi (result, osabi_from_tdesc_string ("GNU/Linux"));
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cpu");
+  tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r13", 13, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r14", 14, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r15", 15, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r16", 16, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r17", 17, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r18", 18, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r19", 19, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r20", 20, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r21", 21, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r22", 22, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r23", 23, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r24", 24, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r25", 25, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r26", 26, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r27", 27, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r28", 28, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r29", 29, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r30", 30, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r31", 31, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lo", 33, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hi", 34, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pc", 37, 1, NULL, 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cp0");
+  tdesc_create_reg (feature, "status", 32, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "badvaddr", 35, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "cause", 36, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "config5", 38, 1, NULL, 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.fpu");
+  tdesc_create_reg (feature, "f0", 39, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f1", 40, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f2", 41, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f3", 42, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f4", 43, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f5", 44, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f6", 45, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f7", 46, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f8", 47, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f9", 48, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f10", 49, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f11", 50, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f12", 51, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f13", 52, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f14", 53, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f15", 54, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f16", 55, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f17", 56, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f18", 57, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f19", 58, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f20", 59, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f21", 60, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f22", 61, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f23", 62, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f24", 63, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f25", 64, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f26", 65, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f27", 66, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f28", 67, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f29", 68, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f30", 69, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f31", 70, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "fcsr", 71, 1, "float", 32, "int");
+  tdesc_create_reg (feature, "fir", 72, 1, "float", 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.linux");
+  tdesc_create_reg (feature, "restart", 73, 1, "system", 32, "int");
+
+  tdesc_mips_fpu64_linux = result;
+}
diff --git a/gdb/features/mips-fpu64-linux.xml b/gdb/features/mips-fpu64-linux.xml
new file mode 100644
index 0000000..bc021c0
--- /dev/null
+++ b/gdb/features/mips-fpu64-linux.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007-2013 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <architecture>mips</architecture>
+  <osabi>GNU/Linux</osabi>
+  <xi:include href="mips-cpu.xml"/>
+  <xi:include href="mips-cp0.xml"/>
+  <xi:include href="mips-fpu64.xml"/>
+
+  <feature name="org.gnu.gdb.mips.linux">
+    <reg name="restart" bitsize="32" group="system"/>
+  </feature>
+</target>
diff --git a/gdb/features/mips-fpu64.xml b/gdb/features/mips-fpu64.xml
new file mode 100644
index 0000000..88dc9d9
--- /dev/null
+++ b/gdb/features/mips-fpu64.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007-2013 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.fpu">
+  <reg name="f0" bitsize="64" type="ieee_double"/>
+  <reg name="f1" bitsize="64" type="ieee_double"/>
+  <reg name="f2" bitsize="64" type="ieee_double"/>
+  <reg name="f3" bitsize="64" type="ieee_double"/>
+  <reg name="f4" bitsize="64" type="ieee_double"/>
+  <reg name="f5" bitsize="64" type="ieee_double"/>
+  <reg name="f6" bitsize="64" type="ieee_double"/>
+  <reg name="f7" bitsize="64" type="ieee_double"/>
+  <reg name="f8" bitsize="64" type="ieee_double"/>
+  <reg name="f9" bitsize="64" type="ieee_double"/>
+  <reg name="f10" bitsize="64" type="ieee_double"/>
+  <reg name="f11" bitsize="64" type="ieee_double"/>
+  <reg name="f12" bitsize="64" type="ieee_double"/>
+  <reg name="f13" bitsize="64" type="ieee_double"/>
+  <reg name="f14" bitsize="64" type="ieee_double"/>
+  <reg name="f15" bitsize="64" type="ieee_double"/>
+  <reg name="f16" bitsize="64" type="ieee_double"/>
+  <reg name="f17" bitsize="64" type="ieee_double"/>
+  <reg name="f18" bitsize="64" type="ieee_double"/>
+  <reg name="f19" bitsize="64" type="ieee_double"/>
+  <reg name="f20" bitsize="64" type="ieee_double"/>
+  <reg name="f21" bitsize="64" type="ieee_double"/>
+  <reg name="f22" bitsize="64" type="ieee_double"/>
+  <reg name="f23" bitsize="64" type="ieee_double"/>
+  <reg name="f24" bitsize="64" type="ieee_double"/>
+  <reg name="f25" bitsize="64" type="ieee_double"/>
+  <reg name="f26" bitsize="64" type="ieee_double"/>
+  <reg name="f27" bitsize="64" type="ieee_double"/>
+  <reg name="f28" bitsize="64" type="ieee_double"/>
+  <reg name="f29" bitsize="64" type="ieee_double"/>
+  <reg name="f30" bitsize="64" type="ieee_double"/>
+  <reg name="f31" bitsize="64" type="ieee_double"/>
+
+  <reg name="fcsr" bitsize="32" group="float"/>
+  <reg name="fir" bitsize="32" group="float"/>
+</feature>
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index 1e874e3..9913d6a 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -357,7 +357,8 @@ clean:
 	rm -f reg-tilegx.c reg-tilegx32.c
 	rm -f arm-with-iwmmxt.c
 	rm -f arm-with-vfpv2.c arm-with-vfpv3.c arm-with-neon.c
-	rm -f mips-linux.c mips-dsp-linux.c
+	rm -f mips-linux.c mips-dsp-linux.c mips-fpu64-linux.c
+	rm -f mips-fpu64-dsp-linux.c
 	rm -f mips64-linux.c mips64-dsp-linux.c
 	rm -f nios2-linux.c
 	rm -f powerpc-32.c powerpc-32l.c powerpc-64l.c powerpc-e500l.c
@@ -710,6 +711,10 @@ mips-linux.c : $(srcdir)/../regformats/mips-linux.dat $(regdat_sh)
 	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips-linux.dat mips-linux.c
 mips-dsp-linux.c : $(srcdir)/../regformats/mips-dsp-linux.dat $(regdat_sh)
 	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips-dsp-linux.dat mips-dsp-linux.c
+mips-fpu64-linux.c : $(srcdir)/../regformats/mips-fpu64-linux.dat $(regdat_sh)
+	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips-fpu64-linux.dat mips-fpu64-linux.c
+mips-fpu64-dsp-linux.c : $(srcdir)/../regformats/mips-fpu64-dsp-linux.dat $(regdat_sh)
+	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips-fpu64-dsp-linux.dat mips-fpu64-dsp-linux.c
 mips64-linux.c : $(srcdir)/../regformats/mips64-linux.dat $(regdat_sh)
 	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips64-linux.dat mips64-linux.c
 mips64-dsp-linux.c : $(srcdir)/../regformats/mips64-dsp-linux.dat $(regdat_sh)
diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv
index a54b9e7..422fd90 100644
--- a/gdb/gdbserver/configure.srv
+++ b/gdb/gdbserver/configure.srv
@@ -187,15 +187,20 @@ case "${target}" in
 			;;
   mips*-*-linux*)	srv_regobj="mips-linux.o"
 			srv_regobj="${srv_regobj} mips-dsp-linux.o"
+			srv_regobj="${srv_regobj} mips-fpu64-linux.o"
+			srv_regobj="${srv_regobj} mips-fpu64-dsp-linux.o"
 			srv_regobj="${srv_regobj} mips64-linux.o"
 			srv_regobj="${srv_regobj} mips64-dsp-linux.o"
 			srv_tgtobj="$srv_linux_obj linux-mips-low.o"
 			srv_tgtobj="${srv_tgtobj} mips-linux-watch.o"
 			srv_xmlfiles="mips-linux.xml"
 			srv_xmlfiles="${srv_xmlfiles} mips-dsp-linux.xml"
+			srv_xmlfiles="${srv_xmlfiles} mips-fpu64-linux.xml"
+			srv_xmlfiles="${srv_xmlfiles} mips-fpu64-dsp-linux.xml"
 			srv_xmlfiles="${srv_xmlfiles} mips-cpu.xml"
 			srv_xmlfiles="${srv_xmlfiles} mips-cp0.xml"
 			srv_xmlfiles="${srv_xmlfiles} mips-fpu.xml"
+			srv_xmlfiles="${srv_xmlfiles} mips-fpu64.xml"
 			srv_xmlfiles="${srv_xmlfiles} mips-dsp.xml"
 			srv_xmlfiles="${srv_xmlfiles} mips64-linux.xml"
 			srv_xmlfiles="${srv_xmlfiles} mips64-dsp-linux.xml"
diff --git a/gdb/regformats/mips-fpu64-dsp-linux.dat b/gdb/regformats/mips-fpu64-dsp-linux.dat
new file mode 100644
index 0000000..0eac27f
--- /dev/null
+++ b/gdb/regformats/mips-fpu64-dsp-linux.dat
@@ -0,0 +1,85 @@
+# DO NOT EDIT: generated from mips-fpu64-dsp-linux.xml
+name:mips_fpu64_dsp_linux
+xmltarget:mips-fpu64-dsp-linux.xml
+expedite:r29,pc
+32:r0
+32:r1
+32:r2
+32:r3
+32:r4
+32:r5
+32:r6
+32:r7
+32:r8
+32:r9
+32:r10
+32:r11
+32:r12
+32:r13
+32:r14
+32:r15
+32:r16
+32:r17
+32:r18
+32:r19
+32:r20
+32:r21
+32:r22
+32:r23
+32:r24
+32:r25
+32:r26
+32:r27
+32:r28
+32:r29
+32:r30
+32:r31
+32:status
+32:lo
+32:hi
+32:badvaddr
+32:cause
+32:pc
+32:config5
+64:f0
+64:f1
+64:f2
+64:f3
+64:f4
+64:f5
+64:f6
+64:f7
+64:f8
+64:f9
+64:f10
+64:f11
+64:f12
+64:f13
+64:f14
+64:f15
+64:f16
+64:f17
+64:f18
+64:f19
+64:f20
+64:f21
+64:f22
+64:f23
+64:f24
+64:f25
+64:f26
+64:f27
+64:f28
+64:f29
+64:f30
+64:f31
+32:fcsr
+32:fir
+32:hi1
+32:lo1
+32:hi2
+32:lo2
+32:hi3
+32:lo3
+32:dspctl
+32:restart
diff --git a/gdb/regformats/mips-fpu64-linux.dat b/gdb/regformats/mips-fpu64-linux.dat
new file mode 100644
index 0000000..ad6c3c6
--- /dev/null
+++ b/gdb/regformats/mips-fpu64-linux.dat
@@ -0,0 +1,78 @@
+# DO NOT EDIT: generated from mips-fpu64-linux.xml
+name:mips_fpu64_linux
+xmltarget:mips-fpu64-linux.xml
+expedite:r29,pc
+32:r0
+32:r1
+32:r2
+32:r3
+32:r4
+32:r5
+32:r6
+32:r7
+32:r8
+32:r9
+32:r10
+32:r11
+32:r12
+32:r13
+32:r14
+32:r15
+32:r16
+32:r17
+32:r18
+32:r19
+32:r20
+32:r21
+32:r22
+32:r23
+32:r24
+32:r25
+32:r26
+32:r27
+32:r28
+32:r29
+32:r30
+32:r31
+32:status
+32:lo
+32:hi
+32:badvaddr
+32:cause
+32:pc
+32:config5
+64:f0
+64:f1
+64:f2
+64:f3
+64:f4
+64:f5
+64:f6
+64:f7
+64:f8
+64:f9
+64:f10
+64:f11
+64:f12
+64:f13
+64:f14
+64:f15
+64:f16
+64:f17
+64:f18
+64:f19
+64:f20
+64:f21
+64:f22
+64:f23
+64:f24
+64:f25
+64:f26
+64:f27
+64:f28
+64:f29
+64:f30
+64:f31
+32:fcsr
+32:fir
+32:restart
-- 
1.9-rc2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 21/24]     MIPSR6 support for GDB
  2016-06-27 14:50 [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size Bhushan Attarde
                   ` (11 preceding siblings ...)
  2016-06-27 14:51 ` [PATCH 02/24] Add MIPS32 FPU64 GDB target descriptions Bhushan Attarde
@ 2016-06-27 14:51 ` Bhushan Attarde
  2016-07-29 21:10   ` Maciej W. Rozycki
  2016-06-27 14:51 ` [PATCH 13/24] Add MIPS MSA GDB target descriptions Bhushan Attarde
                   ` (8 subsequent siblings)
  21 siblings, 1 reply; 37+ messages in thread
From: Bhushan Attarde @ 2016-06-27 14:51 UTC (permalink / raw)
  To: gdb-patches
  Cc: Maciej.Rozycki, Matthew.Fortune, James.Hogan, Andrew.Bennett,
	Jaydeep.Patil, Bhushan Attarde

    This patch adds initial MIPS revision 6 support.

    gdb/ChangeLog:
        * mips-tdep.c (mips_read_fp_register_single): Add declaration.
        (is_mipsr6_isa, mips32_relative_offset21): New functions.
        (mips32_relative_offset26, mips32_blez_pc); Likewise.
        (is_add32bit_overflow, is_add64bit_overflow): Likewise.
        (mips32_instruction_is_compact_branch): Likewise.
        (is_ll_insn, is_sc_insn): Likewise.
        (LLSC_R6_OPCODE, LL_R6_FUNCT, LLE_FUNCT): New definitions.
        (LLD_R6_FUNCT, SC_R6_FUNCT, SCE_FUNCT, SCD_R6_FUNCT): Likewise.
        (mips32_next_pc): New mips64bitreg variable and handle compact
        branch instructions to determine next PC.
        (mips_deal_with_atomic_sequence): Replace opcode checks with
        new is_ll_insn and is_sc_insn functions.
        Add support for R6 compact instructions.
        (mips_about_to_return): Mask the hint and the jalr/jr bit.
        (mips32_stack_frame_destroyed_p): Add jrc.
        (gdb_print_insn_mips): Set dis-both-r5-and-r6 option.
        (gdb_print_insn_mips_n32, gdb_print_insn_mips_n64): Likewise.
        (mips32_instruction_has_delay_slot): Restructure the code and
        add BLEZ, BGTZ instructions.
        (b0s21_imm): New definition.

    include/ChangeLog:

        * opcode/mips.h (INSN2_CONVERTED_TO_COMPACT,
        INSN2_NEXT_NO_DS) New definitions.
        (ASE_MXU, ASE_DSPR3, ASE_VIRT_XPA, ASE_EVA_R6): Likewise.

    opcodes/ChangeLog:
        * micromips-opc.c (alt_isa): New variable
        (I36, I37, I69): New definitions.
        * mips-dis.c (is_isa_r6): New function.
        (parse_mips_dis_option): Handle dis-both-r5-and-r6 option and
        set alt_isa accordingly.
---
 gdb/mips-tdep.c         | 499 +++++++++++++++++++++++++++++++++++++++++++-----
 include/opcode/mips.h   |  13 ++
 opcodes/micromips-opc.c |   3 +
 opcodes/mips-dis.c      |  33 +++-
 4 files changed, 493 insertions(+), 55 deletions(-)

diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index 14e3aa6..68e00ec 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -74,6 +74,9 @@ static int mips16_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch,
 static void mips_print_float_info (struct gdbarch *, struct ui_file *,
 				   struct frame_info *, const char *);
 
+static int mips_read_fp_register_single (struct frame_info *, int,
+					  gdb_byte *);
+
 /* A useful bit in the CP0 status register (MIPS_PS_REGNUM).  */
 /* This bit is set if we are emulating 32-bit FPRs on a 64-bit chip.  */
 #define ST0_FR (1 << 26)
@@ -2388,6 +2391,17 @@ mips_fetch_instruction (struct gdbarch *gdbarch,
   return extract_unsigned_integer (buf, instlen, byte_order);
 }
 
+/* Return one if the gdbarch is based on MIPS Release 6.  */
+
+static int
+is_mipsr6_isa (struct gdbarch *gdbarch)
+{
+  const struct bfd_arch_info *info = gdbarch_bfd_arch_info (gdbarch);
+
+  return (info->mach == bfd_mach_mipsisa32r6
+	  || info->mach == bfd_mach_mipsisa64r6);
+}
+
 /* These are the fields of 32 bit mips instructions.  */
 #define mips32_op(x) (x >> 26)
 #define itype_op(x) (x >> 26)
@@ -2430,6 +2444,7 @@ mips_fetch_instruction (struct gdbarch *gdbarch,
 #define b0s11_op(x) ((x) & 0x7ff)
 #define b0s12_imm(x) ((x) & 0xfff)
 #define b0s16_imm(x) ((x) & 0xffff)
+#define b0s21_imm(x) ((x) & 0x1fffff)
 #define b0s26_imm(x) ((x) & 0x3ffffff)
 #define b6s10_ext(x) (((x) >> 6) & 0x3ff)
 #define b11s5_reg(x) (((x) >> 11) & 0x1f)
@@ -2466,6 +2481,24 @@ mips32_relative_offset (ULONGEST inst)
   return ((itype_immediate (inst) ^ 0x8000) - 0x8000) << 2;
 }
 
+/* Extract the 21-bit signed immediate offset from the MIPS instruction
+   INSN.  */
+
+static LONGEST
+mips32_relative_offset21 (ULONGEST insn)
+{
+  return ((b0s21_imm (insn) ^ 0x100000) - 0x100000) << 2;
+}
+
+/* Extract the 26-bit signed immediate offset from the MIPS instruction
+   INSN.  */
+
+static LONGEST
+mips32_relative_offset26 (ULONGEST insn)
+{
+  return ((b0s26_imm (insn) ^ 0x2000000) - 0x2000000) << 2;
+}
+
 /* Determine the address of the next instruction executed after the INST
    floating condition branch instruction at PC.  COUNT specifies the
    number of the floating condition bits tested by the branch.  */
@@ -2590,6 +2623,53 @@ mips32_bc1_w_pc (struct gdbarch *gdbarch, struct frame_info *frame,
   return pc;
 }
 
+/* Determine the address of the next instruction execute after the INST
+   BLEZ family of branch instructions at PC */
+
+static CORE_ADDR
+mips32_blez_pc (struct gdbarch *gdbarch, struct frame_info *frame,
+		ULONGEST inst, CORE_ADDR pc, int invert)
+{
+  int rs = itype_rs (inst);
+  int rt = itype_rt (inst);
+  LONGEST val_rs = get_frame_register_signed (frame, rs);
+  LONGEST val_rt = get_frame_register_signed (frame, rt);
+  ULONGEST uval_rs = get_frame_register_unsigned (frame, rs);
+  ULONGEST uval_rt = get_frame_register_unsigned (frame, rt);
+  int taken = 0;
+  int delay_slot_size = 0;
+
+  /* BLEZ, BLEZL, BGTZ, BGTZL */
+  if (rt == 0)
+    {
+      delay_slot_size = 4;
+      taken = (val_rs <= 0);
+    }
+  else if (is_mipsr6_isa (gdbarch))
+    {
+      /* BLEZALC, BGTZALC */
+      if (rs == 0 && rt != 0)
+	taken = (val_rt <= 0);
+      /* BGEZALC, BLTZALC */
+      else if (rs == rt && rt != 0)
+	taken = (val_rt >= 0);
+      /* BGEUC, BLTUC */
+      else if (rs != rt && rs != 0 && rt != 0)
+	taken = (uval_rs >= uval_rt);
+    }
+
+  if (invert)
+    taken = !taken;
+
+  /* Calculate branch target */
+  if (taken)
+    pc += mips32_relative_offset (inst);
+  else
+    pc += delay_slot_size;
+
+  return pc;
+}
+
 /* Return nonzero if the gdbarch is an Octeon series.  */
 
 static int
@@ -2618,6 +2698,24 @@ is_octeon_bbit_op (int op, struct gdbarch *gdbarch)
   return 0;
 }
 
+/* Return 1 if A + B would overflow.  */
+
+static int
+is_add32bit_overflow (int32_t a, int32_t b)
+{
+  int32_t r = (uint32_t) a + (uint32_t) b;
+  return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0);
+}
+
+static int
+is_add64bit_overflow (int64_t a, int64_t b)
+{
+  if (a != (int32_t)a)
+    return 1;
+  if (b != (int32_t)b)
+    return 1;
+  return is_add32bit_overflow ((int32_t)a, (int32_t)b);
+}
 
 /* Determine where to set a single step breakpoint while considering
    branch prediction.  */
@@ -2628,12 +2726,18 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
   struct gdbarch *gdbarch = get_frame_arch (frame);
   unsigned long inst;
   int op;
+  int mips64bitreg = 0;
+
+  if (mips_isa_regsize (gdbarch) == 8)
+    mips64bitreg = 1;
+
   inst = mips_fetch_instruction (gdbarch, ISA_MIPS, pc, NULL);
   op = itype_op (inst);
   if ((inst & 0xe0000000) != 0)		/* Not a special, jump or branch
 					   instruction.  */
     {
-      if (op >> 2 == 5)
+      if (op >> 2 == 5 && ((op & 0x02) == 0
+			   || itype_rt (inst) == 0))
 	/* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx */
 	{
 	  switch (op & 0x03)
@@ -2643,7 +2747,7 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
 	    case 1:		/* BNEL */
 	      goto neq_branch;
 	    case 2:		/* BLEZL */
-	      goto less_branch;
+	      goto lez_branch;
 	    case 3:		/* BGTZL */
 	      goto greater_branch;
 	    default:
@@ -2653,11 +2757,13 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
       else if (op == 17 && itype_rs (inst) == 8)
 	/* BC1F, BC1FL, BC1T, BC1TL: 010001 01000 */
 	pc = mips32_bc1_pc (gdbarch, frame, inst, pc + 4, 1);
-      else if (op == 17 && itype_rs (inst) == 9
+      else if (!is_mipsr6_isa (gdbarch)
+	       && op == 17 && itype_rs (inst) == 9
 	       && (itype_rt (inst) & 2) == 0)
 	/* BC1ANY2F, BC1ANY2T: 010001 01001 xxx0x */
 	pc = mips32_bc1_pc (gdbarch, frame, inst, pc + 4, 2);
-      else if (op == 17 && itype_rs (inst) == 10
+      else if (!is_mipsr6_isa (gdbarch)
+	       && op == 17 && itype_rs (inst) == 10
 	       && (itype_rt (inst) & 2) == 0)
 	/* BC1ANY4F, BC1ANY4T: 010001 01010 xxx0x */
 	pc = mips32_bc1_pc (gdbarch, frame, inst, pc + 4, 4);
@@ -2669,7 +2775,7 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
 	/* BZ.V:   010001 01011 */
 	/* BNZ.V:  010001 01111 */
 	pc = mips32_bc1_w_pc (gdbarch, frame, inst, pc + 4);
-      else if (op == 29)
+      else if (!is_mipsr6_isa (gdbarch) && op == 29)
 	/* JALX: 011101 */
 	/* The new PC will be alternate mode.  */
 	{
@@ -2697,7 +2803,114 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
           else
 	    pc += 8;        /* After the delay slot.  */
 	}
+      else if (is_mipsr6_isa (gdbarch))
+	{
+	  /* BOVC, BEQZALC, BEQC and BNVC, BNEZALC, BNEC */
+	  if (op == 8 || op == 24)
+	    {
+	      int rs = rtype_rs (inst);
+	      int rt = rtype_rt (inst);
+	      LONGEST val_rs = get_frame_register_signed (frame, rs);
+	      LONGEST val_rt = get_frame_register_signed (frame, rt);
+	      int taken = 0;
+	      /* BOVC (BNVC) */
+	      if (rs >= rt)
+		{
+		  if (mips64bitreg == 1)
+		    taken = is_add64bit_overflow (val_rs, val_rt);
+		  else
+		    taken = is_add32bit_overflow (val_rs, val_rt);
+		}
+	      /* BEQZALC (BNEZALC) */
+	      else if (rs < rt && rs == 0)
+		taken = (val_rt == 0);
+	      /* BEQC (BNEC) */
+	      else
+		taken = (val_rs == val_rt);
 
+	      /* BNVC, BNEZALC, BNEC */
+	      if (op == 24)
+		taken = !taken;
+
+	      if (taken)
+		pc += mips32_relative_offset (inst) + 4;
+	      else
+		pc += 4;
+	    }
+	  /* BC1EQZ, BC1NEZ */
+	  else if (op == 17 && (itype_rs (inst) == 9 || itype_rs (inst) == 13))
+	    {
+	      gdb_byte status;
+	      gdb_byte true_val = 0;
+	      gdb_byte *raw_buffer = alloca (sizeof (gdb_byte) * 8);
+	      mips_read_fp_register_single (frame, itype_rt (inst) +
+					    gdbarch_num_regs (gdbarch) +
+					    mips_regnum (gdbarch)->fp0,
+					    raw_buffer);
+	      if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+		status = *(raw_buffer + 3);
+	      else
+		status = *(raw_buffer);
+
+	      if (itype_rs (inst) == 13)
+		true_val = 1;
+
+	      if ((status & 0x1) == true_val)
+		pc += mips32_relative_offset (inst) + 4;
+	      else
+		pc += 8;
+	    }
+	  else if (op == 22 || op == 23)
+	  /* BLEZC, BGEZC, BGEC, BGTZC, BLTZC, BLTC */
+	    {
+	      int rs = rtype_rs (inst);
+	      int rt = rtype_rt (inst);
+	      LONGEST val_rs = get_frame_register_signed (frame, rs);
+	      LONGEST val_rt = get_frame_register_signed (frame, rt);
+	      int taken = 0;
+	      /* The R5 rt == 0 case is handled above so we treat it as
+		 an unknown instruction here for future ISA usage.  */
+	      if (rs == 0 && rt != 0)
+		taken = (val_rt <= 0);
+	      else if (rs == rt && rt != 0)
+		taken = (val_rt >= 0);
+	      else if (rs != rt && rs != 0 && rt != 0)
+		taken = (val_rs >= val_rt);
+
+	      if (op == 23)
+		taken = !taken;
+
+	      if (taken)
+		pc += mips32_relative_offset (inst) + 4;
+	      else
+		pc += 4;
+	    }
+	  else if (op == 50 || op == 58)
+	  /* BC, BALC */
+	    pc += mips32_relative_offset26 (inst) + 4;
+	  else if ((op == 54 || op == 62)
+		   && rtype_rs (inst) == 0)
+	  /* JIC, JIALC */
+	    {
+	      pc = get_frame_register_signed (frame, itype_rt (inst));
+	      pc += (itype_immediate (inst) ^ 0x8000) - 0x8000;
+	    }
+	  else if (op == 54 || op == 62)
+	  /* BEQZC, BNEZC */
+	    {
+	      int rs = itype_rs (inst);
+	      LONGEST rs_val = get_frame_register_signed (frame, rs);
+	      int taken = (rs_val == 0);
+	      if (op == 62)
+		taken = !taken;
+	      if (taken)
+		pc += mips32_relative_offset21 (inst) + 4;
+	      else
+		pc += 4;
+	    }
+	  else
+	    pc += 4;		/* Not a branch, next instruction is easy.  */
+	}
       else
 	pc += 4;		/* Not a branch, next instruction is easy.  */
     }
@@ -2757,22 +2970,32 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
 		  pc += 8;	/* after the delay slot */
 		break;
 	      case 0x1c:	/* BPOSGE32 */
+	      case 0x18:	/* BPOSGE32C */
 	      case 0x1e:	/* BPOSGE64 */
 		pc += 4;
 		if (itype_rs (inst) == 0)
 		  {
 		    unsigned int pos = (op & 2) ? 64 : 32;
 		    int dspctl = mips_regnum (gdbarch)->dspctl;
+		    int delay_slot_size = 4;
 
 		    if (dspctl == -1)
 		      /* No way to handle; it'll most likely trap anyway.  */
 		      break;
 
+		    /* BPOSGE32C */
+		    if (op == 0x18)
+		      {
+			if (!is_mipsr6_isa (gdbarch))
+			  break;
+			delay_slot_size = 0;
+		      }
+
 		    if ((get_frame_register_unsigned (frame,
 						      dspctl) & 0x7f) >= pos)
 		      pc += mips32_relative_offset (inst);
 		    else
-		      pc += 4;
+		      pc += delay_slot_size;
 		  }
 		break;
 		/* All of the other instructions in the REGIMM category */
@@ -2806,19 +3029,14 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
 	  else
 	    pc += 8;
 	  break;
-	case 6:		/* BLEZ, BLEZL */
-	  if (get_frame_register_signed (frame, itype_rs (inst)) <= 0)
-	    pc += mips32_relative_offset (inst) + 4;
-	  else
-	    pc += 8;
+	case 6:		/* BLEZ, BLEZL, BLEZALC, BGEZALC, BGEUC */
+	lez_branch:
+	  pc = mips32_blez_pc (gdbarch, frame, inst, pc + 4, 0);
 	  break;
 	case 7:
 	default:
-	greater_branch:	/* BGTZ, BGTZL */
-	  if (get_frame_register_signed (frame, itype_rs (inst)) > 0)
-	    pc += mips32_relative_offset (inst) + 4;
-	  else
-	    pc += 8;
+	greater_branch:	/* BGTZ, BGTZL, BGTZALC, BLTZALC, BLTUC */
+	  pc = mips32_blez_pc (gdbarch, frame, inst, pc + 4, 1);
 	  break;
 	}			/* switch */
     }				/* else */
@@ -3456,6 +3674,46 @@ micromips_instruction_is_compact_branch (unsigned short insn)
     }
 }
 
+/* Return non-zero if the MIPS instruction INSN is a compact branch
+   or jump.  */
+
+static int
+mips32_instruction_is_compact_branch (struct gdbarch *gdbarch, ULONGEST insn)
+{
+  switch (itype_op (insn))
+    {
+    /* BOVC, BEQZALC, BEQC */
+    case 8:
+    /* BNVC, BNEZALC, BNEC */
+    case 24:
+    /* BC */
+    case 50:
+    /* BALC */
+    case 58:
+    /* BEQZC, JIC */
+    case 54:
+    /* BNEZC, JIALC */
+    case 62:
+      return is_mipsr6_isa (gdbarch);
+    /* BLEZC, BGEZC, BGEC */
+    case 22:
+    /* BGTZC, BLTZC, BLTC */
+    case 23:
+    /* BLEZALC, BGEZALC, BGEUC */
+    case 6:
+    /* BGTZALC, BLTZALC, BLTUC */
+    case 7:
+      return (is_mipsr6_isa (gdbarch)
+	      && itype_rt (insn) != 0);
+    /* BPOSGE32C */
+    case 1:
+      return (is_mipsr6_isa (gdbarch)
+	      && itype_rt (insn) == 0x18 && itype_rs (insn) == 0);
+    default:
+      return 0;
+    }
+}
+
 struct mips_frame_cache
 {
   CORE_ADDR base;
@@ -4503,7 +4761,8 @@ restart:
       reg = high_word & 0x1f;
 
       if (high_word == 0x27bd		/* addiu $sp,$sp,-i */
-	  || high_word == 0x23bd	/* addi $sp,$sp,-i */
+	  || (high_word == 0x23bd	/* addi $sp,$sp,-i */
+	      && !is_mipsr6_isa (gdbarch))
 	  || high_word == 0x67bd)	/* daddiu $sp,$sp,-i */
 	{
 	  if (offset < 0)		/* Negative stack adjustment?  */
@@ -4638,7 +4897,8 @@ restart:
 
       /* A jump or branch, or enough non-prologue insns seen?  If so,
          then we must have reached the end of the prologue by now.  */
-      if (prev_delay_slot || non_prologue_insns > 1)
+      if (prev_delay_slot || non_prologue_insns > 1
+	  || mips32_instruction_is_compact_branch (gdbarch, inst))
 	break;
 
       prev_non_prologue_insn = this_non_prologue_insn;
@@ -4944,6 +5204,60 @@ mips_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR addr)
 #define LLD_OPCODE 0x34
 #define SC_OPCODE 0x38
 #define SCD_OPCODE 0x3c
+#define LLSC_R6_OPCODE 0x1f
+#define LL_R6_FUNCT 0x36
+#define LLE_FUNCT 0x2e
+#define LLD_R6_FUNCT 0x37
+#define SC_R6_FUNCT 0x26
+#define SCE_FUNCT 0x1e
+#define SCD_R6_FUNCT 0x27
+
+static int
+is_ll_insn (struct gdbarch *gdbarch, ULONGEST insn)
+{
+  if (itype_op (insn) == LL_OPCODE
+      || itype_op (insn) == LLD_OPCODE)
+    return 1;
+
+  if (rtype_op (insn) == LLSC_R6_OPCODE
+      && rtype_funct (insn) == LLE_FUNCT
+      && (insn & 0x40) == 0)
+    return 1;
+
+  /* Handle LL and LLX varieties.  */
+  if (is_mipsr6_isa (gdbarch)
+      && rtype_op (insn) == LLSC_R6_OPCODE
+      && (rtype_funct (insn) == LL_R6_FUNCT
+	  || rtype_funct (insn) == LLD_R6_FUNCT
+	  || rtype_funct (insn) == LLE_FUNCT))
+    return 1;
+
+  return 0;
+}
+
+static int
+is_sc_insn (struct gdbarch *gdbarch, ULONGEST insn)
+{
+  if (itype_op (insn) == SC_OPCODE
+      || itype_op (insn) == SCD_OPCODE)
+    return 1;
+
+  if (rtype_op (insn) == LLSC_R6_OPCODE
+      && rtype_funct (insn) == SCE_FUNCT
+      && (insn & 0x40) == 0)
+    return 1;
+
+  /* Handle SC and NOT SCX.  The SCX must come first so we
+     do not want to prematurely end the sequence.  */
+  if (is_mipsr6_isa (gdbarch)
+      && rtype_op (insn) == LLSC_R6_OPCODE
+      && (rtype_funct (insn) == SC_R6_FUNCT
+	  || rtype_funct (insn) == SCD_R6_FUNCT)
+      && (insn & 0x40) == 0)
+    return 1;
+
+  return 0;
+}
 
 static int
 mips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
@@ -4957,10 +5271,11 @@ mips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
   int index;
   int last_breakpoint = 0; /* Defaults to 0 (no breakpoints placed).  */  
   const int atomic_sequence_length = 16; /* Instruction sequence length.  */
+  int is_mipsr6 = is_mipsr6_isa (gdbarch);
 
   insn = mips_fetch_instruction (gdbarch, ISA_MIPS, loc, NULL);
   /* Assume all atomic sequences start with a ll/lld instruction.  */
-  if (itype_op (insn) != LL_OPCODE && itype_op (insn) != LLD_OPCODE)
+  if (!is_ll_insn (gdbarch, insn))
     return 0;
 
   /* Assume that no atomic sequence is longer than "atomic_sequence_length" 
@@ -4990,16 +5305,49 @@ mips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
 	  return 0; /* fallback to the standard single-step code.  */
 	case 4: /* BEQ */
 	case 5: /* BNE */
-	case 6: /* BLEZ */
-	case 7: /* BGTZ */
 	case 20: /* BEQL */
 	case 21: /* BNEL */
-	case 22: /* BLEZL */
-	case 23: /* BGTTL */
+	case 22: /* BLEZL (BLEZC, BGEZC, BGEC) */
+	case 23: /* BGTZL (BGTZC, BLTZC, BLTC) */
+	  is_branch = 1;
+	  break;
+	case 6: /* BLEZ (BLEZALC, BGEZALC, BGEUC) */
+	case 7: /* BGTZ (BGTZALC, BLTZALC, BLTUC) */
+	  if (is_mipsr6)
+	    {
+	      /* BLEZALC, BGTZALC */
+	      if (itype_rs (insn) == 0 && itype_rt (insn) != 0)
+		return 0; /* fallback to the standard single-step code.  */
+	      /* BGEZALC, BLTZALC */
+	      else if (itype_rs (insn) == itype_rt (insn)
+		  && itype_rt (insn) != 0)
+		return 0; /* fallback to the standard single-step code.  */
+	    }
 	  is_branch = 1;
 	  break;
+	case 8: /* BOVC, BEQZALC, BEQC */
+	case 24: /* BNVC, BNEZALC, BNEC */
+	  if (is_mipsr6)
+	    is_branch = 1;
+	  break;
+	case 50: /* BC */
+	case 58: /* BALC */
+	  if (is_mipsr6)
+	    return 0; /* fallback to the standard single-step code.  */
+	  break;
+	case 54: /* BEQZC, JIC */
+	case 62: /* BNEZC, JIALC */
+	  if (is_mipsr6)
+	    {
+	      if (itype_rs (insn) == 0) /* JIC, JIALC */
+		return 0; /* fallback to the standard single-step code.  */
+	      else
+		is_branch = 2; /* Marker for branches with a 21-bit offset */
+	    }
+	  break;
 	case 17: /* COP1 */
-	  is_branch = (((itype_rs (insn) == 9 || itype_rs (insn) == 10)
+	  is_branch = ((!is_mipsr6
+		       && (itype_rs (insn) == 9 || itype_rs (insn) == 10)
 			&& (itype_rt (insn) & 0x2) == 0)
 				/* BC1ANY2F, BC1ANY2T, BC1ANY4F, BC1ANY4T */
 		       || (itype_rs (insn) & 0x18) == 0x18
@@ -5013,12 +5361,21 @@ mips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
 	/* Fall through.  */
 	case 18: /* COP2 */
 	case 19: /* COP3 */
-	  is_branch = (itype_rs (insn) == 8); /* BCzF, BCzFL, BCzT, BCzTL */
+			/* BCzF, BCzFL, BCzT, BCzTL, BC*EQZ, BC*NEZ */
+	  is_branch = (itype_rs (insn) == 8)
+		       || (is_mipsr6
+			   && itype_op (insn) != 19
+			   && (itype_rs (insn) == 9
+			       || itype_rs (insn) == 13));
 	  break;
 	}
       if (is_branch)
 	{
-	  branch_bp = loc + mips32_relative_offset (insn) + 4;
+	  /* Is this a special PC21_S2 branch? */
+	  if (is_branch == 2)
+	    branch_bp = loc + mips32_relative_offset21 (insn) + 4;
+	  else
+	    branch_bp = loc + mips32_relative_offset (insn) + 4;
 	  if (last_breakpoint >= 1)
 	    return 0; /* More than one branch found, fallback to the
 			 standard single-step code.  */
@@ -5026,12 +5383,12 @@ mips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
 	  last_breakpoint++;
 	}
 
-      if (itype_op (insn) == SC_OPCODE || itype_op (insn) == SCD_OPCODE)
+      if (is_sc_insn (gdbarch, insn))
 	break;
     }
 
   /* Assume that the atomic sequence ends with a sc/scd instruction.  */
-  if (itype_op (insn) != SC_OPCODE && itype_op (insn) != SCD_OPCODE)
+  if (!is_sc_insn (gdbarch, insn))
     return 0;
 
   loc += MIPS_INSN32_SIZE;
@@ -5265,8 +5622,14 @@ mips_about_to_return (struct gdbarch *gdbarch, CORE_ADDR pc)
   gdb_assert (mips_pc_is_mips (pc));
 
   insn = mips_fetch_instruction (gdbarch, ISA_MIPS, pc, NULL);
-  hint = 0x7c0;
-  return (insn & ~hint) == 0x3e00008;			/* jr(.hb) $ra */
+  /* Mask the hint and the jalr/jr bit */
+  hint = 0x7c1;
+
+  if (is_mipsr6_isa (gdbarch) && insn == 0xd81f0000) /* jrc $31 */
+    return 1;
+
+  /* jr(.hb) $ra and "jalr(.hb) $ra" */
+  return ((insn & ~hint) == 0x3e00008);
 }
 
 
@@ -7895,7 +8258,9 @@ mips32_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
 
 	  if (high_word != 0x27bd	/* addiu $sp,$sp,offset */
 	      && high_word != 0x67bd	/* daddiu $sp,$sp,offset */
-	      && inst != 0x03e00008	/* jr $ra */
+	      && (inst & ~0x1) != 0x03e00008 /* jr $31 or jalr $0, $31 */
+	      && (!is_mipsr6_isa (gdbarch)
+		  || inst != 0xd81f0000) /* jrc $31 */
 	      && inst != 0x00000000)	/* nop */
 	    return 0;
 	}
@@ -8220,12 +8585,17 @@ gdb_print_insn_mips (bfd_vma memaddr, struct disassemble_info *info)
 
   /* Set the disassembler options.  */
   if (!info->disassembler_options)
+    {
     /* This string is not recognized explicitly by the disassembler,
        but it tells the disassembler to not try to guess the ABI from
        the bfd elf headers, such that, if the user overrides the ABI
        of a program linked as NewABI, the disassembly will follow the
        register naming conventions specified by the user.  */
-    info->disassembler_options = "gpr-names=32";
+      if (is_mipsr6_isa (gdbarch))
+	info->disassembler_options = "gpr-names=32,dis-both-r5-and-r6=1";
+      else
+	info->disassembler_options = "gpr-names=32";
+    }
 
   /* Call the appropriate disassembler based on the target endian-ness.  */
   if (info->endian == BFD_ENDIAN_BIG)
@@ -8239,7 +8609,10 @@ gdb_print_insn_mips_n32 (bfd_vma memaddr, struct disassemble_info *info)
 {
   /* Set up the disassembler info, so that we get the right
      register names from libopcodes.  */
-  info->disassembler_options = "gpr-names=n32";
+  if (is_mipsr6_isa (info->application_data))
+    info->disassembler_options = "gpr-names=n32,dis-both-r5-and-r6=1";
+  else
+    info->disassembler_options = "gpr-names=n32";
   info->flavour = bfd_target_elf_flavour;
 
   return gdb_print_insn_mips (memaddr, info);
@@ -8250,7 +8623,10 @@ gdb_print_insn_mips_n64 (bfd_vma memaddr, struct disassemble_info *info)
 {
   /* Set up the disassembler info, so that we get the right
      register names from libopcodes.  */
-  info->disassembler_options = "gpr-names=64";
+  if (is_mipsr6_isa (info->application_data))
+    info->disassembler_options = "gpr-names=64,dis-both-r5-and-r6=1";
+  else
+    info->disassembler_options = "gpr-names=64";
   info->flavour = bfd_target_elf_flavour;
 
   return gdb_print_insn_mips (memaddr, info);
@@ -8416,22 +8792,37 @@ mips32_instruction_has_delay_slot (struct gdbarch *gdbarch, ULONGEST inst)
     {
       rs = itype_rs (inst);
       rt = itype_rt (inst);
-      return (is_octeon_bbit_op (op, gdbarch) 
-	      || op >> 2 == 5	/* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx  */
-	      || op == 29	/* JALX: bits 011101  */
-	      || (op == 17
-		  && (rs == 8
-				/* BC1F, BC1FL, BC1T, BC1TL: 010001 01000  */
-		      || (rs == 9 && (rt & 0x2) == 0)
-				/* BC1ANY2F, BC1ANY2T: bits 010001 01001  */
-		      || (rs == 10 && (rt & 0x2) == 0)
-				/* BC1ANY4F, BC1ANY4T: bits 010001 01010  */
-		      || ((rs & 0x18) == 0x18)
-				/* BZ.df:  bits 010001 110xx */
-				/* BNZ.df: bits 010001 111xx */
-		      || ((rs & 0x1b) == 0x0b))));
-				/* BZ.V:   bits 010001 01011 */
-				/* BNZ.V:  bits 010001 01111 */
+      if (is_octeon_bbit_op (op, gdbarch)
+	      || (op >> 1 == 10)                /* BEQL, BNEL: bits 01010x  */
+	      || (op >> 1 == 11 && rt == 0)     /* BLEZL, BGTZL: bits 01011x  */
+	      || (!is_mipsr6_isa (gdbarch) && op == 29))	/* JALX: bits 011101  */
+        return 1;
+      else if (op == 17)                        /* COP1 */
+    {
+      if (rs == 8              /* BC1F, BC1FL, BC1T, BC1TL: 010001 01000 */
+          || ((rs & 0x18) == 0x18)          /* BZ.df:  bits 010001 110xx */
+                                            /* BNZ.df: bits 010001 111xx */
+          || ((rs & 0x1b) == 0x0b))         /* BZ.V:   bits 010001 01011 */
+                                            /* BNZ.V:  bits 010001 01111 */
+        return 1;
+      else if (!is_mipsr6_isa (gdbarch)
+            /* BC1ANY2F, BC1ANY2T: bits 010001 01001 */
+           && ((rs == 9 && (rt & 0x2) == 0)
+                 /* BC1ANY4F, BC1ANY4T: bits 010001 01010  */
+                || (rs == 10 && (rt & 0x2) == 0)))
+        return 1;
+      else if (is_mipsr6_isa (gdbarch)
+           && (rs == 9                  /* BC1EQZ: 010001 01001  */
+               || rs == 13))            /* BC1NEZ: 010001 01101  */
+        return 1;
+    }
+      else if (op == 18)                /* COP2 */
+    {
+          if (is_mipsr6_isa (gdbarch)
+          && (rs == 9                      /* BC2EQZ: 010010 01001  */
+             || rs == 13))                 /* BC2NEZ: 010010 01101  */
+            return 1;
+    }
     }
   else
     switch (op & 0x07)		/* extract bits 28,27,26  */
@@ -8450,7 +8841,11 @@ mips32_instruction_has_delay_slot (struct gdbarch *gdbarch, ULONGEST inst)
 		|| ((rt & 0x1e) == 0x1c && rs == 0));
 				/* BPOSGE32, BPOSGE64: bits 1110x  */
 	break;			/* end REGIMM  */
-      default:			/* J, JAL, BEQ, BNE, BLEZ, BGTZ  */
+	case 6:			/* BLEZ  */
+	case 7:			/* BGTZ  */
+	 return (itype_rt (inst) == 0);
+	 break;
+      default:			/* J, JAL, BEQ, BNE  */
 	return 1;
 	break;
       }
@@ -9103,6 +9498,8 @@ mips_in_return_stub (struct gdbarch *gdbarch, CORE_ADDR pc, const char *name)
    PC of the stub target.  The stub just loads $t9 and jumps to it,
    so that $t9 has the correct value at function entry.  */
 
+/* TODO: Update for compact jump trampoline */
+
 static CORE_ADDR
 mips_skip_pic_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
 {
diff --git a/include/opcode/mips.h b/include/opcode/mips.h
index 88bf8f8..eace840 100644
--- a/include/opcode/mips.h
+++ b/include/opcode/mips.h
@@ -1102,6 +1102,10 @@ struct mips_opcode
 #define INSN2_VU0_CHANNEL_SUFFIX    0x00004000
 /* Instruction has a forbidden slot.  */
 #define INSN2_FORBIDDEN_SLOT        0x00008000
+/* This indicates pre-R6 instructions mapped to R6 ones.  */
+#define INSN2_CONVERTED_TO_COMPACT  0x00010000
+/* Instruction prevents the following instruction from being in a DS */
+#define INSN2_NEXT_NO_DS	    0x00020000
 
 /* Masks used to mark instructions to indicate which MIPS ISA level
    they were introduced in.  INSN_ISA_MASK masks an enumeration that
@@ -1256,6 +1260,15 @@ static const unsigned int mips_isa_table[] = {
 #define ASE_MSA64		0x00001000
 /* eXtended Physical Address (XPA) Extension.  */
 #define ASE_XPA			0x00002000
+/* MXU Extension.  */
+#define ASE_MXU			0x00004000
+#define ASE_DSPR3		0x00008000
+/* The Virtualization ASE has eXtended Physical Address (XPA) Extension
+   instructions which are only valid when both ASEs are enabled.  */
+#define ASE_VIRT_XPA		0x00010000
+/* The eXtended Physical Address (XPA) Extension has instructions which are
+   only valid for the r6 ISA.  */
+#define ASE_EVA_R6		0x00020000
 
 /* MIPS ISA defines, use instead of hardcoding ISA level.  */
 
diff --git a/opcodes/micromips-opc.c b/opcodes/micromips-opc.c
index e182f47..ac7b6f7 100644
--- a/opcodes/micromips-opc.c
+++ b/opcodes/micromips-opc.c
@@ -253,6 +253,9 @@ decode_micromips_operand (const char *p)
    are accepted as 64-bit microMIPS ISA.  */
 #define I1	INSN_ISA1
 #define I3	INSN_ISA3
+#define I36	INSN_ISA32R5
+#define I37	INSN_ISA32R6
+#define I69	INSN_ISA64R6
 
 /* MIPS DSP ASE support.  */
 #define WR_a	WR_HILO		/* Write DSP accumulators (reuse WR_HILO).  */
diff --git a/opcodes/mips-dis.c b/opcodes/mips-dis.c
index e152876..94bd369 100644
--- a/opcodes/mips-dis.c
+++ b/opcodes/mips-dis.c
@@ -668,6 +668,7 @@ const struct mips_arch_choice mips_arch_choices[] =
    values.  */
 static int mips_processor;
 static int mips_isa;
+static int alt_isa = -1;
 static int mips_ase;
 static int micromips_ase;
 static const char * const *mips_gpr_names;
@@ -764,6 +765,17 @@ is_micromips (Elf_Internal_Ehdr *header)
   return 0;
 }
 
+/* Check if ISA is R6.  */
+
+static inline int
+is_isa_r6 (unsigned long isa)
+{
+  if ((isa & INSN_ISA_MASK) == ISA_MIPS32R6
+      || ((isa & INSN_ISA_MASK) == ISA_MIPS64R6))
+    return 1;
+  return 0;
+}
+
 static void
 set_default_mips_dis_options (struct disassemble_info *info)
 {
@@ -836,6 +848,17 @@ parse_mips_dis_option (const char *option, unsigned int len)
       return;
     }
 
+  if (CONST_STRNEQ (option, "dis-both-r5-and-r6"))
+    {
+      if ((mips_isa & INSN_ISA_MASK) == ISA_MIPS32R6)
+	alt_isa = ISA_MIPS32R5;
+      else if ((mips_isa & INSN_ISA_MASK) == ISA_MIPS64R6)
+	alt_isa = ISA_MIPS64R5;
+      else
+	alt_isa = -1;
+      return;
+    }
+
   if (CONST_STRNEQ (option, "msa"))
     {
       mips_ase |= ASE_MSA;
@@ -1702,10 +1725,12 @@ print_insn_mips (bfd_vma memaddr,
 	      && (word & op->mask) == op->match)
 	    {
 	      /* We always disassemble the jalx instruction, except for MIPS r6.  */
-	      if (!opcode_is_member (op, mips_isa, mips_ase, mips_processor)
-		 && (strcmp (op->name, "jalx")
-		     || (mips_isa & INSN_ISA_MASK) == ISA_MIPS32R6
-		     || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R6))
+	      if ((!opcode_is_member (op, mips_isa, mips_ase, mips_processor)
+		   && (alt_isa == -1
+		       || !opcode_is_member (op, alt_isa, 0, 0))
+		   && (strcmp (op->name, "jalx")
+		       || is_isa_r6 (mips_isa)))
+		  || (op->pinfo2 & INSN2_CONVERTED_TO_COMPACT))
 		continue;
 
 	      /* Figure out instruction type and branch delay information.  */
-- 
1.9-rc2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 05/24]     MIPS: Add config5 to MIPS GDB target descriptions
  2016-06-27 14:50 [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size Bhushan Attarde
                   ` (16 preceding siblings ...)
  2016-06-27 14:51 ` [PATCH 19/24] Add MIPS MSA vector branch instruction support Bhushan Attarde
@ 2016-06-27 14:51 ` Bhushan Attarde
  2016-06-27 14:51 ` [PATCH 18/24] mips-linux-nat: get msa registers Bhushan Attarde
                   ` (3 subsequent siblings)
  21 siblings, 0 replies; 37+ messages in thread
From: Bhushan Attarde @ 2016-06-27 14:51 UTC (permalink / raw)
  To: gdb-patches
  Cc: Maciej.Rozycki, Matthew.Fortune, James.Hogan, Andrew.Bennett,
	Jaydeep.Patil, Bhushan Attarde

    Add the config5 register to the MIPS and MIPS64 GDB target description
    files and regenerate various dependent files. This register contains the
    FRE bit which is used with the FR bit in the status register to implement
    a new floating point register mode.

    The register is placed with the other cp0 registers at register number 38
    (which used to be the first FP register number). The explicit FPU and DSP
    register numbers are removed so that they can all shuffle up by one to
    give space for config5. The explicit FPU register number used to be
    necessary due to the PC register being defined non-linearly at register
    number 37, but the explicit DSP register numbers didn't seem to serve a
    particular purpose as far as I can tell.

    An corresponding -1 entry is added to mips_base_regs in
    gdbserver/linux-mips-low.c for config5, indicating that it cannot be
    accessed using PTRACE_PEEK/PTRACE_POKE.

    gdb/ChangeLog:

    	* features/mips-cp0.xml: Add config5 register.
    	* features/mips64-cp0.xml: Likewise.
    	* features/mips-fpu.xml: Remove explicit register number.
    	* features/mips64-fpu.xml: Likewise.
    	* features/mips-dsp.xml: Remove explicit register numbers.
    	* features/mips64-dsp.xml: Likewise.
    	* features/mips-dsp-linux.c: Regenerate.
    	* features/mips64-dsp-linux.c: Likewise.
    	* features/mips-linux.c: Likewise.
    	* features/mips64-linux.c: Likewise.
    	* regformats/mips-dsp-linux.dat: Regenerate.
    	* regformats/mips64-dsp-linux.dat: Likewise.
    	* regformats/mips-linux.dat: Likewise.
    	* regformats/mips64-linux.dat: Likewise.

    gdb/gdbserver/ChangeLog:

    	* linux-mips-low.c (mips_num_regs, mips_dsp_num_regs): Increment.
    	(mips_base_regs): Add -1 entry for Config5.
---
 gdb/features/mips-cp0.xml           |  1 +
 gdb/features/mips-dsp-linux.c       | 85 +++++++++++++++++++------------------
 gdb/features/mips-dsp.xml           | 14 +++---
 gdb/features/mips-fpu.xml           |  2 +-
 gdb/features/mips-linux.c           | 71 ++++++++++++++++---------------
 gdb/features/mips64-cp0.xml         |  1 +
 gdb/features/mips64-dsp-linux.c     | 85 +++++++++++++++++++------------------
 gdb/features/mips64-dsp.xml         | 14 +++---
 gdb/features/mips64-fpu.xml         |  2 +-
 gdb/features/mips64-linux.c         | 71 ++++++++++++++++---------------
 gdb/gdbserver/linux-mips-low.c      |  6 +--
 gdb/regformats/mips-dsp-linux.dat   |  1 +
 gdb/regformats/mips-linux.dat       |  1 +
 gdb/regformats/mips64-dsp-linux.dat |  1 +
 gdb/regformats/mips64-linux.dat     |  1 +
 15 files changed, 183 insertions(+), 173 deletions(-)

diff --git a/gdb/features/mips-cp0.xml b/gdb/features/mips-cp0.xml
index 773fd88..349672e 100644
--- a/gdb/features/mips-cp0.xml
+++ b/gdb/features/mips-cp0.xml
@@ -10,4 +10,5 @@
   <reg name="status" bitsize="32" regnum="32"/>
   <reg name="badvaddr" bitsize="32" regnum="35"/>
   <reg name="cause" bitsize="32" regnum="36"/>
+  <reg name="config5" bitsize="32" regnum="38"/>
 </feature>
diff --git a/gdb/features/mips-dsp-linux.c b/gdb/features/mips-dsp-linux.c
index 80ceb22..b6e56fc 100644
--- a/gdb/features/mips-dsp-linux.c
+++ b/gdb/features/mips-dsp-linux.c
@@ -57,54 +57,55 @@ initialize_tdesc_mips_dsp_linux (void)
   tdesc_create_reg (feature, "status", 32, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "badvaddr", 35, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "cause", 36, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "config5", 38, 1, NULL, 32, "int");
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.mips.fpu");
-  tdesc_create_reg (feature, "f0", 38, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f1", 39, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f2", 40, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f3", 41, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f4", 42, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f5", 43, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f6", 44, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f7", 45, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f8", 46, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f9", 47, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f10", 48, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f11", 49, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f12", 50, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f13", 51, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f14", 52, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f15", 53, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f16", 54, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f17", 55, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f18", 56, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f19", 57, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f20", 58, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f21", 59, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f22", 60, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f23", 61, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f24", 62, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f25", 63, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f26", 64, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f27", 65, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f28", 66, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f29", 67, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f30", 68, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f31", 69, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "fcsr", 70, 1, "float", 32, "int");
-  tdesc_create_reg (feature, "fir", 71, 1, "float", 32, "int");
+  tdesc_create_reg (feature, "f0", 39, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f1", 40, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f2", 41, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f3", 42, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f4", 43, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f5", 44, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f6", 45, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f7", 46, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f8", 47, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f9", 48, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f10", 49, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f11", 50, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f12", 51, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f13", 52, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f14", 53, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f15", 54, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f16", 55, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f17", 56, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f18", 57, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f19", 58, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f20", 59, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f21", 60, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f22", 61, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f23", 62, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f24", 63, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f25", 64, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f26", 65, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f27", 66, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f28", 67, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f29", 68, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f30", 69, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f31", 70, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "fcsr", 71, 1, "float", 32, "int");
+  tdesc_create_reg (feature, "fir", 72, 1, "float", 32, "int");
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.mips.dsp");
-  tdesc_create_reg (feature, "hi1", 72, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "lo1", 73, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "hi2", 74, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "lo2", 75, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "hi3", 76, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "lo3", 77, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "dspctl", 78, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hi1", 73, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lo1", 74, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hi2", 75, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lo2", 76, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hi3", 77, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lo3", 78, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "dspctl", 79, 1, NULL, 32, "int");
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.mips.linux");
-  tdesc_create_reg (feature, "restart", 79, 1, "system", 32, "int");
+  tdesc_create_reg (feature, "restart", 80, 1, "system", 32, "int");
 
   tdesc_mips_dsp_linux = result;
 }
diff --git a/gdb/features/mips-dsp.xml b/gdb/features/mips-dsp.xml
index f8b7e74..fcc903d 100644
--- a/gdb/features/mips-dsp.xml
+++ b/gdb/features/mips-dsp.xml
@@ -7,12 +7,12 @@
 
 <!DOCTYPE feature SYSTEM "gdb-target.dtd">
 <feature name="org.gnu.gdb.mips.dsp">
-  <reg name="hi1" bitsize="32" regnum="72"/>
-  <reg name="lo1" bitsize="32" regnum="73"/>
-  <reg name="hi2" bitsize="32" regnum="74"/>
-  <reg name="lo2" bitsize="32" regnum="75"/>
-  <reg name="hi3" bitsize="32" regnum="76"/>
-  <reg name="lo3" bitsize="32" regnum="77"/>
+  <reg name="hi1" bitsize="32"/>
+  <reg name="lo1" bitsize="32"/>
+  <reg name="hi2" bitsize="32"/>
+  <reg name="lo2" bitsize="32"/>
+  <reg name="hi3" bitsize="32"/>
+  <reg name="lo3" bitsize="32"/>
 
-  <reg name="dspctl" bitsize="32" regnum="78"/>
+  <reg name="dspctl" bitsize="32"/>
 </feature>
diff --git a/gdb/features/mips-fpu.xml b/gdb/features/mips-fpu.xml
index 4d331a1..44c4150 100644
--- a/gdb/features/mips-fpu.xml
+++ b/gdb/features/mips-fpu.xml
@@ -7,7 +7,7 @@
 
 <!DOCTYPE feature SYSTEM "gdb-target.dtd">
 <feature name="org.gnu.gdb.mips.fpu">
-  <reg name="f0" bitsize="32" type="ieee_single" regnum="38"/>
+  <reg name="f0" bitsize="32" type="ieee_single"/>
   <reg name="f1" bitsize="32" type="ieee_single"/>
   <reg name="f2" bitsize="32" type="ieee_single"/>
   <reg name="f3" bitsize="32" type="ieee_single"/>
diff --git a/gdb/features/mips-linux.c b/gdb/features/mips-linux.c
index c990119..f316835 100644
--- a/gdb/features/mips-linux.c
+++ b/gdb/features/mips-linux.c
@@ -57,45 +57,46 @@ initialize_tdesc_mips_linux (void)
   tdesc_create_reg (feature, "status", 32, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "badvaddr", 35, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "cause", 36, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "config5", 38, 1, NULL, 32, "int");
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.mips.fpu");
-  tdesc_create_reg (feature, "f0", 38, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f1", 39, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f2", 40, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f3", 41, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f4", 42, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f5", 43, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f6", 44, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f7", 45, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f8", 46, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f9", 47, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f10", 48, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f11", 49, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f12", 50, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f13", 51, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f14", 52, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f15", 53, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f16", 54, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f17", 55, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f18", 56, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f19", 57, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f20", 58, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f21", 59, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f22", 60, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f23", 61, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f24", 62, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f25", 63, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f26", 64, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f27", 65, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f28", 66, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f29", 67, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f30", 68, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "f31", 69, 1, NULL, 32, "ieee_single");
-  tdesc_create_reg (feature, "fcsr", 70, 1, "float", 32, "int");
-  tdesc_create_reg (feature, "fir", 71, 1, "float", 32, "int");
+  tdesc_create_reg (feature, "f0", 39, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f1", 40, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f2", 41, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f3", 42, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f4", 43, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f5", 44, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f6", 45, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f7", 46, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f8", 47, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f9", 48, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f10", 49, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f11", 50, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f12", 51, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f13", 52, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f14", 53, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f15", 54, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f16", 55, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f17", 56, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f18", 57, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f19", 58, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f20", 59, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f21", 60, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f22", 61, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f23", 62, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f24", 63, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f25", 64, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f26", 65, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f27", 66, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f28", 67, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f29", 68, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f30", 69, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f31", 70, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "fcsr", 71, 1, "float", 32, "int");
+  tdesc_create_reg (feature, "fir", 72, 1, "float", 32, "int");
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.mips.linux");
-  tdesc_create_reg (feature, "restart", 72, 1, "system", 32, "int");
+  tdesc_create_reg (feature, "restart", 73, 1, "system", 32, "int");
 
   tdesc_mips_linux = result;
 }
diff --git a/gdb/features/mips64-cp0.xml b/gdb/features/mips64-cp0.xml
index 7d20cf9..d1249f4 100644
--- a/gdb/features/mips64-cp0.xml
+++ b/gdb/features/mips64-cp0.xml
@@ -10,4 +10,5 @@
   <reg name="status" bitsize="64" regnum="32"/>
   <reg name="badvaddr" bitsize="64" regnum="35"/>
   <reg name="cause" bitsize="64" regnum="36"/>
+  <reg name="config5" bitsize="64" regnum="38"/>
 </feature>
diff --git a/gdb/features/mips64-dsp-linux.c b/gdb/features/mips64-dsp-linux.c
index bc09078..f75cbd7 100644
--- a/gdb/features/mips64-dsp-linux.c
+++ b/gdb/features/mips64-dsp-linux.c
@@ -55,54 +55,55 @@ initialize_tdesc_mips64_dsp_linux (void)
   tdesc_create_reg (feature, "status", 32, 1, NULL, 64, "int");
   tdesc_create_reg (feature, "badvaddr", 35, 1, NULL, 64, "int");
   tdesc_create_reg (feature, "cause", 36, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "config5", 38, 1, NULL, 64, "int");
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.mips.fpu");
-  tdesc_create_reg (feature, "f0", 38, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f1", 39, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f2", 40, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f3", 41, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f4", 42, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f5", 43, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f6", 44, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f7", 45, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f8", 46, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f9", 47, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f10", 48, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f11", 49, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f12", 50, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f13", 51, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f14", 52, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f15", 53, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f16", 54, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f17", 55, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f18", 56, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f19", 57, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f20", 58, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f21", 59, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f22", 60, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f23", 61, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f24", 62, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f25", 63, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f26", 64, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f27", 65, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f28", 66, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f29", 67, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f30", 68, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f31", 69, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "fcsr", 70, 1, "float", 64, "int");
-  tdesc_create_reg (feature, "fir", 71, 1, "float", 64, "int");
+  tdesc_create_reg (feature, "f0", 39, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f1", 40, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f2", 41, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f3", 42, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f4", 43, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f5", 44, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f6", 45, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f7", 46, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f8", 47, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f9", 48, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f10", 49, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f11", 50, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f12", 51, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f13", 52, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f14", 53, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f15", 54, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f16", 55, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f17", 56, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f18", 57, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f19", 58, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f20", 59, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f21", 60, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f22", 61, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f23", 62, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f24", 63, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f25", 64, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f26", 65, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f27", 66, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f28", 67, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f29", 68, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f30", 69, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f31", 70, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "fcsr", 71, 1, "float", 64, "int");
+  tdesc_create_reg (feature, "fir", 72, 1, "float", 64, "int");
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.mips.dsp");
-  tdesc_create_reg (feature, "hi1", 72, 1, NULL, 64, "int");
-  tdesc_create_reg (feature, "lo1", 73, 1, NULL, 64, "int");
-  tdesc_create_reg (feature, "hi2", 74, 1, NULL, 64, "int");
-  tdesc_create_reg (feature, "lo2", 75, 1, NULL, 64, "int");
-  tdesc_create_reg (feature, "hi3", 76, 1, NULL, 64, "int");
-  tdesc_create_reg (feature, "lo3", 77, 1, NULL, 64, "int");
-  tdesc_create_reg (feature, "dspctl", 78, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hi1", 73, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "lo1", 74, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hi2", 75, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "lo2", 76, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hi3", 77, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "lo3", 78, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "dspctl", 79, 1, NULL, 32, "int");
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.mips.linux");
-  tdesc_create_reg (feature, "restart", 79, 1, "system", 64, "int");
+  tdesc_create_reg (feature, "restart", 80, 1, "system", 64, "int");
 
   tdesc_mips64_dsp_linux = result;
 }
diff --git a/gdb/features/mips64-dsp.xml b/gdb/features/mips64-dsp.xml
index 0a2694e..a627276 100644
--- a/gdb/features/mips64-dsp.xml
+++ b/gdb/features/mips64-dsp.xml
@@ -7,12 +7,12 @@
 
 <!DOCTYPE feature SYSTEM "gdb-target.dtd">
 <feature name="org.gnu.gdb.mips.dsp">
-  <reg name="hi1" bitsize="64" regnum="72"/>
-  <reg name="lo1" bitsize="64" regnum="73"/>
-  <reg name="hi2" bitsize="64" regnum="74"/>
-  <reg name="lo2" bitsize="64" regnum="75"/>
-  <reg name="hi3" bitsize="64" regnum="76"/>
-  <reg name="lo3" bitsize="64" regnum="77"/>
+  <reg name="hi1" bitsize="64"/>
+  <reg name="lo1" bitsize="64"/>
+  <reg name="hi2" bitsize="64"/>
+  <reg name="lo2" bitsize="64"/>
+  <reg name="hi3" bitsize="64"/>
+  <reg name="lo3" bitsize="64"/>
 
-  <reg name="dspctl" bitsize="32" regnum="78"/>
+  <reg name="dspctl" bitsize="32"/>
 </feature>
diff --git a/gdb/features/mips64-fpu.xml b/gdb/features/mips64-fpu.xml
index 7596fec..60b194a 100644
--- a/gdb/features/mips64-fpu.xml
+++ b/gdb/features/mips64-fpu.xml
@@ -7,7 +7,7 @@
 
 <!DOCTYPE feature SYSTEM "gdb-target.dtd">
 <feature name="org.gnu.gdb.mips.fpu">
-  <reg name="f0" bitsize="64" type="ieee_double" regnum="38"/>
+  <reg name="f0" bitsize="64" type="ieee_double"/>
   <reg name="f1" bitsize="64" type="ieee_double"/>
   <reg name="f2" bitsize="64" type="ieee_double"/>
   <reg name="f3" bitsize="64" type="ieee_double"/>
diff --git a/gdb/features/mips64-linux.c b/gdb/features/mips64-linux.c
index 2ecda9b..0c9331b 100644
--- a/gdb/features/mips64-linux.c
+++ b/gdb/features/mips64-linux.c
@@ -55,45 +55,46 @@ initialize_tdesc_mips64_linux (void)
   tdesc_create_reg (feature, "status", 32, 1, NULL, 64, "int");
   tdesc_create_reg (feature, "badvaddr", 35, 1, NULL, 64, "int");
   tdesc_create_reg (feature, "cause", 36, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "config5", 38, 1, NULL, 64, "int");
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.mips.fpu");
-  tdesc_create_reg (feature, "f0", 38, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f1", 39, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f2", 40, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f3", 41, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f4", 42, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f5", 43, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f6", 44, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f7", 45, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f8", 46, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f9", 47, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f10", 48, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f11", 49, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f12", 50, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f13", 51, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f14", 52, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f15", 53, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f16", 54, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f17", 55, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f18", 56, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f19", 57, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f20", 58, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f21", 59, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f22", 60, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f23", 61, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f24", 62, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f25", 63, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f26", 64, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f27", 65, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f28", 66, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f29", 67, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f30", 68, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "f31", 69, 1, NULL, 64, "ieee_double");
-  tdesc_create_reg (feature, "fcsr", 70, 1, "float", 64, "int");
-  tdesc_create_reg (feature, "fir", 71, 1, "float", 64, "int");
+  tdesc_create_reg (feature, "f0", 39, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f1", 40, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f2", 41, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f3", 42, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f4", 43, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f5", 44, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f6", 45, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f7", 46, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f8", 47, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f9", 48, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f10", 49, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f11", 50, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f12", 51, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f13", 52, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f14", 53, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f15", 54, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f16", 55, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f17", 56, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f18", 57, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f19", 58, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f20", 59, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f21", 60, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f22", 61, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f23", 62, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f24", 63, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f25", 64, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f26", 65, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f27", 66, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f28", 67, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f29", 68, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f30", 69, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f31", 70, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "fcsr", 71, 1, "float", 64, "int");
+  tdesc_create_reg (feature, "fir", 72, 1, "float", 64, "int");
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.mips.linux");
-  tdesc_create_reg (feature, "restart", 72, 1, "system", 64, "int");
+  tdesc_create_reg (feature, "restart", 73, 1, "system", 64, "int");
 
   tdesc_mips64_linux = result;
 }
diff --git a/gdb/gdbserver/linux-mips-low.c b/gdb/gdbserver/linux-mips-low.c
index 30a03d5..e9f0b06 100644
--- a/gdb/gdbserver/linux-mips-low.c
+++ b/gdb/gdbserver/linux-mips-low.c
@@ -54,8 +54,8 @@ extern const struct target_desc *tdesc_mips64_dsp_linux;
 #include <sys/reg.h>
 #endif
 
-#define mips_num_regs 73
-#define mips_dsp_num_regs 80
+#define mips_num_regs 74
+#define mips_dsp_num_regs 81
 
 #include <asm/ptrace.h>
 
@@ -81,7 +81,7 @@ union mips_register
   16, 17, 18, 19, 20, 21, 22, 23,					\
   24, 25, 26, 27, 28, 29, 30, 31,					\
 									\
-  -1, MMLO, MMHI, BADVADDR, CAUSE, PC,					\
+  -1, MMLO, MMHI, BADVADDR, CAUSE, PC, -1,				\
 									\
   FPR_BASE,      FPR_BASE + 1,  FPR_BASE + 2,  FPR_BASE + 3,		\
   FPR_BASE + 4,  FPR_BASE + 5,  FPR_BASE + 6,  FPR_BASE + 7,		\
diff --git a/gdb/regformats/mips-dsp-linux.dat b/gdb/regformats/mips-dsp-linux.dat
index ce37bf3..4793256 100644
--- a/gdb/regformats/mips-dsp-linux.dat
+++ b/gdb/regformats/mips-dsp-linux.dat
@@ -41,6 +41,7 @@ expedite:r29,pc
 32:badvaddr
 32:cause
 32:pc
+32:config5
 32:f0
 32:f1
 32:f2
diff --git a/gdb/regformats/mips-linux.dat b/gdb/regformats/mips-linux.dat
index d95e2c9..69457a6 100644
--- a/gdb/regformats/mips-linux.dat
+++ b/gdb/regformats/mips-linux.dat
@@ -41,6 +41,7 @@ expedite:r29,pc
 32:badvaddr
 32:cause
 32:pc
+32:config5
 32:f0
 32:f1
 32:f2
diff --git a/gdb/regformats/mips64-dsp-linux.dat b/gdb/regformats/mips64-dsp-linux.dat
index e73df93..4f30a31 100644
--- a/gdb/regformats/mips64-dsp-linux.dat
+++ b/gdb/regformats/mips64-dsp-linux.dat
@@ -41,6 +41,7 @@ expedite:r29,pc
 64:badvaddr
 64:cause
 64:pc
+64:config5
 64:f0
 64:f1
 64:f2
diff --git a/gdb/regformats/mips64-linux.dat b/gdb/regformats/mips64-linux.dat
index 6770c8f..43144ca 100644
--- a/gdb/regformats/mips64-linux.dat
+++ b/gdb/regformats/mips64-linux.dat
@@ -41,6 +41,7 @@ expedite:r29,pc
 64:badvaddr
 64:cause
 64:pc
+64:config5
 64:f0
 64:f1
 64:f2
-- 
1.9-rc2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 14/24]     Implement core MSA stuff
  2016-06-27 14:50 [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size Bhushan Attarde
                   ` (13 preceding siblings ...)
  2016-06-27 14:51 ` [PATCH 13/24] Add MIPS MSA GDB target descriptions Bhushan Attarde
@ 2016-06-27 14:51 ` Bhushan Attarde
  2016-06-27 14:51 ` [PATCH 07/24] MIPS: Make Linux restart register more dynamic Bhushan Attarde
                   ` (6 subsequent siblings)
  21 siblings, 0 replies; 37+ messages in thread
From: Bhushan Attarde @ 2016-06-27 14:51 UTC (permalink / raw)
  To: gdb-patches
  Cc: Maciej.Rozycki, Matthew.Fortune, James.Hogan, Andrew.Bennett,
	Jaydeep.Patil, Bhushan Attarde

    gdb/ChangeLog:
        * mips-tdep.c (mips_vector_register_p, mips_msa_128b_type): New
        functions.
        (mips_register_name): Add mips_msa_names containing msa register
        names and return msa register name when appropriate.
        (mips_get_fp_single_location): Add new variable "offs" and set
        "loc->offset" correctly.
        (mips_pseudo_register_read): Consider msa registers.
        (mips_pseudo_register_write): Likewise.
        (mips_print_register, print_gp_register_row): Likewise.
        (mips_register_type): Return mips_msa_128b_type for vector
        registers.
        (mips_gdbarch_init): Initialise w0, msa_ir and msa_csr to -1
        and then set them appropriately.
        (msa_128b_type): Initialise to NULL.

        * mips-tdep.h (mips_regnum): New w0, msa_ir, msa_csr fields.
        (gdbarch_tdep): Add msa_128b_type field.
---
 gdb/mips-tdep.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
 gdb/mips-tdep.h |   4 ++
 2 files changed, 190 insertions(+), 12 deletions(-)

diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index 13c1532..f98c288 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -221,6 +221,16 @@ mips_float_register_p (struct gdbarch *gdbarch, int regnum)
 	  && rawnum < mips_regnum (gdbarch)->fp0 + 32);
 }
 
+static int
+mips_vector_register_p (struct gdbarch *gdbarch, int regnum)
+{
+  int rawnum = regnum % gdbarch_num_regs (gdbarch);
+
+  return (mips_regnum (gdbarch)->w0 >= 0
+	  && rawnum >= mips_regnum (gdbarch)->w0
+	  && rawnum < mips_regnum (gdbarch)->w0 + 32);
+}
+
 #define MIPS_EABI(gdbarch) (gdbarch_tdep (gdbarch)->mips_abi \
 		     == MIPS_ABI_EABI32 \
 		   || gdbarch_tdep (gdbarch)->mips_abi == MIPS_ABI_EABI64)
@@ -684,6 +694,8 @@ static const char *
 mips_register_name (struct gdbarch *gdbarch, int regno)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  const struct mips_regnum *regnum = mips_regnum (gdbarch);
+
   /* GPR names for all ABIs other than n32/n64.  */
   static char *mips_gpr_names[] = {
     "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
@@ -700,6 +712,14 @@ mips_register_name (struct gdbarch *gdbarch, int regno)
     "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
   };
 
+  /* MSA vector register names.  */
+  static const char *const mips_msa_names[] = {
+      "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7",
+      "w8", "w9", "w10", "w11", "w12", "w13", "w14", "w15",
+      "w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23",
+      "w24", "w25", "w26", "w27", "w28", "w29", "w30", "w31",
+  };
+
   enum mips_abi abi = mips_abi (gdbarch);
 
   /* Map [gdbarch_num_regs .. 2*gdbarch_num_regs) onto the raw registers, 
@@ -727,6 +747,8 @@ mips_register_name (struct gdbarch *gdbarch, int regno)
       else
 	return mips_gpr_names[rawnum];
     }
+  else if (regnum->w0 >= 0 && rawnum >= regnum->w0 && rawnum < regnum->w0 + 32)
+    return mips_msa_names[rawnum - regnum->w0];
   else if (tdesc_has_registers (gdbarch_target_desc (gdbarch)))
     return tdesc_register_name (gdbarch, rawnum);
   else if (32 <= rawnum && rawnum < gdbarch_num_regs (gdbarch))
@@ -831,7 +853,7 @@ mips_get_fp_single_location (struct gdbarch *gdbarch,
   int raw_num = mips_regnum (gdbarch)->fp0;
   int raw_len = register_size (gdbarch, raw_num);
   enum mips_fpu_mode fp_mode = gdbarch_tdep (gdbarch)->fp_mode;
-  int big_endian;
+  int big_endian, offs;
 
   /* Only even doubles provided, in pairs of 32-bit registers.  */
   if (raw_len == 4)
@@ -846,11 +868,13 @@ mips_get_fp_single_location (struct gdbarch *gdbarch,
       return 1;
     }
 
-  if (raw_len != 8)
+  if (raw_len < 8)
     return 0;
 
-  /* All doubles provided.  */
+  /* All doubles provided, potentially at least significant end of vector
+     register.  */
   big_endian = (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG);
+  offs = big_endian ? (raw_len - 8) : 0;
 
   loc->size = 4;
   switch (fp_mode)
@@ -858,11 +882,11 @@ mips_get_fp_single_location (struct gdbarch *gdbarch,
     case MIPS_FPU_32:
     case MIPS_FPU_HYBRID:
       loc->regnum = raw_num + (idx & ~1);
-      loc->offset = 4 * (big_endian ^ (idx & 1));
+      loc->offset = offs + 4 * (big_endian ^ (idx & 1));
       return 1;
     case MIPS_FPU_64:
       loc->regnum = raw_num + idx;
-      loc->offset = 4 * big_endian;
+      loc->offset = offs + 4 * big_endian;
       return 1;
     default:
       return 0;
@@ -899,16 +923,17 @@ mips_get_fp_double_location (struct gdbarch *gdbarch,
       return 2;
     }
 
-  if (raw_len != 8)
+  if (raw_len < 8)
     return 0;
 
   /* FPU32 doesn't have odd doubles */
   if (fp_mode == MIPS_FPU_32 && idx & 1)
     return 0;
 
-  /* All doubles provided.  */
+  /* All doubles provided, potentially at least significant end of vector
+     register.  */
   loc->regnum = raw_num + idx;
-  loc->offset = 0;
+  loc->offset = big_endian ? (raw_len - 8) : 0;
   loc->size = 8;
   return 1;
 }
@@ -999,6 +1024,7 @@ static enum register_status
 mips_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 			   int cookednum, gdb_byte *buf)
 {
+  int big_endian = (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG);
   int rawnum = cookednum % gdbarch_num_regs (gdbarch);
   int fpnum;
   int raw_len, cooked_len;
@@ -1018,6 +1044,22 @@ mips_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
       parts = mips_get_fp_multi_location (gdbarch, fpnum, cooked_len, loc);
       return mips_regcache_raw_read_parts (regcache, loc, parts, &buf);
     }
+  else if (mips_vector_register_p (gdbarch, rawnum))
+    {
+      int fp_rawnum, fp_raw_len;
+
+      fpnum = rawnum - mips_regnum (gdbarch)->w0;
+      fp_rawnum = mips_regnum (gdbarch)->fp0 + fpnum;
+      fp_raw_len = register_size (gdbarch, fp_rawnum);
+
+      if (fp_raw_len < cooked_len)
+	return REG_UNAVAILABLE;
+
+      /* fill from normal fp register */
+      return regcache_raw_read_part (regcache, fp_rawnum,
+				     big_endian * (fp_raw_len - cooked_len),
+				     cooked_len, buf);
+    }
   else if (raw_len == cooked_len)
     return regcache_raw_read (regcache, rawnum, buf);
   else if (raw_len > cooked_len)
@@ -1045,6 +1087,7 @@ mips_pseudo_register_write (struct gdbarch *gdbarch,
 			    struct regcache *regcache, int cookednum,
 			    const gdb_byte *buf)
 {
+  int big_endian = (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG);
   int rawnum = cookednum % gdbarch_num_regs (gdbarch);
   int fpnum;
   int raw_len, cooked_len;
@@ -1064,6 +1107,22 @@ mips_pseudo_register_write (struct gdbarch *gdbarch,
       parts = mips_get_fp_multi_location (gdbarch, fpnum, cooked_len, loc);
       mips_regcache_raw_write_parts (regcache, loc, parts, &buf);
     }
+  else if (mips_vector_register_p (gdbarch, rawnum))
+    {
+      int fp_rawnum, fp_raw_len;
+
+      fpnum = rawnum - mips_regnum (gdbarch)->w0;
+      fp_rawnum = mips_regnum (gdbarch)->fp0 + fpnum;
+      fp_raw_len = register_size (gdbarch, fp_rawnum);
+
+      if (fp_raw_len < cooked_len)
+	return;
+
+      /* write to normal fp register */
+      regcache_raw_write_part (regcache, fp_rawnum,
+			       big_endian * (fp_raw_len - cooked_len),
+			       cooked_len, buf);
+    }
   else if (raw_len == cooked_len)
     regcache_raw_write (regcache, rawnum, buf);
   else if (raw_len > cooked_len)
@@ -1441,6 +1500,58 @@ mips_fp_type (struct gdbarch *gdbarch, int fpnum)
     return mips_fp32_type (gdbarch);
 }
 
+/* FIXME: The vector types are not correctly ordered on big-endian
+   targets.  Just as s0 is the low bits of d0, d0[0] is also the low
+   bits of d0 - regardless of what unit size is being held in d0.  So
+   the offset of the first uint8 in d0 is 7, but the offset of the
+   first float is 4.  This code works as-is for little-endian
+   targets.  */
+
+static struct type *
+mips_msa_128b_type (struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (tdep->msa_128b_type == NULL)
+    {
+      const struct builtin_type *bt = builtin_type (gdbarch);
+      struct type *t;
+
+      /* The type we're building is this:
+
+      union __gdb_builtin_type_msa_128
+      {
+        float    f32[4];
+        double   f64[2];
+        uint8_t  u8[16];
+        uint16_t u16[8];
+        uint32_t u32[4];
+        uint64_t u64[2];
+      }; */
+
+      t = arch_composite_type (gdbarch, "__gdb_builtin_type_msa_128",
+			       TYPE_CODE_UNION);
+      append_composite_type_field (t, "u8",
+				   init_vector_type (bt->builtin_uint8, 16));
+      append_composite_type_field (t, "u16",
+				   init_vector_type (bt->builtin_uint16, 8));
+      append_composite_type_field (t, "u32",
+				   init_vector_type (bt->builtin_uint32, 4));
+      append_composite_type_field (t, "u64",
+				   init_vector_type (bt->builtin_uint64, 2));
+      append_composite_type_field (t, "f32",
+				   init_vector_type (bt->builtin_float,  4));
+      append_composite_type_field (t, "f64",
+				   init_vector_type (bt->builtin_double, 2));
+
+      TYPE_VECTOR (t) = 1;
+      TYPE_NAME (t) = "msa_128";
+      tdep->msa_128b_type = t;
+    }
+
+  return tdep->msa_128b_type;
+}
+
 /* Get floating point rounding mode enumeration type */
 
 static struct type *
@@ -1693,6 +1804,9 @@ mips_register_type (struct gdbarch *gdbarch, int regnum)
 	return (mips_float_regsize (gdbarch) == 4
 		? builtin_type (gdbarch)->builtin_float
 		: builtin_type (gdbarch)->builtin_double);
+      else if (mips_vector_register_p (gdbarch, regnum))
+	/* no raw representation, share fp registers */
+	return builtin_type (gdbarch)->builtin_int0;
       else
 	return (regsize == 4
 		? builtin_type (gdbarch)->builtin_int32
@@ -1710,6 +1824,8 @@ mips_register_type (struct gdbarch *gdbarch, int regnum)
          Use the current setting for cooked registers.  */
       if (mips_float_register_p (gdbarch, regnum))
 	return mips_fp_type (gdbarch, rawnum - mips_regnum (gdbarch)->fp0);
+      else if (mips_vector_register_p (gdbarch, regnum))
+	return mips_msa_128b_type (gdbarch);
       else if (rawnum == mips_regnum (gdbarch)->fp_control_status)
 	return mips_fcsr_type (gdbarch);
       else if (rawnum == mips_regnum (gdbarch)->fp_implementation_revision)
@@ -1752,8 +1868,13 @@ mips_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
 
   gdb_assert (regnum >= num_regs && regnum < 2 * num_regs);
 
-  /* Absent registers are still absent.  */
   rawtype = gdbarch_register_type (gdbarch, rawnum);
+
+  /* Vector registers extend FP registers */
+  if (mips_vector_register_p (gdbarch, rawnum))
+    return mips_msa_128b_type (gdbarch);
+
+  /* Absent registers are still absent. */
   if (TYPE_LENGTH (rawtype) == 0)
     return rawtype;
 
@@ -7111,6 +7232,11 @@ mips_print_register (struct ui_file *file, struct frame_info *frame, int regnum)
       print_control_register (file, frame, regnum);
       return;
     }
+  if (mips_vector_register_p (gdbarch, regnum))
+    {
+      default_print_registers_info (gdbarch, file, frame, regnum, 0);
+      return;
+    }
 
   val = get_frame_register_value (frame, regnum);
 
@@ -7257,7 +7383,8 @@ print_gp_register_row (struct ui_file *file, struct frame_info *frame,
     {
       if (*gdbarch_register_name (gdbarch, regnum) == '\0')
 	continue;		/* unused register */
-      if (mips_float_register_p (gdbarch, regnum))
+      if (mips_float_register_p (gdbarch, regnum) ||
+	  mips_vector_register_p (gdbarch, regnum))
 	break;			/* End the row: reached FP register.  */
       /* Large registers are handled separately.  */
       if (register_size (gdbarch, regnum) > mips_abi_regsize (gdbarch))
@@ -7296,7 +7423,8 @@ print_gp_register_row (struct ui_file *file, struct frame_info *frame,
     {
       if (*gdbarch_register_name (gdbarch, regnum) == '\0')
 	continue;		/* unused register */
-      if (mips_float_register_p (gdbarch, regnum))
+      if (mips_float_register_p (gdbarch, regnum) ||
+	  mips_vector_register_p (gdbarch, regnum))
 	break;			/* End row: reached FP register.  */
       if (register_size (gdbarch, regnum) > mips_abi_regsize (gdbarch))
 	break;			/* End row: large register.  */
@@ -7371,6 +7499,17 @@ mips_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file,
 	      else
 		regnum += MIPS_NUMREGS;	/* Skip floating point regs.  */
 	    }
+	  else if (mips_vector_register_p (gdbarch, regnum))
+	    {
+	      if (all)		/* True for "INFO ALL-REGISTERS" command.  */
+		{
+		  default_print_registers_info (gdbarch, file, frame, regnum,
+						all);
+		  ++regnum;
+		}
+	      else
+		regnum += MIPS_NUMREGS;	/* Skip vector regs.  */
+	    }
 	  else if (mips_register_reggroup_p (gdbarch, regnum, float_reggroup) ||
 		   mips_register_reggroup_p (gdbarch, regnum, vector_reggroup))
 	    /* FP & MSA control registers */
@@ -8790,7 +8929,15 @@ mips_dwarf_dwarf2_ecoff_reg_to_regnum (struct gdbarch *gdbarch, int num)
   if (num >= 0 && num < 32)
     regnum = num;
   else if (num >= 32 && num < 64)
-    regnum = num + mips_regnum (gdbarch)->fp0 - 32;
+    {
+      /* If FR=1, it could be referring to an MSA vector register (which aliases
+	 the corresponding single and double precision fp register). Therefore
+	 if vector registers are available use them instead.  */
+      if (mips_regnum (gdbarch)->w0 != -1 && mips_float_regsize (gdbarch) == 8)
+	regnum = num + mips_regnum (gdbarch)->w0 - 32;
+      else
+	regnum = num + mips_regnum (gdbarch)->fp0 - 32;
+    }
   else if (num == 64)
     regnum = mips_regnum (gdbarch)->hi;
   else if (num == 65)
@@ -8964,6 +9111,9 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   /* Fill in the OS dependent register numbers and names.  */
   mips_regnum.config5 = -1;
+  mips_regnum.w0 = -1;
+  mips_regnum.msa_ir = -1;
+  mips_regnum.msa_csr = -1;
   mips_regnum.linux_restart = -1;
   if (info.osabi == GDB_OSABI_IRIX)
     {
@@ -9167,6 +9317,29 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 	    }
 	}
 
+      /* MSA vector control registers */
+      feature = tdesc_find_feature (info.target_desc,
+				    "org.gnu.gdb.mips.msa");
+      if (feature != NULL)
+	{
+	  /* Allocate a new registers.  */
+	  mips_regnum.w0 = num_regs;
+	  num_regs += 32;
+	  mips_regnum.msa_ir = num_regs++;
+	  mips_regnum.msa_csr = num_regs++;
+
+	  valid_p = 1;
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      mips_regnum.msa_csr, "msacsr");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      mips_regnum.msa_ir, "msair");
+	  if (!valid_p)
+	    {
+	      tdesc_data_cleanup (tdesc_data);
+	      return NULL;
+	    }
+	}
+
       /* It would be nice to detect an attempt to use a 64-bit ABI
 	 when only 32-bit registers are provided.  */
       reg_names = NULL;
@@ -9409,6 +9582,7 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->fp32_type = NULL;
   tdep->fp64_type = NULL;
   tdep->fp96_type = NULL;
+  tdep->msa_128b_type = NULL;
 
   if (info.target_desc)
     {
diff --git a/gdb/mips-tdep.h b/gdb/mips-tdep.h
index 110eb6c..b5f00fc 100644
--- a/gdb/mips-tdep.h
+++ b/gdb/mips-tdep.h
@@ -70,6 +70,9 @@ struct mips_regnum
   int lo;		/* ...  */
   int dspacc;		/* SmartMIPS/DSP accumulators.  */
   int dspctl;		/* DSP control.  */
+  int w0;
+  int msa_ir;
+  int msa_csr;
   int linux_restart;
 };
 extern const struct mips_regnum *mips_regnum (struct gdbarch *gdbarch);
@@ -139,6 +142,7 @@ struct gdbarch_tdep
   struct type *fp32_type;
   struct type *fp64_type;
   struct type *fp96_type;
+  struct type *msa_128b_type;
 
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
-- 
1.9-rc2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 19/24]     Add MIPS MSA vector branch instruction support
  2016-06-27 14:50 [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size Bhushan Attarde
                   ` (15 preceding siblings ...)
  2016-06-27 14:51 ` [PATCH 07/24] MIPS: Make Linux restart register more dynamic Bhushan Attarde
@ 2016-06-27 14:51 ` Bhushan Attarde
  2016-06-27 14:51 ` [PATCH 05/24] MIPS: Add config5 to MIPS GDB target descriptions Bhushan Attarde
                   ` (4 subsequent siblings)
  21 siblings, 0 replies; 37+ messages in thread
From: Bhushan Attarde @ 2016-06-27 14:51 UTC (permalink / raw)
  To: gdb-patches
  Cc: Maciej.Rozycki, Matthew.Fortune, James.Hogan, Andrew.Bennett,
	Jaydeep.Patil, Bhushan Attarde

    Add support for the MIPS & microMIPS MSA vector branch instructions,
    primarily to allow them to be single stepped.

    There are 4 such branch encodings:
     - BZ.df (BZ.B, BZ.H, BZ.W, BZ.D)
       Branch if any element in vector in the given format is zero.
     - BZ.V
       Branch if every element in vector in any format (i.e. the whole vector)
       is zero.
     - BNZ.df (BZ.B, BZ.H, BZ.W, BZ.D)
       Branch if no element in vector in the given format is zero. This is the
       inverse of BZ.df.
     - BNZ.V
       Branch if any element in vector in any format (i.e. any bit in whole
       vector) is non-zero. This is the inverse of BZ.V.

    The MIPS encodings use the COP1 opcode, and the microMIPS encodings use
    the POOL32D opcode.

    gdb/ChangeLog:

    	* mips-tdep.c (mips_bc1_w_taken): New function.
    	(mips32_bc1_w_pc): Likewise.
    	(micromips_bc1_w_pc): Likewise.
    	(mips32_next_pc): Add cases for BZ.df/BNZ.df and BZ.V/BNZ.V.
    	(micromips_next_pc): Likewise.
    	(mips_deal_with_atomic_sequence): Recognise BZ.df/BNZ.df and
    	BZ.V/BNZ.V as branches.
    	(micromips_deal_with_atomic_sequence): Likewise.
    	(mips32_instruction_has_delay_slot): Likewise.
    	(micromips_instruction_has_delay_slot): Likewise.
---
 gdb/mips-tdep.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 171 insertions(+), 4 deletions(-)

diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index 63291db..7a6d23d 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -2496,6 +2496,100 @@ mips32_bc1_pc (struct gdbarch *gdbarch, struct frame_info *frame,
   return pc;
 }
 
+/* Determine whether a vector branch will be taken.
+   Returns 1 if branch taken, 0 if branch not taken, -1 on error. */
+
+static int
+mips_bc1_w_taken (struct gdbarch *gdbarch, struct frame_info *frame,
+		  unsigned int op, unsigned int wt)
+{
+  int wr = gdbarch_num_regs (gdbarch) + mips_regnum (gdbarch)->w0;
+  int taken = -1;
+  int size, elem_size, tog;
+  gdb_byte *buf, *end, *elem_end;
+
+  if (wr == -1)
+    /* No way to handle; it'll most likely trap anyway.  */
+    return -1;
+  wr += wt;
+
+  /* Read vector register.  */
+  size = register_size (gdbarch, wr);
+  buf = alloca (size);
+  if (!deprecated_frame_register_read (frame, wr, buf))
+    return -1;
+
+  if ((op & 0x18) == 0x18)
+    {
+      elem_size = 1 << (op & 0x3);
+      /* Check whether this branch would be taken first:
+	 BZ.df: 110xx (branch if at least one element is zero) */
+      taken = 0;
+      for (end = buf + size; buf < end;)
+	{
+	  taken = 1;
+	  for (elem_end = buf + elem_size; buf < elem_end; ++buf)
+	    if (*buf)
+	      {
+		/* this element is non-zero */
+		taken = 0;
+		break;
+	      }
+	  if (taken)
+	    /* this element zero, branch taken */
+	    break;
+	  buf = elem_end;
+	}
+
+      if (op & 0x4)
+	/* BNZ.df: 111xx (branch if all elements are non-zero)
+	   Branch taken is inverted compared to BZ.df */
+	taken = !taken;
+    }
+  else if ((op & 0x1b) == 0x0b)
+    {
+      /* Check whether this branch would be taken first:
+	 BZ.V:  01011 (branch if all elements are zero) */
+      taken = 1;
+      for (end = buf + size; buf < end; ++buf)
+	if (*buf)
+	  {
+	    /* this element is non-zero, branch not taken */
+	    taken = 0;
+	    break;
+	  }
+      if (op & 0x4)
+	/* BNZ.V: 01111 (branch if any elements are non-zero)
+	   Branch taken is inverted compared to BZ.V */
+	taken = !taken;
+    }
+
+  return taken;
+}
+
+/* Determine the address of the next instruction executed after the INST
+   vector branch instruction at PC.  */
+
+static CORE_ADDR
+mips32_bc1_w_pc (struct gdbarch *gdbarch, struct frame_info *frame,
+		 ULONGEST inst, CORE_ADDR pc)
+{
+  int op = itype_rs (inst);
+  int wt = itype_rt (inst);
+  int taken;
+
+  /* Will the branch be taken? */
+  taken = mips_bc1_w_taken (gdbarch, frame, op, wt);
+
+  /* Calculate branch target */
+  if (taken > 0)
+    pc += mips32_relative_offset (inst);
+  else if (taken == 0)
+    pc += 4;
+
+  return pc;
+}
+
 /* Return nonzero if the gdbarch is an Octeon series.  */
 
 static int
@@ -2567,6 +2661,14 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
 	       && (itype_rt (inst) & 2) == 0)
 	/* BC1ANY4F, BC1ANY4T: 010001 01010 xxx0x */
 	pc = mips32_bc1_pc (gdbarch, frame, inst, pc + 4, 4);
+      else if (op == 17 && (itype_rs (inst) & 0x18) == 0x18)
+	/* BZ.df:  010001 110xx */
+	/* BNZ.df: 010001 111xx */
+	pc = mips32_bc1_w_pc (gdbarch, frame, inst, pc + 4);
+      else if (op == 17 && (itype_rs (inst) & 0x1b) == 0x0b)
+	/* BZ.V:   010001 01011 */
+	/* BNZ.V:  010001 01111 */
+	pc = mips32_bc1_w_pc (gdbarch, frame, inst, pc + 4);
       else if (op == 29)
 	/* JALX: 011101 */
 	/* The new PC will be alternate mode.  */
@@ -2793,6 +2895,30 @@ micromips_bc1_pc (struct gdbarch *gdbarch, struct frame_info *frame,
 }
 
 /* Calculate the address of the next microMIPS instruction to execute
+   after the INSN coprocessor 1 vector conditional branch instruction
+   at the address PC.  */
+
+static CORE_ADDR
+micromips_bc1_w_pc (struct gdbarch *gdbarch, struct frame_info *frame,
+		    ULONGEST insn, CORE_ADDR pc)
+{
+  int op = b5s5_op (insn >> 16);
+  int wt = b0s5_reg (insn >> 16);
+  int taken;
+
+  /* Will the branch be taken? */
+  taken = mips_bc1_w_taken (gdbarch, frame, op, wt);
+
+  /* Calculate branch target */
+  if (taken > 0)
+    pc += micromips_relative_offset16 (insn);
+  else if (taken == 0)
+    pc += micromips_pc_insn_size (gdbarch, pc);
+
+  return pc;
+}
+
+/* Calculate the address of the next microMIPS instruction to execute
    after the instruction at the address PC.  */
 
 static CORE_ADDR
@@ -2914,6 +3040,16 @@ micromips_next_pc (struct frame_info *frame, CORE_ADDR pc)
 	    }
 	  break;
 
+	case 0x20: /* POOL32D: bits 100000 */
+	  if ((b5s5_op (insn) & 0x18) == 0x18
+			/* BZ.df:  bits 100000 110xx */
+			/* BNZ.df: bits 100000 111xx */
+	      || (b5s5_op (insn) & 0x1b) == 0x0b)
+			/* BZ.V:   bits 100000 01011 */
+			/* BNZ.V:  bits 100000 01111 */
+	      pc = micromips_bc1_w_pc (gdbarch, frame, insn, pc);
+	  break;
+
 	case 0x1d: /* JALS: bits 011101 */
 	case 0x35: /* J: bits 110101 */
 	case 0x3d: /* JAL: bits 111101 */
@@ -4863,9 +4999,16 @@ mips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
 	  is_branch = 1;
 	  break;
 	case 17: /* COP1 */
-	  is_branch = ((itype_rs (insn) == 9 || itype_rs (insn) == 10)
-		       && (itype_rt (insn) & 0x2) == 0);
-	  if (is_branch) /* BC1ANY2F, BC1ANY2T, BC1ANY4F, BC1ANY4T */
+	  is_branch = (((itype_rs (insn) == 9 || itype_rs (insn) == 10)
+			&& (itype_rt (insn) & 0x2) == 0)
+				/* BC1ANY2F, BC1ANY2T, BC1ANY4F, BC1ANY4T */
+		       || (itype_rs (insn) & 0x18) == 0x18
+				/* BZ.df:  010001 110xx */
+				/* BNZ.df: 010001 111xx */
+		       || (itype_rs (insn) & 0x1b) == 0x0b);
+				/* BZ.V:   010001 01011 */
+				/* BNZ.V:  010001 01111 */
+	  if (is_branch)
 	    break;
 	/* Fall through.  */
 	case 18: /* COP2 */
@@ -4956,6 +5099,16 @@ micromips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
 	case 2 * MIPS_INSN16_SIZE:
 	  switch (micromips_op (insn))
 	    {
+	    case 0x20: /* POOL32D: bits 100000 */
+	      if ((b5s5_op (insn) & 0x18) != 0x18
+				/* BZ.df:  bits 100000 110xx */
+				/* BNZ.df: bits 100000 111xx */
+		  && (b5s5_op (insn) & 0x1b) != 0x0b)
+				/* BZ.V:   bits 100000 01011 */
+				/* BNZ.V:  bits 100000 01111 */
+		break;
+	      goto handle_branch;
+
 	    case 0x10: /* POOL32I: bits 010000 */
 	      if ((b5s5_op (insn) & 0x18) != 0x0
 				/* BLTZ, BLTZAL, BGEZ, BGEZAL: 010000 000xx */
@@ -4978,6 +5131,7 @@ micromips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
 
 	    case 0x25: /* BEQ: bits 100101 */
 	    case 0x2d: /* BNE: bits 101101 */
+handle_branch:
 	      insn <<= 16;
 	      insn |= mips_fetch_instruction (gdbarch,
 					      ISA_MICROMIPS, loc, NULL);
@@ -8259,8 +8413,14 @@ mips32_instruction_has_delay_slot (struct gdbarch *gdbarch, ULONGEST inst)
 				/* BC1F, BC1FL, BC1T, BC1TL: 010001 01000  */
 		      || (rs == 9 && (rt & 0x2) == 0)
 				/* BC1ANY2F, BC1ANY2T: bits 010001 01001  */
-		      || (rs == 10 && (rt & 0x2) == 0))));
+		      || (rs == 10 && (rt & 0x2) == 0)
 				/* BC1ANY4F, BC1ANY4T: bits 010001 01010  */
+		      || ((rs & 0x18) == 0x18)
+				/* BZ.df:  bits 010001 110xx */
+				/* BNZ.df: bits 010001 111xx */
+		      || ((rs & 0x1b) == 0x0b))));
+				/* BZ.V:   bits 010001 01011 */
+				/* BNZ.V:  bits 010001 01111 */
     }
   else
     switch (op & 0x07)		/* extract bits 28,27,26  */
@@ -8331,6 +8491,13 @@ micromips_instruction_has_delay_slot (ULONGEST insn, int mustbe32)
     case 0x35:			/* J: bits 110101 */
     case 0x2d:			/* BNE: bits 101101 */
     case 0x25:			/* BEQ: bits 100101 */
+    case 0x20:			/* POOL32D: bits 100000 */
+      return ((b5s5_op (major) & 0x18) == 0x18
+				/* BZ.df:  bits 100000 110xx */
+				/* BNZ.df: bits 100000 111xx */
+	      || ((b5s5_op (major) & 0x1b) == 0x0b));
+				/* BZ.V:   bits 100000 01011 */
+				/* BNZ.V:  bits 100000 01111 */
     case 0x1d:			/* JALS: bits 011101 */
       return 1;
     case 0x10:			/* POOL32I: bits 010000 */
-- 
1.9-rc2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 12/24]     o32 sigframe unwinding with FR1
  2016-06-27 14:50 [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size Bhushan Attarde
                   ` (18 preceding siblings ...)
  2016-06-27 14:51 ` [PATCH 18/24] mips-linux-nat: get msa registers Bhushan Attarde
@ 2016-06-27 14:51 ` Bhushan Attarde
  2016-07-25 14:03 ` [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size Maciej W. Rozycki
  2016-11-08 19:46 ` Yao Qi
  21 siblings, 0 replies; 37+ messages in thread
From: Bhushan Attarde @ 2016-06-27 14:51 UTC (permalink / raw)
  To: gdb-patches
  Cc: Maciej.Rozycki, Matthew.Fortune, James.Hogan, Andrew.Bennett,
	Jaydeep.Patil, Bhushan Attarde

    gdb/ChangeLog:

        * mips-linux-tdep.c (SIGCONTEXT_USEDMATH): New definition.
        (USED_FP, USED_FR1, USED_HYBRID_FPRS): Add fallback definitions.
        (mips_linux_o32_sigframe_init): Frame override of raw register.
---
 gdb/mips-linux-tdep.c | 35 ++++++++++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/gdb/mips-linux-tdep.c b/gdb/mips-linux-tdep.c
index d337a5b..e1f113f 100644
--- a/gdb/mips-linux-tdep.c
+++ b/gdb/mips-linux-tdep.c
@@ -1053,6 +1053,7 @@ static const struct tramp_frame micromips_linux_n64_rt_sigframe = {
 #define SIGCONTEXT_REGS     (2 * 8)
 #define SIGCONTEXT_FPREGS   (34 * 8)
 #define SIGCONTEXT_FPCSR    (66 * 8 + 4)
+#define SIGCONTEXT_USEDMATH (67 * 8 + 4)
 #define SIGCONTEXT_DSPCTL   (68 * 8 + 0)
 #define SIGCONTEXT_HI       (69 * 8)
 #define SIGCONTEXT_LO       (70 * 8)
@@ -1067,6 +1068,16 @@ static const struct tramp_frame micromips_linux_n64_rt_sigframe = {
 
 #define SIGCONTEXT_REG_SIZE 8
 
+#ifndef USED_FP
+#define USED_FP		    (1 << 0)
+#endif
+#ifndef USED_FR1
+#define USED_FR1	    (1 << 1)
+#endif
+#ifndef USED_HYBRID_FPRS
+#define USED_HYBRID_FPRS    (1 << 2)
+#endif
+
 static void
 mips_linux_o32_sigframe_init (const struct tramp_frame *self,
 			      struct frame_info *this_frame,
@@ -1079,6 +1090,9 @@ mips_linux_o32_sigframe_init (const struct tramp_frame *self,
   CORE_ADDR sigcontext_base;
   const struct mips_regnum *regs = mips_regnum (gdbarch);
   CORE_ADDR regs_base;
+  gdb_byte buf[4];
+  uint32_t used_math;
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
 
   if (self == &mips_linux_o32_sigframe
       || self == &micromips_linux_o32_sigframe)
@@ -1109,6 +1123,14 @@ mips_linux_o32_sigframe_init (const struct tramp_frame *self,
 			     (regs_base + SIGCONTEXT_REGS
 			      + ireg * SIGCONTEXT_REG_SIZE));
 
+  /* Read the used_math field.  */
+  if (safe_frame_unwind_memory (this_frame,
+				sigcontext_base + SIGCONTEXT_USEDMATH,
+				buf, 4))
+    used_math = extract_unsigned_integer (buf, 4, gdbarch_byte_order (gdbarch));
+  else
+    used_math = 0;
+
   /* The way that floating point registers are saved, unfortunately,
      depends on the architecture the kernel is built for.  For the r3000 and
      tx39, four bytes of each register are at the beginning of each of the
@@ -1118,7 +1140,18 @@ mips_linux_o32_sigframe_init (const struct tramp_frame *self,
      layout, since we can't tell, and it's much more common.  Which bits are
      the "high" bits depends on endianness.  */
   for (ireg = 0; ireg < 32; ireg++)
-    if ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) != (ireg & 1))
+    if (used_math & USED_FR1)
+      {
+	trad_frame_set_reg_addr (this_cache,
+				 ireg + regs->fp0,
+				 (sigcontext_base + SIGCONTEXT_FPREGS
+				  + ireg * SIGCONTEXT_REG_SIZE));
+	trad_frame_set_reg_addr (this_cache,
+				 ireg + regs->fp0 + gdbarch_num_regs (gdbarch),
+				 (sigcontext_base + SIGCONTEXT_FPREGS
+				  + ireg * SIGCONTEXT_REG_SIZE));
+      }
+    else if ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) != (ireg & 1))
       trad_frame_set_reg_addr (this_cache,
 			       ireg + regs->fp0 + gdbarch_num_regs (gdbarch),
 			       (sigcontext_base + SIGCONTEXT_FPREGS + 4
-- 
1.9-rc2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 07/24]     MIPS: Make Linux restart register more dynamic
  2016-06-27 14:50 [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size Bhushan Attarde
                   ` (14 preceding siblings ...)
  2016-06-27 14:51 ` [PATCH 14/24] Implement core MSA stuff Bhushan Attarde
@ 2016-06-27 14:51 ` Bhushan Attarde
  2016-06-27 14:51 ` [PATCH 19/24] Add MIPS MSA vector branch instruction support Bhushan Attarde
                   ` (5 subsequent siblings)
  21 siblings, 0 replies; 37+ messages in thread
From: Bhushan Attarde @ 2016-06-27 14:51 UTC (permalink / raw)
  To: gdb-patches
  Cc: Maciej.Rozycki, Matthew.Fortune, James.Hogan, Andrew.Bennett,
	Jaydeep.Patil, Bhushan Attarde

    The Linux restart register has a fixed register number defined by
    MIPS_RESTART_REGNUM. The number of raw and pseudo registers is increased
    to MIPS_RESTART_REGNUM + 1 if it is safe to do so (if a target description
    is available) with an assert to ensure that the number of registers hasn't
    already exceeded MIPS_RESTART_REGNUM.

    This isn't conducive to adding more optional dynamic registers since
    MIPS_RESTART_REGNUM would keep needing to be updated to avoid the assert,
    so add a linux_restart register number to the struct mips_regnum and
    assign the register number dynamically.

    gdb/ChangeLog:

    	* mips-linux-nat.c (mips_linux_register_addr,
    	mips64_linux_register_addr): Use mips_regnum::linux_restart in
    	preference to mips_linux_restart_reg_p and MIPS_RESTART_REGNUM.
    	* mips-linux-tdep.c (mips_supply_gregset, mips_fill_gregset,
    	mips64_supply_gregset, mips64_fill_gregset,
    	mips_linux_o32_sigframe_init, mips_linux_n32n64_sigframe_init,
    	mips_linux_write_pc): Likewise.
    	(mips_linux_restart_reg_p): Remove.
    	(mips_linux_init_abi): Assign linux_restart register number
    	dynamically and only if the target provides it.
    	* mips-linux-tdep.h: Remove MIPS_RESTART_REGNUM enum value.
    	(mips_linux_restart_reg_p): Remove declaration.
    	* mips-tdep.c (mips_gdbarch_init): Initialise linux_restart register
    	number to -1.
    	* mips-tdep.h (struct mips_regnum): Add linux_restart member.
---
 gdb/mips-linux-nat.c  |  4 +--
 gdb/mips-linux-tdep.c | 80 ++++++++++++++++++++++++---------------------------
 gdb/mips-linux-tdep.h | 10 -------
 gdb/mips-tdep.c       |  1 +
 gdb/mips-tdep.h       |  1 +
 5 files changed, 42 insertions(+), 54 deletions(-)

diff --git a/gdb/mips-linux-nat.c b/gdb/mips-linux-nat.c
index 543cc36..fd1837f 100644
--- a/gdb/mips-linux-nat.c
+++ b/gdb/mips-linux-nat.c
@@ -117,7 +117,7 @@ mips_linux_register_addr (struct gdbarch *gdbarch, int regno, int store)
     regaddr = DSP_BASE + (regno - mips_regnum (gdbarch)->dspacc);
   else if (regno == mips_regnum (gdbarch)->dspctl)
     regaddr = DSP_CONTROL;
-  else if (mips_linux_restart_reg_p (gdbarch) && regno == MIPS_RESTART_REGNUM)
+  else if (regno == mips_regnum (gdbarch)->linux_restart)
     regaddr = 0;
   else
     regaddr = (CORE_ADDR) -1;
@@ -158,7 +158,7 @@ mips64_linux_register_addr (struct gdbarch *gdbarch, int regno, int store)
     regaddr = DSP_BASE + (regno - mips_regnum (gdbarch)->dspacc);
   else if (regno == mips_regnum (gdbarch)->dspctl)
     regaddr = DSP_CONTROL;
-  else if (mips_linux_restart_reg_p (gdbarch) && regno == MIPS_RESTART_REGNUM)
+  else if (regno == mips_regnum (gdbarch)->linux_restart)
     regaddr = 0;
   else
     regaddr = (CORE_ADDR) -1;
diff --git a/gdb/mips-linux-tdep.c b/gdb/mips-linux-tdep.c
index 6b9743b..82b8127 100644
--- a/gdb/mips-linux-tdep.c
+++ b/gdb/mips-linux-tdep.c
@@ -141,8 +141,9 @@ mips_supply_gregset (struct regcache *regcache,
   for (regi = EF_REG0 + 1; regi <= EF_REG31; regi++)
     supply_32bit_reg (regcache, regi - EF_REG0, regp + regi);
 
-  if (mips_linux_restart_reg_p (gdbarch))
-    supply_32bit_reg (regcache, MIPS_RESTART_REGNUM, regp + EF_REG0);
+  if (mips_regnum (gdbarch)->linux_restart >= 0)
+    supply_32bit_reg (regcache, mips_regnum (gdbarch)->linux_restart,
+		      regp + EF_REG0);
 
   supply_32bit_reg (regcache, mips_regnum (gdbarch)->lo, regp + EF_LO);
   supply_32bit_reg (regcache, mips_regnum (gdbarch)->hi, regp + EF_HI);
@@ -191,7 +192,9 @@ mips_fill_gregset (const struct regcache *regcache,
       mips_fill_gregset (regcache, gregsetp, mips_regnum (gdbarch)->badvaddr);
       mips_fill_gregset (regcache, gregsetp, MIPS_PS_REGNUM);
       mips_fill_gregset (regcache, gregsetp, mips_regnum (gdbarch)->cause);
-      mips_fill_gregset (regcache, gregsetp, MIPS_RESTART_REGNUM);
+      if (mips_regnum (gdbarch)->linux_restart >= 0)
+	mips_fill_gregset (regcache, gregsetp,
+			   mips_regnum (gdbarch)->linux_restart);
       return;
    }
 
@@ -214,8 +217,7 @@ mips_fill_gregset (const struct regcache *regcache,
     regaddr = EF_CP0_STATUS;
   else if (regno == mips_regnum (gdbarch)->cause)
     regaddr = EF_CP0_CAUSE;
-  else if (mips_linux_restart_reg_p (gdbarch)
-	   && regno == MIPS_RESTART_REGNUM)
+  else if (regno == mips_regnum (gdbarch)->linux_restart)
     regaddr = EF_REG0;
   else
     regaddr = -1;
@@ -388,8 +390,8 @@ mips64_supply_gregset (struct regcache *regcache,
     supply_64bit_reg (regcache, regi - MIPS64_EF_REG0,
 		      (const gdb_byte *) (regp + regi));
 
-  if (mips_linux_restart_reg_p (gdbarch))
-    supply_64bit_reg (regcache, MIPS_RESTART_REGNUM,
+  if (mips_regnum (gdbarch)->linux_restart >= 0)
+    supply_64bit_reg (regcache, mips_regnum (gdbarch)->linux_restart,
 		      (const gdb_byte *) (regp + MIPS64_EF_REG0));
 
   supply_64bit_reg (regcache, mips_regnum (gdbarch)->lo,
@@ -444,7 +446,8 @@ mips64_fill_gregset (const struct regcache *regcache,
 			   mips_regnum (gdbarch)->badvaddr);
       mips64_fill_gregset (regcache, gregsetp, MIPS_PS_REGNUM);
       mips64_fill_gregset (regcache, gregsetp,  mips_regnum (gdbarch)->cause);
-      mips64_fill_gregset (regcache, gregsetp, MIPS_RESTART_REGNUM);
+      mips64_fill_gregset (regcache, gregsetp,
+			   mips_regnum (gdbarch)->linux_restart);
       return;
    }
 
@@ -462,8 +465,7 @@ mips64_fill_gregset (const struct regcache *regcache,
     regaddr = MIPS64_EF_CP0_STATUS;
   else if (regno == mips_regnum (gdbarch)->cause)
     regaddr = MIPS64_EF_CP0_CAUSE;
-  else if (mips_linux_restart_reg_p (gdbarch)
-	   && regno == MIPS_RESTART_REGNUM)
+  else if (regno == mips_regnum (gdbarch)->linux_restart)
     regaddr = MIPS64_EF_REG0;
   else
     regaddr = -1;
@@ -1094,9 +1096,9 @@ mips_linux_o32_sigframe_init (const struct tramp_frame *self,
   else
     regs_base = sigcontext_base;
 
-  if (mips_linux_restart_reg_p (gdbarch))
+  if (mips_regnum (gdbarch)->linux_restart >= 0)
     trad_frame_set_reg_addr (this_cache,
-			     (MIPS_RESTART_REGNUM
+			     (mips_regnum (gdbarch)->linux_restart
 			      + gdbarch_num_regs (gdbarch)),
 			     regs_base + SIGCONTEXT_REGS);
 
@@ -1286,9 +1288,9 @@ mips_linux_n32n64_sigframe_init (const struct tramp_frame *self,
   else
     sigcontext_base = frame_sp + N64_SIGFRAME_SIGCONTEXT_OFFSET;
 
-  if (mips_linux_restart_reg_p (gdbarch))
+  if (mips_regnum (gdbarch)->linux_restart >= 0)
     trad_frame_set_reg_addr (this_cache,
-			     (MIPS_RESTART_REGNUM
+			     (mips_regnum (gdbarch)->linux_restart
 			      + gdbarch_num_regs (gdbarch)),
 			     sigcontext_base + N64_SIGCONTEXT_REGS);
 
@@ -1387,23 +1389,9 @@ mips_linux_write_pc (struct regcache *regcache, CORE_ADDR pc)
   mips_write_pc (regcache, pc);
 
   /* Clear the syscall restart flag.  */
-  if (mips_linux_restart_reg_p (gdbarch))
-    regcache_cooked_write_unsigned (regcache, MIPS_RESTART_REGNUM, 0);
-}
-
-/* Return 1 if MIPS_RESTART_REGNUM is usable.  */
-
-int
-mips_linux_restart_reg_p (struct gdbarch *gdbarch)
-{
-  /* If we do not have a target description with registers, then
-     MIPS_RESTART_REGNUM will not be included in the register set.  */
-  if (!tdesc_has_registers (gdbarch_target_desc (gdbarch)))
-    return 0;
-
-  /* If we do, then MIPS_RESTART_REGNUM is safe to check; it will
-     either be GPR-sized or missing.  */
-  return register_size (gdbarch, MIPS_RESTART_REGNUM) > 0;
+  if (mips_regnum (gdbarch)->linux_restart >= 0)
+    regcache_cooked_write_unsigned (regcache,
+				    mips_regnum (gdbarch)->linux_restart, 0);
 }
 
 /* When FRAME is at a syscall instruction, return the PC of the next
@@ -1743,19 +1731,27 @@ mips_linux_init_abi (struct gdbarch_info info,
     {
       const struct tdesc_feature *feature;
 
-      /* If we have target-described registers, then we can safely
-	 reserve a number for MIPS_RESTART_REGNUM (whether it is
-	 described or not).  */
-      gdb_assert (gdbarch_num_regs (gdbarch) <= MIPS_RESTART_REGNUM);
-      set_gdbarch_num_regs (gdbarch, MIPS_RESTART_REGNUM + 1);
-      set_gdbarch_num_pseudo_regs (gdbarch, MIPS_RESTART_REGNUM + 1);
-
-      /* If it's present, then assign it to the reserved number.  */
+      /* If "restart" is present in the target register description,
+	 then assign it to a new register number.  */
       feature = tdesc_find_feature (info.target_desc,
 				    "org.gnu.gdb.mips.linux");
-      if (feature != NULL)
-	tdesc_numbered_register (feature, (((struct gdbarch_tdep_info*)(info.tdep_info))->tdesc_data),
-				 MIPS_RESTART_REGNUM, "restart");
+      if (feature != NULL
+	  && tdesc_unnumbered_register (feature, "restart"))
+	{
+	  int restart_regnum;
+	  /* We cast away const'ness in order to set linux_restart.
+	     */
+	  struct mips_regnum *regnum =
+			(struct mips_regnum *)mips_regnum (gdbarch);
+
+	  restart_regnum = gdbarch_num_regs (gdbarch);
+	  regnum->linux_restart = restart_regnum;
+	  set_gdbarch_num_regs (gdbarch, restart_regnum + 1);
+	  set_gdbarch_num_pseudo_regs (gdbarch, restart_regnum + 1);
+
+	  tdesc_numbered_register (feature, (((struct gdbarch_tdep_info*)(info.tdep_info))->tdesc_data),
+				   restart_regnum, "restart");
+	}
     }
 }
 
diff --git a/gdb/mips-linux-tdep.h b/gdb/mips-linux-tdep.h
index e8a69fb..4537fcd 100644
--- a/gdb/mips-linux-tdep.h
+++ b/gdb/mips-linux-tdep.h
@@ -95,13 +95,3 @@ void mips64_supply_fpregset (struct regcache *,
 			     const mips64_elf_fpregset_t *);
 void mips64_fill_fpregset (const struct regcache *,
 			   mips64_elf_fpregset_t *, int);
-
-enum {
-  /* The Linux kernel stores an error code from any interrupted
-     syscall in a "register" (in $0's save slot).  */
-  MIPS_RESTART_REGNUM = 79
-};
-
-/* Return 1 if MIPS_RESTART_REGNUM is usable.  */
-
-int mips_linux_restart_reg_p (struct gdbarch *gdbarch);
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index 28cfb57..61b560c 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -8261,6 +8261,7 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   /* Fill in the OS dependent register numbers and names.  */
   mips_regnum.config5 = -1;
+  mips_regnum.linux_restart = -1;
   if (info.osabi == GDB_OSABI_IRIX)
     {
       mips_regnum.fp0 = 32;
diff --git a/gdb/mips-tdep.h b/gdb/mips-tdep.h
index 39af72b..97bfab3 100644
--- a/gdb/mips-tdep.h
+++ b/gdb/mips-tdep.h
@@ -70,6 +70,7 @@ struct mips_regnum
   int lo;		/* ...  */
   int dspacc;		/* SmartMIPS/DSP accumulators.  */
   int dspctl;		/* DSP control.  */
+  int linux_restart;
 };
 extern const struct mips_regnum *mips_regnum (struct gdbarch *gdbarch);
 
-- 
1.9-rc2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 20/24]     Drop FP and MSA control registers from default info registers
  2016-06-27 14:50 [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size Bhushan Attarde
                   ` (8 preceding siblings ...)
  2016-06-27 14:51 ` [PATCH 09/24] MIPS: Enhance cooked FP format Bhushan Attarde
@ 2016-06-27 14:51 ` Bhushan Attarde
  2016-06-27 14:51 ` [PATCH 23/24] MIPS R6 opcode table shuffle for LDC2/SDC2 Bhushan Attarde
                   ` (11 subsequent siblings)
  21 siblings, 0 replies; 37+ messages in thread
From: Bhushan Attarde @ 2016-06-27 14:51 UTC (permalink / raw)
  To: gdb-patches
  Cc: Maciej.Rozycki, Matthew.Fortune, James.Hogan, Andrew.Bennett,
	Jaydeep.Patil, Bhushan Attarde

    gdb/ChangeLog:
        * mips-tdep.c (print_gp_register_row, mips_print_registers_info):
        Skip FP & MSA control registers.
---
 gdb/mips-tdep.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index 7a6d23d..14e3aa6 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -7650,6 +7650,9 @@ print_gp_register_row (struct ui_file *file, struct frame_info *frame,
       if (mips_float_register_p (gdbarch, regnum) ||
 	  mips_vector_register_p (gdbarch, regnum))
 	break;			/* End the row: reached FP register.  */
+      if (mips_register_reggroup_p (gdbarch, regnum, float_reggroup) ||
+	  mips_register_reggroup_p (gdbarch, regnum, vector_reggroup))
+	break;
       /* Large registers are handled separately.  */
       if (register_size (gdbarch, regnum) > mips_abi_regsize (gdbarch))
 	{
@@ -7690,6 +7693,9 @@ print_gp_register_row (struct ui_file *file, struct frame_info *frame,
       if (mips_float_register_p (gdbarch, regnum) ||
 	  mips_vector_register_p (gdbarch, regnum))
 	break;			/* End row: reached FP register.  */
+      if (mips_register_reggroup_p (gdbarch, regnum, float_reggroup) ||
+	 mips_register_reggroup_p (gdbarch, regnum, vector_reggroup))
+	break;
       if (register_size (gdbarch, regnum) > mips_abi_regsize (gdbarch))
 	break;			/* End row: large register.  */
 
@@ -7776,8 +7782,13 @@ mips_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file,
 	    }
 	  else if (mips_register_reggroup_p (gdbarch, regnum, float_reggroup) ||
 		   mips_register_reggroup_p (gdbarch, regnum, vector_reggroup))
-	    /* FP & MSA control registers */
-	    regnum = print_control_register_row (file, frame, regnum);
+	    {
+	      /* FP & MSA control registers */
+	      if (all)		/* True for "INFO ALL-REGISTERS" command.  */
+		regnum = print_control_register_row (file, frame, regnum);
+	      else
+		++regnum;
+	    }
 	  else
 	    regnum = print_gp_register_row (file, frame, regnum);
 	}
-- 
1.9-rc2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 18/24]     mips-linux-nat: get msa registers
  2016-06-27 14:50 [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size Bhushan Attarde
                   ` (17 preceding siblings ...)
  2016-06-27 14:51 ` [PATCH 05/24] MIPS: Add config5 to MIPS GDB target descriptions Bhushan Attarde
@ 2016-06-27 14:51 ` Bhushan Attarde
  2016-06-27 14:51 ` [PATCH 12/24] o32 sigframe unwinding with FR1 Bhushan Attarde
                   ` (2 subsequent siblings)
  21 siblings, 0 replies; 37+ messages in thread
From: Bhushan Attarde @ 2016-06-27 14:51 UTC (permalink / raw)
  To: gdb-patches
  Cc: Maciej.Rozycki, Matthew.Fortune, James.Hogan, Andrew.Bennett,
	Jaydeep.Patil, Bhushan Attarde

    This patch gets MSA registers using ptrace and sets up internal register
    state.

    gdb/gdbserver/ChangeLog:
        * mips-linux-nat.c (have_ptrace_getregset_msa): New variable.
        (mips64_linux_regsets_store_registers): Likewaise.
        (mips64_linux_regsets_fetch_registers): New is_vec variable.
        Get MSA regset first and then fp regset.
        (mips64_linux_regsets_store_registers): Likewaise.

    include/ChangeLog:
        * elf/common.h (NT_MIPS_MSA): New definition.
---
 gdb/mips-linux-nat.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++++---
 include/elf/common.h |   1 +
 2 files changed, 156 insertions(+), 8 deletions(-)

diff --git a/gdb/mips-linux-nat.c b/gdb/mips-linux-nat.c
index 20e3d17..a674885 100644
--- a/gdb/mips-linux-nat.c
+++ b/gdb/mips-linux-nat.c
@@ -68,6 +68,7 @@ static int have_ptrace_regsets = 1;
 /* Does the current host support PTRACE_GETREGSET?  */
 static int have_ptrace_getregset_gp = 1;
 static int have_ptrace_getregset_fp = 1;
+static int have_ptrace_getregset_msa = 1;
 
 /* Saved function pointers to fetch and store a single register using
    PTRACE_PEEKUSER and PTRACE_POKEUSER.  */
@@ -231,7 +232,7 @@ mips64_linux_regsets_fetch_registers (struct target_ops *ops,
 {
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
   int big_endian = (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG);
-  int is_fp, is_dsp;
+  int is_fp, is_dsp, is_vec;
   int have_dsp;
   int regi;
   int tid;
@@ -252,6 +253,14 @@ mips64_linux_regsets_fetch_registers (struct target_ops *ops,
   else
     is_fp = 0;
 
+  /* Vector registers are optional but overlap fp registers */
+  if (regno == mips_regnum (gdbarch)->msa_csr)
+    is_vec = 1;
+  else if (regno == mips_regnum (gdbarch)->msa_ir)
+    is_vec = 1;
+  else
+    is_vec = 0;
+
   /* DSP registers are optional and not a part of any set.  */
   have_dsp = mips_regnum (gdbarch)->dspctl != -1;
   if (!have_dsp)
@@ -268,7 +277,7 @@ mips64_linux_regsets_fetch_registers (struct target_ops *ops,
   if (tid == 0)
     tid = ptid_get_pid (inferior_ptid);
 
-  if (regno == -1 || (!is_fp && !is_dsp))
+  if (regno == -1 || (!is_fp && !is_dsp && !is_vec))
     {
       mips64_elf_gregset_t regs;
 
@@ -286,13 +295,72 @@ mips64_linux_regsets_fetch_registers (struct target_ops *ops,
 			     (const mips64_elf_gregset_t *) &regs);
     }
 
-  if (is_fp)
+  if (is_fp || is_vec)
     {
       const struct mips_regnum *rn = mips_regnum (gdbarch);
       int float_regnum = rn->fp0;
 
+      /* Try the MSA regset first if vector registers are desired */
+      if (rn->msa_csr != -1
+	  && have_ptrace_getregset_gp && have_ptrace_getregset_msa)
+	{
+	  unsigned char w_regs[34][16];
+	  unsigned char buf[16];
+	  struct iovec iovec;
+	  int ret;
+
+	  iovec.iov_base = &w_regs;
+	  iovec.iov_len = sizeof (w_regs);
+
+	  ret = ptrace (PTRACE_GETREGSET, tid, NT_MIPS_MSA, &iovec);
+	  if (ret < 0)
+	    {
+	      if (errno == EIO)
+		have_ptrace_getregset_gp = 0;
+	      else if (errno == EINVAL)
+		have_ptrace_getregset_msa = 0;
+	      else
+		perror_with_name (_("Unable to fetch FP/MSA registers."));
+	    }
+	  else
+	    {
+	      /* full vector including float */
+	      if (big_endian)
+		for (regi = 0; regi < 32; regi++)
+		  {
+		    /* swap 64-bit halves, so it's a single word */
+		    memcpy(buf, w_regs[regi] + 8, 8);
+		    memcpy(buf + 8, w_regs[regi], 8);
+		    regcache_raw_supply (regcache, float_regnum + regi, buf);
+		  }
+	      else
+		for (regi = 0; regi < 32; regi++)
+		  regcache_raw_supply (regcache, float_regnum + regi,
+				       (char *) w_regs[regi]);
+
+	      if (iovec.iov_len >= 32*16 + 4)
+		regcache_raw_supply (regcache, rn->fp_implementation_revision,
+				     (char *) (w_regs + 32) + 0);
+	      if (iovec.iov_len >= 32*16 + 8)
+		regcache_raw_supply (regcache, rn->fp_control_status,
+				     (char *) (w_regs + 32) + 4);
+	      if (iovec.iov_len >= 32*16 + 12)
+		regcache_raw_supply (regcache, rn->msa_ir,
+				     (char *) (w_regs + 32) + 8);
+	      if (iovec.iov_len >= 32*16 + 16)
+		regcache_raw_supply (regcache, rn->msa_csr,
+				     (char *) (w_regs + 32) + 12);
+	      if (iovec.iov_len >= 33*16 + 4)
+		regcache_raw_supply (regcache, rn->config5,
+				     (char *) (w_regs + 33) + 0);
+
+	      /* we've got fp registers now */
+	      is_fp = 0;
+	    }
+	}
+
       /* Try the FP regset next as it may contain Config5 */
-      if (have_ptrace_getregset_gp && have_ptrace_getregset_fp)
+      if (is_fp && have_ptrace_getregset_gp && have_ptrace_getregset_fp)
 	{
 	  unsigned char fp_regs[34][8];
 	  struct iovec iovec;
@@ -396,7 +464,7 @@ mips64_linux_regsets_store_registers (struct target_ops *ops,
 {
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
   int big_endian = (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG);
-  int is_fp, is_dsp;
+  int is_fp, is_dsp, is_vec;
   int have_dsp;
   int regi;
   int tid;
@@ -417,6 +485,17 @@ mips64_linux_regsets_store_registers (struct target_ops *ops,
   else
     is_fp = 0;
 
+  /* Vector registers are optional but overlap fp registers */
+  if (regno >= mips_regnum (gdbarch)->w0
+      && regno <= mips_regnum (gdbarch)->w0 + 32)
+    is_vec = 1;
+  else if (regno == mips_regnum (gdbarch)->msa_csr)
+    is_vec = 1;
+  else if (regno == mips_regnum (gdbarch)->msa_ir)
+    is_vec = 1;
+  else
+    is_vec = 0;
+
   /* DSP registers are optional and not a part of any set.  */
   have_dsp = mips_regnum (gdbarch)->dspctl != -1;
   if (!have_dsp)
@@ -433,7 +512,7 @@ mips64_linux_regsets_store_registers (struct target_ops *ops,
   if (tid == 0)
     tid = ptid_get_pid (inferior_ptid);
 
-  if (regno == -1 || (!is_fp && !is_dsp))
+  if (regno == -1 || (!is_fp && !is_dsp && !is_vec))
     {
       mips64_elf_gregset_t regs;
 
@@ -446,13 +525,81 @@ mips64_linux_regsets_store_registers (struct target_ops *ops,
 	perror_with_name (_("Couldn't set registers"));
     }
 
-  if (is_fp)
+  if (is_fp || is_vec)
     {
       const struct mips_regnum *rn = mips_regnum (gdbarch);
       int float_regnum = rn->fp0;
 
+      /* Try the MSA regset first if vector registers are desired */
+      if (rn->msa_csr != -1
+	  && have_ptrace_getregset_gp && have_ptrace_getregset_msa)
+	{
+	  unsigned char w_regs[34][16];
+	  unsigned char buf[16];
+	  struct iovec iovec;
+	  int ret;
+
+	  iovec.iov_base = &w_regs;
+	  iovec.iov_len = sizeof (w_regs);
+
+	  ret = ptrace (PTRACE_GETREGSET, tid, NT_MIPS_MSA, &iovec);
+	  if (ret < 0)
+	    {
+	      if (errno == EIO)
+		have_ptrace_getregset_gp = 0;
+	      else if (errno == EINVAL)
+		have_ptrace_getregset_msa = 0;
+	      else
+		perror_with_name (_("Unable to fetch FP/MSA registers."));
+	    }
+	  else
+	    {
+	      /* full vector including float */
+	      if (big_endian)
+		for (regi = 0; regi < 32; regi++)
+		  {
+		    regcache_raw_collect (regcache, float_regnum + regi, buf);
+		    /* swap 64-bit halves, as it's a single word */
+		    memcpy(w_regs[regi], buf + 8, 8);
+		    memcpy(w_regs[regi] + 8, buf, 8);
+		  }
+	      else
+		for (regi = 0; regi < 32; regi++)
+		  regcache_raw_collect (regcache, float_regnum + regi,
+					(char *) w_regs[regi]);
+
+	      regcache_raw_collect (regcache, rn->fp_implementation_revision,
+				    (char *) (w_regs + 32) + 0);
+	      regcache_raw_collect (regcache, rn->fp_control_status,
+				    (char *) (w_regs + 32) + 4);
+	      regcache_raw_collect (regcache, rn->msa_ir,
+				    (char *) (w_regs + 32) + 8);
+	      regcache_raw_collect (regcache, rn->msa_csr,
+				    (char *) (w_regs + 32) + 12);
+	      regcache_raw_collect (regcache, rn->config5,
+				    (char *) (w_regs + 33) + 0);
+
+	      /* don't modify iovec length from amount of data returned */
+	      ret = ptrace (PTRACE_SETREGSET, tid, NT_MIPS_MSA, &iovec);
+	      if (ret < 0)
+		{
+		  if (errno == EIO)
+		    have_ptrace_getregset_gp = 0;
+		  if (errno == EINVAL)
+		    have_ptrace_getregset_msa = 0;
+		  else
+		    perror_with_name (_("Unable to store FP/MSA registers."));
+		}
+	      else
+		{
+		  /* we've written fp registers now */
+		  is_fp = 0;
+		}
+	    }
+	}
+
       /* Try the FP regset next as it may contain Config5 */
-      if (have_ptrace_getregset_gp && have_ptrace_getregset_fp)
+      if (is_fp && have_ptrace_getregset_gp && have_ptrace_getregset_fp)
 	{
 	  unsigned char fp_regs[34][8];
 	  struct iovec iovec;
diff --git a/include/elf/common.h b/include/elf/common.h
index 087d876..5955874 100644
--- a/include/elf/common.h
+++ b/include/elf/common.h
@@ -580,6 +580,7 @@
 					/*   note name must be "LINUX".  */
 #define NT_ARM_HW_WATCH	0x403		/* AArch hardware watchpoint registers */
 					/*   note name must be "LINUX".  */
+#define NT_MIPS_MSA	0x600		/* MIPS MSA vector registers. */
 #define NT_SIGINFO	0x53494749	/* Fields of siginfo_t.  */
 #define NT_FILE		0x46494c45	/* Description of mapped files.  */
 
-- 
1.9-rc2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 23/24]     MIPS R6 opcode table shuffle for LDC2/SDC2
  2016-06-27 14:50 [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size Bhushan Attarde
                   ` (9 preceding siblings ...)
  2016-06-27 14:51 ` [PATCH 20/24] Drop FP and MSA control registers from default info registers Bhushan Attarde
@ 2016-06-27 14:51 ` Bhushan Attarde
  2016-06-27 14:51 ` [PATCH 02/24] Add MIPS32 FPU64 GDB target descriptions Bhushan Attarde
                   ` (10 subsequent siblings)
  21 siblings, 0 replies; 37+ messages in thread
From: Bhushan Attarde @ 2016-06-27 14:51 UTC (permalink / raw)
  To: gdb-patches
  Cc: Maciej.Rozycki, Matthew.Fortune, James.Hogan, Andrew.Bennett,
	Jaydeep.Patil, Bhushan Attarde

    opcodes/ChangeLog:
        * mips-opc.c (mips_builtin_opcodes): Move all ldc2 and sdc2 at
        the bottom of the table.
---
 opcodes/mips-opc.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/opcodes/mips-opc.c b/opcodes/mips-opc.c
index 79a8417..c5c7755 100644
--- a/opcodes/mips-opc.c
+++ b/opcodes/mips-opc.c
@@ -1243,9 +1243,7 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"ldc1",		"E,A(b)",	0,    (int) M_LDC1_AB,	INSN_MACRO,		INSN2_M_FP_D,	I2,		0,	SF },
 {"l.d",			"T,o(b)",	0xd4000000, 0xfc000000, WR_1|RD_3|CLD|FP_D,	0,		I2,		0,	SF }, /* ldc1 */
 {"l.d",			"T,A(b)",	0,    (int) M_L_DAB,	INSN_MACRO,		INSN2_M_FP_D,	I1,		0,	0 },
-{"ldc2",		"E,+:(d)",	0x49c00000, 0xffe00000,	RD_3|WR_C2|CLD,		0,		I37,		0,	0 },
-{"ldc2",		"E,o(b)",	0xd8000000, 0xfc000000,	RD_3|WR_CC|CLD,		0,		I2,		0,	IOCT|IOCTP|IOCT2|EE|I37 },
-{"ldc2",		"E,A(b)",	0,    (int) M_LDC2_AB,	INSN_MACRO,		0,		I2,		0,	IOCT|IOCTP|IOCT2|EE },
+/* ldc2 is at the end of the table.  */
 {"ldc3",		"E,o(b)",	0xdc000000, 0xfc000000,	RD_3|WR_CC|CLD,		0,		I2,		0,	IOCT|IOCTP|IOCT2|EE },
 {"ldc3",		"E,A(b)",	0,    (int) M_LDC3_AB,	INSN_MACRO,		0,		I2,		0,	IOCT|IOCTP|IOCT2|EE },
 {"ldl",			"t,o(b)",	0x68000000, 0xfc000000, WR_1|RD_3|LM,		0,		I3,		0,	I69 },
@@ -1812,9 +1810,7 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"sdc1",		"E,o(b)",	0xf4000000, 0xfc000000, RD_1|RD_3|SM|FP_D,	0,		I2,		0,	SF },
 {"sdc1",		"T,A(b)",	0,    (int) M_SDC1_AB,	INSN_MACRO,		INSN2_M_FP_D,	I2,		0,	SF },
 {"sdc1",		"E,A(b)",	0,    (int) M_SDC1_AB,	INSN_MACRO,		INSN2_M_FP_D,	I2,		0,	SF },
-{"sdc2",		"E,+:(d)",	0x49e00000, 0xffe00000,	RD_3|RD_C2|SM,		0,		I37,		0,	0 },
-{"sdc2",		"E,o(b)",	0xf8000000, 0xfc000000,	RD_3|RD_C2|SM,		0,		I2,		0,	IOCT|IOCTP|IOCT2|EE|I37 },
-{"sdc2",		"E,A(b)",	0,    (int) M_SDC2_AB,	INSN_MACRO,		0,		I2,		0,	IOCT|IOCTP|IOCT2|EE },
+/* sdc2 is at the end of the table.  */
 {"sdc3",		"E,o(b)",	0xfc000000, 0xfc000000,	RD_3|RD_C3|SM,		0,		I2,		0,	IOCT|IOCTP|IOCT2|EE },
 {"sdc3",		"E,A(b)",	0,    (int) M_SDC3_AB,	INSN_MACRO,		0,		I2,		0,	IOCT|IOCTP|IOCT2|EE },
 {"s.d",			"T,o(b)",	0xf4000000, 0xfc000000, RD_1|RD_3|SM|FP_D,	0,		I2,		0,	SF },
@@ -3347,6 +3343,12 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"cop3",		"C",		0,    (int) M_COP3,	INSN_MACRO,		0,		I1,		0,	IOCT|IOCTP|IOCT2 },
 /* RFE conflicts with the new Virt spec instruction tlbgp. */
 {"rfe",			"",		0x42000010, 0xffffffff,	0,			0,		I1|T3,		0,	0 },
+{"ldc2",		"E,+:(d)",	0x49c00000, 0xffe00000,	RD_3|WR_C2|CLD,		0,		I37,		0,	0 },
+{"ldc2",		"E,o(b)",	0xd8000000, 0xfc000000,	RD_3|WR_CC|CLD,		0,		I2,		0,	IOCT|IOCTP|IOCT2|EE|I37 },
+{"ldc2",		"E,A(b)",	0,    (int) M_LDC2_AB,	INSN_MACRO,		0,		I2,		0,	IOCT|IOCTP|IOCT2|EE },
+{"sdc2",		"E,+:(d)",	0x49e00000, 0xffe00000,	RD_3|RD_C2|SM,		0,		I37,		0,	0 },
+{"sdc2",		"E,o(b)",	0xf8000000, 0xfc000000,	RD_3|RD_C2|SM,		0,		I2,		0,	IOCT|IOCTP|IOCT2|EE|I37 },
+{"sdc2",		"E,A(b)",	0,    (int) M_SDC2_AB,	INSN_MACRO,		0,		I2,		0,	IOCT|IOCTP|IOCT2|EE },
 };
 
 #define MIPS_NUM_OPCODES \
-- 
1.9-rc2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 13/24]     Add MIPS MSA GDB target descriptions
  2016-06-27 14:50 [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size Bhushan Attarde
                   ` (12 preceding siblings ...)
  2016-06-27 14:51 ` [PATCH 21/24] MIPSR6 support for GDB Bhushan Attarde
@ 2016-06-27 14:51 ` Bhushan Attarde
  2016-06-27 14:51 ` [PATCH 14/24] Implement core MSA stuff Bhushan Attarde
                   ` (7 subsequent siblings)
  21 siblings, 0 replies; 37+ messages in thread
From: Bhushan Attarde @ 2016-06-27 14:51 UTC (permalink / raw)
  To: gdb-patches
  Cc: Maciej.Rozycki, Matthew.Fortune, James.Hogan, Andrew.Bennett,
	Jaydeep.Patil, Bhushan Attarde

    Add a couple of new target descriptions for MIPS32 and MIPS64 targets with
    128-bit MSA (SIMD) vector registers (and no DSP).

    These are similar to their non-MSA FPU64 counterparts except that the FPU
    registers are 128bits wide, and an extra msa feature is included with the
    two relevant MSA control registers, the MSA implementation register and
    the MSA control & status register.

    gdb/ChangeLog:

    	* features/Makefile (WHICH): Add mips-msa-linux and
    	mips64-msa-linux.
    	(mips-msa-expedite): Set.
    	(mips64-msa-expedite): Set.
    	* features/mips-fpu128.xml: New file.
    	* features/mips-msa-linux.xml: New file.
    	* features/mips-msa.xml: New file.
    	* features/mips64-fpu128.xml: New file.
    	* features/mips64-msa-linux.xml: New file.
    	* features/mips64-msa.xml: New file.
    	* features/mips-msa-linux.c: New generated file.
    	* features/mips64-msa-linux.c: New generated file.
    	* regformats/mips-msa-linux.dat: New generated file.
    	* regformats/mips64-msa-linux.dat: New generated file.

    gdb/gdbserver/ChangeLog:

    	* Makefile.in (clean): Remove mips-msa-linux.c and
    	mips64-msa-linux.c.
    	(mips-msa-linux.c) : New rule.
    	(mips64-msa-linux.c) : New rule.
    	* configure.srv (srv_regobj): Add mips-msa-linux.o and
    	mips64-msa-linux.o.
    	(srv_xmlfiles): Add mips-fpu128.xml, mips-msa-linux.xml,
    	mips-msa.xml, mips64-fpu128.xml, mips64-msa-linux.xml, and
    	mips64-msa.xml.
---
 gdb/features/Makefile               |   5 +-
 gdb/features/mips-fpu128.xml        |  47 +++++++++++++++
 gdb/features/mips-msa-linux.c       | 110 ++++++++++++++++++++++++++++++++++++
 gdb/features/mips-msa-linux.xml     |  26 +++++++++
 gdb/features/mips-msa.xml           |  12 ++++
 gdb/features/mips64-fpu128.xml      |  47 +++++++++++++++
 gdb/features/mips64-msa-linux.c     | 108 +++++++++++++++++++++++++++++++++++
 gdb/features/mips64-msa-linux.xml   |  24 ++++++++
 gdb/features/mips64-msa.xml         |  12 ++++
 gdb/gdbserver/Makefile.in           |   8 ++-
 gdb/gdbserver/configure.srv         |   8 +++
 gdb/regformats/mips-msa-linux.dat   |  80 ++++++++++++++++++++++++++
 gdb/regformats/mips64-msa-linux.dat |  80 ++++++++++++++++++++++++++
 13 files changed, 564 insertions(+), 3 deletions(-)
 create mode 100644 gdb/features/mips-fpu128.xml
 create mode 100644 gdb/features/mips-msa-linux.c
 create mode 100644 gdb/features/mips-msa-linux.xml
 create mode 100644 gdb/features/mips-msa.xml
 create mode 100644 gdb/features/mips64-fpu128.xml
 create mode 100644 gdb/features/mips64-msa-linux.c
 create mode 100644 gdb/features/mips64-msa-linux.xml
 create mode 100644 gdb/features/mips64-msa.xml
 create mode 100644 gdb/regformats/mips-msa-linux.dat
 create mode 100644 gdb/regformats/mips64-msa-linux.dat

diff --git a/gdb/features/Makefile b/gdb/features/Makefile
index b6baaf66..d0d1d4c 100644
--- a/gdb/features/Makefile
+++ b/gdb/features/Makefile
@@ -59,7 +59,8 @@ WHICH = aarch64 \
 	i386/x32-avx512 i386/x32-avx512-linux \
 	microblaze-with-stack-protect \
 	mips-linux mips-dsp-linux mips-fpu64-linux mips-fpu64-dsp-linux \
-	mips64-linux mips64-dsp-linux \
+	mips-msa-linux \
+	mips64-linux mips64-dsp-linux mips64-msa-linux \
 	nios2-linux \
 	rs6000/powerpc-32 \
 	rs6000/powerpc-32l rs6000/powerpc-altivec32l rs6000/powerpc-e500l \
@@ -105,8 +106,10 @@ mips-expedite = r29,pc
 mips-dsp-expedite = r29,pc
 mips-fpu64-expedite = r29,pc
 mips-fpu64-dsp-expedite = r29,pc
+mips-msa-expedite = r29,pc
 mips64-expedite = r29,pc
 mips64-dsp-expedite = r29,pc
+mips64-msa-expedite = r29,pc
 nios2-linux-expedite = sp,pc
 powerpc-expedite = r1,pc
 rs6000/powerpc-cell32l-expedite = r1,pc,r0,orig_r3,r4
diff --git a/gdb/features/mips-fpu128.xml b/gdb/features/mips-fpu128.xml
new file mode 100644
index 0000000..25bd820
--- /dev/null
+++ b/gdb/features/mips-fpu128.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2010-2013 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.fpu">
+  <vector id="msa128" type="ieee_double" count="2"/>
+
+  <reg name="f0" bitsize="128" type="msa128"/>
+  <reg name="f1" bitsize="128" type="msa128"/>
+  <reg name="f2" bitsize="128" type="msa128"/>
+  <reg name="f3" bitsize="128" type="msa128"/>
+  <reg name="f4" bitsize="128" type="msa128"/>
+  <reg name="f5" bitsize="128" type="msa128"/>
+  <reg name="f6" bitsize="128" type="msa128"/>
+  <reg name="f7" bitsize="128" type="msa128"/>
+  <reg name="f8" bitsize="128" type="msa128"/>
+  <reg name="f9" bitsize="128" type="msa128"/>
+  <reg name="f10" bitsize="128" type="msa128"/>
+  <reg name="f11" bitsize="128" type="msa128"/>
+  <reg name="f12" bitsize="128" type="msa128"/>
+  <reg name="f13" bitsize="128" type="msa128"/>
+  <reg name="f14" bitsize="128" type="msa128"/>
+  <reg name="f15" bitsize="128" type="msa128"/>
+  <reg name="f16" bitsize="128" type="msa128"/>
+  <reg name="f17" bitsize="128" type="msa128"/>
+  <reg name="f18" bitsize="128" type="msa128"/>
+  <reg name="f19" bitsize="128" type="msa128"/>
+  <reg name="f20" bitsize="128" type="msa128"/>
+  <reg name="f21" bitsize="128" type="msa128"/>
+  <reg name="f22" bitsize="128" type="msa128"/>
+  <reg name="f23" bitsize="128" type="msa128"/>
+  <reg name="f24" bitsize="128" type="msa128"/>
+  <reg name="f25" bitsize="128" type="msa128"/>
+  <reg name="f26" bitsize="128" type="msa128"/>
+  <reg name="f27" bitsize="128" type="msa128"/>
+  <reg name="f28" bitsize="128" type="msa128"/>
+  <reg name="f29" bitsize="128" type="msa128"/>
+  <reg name="f30" bitsize="128" type="msa128"/>
+  <reg name="f31" bitsize="128" type="msa128"/>
+
+  <reg name="fcsr" bitsize="32" group="float"/>
+  <reg name="fir"  bitsize="32" group="float"/>
+</feature>
diff --git a/gdb/features/mips-msa-linux.c b/gdb/features/mips-msa-linux.c
new file mode 100644
index 0000000..ccaad09
--- /dev/null
+++ b/gdb/features/mips-msa-linux.c
@@ -0,0 +1,110 @@
+/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
+  Original: mips-msa-linux.xml */
+
+#include "defs.h"
+#include "osabi.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_mips_msa_linux;
+static void
+initialize_tdesc_mips_msa_linux (void)
+{
+  struct target_desc *result = allocate_target_description ();
+  struct tdesc_feature *feature;
+  struct tdesc_type *field_type;
+
+  set_tdesc_architecture (result, bfd_scan_arch ("mips"));
+
+  set_tdesc_osabi (result, osabi_from_tdesc_string ("GNU/Linux"));
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cpu");
+  tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r13", 13, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r14", 14, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r15", 15, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r16", 16, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r17", 17, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r18", 18, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r19", 19, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r20", 20, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r21", 21, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r22", 22, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r23", 23, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r24", 24, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r25", 25, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r26", 26, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r27", 27, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r28", 28, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r29", 29, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r30", 30, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r31", 31, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lo", 33, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hi", 34, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pc", 37, 1, NULL, 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cp0");
+  tdesc_create_reg (feature, "status", 32, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "badvaddr", 35, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "cause", 36, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "config5", 38, 1, NULL, 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.fpu");
+  field_type = tdesc_named_type (feature, "ieee_double");
+  tdesc_create_vector (feature, "msa128", field_type, 2);
+
+  tdesc_create_reg (feature, "f0", 39, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f1", 40, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f2", 41, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f3", 42, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f4", 43, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f5", 44, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f6", 45, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f7", 46, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f8", 47, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f9", 48, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f10", 49, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f11", 50, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f12", 51, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f13", 52, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f14", 53, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f15", 54, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f16", 55, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f17", 56, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f18", 57, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f19", 58, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f20", 59, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f21", 60, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f22", 61, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f23", 62, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f24", 63, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f25", 64, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f26", 65, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f27", 66, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f28", 67, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f29", 68, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f30", 69, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f31", 70, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "fcsr", 71, 1, "float", 32, "int");
+  tdesc_create_reg (feature, "fir", 72, 1, "float", 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.msa");
+  tdesc_create_reg (feature, "msacsr", 73, 1, "vector", 32, "int");
+  tdesc_create_reg (feature, "msair", 74, 1, "vector", 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.linux");
+  tdesc_create_reg (feature, "restart", 75, 1, "system", 32, "int");
+
+  tdesc_mips_msa_linux = result;
+}
diff --git a/gdb/features/mips-msa-linux.xml b/gdb/features/mips-msa-linux.xml
new file mode 100644
index 0000000..45cbc3a
--- /dev/null
+++ b/gdb/features/mips-msa-linux.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007-2013 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <architecture>mips</architecture>
+  <osabi>GNU/Linux</osabi>
+  <xi:include href="mips-cpu.xml"/>
+  <feature name="org.gnu.gdb.mips.cp0">
+    <reg name="status" bitsize="32" regnum="32"/>
+    <reg name="badvaddr" bitsize="32" regnum="35"/>
+    <reg name="cause" bitsize="32" regnum="36"/>
+    <reg name="config5" bitsize="32" regnum="38"/>
+  </feature>
+  <xi:include href="mips-fpu128.xml"/>
+  <xi:include href="mips-msa.xml"/>
+
+  <feature name="org.gnu.gdb.mips.linux">
+    <reg name="restart" bitsize="32" group="system"/>
+  </feature>
+
+</target>
diff --git a/gdb/features/mips-msa.xml b/gdb/features/mips-msa.xml
new file mode 100644
index 0000000..c36c24f
--- /dev/null
+++ b/gdb/features/mips-msa.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2010-2013 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.msa">
+  <reg name="msacsr" bitsize="32" group="vector"/>
+  <reg name="msair"  bitsize="32" group="vector"/>
+</feature>
diff --git a/gdb/features/mips64-fpu128.xml b/gdb/features/mips64-fpu128.xml
new file mode 100644
index 0000000..d176ae9
--- /dev/null
+++ b/gdb/features/mips64-fpu128.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2010-2013 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.fpu">
+  <vector id="msa128" type="ieee_double" count="2"/>
+
+  <reg name="f0" bitsize="128" type="msa128"/>
+  <reg name="f1" bitsize="128" type="msa128"/>
+  <reg name="f2" bitsize="128" type="msa128"/>
+  <reg name="f3" bitsize="128" type="msa128"/>
+  <reg name="f4" bitsize="128" type="msa128"/>
+  <reg name="f5" bitsize="128" type="msa128"/>
+  <reg name="f6" bitsize="128" type="msa128"/>
+  <reg name="f7" bitsize="128" type="msa128"/>
+  <reg name="f8" bitsize="128" type="msa128"/>
+  <reg name="f9" bitsize="128" type="msa128"/>
+  <reg name="f10" bitsize="128" type="msa128"/>
+  <reg name="f11" bitsize="128" type="msa128"/>
+  <reg name="f12" bitsize="128" type="msa128"/>
+  <reg name="f13" bitsize="128" type="msa128"/>
+  <reg name="f14" bitsize="128" type="msa128"/>
+  <reg name="f15" bitsize="128" type="msa128"/>
+  <reg name="f16" bitsize="128" type="msa128"/>
+  <reg name="f17" bitsize="128" type="msa128"/>
+  <reg name="f18" bitsize="128" type="msa128"/>
+  <reg name="f19" bitsize="128" type="msa128"/>
+  <reg name="f20" bitsize="128" type="msa128"/>
+  <reg name="f21" bitsize="128" type="msa128"/>
+  <reg name="f22" bitsize="128" type="msa128"/>
+  <reg name="f23" bitsize="128" type="msa128"/>
+  <reg name="f24" bitsize="128" type="msa128"/>
+  <reg name="f25" bitsize="128" type="msa128"/>
+  <reg name="f26" bitsize="128" type="msa128"/>
+  <reg name="f27" bitsize="128" type="msa128"/>
+  <reg name="f28" bitsize="128" type="msa128"/>
+  <reg name="f29" bitsize="128" type="msa128"/>
+  <reg name="f30" bitsize="128" type="msa128"/>
+  <reg name="f31" bitsize="128" type="msa128"/>
+
+  <reg name="fcsr" bitsize="64" group="float"/>
+  <reg name="fir"  bitsize="64" group="float"/>
+</feature>
diff --git a/gdb/features/mips64-msa-linux.c b/gdb/features/mips64-msa-linux.c
new file mode 100644
index 0000000..31dd697
--- /dev/null
+++ b/gdb/features/mips64-msa-linux.c
@@ -0,0 +1,108 @@
+/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
+  Original: mips64-msa-linux.xml */
+
+#include "defs.h"
+#include "osabi.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_mips64_msa_linux;
+static void
+initialize_tdesc_mips64_msa_linux (void)
+{
+  struct target_desc *result = allocate_target_description ();
+  struct tdesc_feature *feature;
+  struct tdesc_type *field_type;
+
+  set_tdesc_architecture (result, bfd_scan_arch ("mips"));
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cpu");
+  tdesc_create_reg (feature, "r0", 0, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r1", 1, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r2", 2, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r3", 3, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r4", 4, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r5", 5, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r6", 6, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r7", 7, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r8", 8, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r9", 9, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r10", 10, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r11", 11, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r12", 12, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r13", 13, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r14", 14, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r15", 15, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r16", 16, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r17", 17, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r18", 18, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r19", 19, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r20", 20, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r21", 21, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r22", 22, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r23", 23, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r24", 24, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r25", 25, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r26", 26, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r27", 27, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r28", 28, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r29", 29, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r30", 30, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r31", 31, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "lo", 33, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hi", 34, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "pc", 37, 1, NULL, 64, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cp0");
+  tdesc_create_reg (feature, "status", 32, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "badvaddr", 35, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "cause", 36, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "config5", 38, 1, NULL, 64, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.fpu");
+  field_type = tdesc_named_type (feature, "ieee_double");
+  tdesc_create_vector (feature, "msa128", field_type, 2);
+
+  tdesc_create_reg (feature, "f0", 39, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f1", 40, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f2", 41, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f3", 42, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f4", 43, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f5", 44, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f6", 45, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f7", 46, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f8", 47, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f9", 48, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f10", 49, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f11", 50, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f12", 51, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f13", 52, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f14", 53, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f15", 54, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f16", 55, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f17", 56, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f18", 57, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f19", 58, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f20", 59, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f21", 60, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f22", 61, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f23", 62, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f24", 63, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f25", 64, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f26", 65, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f27", 66, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f28", 67, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f29", 68, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f30", 69, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "f31", 70, 1, NULL, 128, "msa128");
+  tdesc_create_reg (feature, "fcsr", 71, 1, "float", 64, "int");
+  tdesc_create_reg (feature, "fir", 72, 1, "float", 64, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.msa");
+  tdesc_create_reg (feature, "msacsr", 73, 1, "vector", 64, "int");
+  tdesc_create_reg (feature, "msair", 74, 1, "vector", 64, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.linux");
+  tdesc_create_reg (feature, "restart", 75, 1, "system", 64, "int");
+
+  tdesc_mips64_msa_linux = result;
+}
diff --git a/gdb/features/mips64-msa-linux.xml b/gdb/features/mips64-msa-linux.xml
new file mode 100644
index 0000000..709ad50
--- /dev/null
+++ b/gdb/features/mips64-msa-linux.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007-2013 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <architecture>mips</architecture>
+  <xi:include href="mips64-cpu.xml"/>
+  <feature name="org.gnu.gdb.mips.cp0">
+    <reg name="status" bitsize="64" regnum="32"/>
+    <reg name="badvaddr" bitsize="64" regnum="35"/>
+    <reg name="cause" bitsize="64" regnum="36"/>
+    <reg name="config5" bitsize="64" regnum="38"/>
+  </feature>
+  <xi:include href="mips64-fpu128.xml"/>
+  <xi:include href="mips64-msa.xml"/>
+
+  <feature name="org.gnu.gdb.mips.linux">
+    <reg name="restart" bitsize="64" group="system"/>
+  </feature>
+</target>
diff --git a/gdb/features/mips64-msa.xml b/gdb/features/mips64-msa.xml
new file mode 100644
index 0000000..832f722
--- /dev/null
+++ b/gdb/features/mips64-msa.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2010-2013 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.msa">
+  <reg name="msacsr" bitsize="64" group="vector"/>
+  <reg name="msair"  bitsize="64" group="vector"/>
+</feature>
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index 9913d6a..4d97705 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -358,8 +358,8 @@ clean:
 	rm -f arm-with-iwmmxt.c
 	rm -f arm-with-vfpv2.c arm-with-vfpv3.c arm-with-neon.c
 	rm -f mips-linux.c mips-dsp-linux.c mips-fpu64-linux.c
-	rm -f mips-fpu64-dsp-linux.c
-	rm -f mips64-linux.c mips64-dsp-linux.c
+	rm -f mips-fpu64-dsp-linux.c mips-msa-linux.c
+	rm -f mips64-linux.c mips64-dsp-linux.c mips64-msa-linux.c
 	rm -f nios2-linux.c
 	rm -f powerpc-32.c powerpc-32l.c powerpc-64l.c powerpc-e500l.c
 	rm -f powerpc-altivec32l.c powerpc-cell32l.c powerpc-vsx32l.c
@@ -715,10 +715,14 @@ mips-fpu64-linux.c : $(srcdir)/../regformats/mips-fpu64-linux.dat $(regdat_sh)
 	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips-fpu64-linux.dat mips-fpu64-linux.c
 mips-fpu64-dsp-linux.c : $(srcdir)/../regformats/mips-fpu64-dsp-linux.dat $(regdat_sh)
 	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips-fpu64-dsp-linux.dat mips-fpu64-dsp-linux.c
+mips-msa-linux.c : $(srcdir)/../regformats/mips-msa-linux.dat $(regdat_sh)
+	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips-msa-linux.dat mips-msa-linux.c
 mips64-linux.c : $(srcdir)/../regformats/mips64-linux.dat $(regdat_sh)
 	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips64-linux.dat mips64-linux.c
 mips64-dsp-linux.c : $(srcdir)/../regformats/mips64-dsp-linux.dat $(regdat_sh)
 	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips64-dsp-linux.dat mips64-dsp-linux.c
+mips64-msa-linux.c : $(srcdir)/../regformats/mips64-msa-linux.dat $(regdat_sh)
+	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips64-msa-linux.dat mips64-msa-linux.c
 nios2-linux.c :	$(srcdir)/../regformats/nios2-linux.dat $(regdat_sh)
 	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/nios2-linux.dat nios2-linux.c
 powerpc-32.c : $(srcdir)/../regformats/rs6000/powerpc-32.dat $(regdat_sh)
diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv
index 422fd90..f0300c1 100644
--- a/gdb/gdbserver/configure.srv
+++ b/gdb/gdbserver/configure.srv
@@ -189,25 +189,33 @@ case "${target}" in
 			srv_regobj="${srv_regobj} mips-dsp-linux.o"
 			srv_regobj="${srv_regobj} mips-fpu64-linux.o"
 			srv_regobj="${srv_regobj} mips-fpu64-dsp-linux.o"
+			srv_regobj="${srv_regobj} mips-msa-linux.o"
 			srv_regobj="${srv_regobj} mips64-linux.o"
 			srv_regobj="${srv_regobj} mips64-dsp-linux.o"
+			srv_regobj="${srv_regobj} mips64-msa-linux.o"
 			srv_tgtobj="$srv_linux_obj linux-mips-low.o"
 			srv_tgtobj="${srv_tgtobj} mips-linux-watch.o"
 			srv_xmlfiles="mips-linux.xml"
 			srv_xmlfiles="${srv_xmlfiles} mips-dsp-linux.xml"
 			srv_xmlfiles="${srv_xmlfiles} mips-fpu64-linux.xml"
 			srv_xmlfiles="${srv_xmlfiles} mips-fpu64-dsp-linux.xml"
+			srv_xmlfiles="${srv_xmlfiles} mips-msa-linux.xml"
 			srv_xmlfiles="${srv_xmlfiles} mips-cpu.xml"
 			srv_xmlfiles="${srv_xmlfiles} mips-cp0.xml"
 			srv_xmlfiles="${srv_xmlfiles} mips-fpu.xml"
 			srv_xmlfiles="${srv_xmlfiles} mips-fpu64.xml"
 			srv_xmlfiles="${srv_xmlfiles} mips-dsp.xml"
+			srv_xmlfiles="${srv_xmlfiles} mips-fpu128.xml"
+			srv_xmlfiles="${srv_xmlfiles} mips-msa.xml"
 			srv_xmlfiles="${srv_xmlfiles} mips64-linux.xml"
 			srv_xmlfiles="${srv_xmlfiles} mips64-dsp-linux.xml"
+			srv_xmlfiles="${srv_xmlfiles} mips64-msa-linux.xml"
 			srv_xmlfiles="${srv_xmlfiles} mips64-cpu.xml"
 			srv_xmlfiles="${srv_xmlfiles} mips64-cp0.xml"
 			srv_xmlfiles="${srv_xmlfiles} mips64-fpu.xml"
 			srv_xmlfiles="${srv_xmlfiles} mips64-dsp.xml"
+			srv_xmlfiles="${srv_xmlfiles} mips64-fpu128.xml"
+			srv_xmlfiles="${srv_xmlfiles} mips64-msa.xml"
 			srv_linux_regsets=yes
 			srv_linux_usrregs=yes
 			srv_linux_thread_db=yes
diff --git a/gdb/regformats/mips-msa-linux.dat b/gdb/regformats/mips-msa-linux.dat
new file mode 100644
index 0000000..033a464
--- /dev/null
+++ b/gdb/regformats/mips-msa-linux.dat
@@ -0,0 +1,80 @@
+# DO NOT EDIT: generated from mips-msa-linux.xml
+name:mips_msa_linux
+xmltarget:mips-msa-linux.xml
+expedite:r29,pc
+32:r0
+32:r1
+32:r2
+32:r3
+32:r4
+32:r5
+32:r6
+32:r7
+32:r8
+32:r9
+32:r10
+32:r11
+32:r12
+32:r13
+32:r14
+32:r15
+32:r16
+32:r17
+32:r18
+32:r19
+32:r20
+32:r21
+32:r22
+32:r23
+32:r24
+32:r25
+32:r26
+32:r27
+32:r28
+32:r29
+32:r30
+32:r31
+32:status
+32:lo
+32:hi
+32:badvaddr
+32:cause
+32:pc
+32:config5
+128:f0
+128:f1
+128:f2
+128:f3
+128:f4
+128:f5
+128:f6
+128:f7
+128:f8
+128:f9
+128:f10
+128:f11
+128:f12
+128:f13
+128:f14
+128:f15
+128:f16
+128:f17
+128:f18
+128:f19
+128:f20
+128:f21
+128:f22
+128:f23
+128:f24
+128:f25
+128:f26
+128:f27
+128:f28
+128:f29
+128:f30
+128:f31
+32:fcsr
+32:fir
+32:msacsr
+32:msair
+32:restart
diff --git a/gdb/regformats/mips64-msa-linux.dat b/gdb/regformats/mips64-msa-linux.dat
new file mode 100644
index 0000000..0c84133
--- /dev/null
+++ b/gdb/regformats/mips64-msa-linux.dat
@@ -0,0 +1,80 @@
+# DO NOT EDIT: generated from mips64-msa-linux.xml
+name:mips64_msa_linux
+xmltarget:mips64-msa-linux.xml
+expedite:r29,pc
+64:r0
+64:r1
+64:r2
+64:r3
+64:r4
+64:r5
+64:r6
+64:r7
+64:r8
+64:r9
+64:r10
+64:r11
+64:r12
+64:r13
+64:r14
+64:r15
+64:r16
+64:r17
+64:r18
+64:r19
+64:r20
+64:r21
+64:r22
+64:r23
+64:r24
+64:r25
+64:r26
+64:r27
+64:r28
+64:r29
+64:r30
+64:r31
+64:status
+64:lo
+64:hi
+64:badvaddr
+64:cause
+64:pc
+64:config5
+128:f0
+128:f1
+128:f2
+128:f3
+128:f4
+128:f5
+128:f6
+128:f7
+128:f8
+128:f9
+128:f10
+128:f11
+128:f12
+128:f13
+128:f14
+128:f15
+128:f16
+128:f17
+128:f18
+128:f19
+128:f20
+128:f21
+128:f22
+128:f23
+128:f24
+128:f25
+128:f26
+128:f27
+128:f28
+128:f29
+128:f30
+128:f31
+64:fcsr
+64:fir
+64:msacsr
+64:msair
+64:restart
-- 
1.9-rc2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 04/24]     Add MIPS Config5 register related support
  2016-06-27 14:50 [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size Bhushan Attarde
                   ` (4 preceding siblings ...)
  2016-06-27 14:50 ` [PATCH 11/24] MIPS: Add support for hybrid fp32/fp64 mode Bhushan Attarde
@ 2016-06-27 14:51 ` Bhushan Attarde
  2016-06-27 14:51 ` [PATCH 22/24] Support all new ABIs when detecting if an FPU is present Bhushan Attarde
                   ` (15 subsequent siblings)
  21 siblings, 0 replies; 37+ messages in thread
From: Bhushan Attarde @ 2016-06-27 14:51 UTC (permalink / raw)
  To: gdb-patches
  Cc: Maciej.Rozycki, Matthew.Fortune, James.Hogan, Andrew.Bennett,
	Jaydeep.Patil, Bhushan Attarde

    This patch has below changes:

    1. Add a Config5 register binding in order to get access to the FRE
    floating point mode bit. The internal register number is allocated
    dynamically only when provided by the target description, and is tracked in
    struct mips_regnum.

    2. MIPS native: Use FP regset to support Config5
    Use the NT_FPREGSET register set in preference to PTRACE_GETFPREGS for
    getting the floating point registers. This register set also provides the
    Config5 register which PTRACE_GETFPREGS doesn't.

    3. Define type for the MIPS CP0 Config5 register, allowing the important
    fields to be decoded.

    gdb/ChangeLog:

    	* mips-tdep.c (mips_config5_type): New function.
        (mips_linux_reg_names): Add config5.
    	(mips_gdbarch_init): Initialise config5 register number and bind
    	to named config5 register in target description.
        (mips_value_to_register): Return config5_type for config5 register.
    	* mips-tdep.h (struct mips_regnum): New config5 field.
        (gdbarch_tdep): New config5_type field.
    	* mips-linux-nat.c: Include "elf/common.h".
    	(PTRACE_GETREGSET, PTRACE_SETREGSET): New fallback definitions.
    	(have_ptrace_getregset_gp, have_ptrace_getregset_fp): New variables.
    	(mips64_linux_regsets_fetch_registers): Use PTRACE_GETREGSET with
    	NT_FPREGSET in preferance to PTRACE_GETFPREGS to get FP and
    	Config5 registers.
    	(mips64_linux_regsets_store_registers): Use PTRACE_SETREGSET with
    	NT_FPREGSET in preferance to PTRACE_SETFPREGS to get FP and
    	Config5 registers
---
 gdb/mips-linux-nat.c | 221 ++++++++++++++++++++++++++++++++++++++++++++++-----
 gdb/mips-tdep.c      |  35 ++++++++
 gdb/mips-tdep.h      |   4 +
 3 files changed, 239 insertions(+), 21 deletions(-)

diff --git a/gdb/mips-linux-nat.c b/gdb/mips-linux-nat.c
index bfe9fcb..627c652 100644
--- a/gdb/mips-linux-nat.c
+++ b/gdb/mips-linux-nat.c
@@ -27,6 +27,7 @@
 #include "linux-nat.h"
 #include "mips-linux-tdep.h"
 #include "target-descriptions.h"
+#include "elf/common.h"
 
 #include "gdb_proc_service.h"
 #include "gregset.h"
@@ -46,10 +47,22 @@
 #define PTRACE_GET_THREAD_AREA 25
 #endif
 
+#ifndef PTRACE_GETREGSET
+#define PTRACE_GETREGSET	0x4204
+#endif
+
+#ifndef PTRACE_SETREGSET
+#define PTRACE_SETREGSET	0x4205
+#endif
+
 /* Assume that we have PTRACE_GETREGS et al. support.  If we do not,
    we'll clear this and use PTRACE_PEEKUSER instead.  */
 static int have_ptrace_regsets = 1;
 
+/* Does the current host support PTRACE_GETREGSET?  */
+static int have_ptrace_getregset_gp = 1;
+static int have_ptrace_getregset_fp = 1;
+
 /* Saved function pointers to fetch and store a single register using
    PTRACE_PEEKUSER and PTRACE_POKEUSER.  */
 
@@ -217,18 +230,25 @@ mips64_linux_regsets_fetch_registers (struct target_ops *ops,
 				      struct regcache *regcache, int regno)
 {
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  int big_endian = (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG);
   int is_fp, is_dsp;
   int have_dsp;
   int regi;
   int tid;
 
-  if (regno >= mips_regnum (gdbarch)->fp0
-      && regno <= mips_regnum (gdbarch)->fp0 + 32)
+  /* FP registers can be obtained in several ways.
+     is_fp will be cleared once the registers have been obtained.  */
+  if (regno == -1)
+    is_fp = 1;
+  else if (regno >= mips_regnum (gdbarch)->fp0
+	   && regno <= mips_regnum (gdbarch)->fp0 + 32)
     is_fp = 1;
   else if (regno == mips_regnum (gdbarch)->fp_control_status)
     is_fp = 1;
   else if (regno == mips_regnum (gdbarch)->fp_implementation_revision)
     is_fp = 1;
+  else if (regno == mips_regnum (gdbarch)->config5)
+    is_fp = 1;
   else
     is_fp = 0;
 
@@ -266,23 +286,93 @@ mips64_linux_regsets_fetch_registers (struct target_ops *ops,
 			     (const mips64_elf_gregset_t *) &regs);
     }
 
-  if (regno == -1 || is_fp)
+  if (is_fp)
     {
-      mips64_elf_fpregset_t fp_regs;
+      const struct mips_regnum *rn = mips_regnum (gdbarch);
+      int float_regnum = rn->fp0;
 
-      if (ptrace (PTRACE_GETFPREGS, tid, 0L,
-		  (PTRACE_TYPE_ARG3) &fp_regs) == -1)
+      /* Try the FP regset next as it may contain Config5 */
+      if (have_ptrace_getregset_gp && have_ptrace_getregset_fp)
 	{
-	  if (errno == EIO)
+	  unsigned char fp_regs[34][8];
+	  struct iovec iovec;
+	  int ret;
+
+	  iovec.iov_base = &fp_regs;
+	  iovec.iov_len = sizeof (fp_regs);
+
+	  ret = ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET, &iovec);
+	  if (ret < 0)
 	    {
-	      have_ptrace_regsets = 0;
-	      return;
+	      if (errno == EIO)
+		have_ptrace_getregset_gp = 0;
+	      else if (errno == EINVAL)
+		have_ptrace_getregset_fp = 0;
+	      else
+		perror_with_name (_("Unable to fetch FP registers."));
+	    }
+	  else
+	    {
+	      for (regi = 0; regi < 32; regi++)
+		{
+		  if (register_size (gdbarch, float_regnum + regi) == 8)
+		    {
+		      /* FR = 1
+			 copy entire double */
+		      regcache_raw_supply (regcache, float_regnum + regi,
+					   (char *) fp_regs[regi]);
+		    }
+		  else if (regi & 1)
+		    {
+		      /* FR = 0
+			 odd single from top of even double */
+		      regcache_raw_supply (regcache, float_regnum + regi,
+					   (char *) fp_regs[regi - 1] +
+					   4 - 4*big_endian);
+		    }
+		  else
+		    {
+		      /* FR = 0
+			 even single from bottom of even double */
+		      regcache_raw_supply (regcache, float_regnum + regi,
+					   (char *) fp_regs[regi] + 4 * big_endian);
+		    }
+		}
+
+	      if (iovec.iov_len >= 32*8 + 4)
+		regcache_raw_supply (regcache, rn->fp_control_status,
+				     (char *) (fp_regs + 32) + 0);
+	      if (iovec.iov_len >= 32*8 + 8)
+		regcache_raw_supply (regcache, rn->fp_implementation_revision,
+				     (char *) (fp_regs + 32) + 4);
+	      if (iovec.iov_len >= 33*8 + 4 && rn->config5 >= 0)
+		regcache_raw_supply (regcache, rn->config5,
+				     (char *) (fp_regs + 33) + 0);
+
+	      /* we've got fp registers now */
+	      is_fp = 0;
 	    }
-	  perror_with_name (_("Couldn't get FP registers"));
 	}
 
-      mips64_supply_fpregset (regcache,
-			      (const mips64_elf_fpregset_t *) &fp_regs);
+      /* Fall back to GETFPREGS. */
+      if (is_fp)
+	{
+	  mips64_elf_fpregset_t fp_regs;
+
+	  if (ptrace (PTRACE_GETFPREGS, tid, 0L,
+		      (PTRACE_TYPE_ARG3) &fp_regs) == -1)
+	    {
+	      if (errno == EIO)
+		{
+		  have_ptrace_regsets = 0;
+		  return;
+		}
+	      perror_with_name (_("Couldn't get FP registers"));
+	    }
+
+	  mips64_supply_fpregset (regcache,
+				  (const mips64_elf_fpregset_t *) &fp_regs);
+	}
     }
 
   if (is_dsp)
@@ -305,11 +395,16 @@ mips64_linux_regsets_store_registers (struct target_ops *ops,
 				      struct regcache *regcache, int regno)
 {
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  int big_endian = (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG);
   int is_fp, is_dsp;
   int have_dsp;
   int regi;
   int tid;
 
+  /* FP registers can be written in several ways.
+     is_fp will be cleared once the registers have been written.  */
+  if (regno == -1)
+    is_fp = 1;
   if (regno >= mips_regnum (gdbarch)->fp0
       && regno <= mips_regnum (gdbarch)->fp0 + 32)
     is_fp = 1;
@@ -317,6 +412,8 @@ mips64_linux_regsets_store_registers (struct target_ops *ops,
     is_fp = 1;
   else if (regno == mips_regnum (gdbarch)->fp_implementation_revision)
     is_fp = 1;
+  else if (regno == mips_regnum (gdbarch)->config5)
+    is_fp = 1;
   else
     is_fp = 0;
 
@@ -349,19 +446,101 @@ mips64_linux_regsets_store_registers (struct target_ops *ops,
 	perror_with_name (_("Couldn't set registers"));
     }
 
-  if (regno == -1 || is_fp)
+  if (is_fp)
     {
-      mips64_elf_fpregset_t fp_regs;
+      const struct mips_regnum *rn = mips_regnum (gdbarch);
+      int float_regnum = rn->fp0;
+
+      /* Try the FP regset next as it may contain Config5 */
+      if (have_ptrace_getregset_gp && have_ptrace_getregset_fp)
+	{
+	  unsigned char fp_regs[34][8];
+	  struct iovec iovec;
+	  int ret;
+
+	  iovec.iov_base = &fp_regs;
+	  iovec.iov_len = sizeof (fp_regs);
 
-      if (ptrace (PTRACE_GETFPREGS, tid, 0L,
-		  (PTRACE_TYPE_ARG3) &fp_regs) == -1)
-	perror_with_name (_("Couldn't get FP registers"));
+	  ret = ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET, &iovec);
+	  if (ret < 0)
+	    {
+	      if (errno == EIO)
+		have_ptrace_getregset_gp = 0;
+	      else if (errno == EINVAL)
+		have_ptrace_getregset_fp = 0;
+	      else
+		perror_with_name (_("Unable to fetch FP registers."));
+	    }
+	  else
+	    {
+	      for (regi = 0; regi < 32; regi++)
+		{
+		  if (register_size (gdbarch, float_regnum + regi) == 8)
+		    {
+		      /* FR = 1
+			 copy entire double */
+		      regcache_raw_collect (regcache, float_regnum + regi,
+					   (char *) fp_regs[regi]);
+		    }
+		  else if (regi & 1)
+		    {
+		      /* FR = 0
+			 odd single from top of even double */
+		      regcache_raw_collect (regcache, float_regnum + regi,
+					   (char *) fp_regs[regi - 1] +
+					   4 - 4*big_endian);
+		    }
+		  else
+		    {
+		      /* FR = 0
+			 even single from bottom of even double */
+		      regcache_raw_collect (regcache, float_regnum + regi,
+					   (char *) fp_regs[regi] + 4 * big_endian);
+		    }
+		}
+
+	      regcache_raw_collect (regcache, rn->fp_control_status,
+				   (char *) (fp_regs + 32) + 0);
+	      regcache_raw_collect (regcache, rn->fp_implementation_revision,
+				   (char *) (fp_regs + 32) + 4);
+	      if (rn->config5 >= 0)
+		regcache_raw_collect (regcache, rn->config5,
+				      (char *) (fp_regs + 33) + 0);
+
+	      /* don't modify iovec length from amount of data returned */
+	      ret = ptrace (PTRACE_SETREGSET, tid, NT_FPREGSET, &iovec);
+	      if (ret < 0)
+		{
+		  if (errno == EIO)
+		    have_ptrace_getregset_gp = 0;
+		  else if (errno == EINVAL)
+		    have_ptrace_getregset_fp = 0;
+		  else
+		    perror_with_name (_("Unable to store FP/MSA registers."));
+		}
+	      else
+		{
+		  /* we've got fp registers now */
+		  is_fp = 0;
+		}
+	    }
+	}
 
-      mips64_fill_fpregset (regcache, &fp_regs, regno);
+      /* Fall back to SETFPREGS. */
+      if (is_fp)
+	{
+	  mips64_elf_fpregset_t fp_regs;
+
+	  if (ptrace (PTRACE_GETFPREGS, tid, 0L,
+		      (PTRACE_TYPE_ARG3) &fp_regs) == -1)
+	    perror_with_name (_("Couldn't get FP registers"));
 
-      if (ptrace (PTRACE_SETFPREGS, tid, 0L,
-		  (PTRACE_TYPE_ARG3) &fp_regs) == -1)
-	perror_with_name (_("Couldn't set FP registers"));
+	  mips64_fill_fpregset (regcache, &fp_regs, regno);
+
+	  if (ptrace (PTRACE_SETFPREGS, tid, 0L,
+		      (PTRACE_TYPE_ARG3) &fp_regs) == -1)
+	    perror_with_name (_("Couldn't set FP registers"));
+	}
     }
 
   if (is_dsp)
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index ae4dc2e..28cfb57 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -993,6 +993,25 @@ mips_register_to_value (struct frame_info *frame, int regnum,
     }
 }
 
+static struct type *
+mips_config5_type (struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (tdep->config5_type == NULL)
+    {
+      struct type *t;
+      /* top half has flags */
+      t = arch_flags_type (gdbarch, "__gdb_builtin_type_config5", 4);
+      append_flags_type_flag (t, 8, "FRE");
+
+      TYPE_NAME (t) = "config5";
+      tdep->config5_type = t;
+    }
+
+  return tdep->config5_type;
+}
+
 static void
 mips_value_to_register (struct frame_info *frame, int regnum,
 			struct type *type, const gdb_byte *from)
@@ -1080,6 +1099,8 @@ mips_register_type (struct gdbarch *gdbarch, int regnum)
       else if (rawnum == mips_regnum (gdbarch)->fp_control_status
 	  || rawnum == mips_regnum (gdbarch)->fp_implementation_revision)
 	return builtin_type (gdbarch)->builtin_int32;
+      else if (rawnum == mips_regnum (gdbarch)->config5)
+	return mips_config5_type (gdbarch);
       else if (gdbarch_osabi (gdbarch) != GDB_OSABI_IRIX
 	       && gdbarch_osabi (gdbarch) != GDB_OSABI_LINUX
 	       && rawnum >= MIPS_FIRST_EMBED_REGNUM
@@ -1152,6 +1173,9 @@ mips_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
 	      && rawnum < mips_regnum (gdbarch)->dspacc + 6)))
     return builtin_type (gdbarch)->builtin_int32;
 
+  if (rawnum == mips_regnum (gdbarch)->config5)
+    return mips_config5_type (gdbarch);
+
   if (gdbarch_osabi (gdbarch) != GDB_OSABI_IRIX
       && gdbarch_osabi (gdbarch) != GDB_OSABI_LINUX
       && rawnum >= MIPS_EMBED_FP0_REGNUM + 32
@@ -8236,6 +8260,7 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     info.tdep_info = &tdep_info;
 
   /* Fill in the OS dependent register numbers and names.  */
+  mips_regnum.config5 = -1;
   if (info.osabi == GDB_OSABI_IRIX)
     {
       mips_regnum.fp0 = 32;
@@ -8350,6 +8375,15 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       valid_p &= tdesc_numbered_register (feature, tdesc_data,
 					  mips_regnum.cause, "cause");
 
+      /* Optionally, Config5 contains FP mode bits */
+      if (tdesc_unnumbered_register (feature, "config5"))
+	{
+	  /* Allocate a new register.  */
+	  mips_regnum.config5 = num_regs++;
+	  tdesc_numbered_register (feature, tdesc_data,
+				   mips_regnum.config5, "config5");
+	}
+
       if (!valid_p)
 	{
 	  tdesc_data_cleanup (tdesc_data);
@@ -8666,6 +8700,7 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->register_size = 0;
   tdep->fp_register_size = info.tdep_info->fp_register_size;
   tdep->fp_register_size_fixed_p = 0;
+  tdep->config5_type = NULL;
 
   if (info.target_desc)
     {
diff --git a/gdb/mips-tdep.h b/gdb/mips-tdep.h
index 6c1d9ca..39af72b 100644
--- a/gdb/mips-tdep.h
+++ b/gdb/mips-tdep.h
@@ -63,6 +63,7 @@ struct mips_regnum
   int fp0;
   int fp_implementation_revision;
   int fp_control_status;
+  int config5;
   int badvaddr;		/* Bad vaddr for addressing exception.  */
   int cause;		/* Describes last exception.  */
   int hi;		/* Multiply/divide temp.  */
@@ -119,6 +120,9 @@ struct gdbarch_tdep
   int fp_register_size_fixed_p;
   int fp_register_size;
 
+  /* ISA-specific data types.  */
+  struct type *config5_type;
+
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
-- 
1.9-rc2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 24/24]     MIPS R6 forbidden slot support
  2016-06-27 14:50 [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size Bhushan Attarde
                   ` (6 preceding siblings ...)
  2016-06-27 14:51 ` [PATCH 22/24] Support all new ABIs when detecting if an FPU is present Bhushan Attarde
@ 2016-06-27 14:51 ` Bhushan Attarde
  2016-06-27 14:51 ` [PATCH 09/24] MIPS: Enhance cooked FP format Bhushan Attarde
                   ` (13 subsequent siblings)
  21 siblings, 0 replies; 37+ messages in thread
From: Bhushan Attarde @ 2016-06-27 14:51 UTC (permalink / raw)
  To: gdb-patches
  Cc: Maciej.Rozycki, Matthew.Fortune, James.Hogan, Andrew.Bennett,
	Jaydeep.Patil, Bhushan Attarde

    This approach leads to single step skipping forbidden slots.
    It also means that breakpoints cannot be set on forbidden slots and
    are instead moved to the next instruction.

    gdb/ChangeLog:
        * mips-tdep.c (mips32_next_pc): Step through the forbidden slot.
        (mips32_instruction_is_compact_branch): Add R6 compact branch
        instructions.
        (mips32_insn_at_pc_has_forbidden_slot): New function.
        (mips_adjust_breakpoint_address): Update comment and adjust
        breakpoint address in case of conditional compact branch
        instructions.
---
 gdb/mips-tdep.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 88 insertions(+), 18 deletions(-)

diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index d5dd668..50f7bac 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -2637,7 +2637,7 @@ mips32_blez_pc (struct gdbarch *gdbarch, struct frame_info *frame,
   ULONGEST uval_rs = get_frame_register_unsigned (frame, rs);
   ULONGEST uval_rt = get_frame_register_unsigned (frame, rt);
   int taken = 0;
-  int delay_slot_size = 0;
+  int delay_slot_size = 4;
 
   /* BLEZ, BLEZL, BGTZ, BGTZL */
   if (rt == 0)
@@ -2656,6 +2656,12 @@ mips32_blez_pc (struct gdbarch *gdbarch, struct frame_info *frame,
       /* BGEUC, BLTUC */
       else if (rs != rt && rs != 0 && rt != 0)
 	taken = (uval_rs >= uval_rt);
+
+      /* Step through the forbidden slot to avoid repeated exceptions we do
+	 not currently have access to the BD bit when hitting a breakpoint
+	 and therefore cannot tell if the breakpoint hit on the branch or the
+	 forbidden slot.  */
+      /* delay_slot_size = 0; */
     }
 
   if (invert)
@@ -2835,7 +2841,11 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
 	      if (taken)
 		pc += mips32_relative_offset (inst) + 4;
 	      else
-		pc += 4;
+		/* Step through the forbidden slot to avoid repeated exceptions
+		   we do not currently have access to the BD bit when hitting a
+		   breakpoint and therefore cannot tell if the breakpoint
+		   hit on the branch or the forbidden slot.  */
+		pc += 8;
 	    }
 	  /* BC1EQZ, BC1NEZ */
 	  else if (op == 17 && (itype_rs (inst) == 9 || itype_rs (inst) == 13))
@@ -2883,7 +2893,11 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
 	      if (taken)
 		pc += mips32_relative_offset (inst) + 4;
 	      else
-		pc += 4;
+		/* Step through the forbidden slot to avoid repeated exceptions
+		   we do not currently have access to the BD bit when hitting a
+		   breakpoint and therefore cannot tell if the breakpoint
+		   hit on the branch or the forbidden slot.  */
+		pc += 8;
 	    }
 	  else if (op == 50 || op == 58)
 	  /* BC, BALC */
@@ -2906,7 +2920,11 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
 	      if (taken)
 		pc += mips32_relative_offset21 (inst) + 4;
 	      else
-		pc += 4;
+		/* Step through the forbidden slot to avoid repeated exceptions
+		   we do not currently have access to the BD bit when hitting a
+		   breakpoint and therefore cannot tell if the breakpoint
+		   hit on the branch or the forbidden slot.  */
+		pc += 8;
 	    }
 	  else
 	    pc += 4;		/* Not a branch, next instruction is easy.  */
@@ -2988,7 +3006,13 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
 		      {
 			if (!is_mipsr6_isa (gdbarch))
 			  break;
-			delay_slot_size = 0;
+
+			/* Step through the forbidden slot to avoid repeated
+			   exceptions we do not currently have access to the BD
+			   bit when hitting a breakpoint and therefore cannot
+			   tell if the breakpoint hit on the branch or the
+			   forbidden slot.  */
+			/* delay_slot_size = 0; */
 		      }
 
 		    if ((get_frame_register_unsigned (frame,
@@ -3675,26 +3699,36 @@ micromips_instruction_is_compact_branch (unsigned short insn)
 }
 
 /* Return non-zero if the MIPS instruction INSN is a compact branch
-   or jump.  */
+   or jump.  A value of 1 indicates an unconditional compact branch
+   and a value of 2 indicates a conditional compact branch.  */
 
 static int
 mips32_instruction_is_compact_branch (struct gdbarch *gdbarch, ULONGEST insn)
 {
   switch (itype_op (insn))
     {
-    /* BOVC, BEQZALC, BEQC */
-    case 8:
-    /* BNVC, BNEZALC, BNEC */
-    case 24:
     /* BC */
     case 50:
     /* BALC */
     case 58:
+      if (is_mipsr6_isa (gdbarch))
+	return 1;
+      break;
+    /* BOVC, BEQZALC, BEQC */
+    case 8:
+    /* BNVC, BNEZALC, BNEC */
+    case 24:
+      if (is_mipsr6_isa (gdbarch))
+	return 2;
+      break;
     /* BEQZC, JIC */
     case 54:
     /* BNEZC, JIALC */
     case 62:
-      return is_mipsr6_isa (gdbarch);
+      if (is_mipsr6_isa (gdbarch))
+	/* JIC, JIALC are unconditional */
+	return (itype_rs (insn) == 0) ? 1 : 2;
+      break;
     /* BLEZC, BGEZC, BGEC */
     case 22:
     /* BGTZC, BLTZC, BLTC */
@@ -3703,15 +3737,33 @@ mips32_instruction_is_compact_branch (struct gdbarch *gdbarch, ULONGEST insn)
     case 6:
     /* BGTZALC, BLTZALC, BLTUC */
     case 7:
-      return (is_mipsr6_isa (gdbarch)
-	      && itype_rt (insn) != 0);
+      if (is_mipsr6_isa (gdbarch)
+	  && itype_rt (insn) != 0)
+	return 2;
+      break;
     /* BPOSGE32C */
     case 1:
-      return (is_mipsr6_isa (gdbarch)
-	      && itype_rt (insn) == 0x18 && itype_rs (insn) == 0);
-    default:
-      return 0;
+      if (is_mipsr6_isa (gdbarch)
+	  && itype_rt (insn) == 0x18 && itype_rs (insn) == 0)
+	return 2;
     }
+  return 0;
+}
+
+/* Return non-zero if a standard MIPS instruction at ADDR has a branch
+   forbidden slot (i.e. it is a conditional compact branch instruction).  */
+
+static int
+mips32_insn_at_pc_has_forbidden_slot (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+  ULONGEST insn;
+  int status;
+
+  insn = mips_fetch_instruction (gdbarch, ISA_MIPS, addr, &status);
+  if (status)
+    return 0;
+
+  return mips32_instruction_is_compact_branch (gdbarch, insn) == 2;
 }
 
 struct mips_frame_cache
@@ -9064,7 +9116,18 @@ mips_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr)
 
      So, we'll use the second solution.  To do this we need to know if
      the instruction we're trying to set the breakpoint on is in the
-     branch delay slot.  */
+     branch delay slot.
+
+     A similar problem occurs for breakpoints on forbidden slots where
+     the trap will be reported for the branch with the BD bit set.
+     In this case it would be ideal to recover using solution 1 from
+     above as there is no problem with the branch being skipped
+     (since the forbidden slot only exists on not-taken branches).
+     However, the BD bit is not available in all scenarios currently
+     so instead we move the breakpoint on to the next instruction.
+     This means that it is not possible to stop on an instruction
+     that can be in a forbidden slot even if that instruction is
+     jumped to directly.  */
 
   boundary = mips_segment_boundary (bpaddr);
 
@@ -9086,6 +9149,13 @@ mips_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr)
       prev_addr = bpaddr - 4;
       if (mips32_insn_at_pc_has_delay_slot (gdbarch, prev_addr))
 	bpaddr = prev_addr;
+      /* If the previous instruction has a forbidden slot, we have to
+	 move the breakpoint to the following instruction to prevent
+	 breakpoints in forbidden slots being reported as unknown
+	 traps.  */
+      else if (mips32_insn_at_pc_has_forbidden_slot (gdbarch, prev_addr))
+
+	bpaddr += 4;
     }
   else
     {
-- 
1.9-rc2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 22/24]     Support all new ABIs when detecting if an FPU is present
  2016-06-27 14:50 [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size Bhushan Attarde
                   ` (5 preceding siblings ...)
  2016-06-27 14:51 ` [PATCH 04/24] Add MIPS Config5 register related support Bhushan Attarde
@ 2016-06-27 14:51 ` Bhushan Attarde
  2016-06-27 14:51 ` [PATCH 24/24] MIPS R6 forbidden slot support Bhushan Attarde
                   ` (14 subsequent siblings)
  21 siblings, 0 replies; 37+ messages in thread
From: Bhushan Attarde @ 2016-06-27 14:51 UTC (permalink / raw)
  To: gdb-patches
  Cc: Maciej.Rozycki, Matthew.Fortune, James.Hogan, Andrew.Bennett,
	Jaydeep.Patil, Bhushan Attarde

    gdb/ChangeLog:
        * mips-tdep.c (mips_gdbarch_init): Handle fpxx, fp64 and
        fp64a ABI's.
---
 gdb/mips-tdep.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index 68e00ec..d5dd668 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -10163,6 +10163,9 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       switch (elf_fpu_type)
 	{
 	case Val_GNU_MIPS_ABI_FP_DOUBLE:
+	case Val_GNU_MIPS_ABI_FP_XX:
+	case Val_GNU_MIPS_ABI_FP_64:
+	case Val_GNU_MIPS_ABI_FP_64A:
 	  fpu_type = MIPS_FPU_DOUBLE;
 	  break;
 	case Val_GNU_MIPS_ABI_FP_SINGLE:
-- 
1.9-rc2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 01/24]     MIPS: Handle run-time reconfigurable FPR size
  2016-06-27 14:50 [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size Bhushan Attarde
                   ` (19 preceding siblings ...)
  2016-06-27 14:51 ` [PATCH 12/24] o32 sigframe unwinding with FR1 Bhushan Attarde
@ 2016-07-25 14:03 ` Maciej W. Rozycki
  2016-10-18 17:37   ` Maciej W. Rozycki
  2016-11-08 19:46 ` Yao Qi
  21 siblings, 1 reply; 37+ messages in thread
From: Maciej W. Rozycki @ 2016-07-25 14:03 UTC (permalink / raw)
  To: Bhushan Attarde
  Cc: gdb-patches, Matthew Fortune, James Hogan, Andrew Bennett, Jaydeep.Patil

Bhushan,

 Since this is virtually unchanged from the original submission I think it 
will be appropriate if you include a:

From: Maciej W. Rozycki <macro@codesourcery.com>

line at the beginning of the description to give a correct attribution.

>         * mips-irix-tdep.c (mips_irix_init_abi): Set
>         fp_register_size_fixed_p in gdbarch target data.

 This part is now gone along with IRIX support, so please remove it from 
the ChangeLog entry, and also make sure the rest of the ChangeLog entry is 
still consistent with the patch itself after adjustments.

> diff --git a/gdb/mips-linux-tdep.c b/gdb/mips-linux-tdep.c
> index 8dc0566..6b9743b 100644
> --- a/gdb/mips-linux-tdep.c
> +++ b/gdb/mips-linux-tdep.c
> @@ -1737,8 +1737,9 @@ mips_linux_init_abi (struct gdbarch_info info,
>  				    mips_gdb_signal_to_target);
>  

 You've lost the removal of the `tdesc_data' local variable from the 
original change here and this variable becomes unused -- was it by 
accident?

>    tdep->syscall_next_pc = mips_linux_syscall_next_pc;
> +  tdep->fp_register_size_fixed_p = 1;
>  
> -  if (tdesc_data)
> +  if (((struct gdbarch_tdep_info*)(info.tdep_info))->tdesc_data)

 Bad formatting here, you need a space after the cast.

>      {
>        const struct tdesc_feature *feature;
>  
> @@ -1753,8 +1754,8 @@ mips_linux_init_abi (struct gdbarch_info info,
>        feature = tdesc_find_feature (info.target_desc,
>  				    "org.gnu.gdb.mips.linux");
>        if (feature != NULL)
> -	tdesc_numbered_register (feature, tdesc_data, MIPS_RESTART_REGNUM,
> -				 "restart");
> +	tdesc_numbered_register (feature, (((struct gdbarch_tdep_info*)(info.tdep_info))->tdesc_data),

 Likewise.  Also lines are supposed to fit in 74 columns unless there is a 
good justification to make an exception, in which case they must not 
exceed 80 columns, as per GDB formatting style (please see 
<https://sourceware.org/gdb/wiki/Internals%20GDB-C-Coding-Standards> for 
details).  So this line needs to be wrapped.

 However, I think this will best be sorted out with an auxiliary local 
`tdep_info' variable, in which case you won't need a cast at all.

> diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
> index 63c1560..ae4dc2e 100644
> --- a/gdb/mips-tdep.c
> +++ b/gdb/mips-tdep.c
> @@ -6260,20 +6310,19 @@ mips_print_fp_register (struct ui_file *file, struct frame_info *frame,
>  			int regnum)
>  {				/* Do values for FP (float) regs.  */
>    struct gdbarch *gdbarch = get_frame_arch (frame);
> +  int fpsize = register_size (gdbarch, regnum);
>    gdb_byte *raw_buffer;
>    double doub, flt1;	/* Doubles extracted from raw hex data.  */
>    int inv1, inv2;
>  
> -  raw_buffer
> -    = ((gdb_byte *)
> -       alloca (2 * register_size (gdbarch, mips_regnum (gdbarch)->fp0)));
> +  raw_buffer = alloca (2 * fpsize);

 You need to keep this cast here; have you tried building GDB with a C++ 
compiler?

 You've lost a change to `mips_print_float_info' here -- again, was it by 
accident?

> @@ -8167,6 +8216,7 @@ value_of_mips_user_reg (struct frame_info *frame, const void *baton)
>  static struct gdbarch *
>  mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>  {
> +  struct gdbarch_tdep_info tdep_info = { NULL };
>    struct gdbarch *gdbarch;
>    struct gdbarch_tdep *tdep;
>    int elf_flags;
> @@ -8181,6 +8231,10 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>    int dspacc;
>    int dspctl;
>  
> +  /* Wire in an empty template tdep_info if one hasn't been supplied.  */
> +  if (info.tdep_info == NULL)
> +    info.tdep_info = &tdep_info;
> +
>    /* Fill in the OS dependent register numbers and names.  */
>    if (info.osabi == GDB_OSABI_IRIX)
>      {
[...]
> @@ -8311,7 +8366,15 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>  	  return NULL;
>  	}
>  
> -      valid_p = 1;
> +      /* Set the floating-point register size, assuming that whoever
> +         supplied the description got the current setting right wrt
> +         CP0 Status register's bit FR if applicable.  */
> +      fpsize = tdesc_register_size (feature, mips_fprs[0]) / 8;
> +
> +      /* Only accept a description whose floating-point register size
> +         matches the requested size or if none was specified.  */
> +      valid_p = (info.tdep_info->fp_register_size == 0
> +		 || info.tdep_info->fp_register_size == fpsize);
>        for (i = 0; i < 32; i++)
>  	valid_p &= tdesc_numbered_register (feature, tdesc_data,
>  					    i + mips_regnum.fp0, mips_fprs[i]);
> @@ -8366,6 +8429,9 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>  	    }
>  	}
>  
> +      /* Fix the floating-point register size found.  */
> +      info.tdep_info->fp_register_size = fpsize;
> +
>        /* It would be nice to detect an attempt to use a 64-bit ABI
>  	 when only 32-bit registers are provided.  */
>        reg_names = NULL;
> @@ -8576,6 +8642,11 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>        /* Be pedantic about which FPU is selected.  */
>        if (gdbarch_tdep (arches->gdbarch)->mips_fpu_type != fpu_type)
>  	continue;
> +      /* Ditto the requested floating-point register size if any.  */
> +      if (info.tdep_info->fp_register_size != 0
> +	  && (gdbarch_tdep (arches->gdbarch)->fp_register_size)
> +	      != info.tdep_info->fp_register_size)
> +	continue;
>  
>        if (tdesc_data != NULL)
>  	tdesc_data_cleanup (tdesc_data);
> @@ -8593,6 +8664,8 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>    tdep->mips_fpu_type = fpu_type;
>    tdep->register_size_valid_p = 0;
>    tdep->register_size = 0;
> +  tdep->fp_register_size = info.tdep_info->fp_register_size;
> +  tdep->fp_register_size_fixed_p = 0;
>  
>    if (info.target_desc)
>      {
[...]
> @@ -8869,7 +8949,7 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>    mips_register_g_packet_guesses (gdbarch);
>  
>    /* Hook in OS ABI-specific overrides, if they have been registered.  */
> -  info.tdep_info = tdesc_data;
> +  ((struct gdbarch_tdep_info*)(info.tdep_info))->tdesc_data = tdesc_data;

 Missing space after the cast again, but why don't you need the same cast 
to access `info.tdep_info->fp_register_size' above?  Have you verified 
this change actually builds?

 Overall again I think it'll be best refactored to avoid these casts, e.g. 
rename the existing null `tdep_info' to `null_tdep_info', and then add a 
new `tdep_info' variable to keep a correctly typed pointer and use it 
throughout.

> diff --git a/gdb/regcache.c b/gdb/regcache.c
> index f0ba0cf..c3405b6 100644
> --- a/gdb/regcache.c
> +++ b/gdb/regcache.c
> @@ -534,16 +534,35 @@ get_thread_arch_regcache (ptid_t ptid, struct gdbarch *gdbarch)
>  static ptid_t current_thread_ptid;
>  static struct gdbarch *current_thread_arch;
>  
> -struct regcache *
> -get_thread_regcache (ptid_t ptid)
> +static void
> +set_current_thread_ptid_arch (ptid_t ptid)
>  {
>    if (!current_thread_arch || !ptid_equal (current_thread_ptid, ptid))
>      {
>        current_thread_ptid = ptid;
>        current_thread_arch = target_thread_architecture (ptid);
>      }
> +}
> +
> +struct regcache *
> +get_thread_regcache (ptid_t ptid)
> +{
> +  int registers_changed_p = current_regcache == NULL;
> +  struct regcache *new_regcache;
> +
> +  set_current_thread_ptid_arch (ptid);
> +  new_regcache = get_thread_arch_regcache (ptid, current_thread_arch);
> +
> +  if (registers_changed_p
> +      && gdbarch_regcache_changed_p (current_thread_arch)
> +      && gdbarch_regcache_changed (current_thread_arch, new_regcache))
> +    {
> +      registers_changed ();
> +      set_current_thread_ptid_arch (ptid);
> +      new_regcache = get_thread_arch_regcache (ptid, current_thread_arch);
> +    }
>  
> -  return get_thread_arch_regcache (ptid, current_thread_arch);
> +  return new_regcache;
>  }
>  
>  struct regcache *

 As per <https://sourceware.org/ml/gdb-patches/2012-06/msg00291.html> this 
part requires a general maintainer's approval.

 ISTR though I hit issues with core file handling triggered by this part 
of the change, only observed after the original patch submission (and 
likely the reason I didn't just ping the patch).  So while this patch adds 
new functionality and therefore does not have to have each and every case 
handled right away from the beginning, please double-check it does not 
break things, and in particular does not cause a crash while handling a 
core file.

 Also a similar wrapper around `get_thread_arch_regcache' may be needed 
for places that call it directly rather than via `get_thread_regcache'.  
Please investigate.

  Maciej

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 21/24]     MIPSR6 support for GDB
  2016-06-27 14:51 ` [PATCH 21/24] MIPSR6 support for GDB Bhushan Attarde
@ 2016-07-29 21:10   ` Maciej W. Rozycki
  0 siblings, 0 replies; 37+ messages in thread
From: Maciej W. Rozycki @ 2016-07-29 21:10 UTC (permalink / raw)
  To: Bhushan Attarde
  Cc: gdb-patches, binutils, Matthew Fortune, James Hogan,
	Andrew Bennett, Jaydeep Patil

On Mon, 27 Jun 2016, Bhushan Attarde wrote:

>     This patch adds initial MIPS revision 6 support.

 This patch does not apply.  Can you please post a correct version right 
away, cc-ing <binutils@sourceware.org> as parts of this change apply to 
code which is maintained as a part of the binutils project?  No need to 
split at this time.

 Also please make sure any future patches you post are against the tip of 
the branch they are intended for.

  Maciej

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 02/24]     Add MIPS32 FPU64 GDB target descriptions
  2016-06-27 14:51 ` [PATCH 02/24] Add MIPS32 FPU64 GDB target descriptions Bhushan Attarde
@ 2016-10-12 12:42   ` Maciej W. Rozycki
  2016-10-12 13:58     ` James Hogan
  0 siblings, 1 reply; 37+ messages in thread
From: Maciej W. Rozycki @ 2016-10-12 12:42 UTC (permalink / raw)
  To: Bhushan Attarde
  Cc: gdb-patches, Matthew Fortune, James Hogan, Andrew Bennett, Jaydeep.Patil

On Mon, 27 Jun 2016, Bhushan Attarde wrote:

>     Add a couple of new target descriptions for MIPS32 targets with 64-bit
>     floating point registers, with and without DSP.
> 
>     These are identical to their 32-bit FPU counterparts except that the FP
>     registers are 64-bits long to allow for debugging of F64=1 MIPS32 targets
>     such as MIPS32r2 compatible cores, and they include the Config5 CP0
>     register which has an FRE bit.

 Hmm, has Linux kernel support for CP0.Config5 accesses gone upstream 
already?  Can you give me an upstream commit ID and/or reference to the 
discussion where it has been approved if so?

 More importantly, what do we need CP0.Config5 access for in the first 
place?  It looks to me like this bit is irrelevant to GDB as it does not 
affect the native (raw) register format.  So the only use would be to let 
the user running a debugging session switch between the FRE and NFRE modes 
without the need to poke at CP1C.FRE or CP1C.NFRE registers with a CTC1 
instruction, which by itself makes sense to me, but needs a further 
consideration.

 Additionally exposing CP0.Config5 may have security implications, 
especially as parts of the register have not been defined yet in the 
architectures and we'd have to force architecture maintainers somehow to 
ask us every time they intend to add a bit to this register to check if 
this has security implications and has to be avoided and/or explicitly 
handled in software.

 So overall it looks to me like we should avoid it.  What we ought to do 
instead is -- since we need to extend structures anyway -- I think adding 
all the remaining CP1C registers.  This would cover the earlier CP1C.UFR 
and CP1C.UNFR registers as well as any future additions, which would be 
further qualified with CP1.FIR bits to remove unimplemented registers from 
the view.  Given the unusual semantics of these registers I'd be tempted 
to map both pairs to the read register only and pretend it to be r/w with 
the LSB directly mapping to CP0.Status.FR and CP0.Config5.FRE as with 
CFC1.  Access would be r/o if user access to the selected bit was not 
permitted.

 This would provide the necessary semantics and avoid any security 
implications as GDB would only be able to poke/peek at the same bits the 
debuggee itself could.

 This could be sorted out the same way in core files.

 Finally, do we need to have these bits recorded in a signal frame?

>     F64 targets have an FR bit in the status register to specify the effective
>     register size, and the FRE bit is used with FR=1 to enable a compatibility
>     mode which is similar to FR=0 but with usable odd doubles which don't
>     alias with any other FP registers.

 This seems to contradict to how I read the architecture specification, 
which IIUC states that CP0.Config5.FRE=1 merely causes all single FP 
operations to trap.  All 32 64-bit registers are usable for doubles with 
CP0.Status.FR=1 regardless of the state of CP0.Config5.FRE.  Have I missed 
anything here?  Can you please elaborate and perhaps rephrase the sentence 
so that the implications for GDB are more clearly seen?

 Further comments as to the change itself follow.

>     gdb/ChangeLog:
> 
>     	* features/Makefile (WHICH): Add mips-fpu64-linux and
>     	mips-fpu64-dsp-linux and Sort microblaze out of the way

 Mid-sentence capitalisation issue here.

>         of mips/mips64

 Indentation and missing full stop.

>     	(mips-fpu64-expedite): Set.
>     	(mips-fpu64-dsp-expedite): Set.
>     	* features/mips-fpu64-dsp-linux.xml: New file.
>     	* features/mips-fpu64-linux.xml: New file.
>     	* features/mips-fpu64.xml: New file.
>     	* features/mips-fpu64-dsp-linux.c: New generated file.
>     	* features/mips-fpu64-linux.c: New generated file.
>     	* regformats/mips-fpu64-dsp-linux.dat: New generated file.
>     	* regformats/mips-fpu64-linux.dat: New generated file.
> 
>     gdb/gdbserver/ChangeLog:
> 
>     	* Makefile.in (clean): Delete mips-fpu64-linux.c and
>     	mips-fpu64-dsp-linux.c.

 I think "Delete" is confusing here: are you deleting from the rule or 
deleting files?  Please rephrase to make it unambiguous.  Maybe: "Add a 
deletion of..."?

> diff --git a/gdb/features/Makefile b/gdb/features/Makefile
> index 10173cf..b6baaf66 100644
> --- a/gdb/features/Makefile
> +++ b/gdb/features/Makefile
> @@ -57,8 +57,8 @@ WHICH = aarch64 \
>  	i386/x32 i386/x32-linux \
>  	i386/x32-avx i386/x32-avx-linux \
>  	i386/x32-avx512 i386/x32-avx512-linux \
> -	mips-linux mips-dsp-linux \
>  	microblaze-with-stack-protect \
> +	mips-linux mips-dsp-linux mips-fpu64-linux mips-fpu64-dsp-linux \
>  	mips64-linux mips64-dsp-linux \
>  	nios2-linux \
>  	rs6000/powerpc-32 \
> @@ -100,11 +100,13 @@ i386/x32-avx-expedite = rbp,rsp,rip
>  i386/x32-avx-linux-expedite = rbp,rsp,rip
>  i386/x32-avx512-expedite = rbp,rsp,rip
>  i386/x32-avx512-linux-expedite = rbp,rsp,rip
> +microblaze-expedite = r1,rpc
>  mips-expedite = r29,pc
>  mips-dsp-expedite = r29,pc
> +mips-fpu64-expedite = r29,pc
> +mips-fpu64-dsp-expedite = r29,pc
>  mips64-expedite = r29,pc
>  mips64-dsp-expedite = r29,pc
> -microblaze-expedite = r1,rpc
>  nios2-linux-expedite = sp,pc
>  powerpc-expedite = r1,pc
>  rs6000/powerpc-cell32l-expedite = r1,pc,r0,orig_r3,r4

 Please split Microblaze changes off to a separate preparatory patch.  
They can probably go in right away as obviously correct, but as a newcomer 
please allow 48 hours for people to chime in before committing.

 Speaking of which -- I don't see you listed in gdb/MAINTAINERS, so can 
you please clarify your status WRT the FSF copyright assignment?  Are you 
covered by a company assignment?  If your paperwork has been cleared, then  
I can commit your change on your behalf.

> diff --git a/gdb/features/mips-fpu64-dsp-linux.xml b/gdb/features/mips-fpu64-dsp-linux.xml
> new file mode 100644
> index 0000000..f0de5ce
> --- /dev/null
> +++ b/gdb/features/mips-fpu64-dsp-linux.xml
> @@ -0,0 +1,20 @@
> +<?xml version="1.0"?>
> +<!-- Copyright (C) 2012-2013 Free Software Foundation, Inc.

 You need to list the current year in copyright notices for newly 
submitted files, i.e.:

<!-- Copyright (C) 2016 Free Software Foundation, Inc.

Likewise throughout.

> diff --git a/gdb/features/mips-fpu64.xml b/gdb/features/mips-fpu64.xml
> new file mode 100644
> index 0000000..88dc9d9
> --- /dev/null
> +++ b/gdb/features/mips-fpu64.xml
> @@ -0,0 +1,45 @@
> +<?xml version="1.0"?>
> +<!-- Copyright (C) 2007-2013 Free Software Foundation, Inc.
> +
> +     Copying and distribution of this file, with or without modification,
> +     are permitted in any medium without royalty provided the copyright
> +     notice and this notice are preserved.  -->
> +
> +<!DOCTYPE feature SYSTEM "gdb-target.dtd">
> +<feature name="org.gnu.gdb.mips.fpu">
> +  <reg name="f0" bitsize="64" type="ieee_double"/>
> +  <reg name="f1" bitsize="64" type="ieee_double"/>
> +  <reg name="f2" bitsize="64" type="ieee_double"/>
> +  <reg name="f3" bitsize="64" type="ieee_double"/>
> +  <reg name="f4" bitsize="64" type="ieee_double"/>
> +  <reg name="f5" bitsize="64" type="ieee_double"/>
> +  <reg name="f6" bitsize="64" type="ieee_double"/>
> +  <reg name="f7" bitsize="64" type="ieee_double"/>
> +  <reg name="f8" bitsize="64" type="ieee_double"/>
> +  <reg name="f9" bitsize="64" type="ieee_double"/>
> +  <reg name="f10" bitsize="64" type="ieee_double"/>
> +  <reg name="f11" bitsize="64" type="ieee_double"/>
> +  <reg name="f12" bitsize="64" type="ieee_double"/>
> +  <reg name="f13" bitsize="64" type="ieee_double"/>
> +  <reg name="f14" bitsize="64" type="ieee_double"/>
> +  <reg name="f15" bitsize="64" type="ieee_double"/>
> +  <reg name="f16" bitsize="64" type="ieee_double"/>
> +  <reg name="f17" bitsize="64" type="ieee_double"/>
> +  <reg name="f18" bitsize="64" type="ieee_double"/>
> +  <reg name="f19" bitsize="64" type="ieee_double"/>
> +  <reg name="f20" bitsize="64" type="ieee_double"/>
> +  <reg name="f21" bitsize="64" type="ieee_double"/>
> +  <reg name="f22" bitsize="64" type="ieee_double"/>
> +  <reg name="f23" bitsize="64" type="ieee_double"/>
> +  <reg name="f24" bitsize="64" type="ieee_double"/>
> +  <reg name="f25" bitsize="64" type="ieee_double"/>
> +  <reg name="f26" bitsize="64" type="ieee_double"/>
> +  <reg name="f27" bitsize="64" type="ieee_double"/>
> +  <reg name="f28" bitsize="64" type="ieee_double"/>
> +  <reg name="f29" bitsize="64" type="ieee_double"/>
> +  <reg name="f30" bitsize="64" type="ieee_double"/>
> +  <reg name="f31" bitsize="64" type="ieee_double"/>
> +
> +  <reg name="fcsr" bitsize="32" group="float"/>
> +  <reg name="fir" bitsize="32" group="float"/>
> +</feature>

 This is AFAICT the same as mips64-fpu.xml, except for the sizes of `fcsr' 
and `fir', wrongly set to 64 bits in the latter file.  I think we ought to 
avoid the unnecessary duplication, and just use a single template for the 
FPU, which is the same in the 64-bit FP case regardless of the machine 
word width of the CPU.

 Can you therefore please just reuse mips64-fpu.xml here, which I think 
should be renamed at the same time to mips-fpu64.xml, as with your 
proposal (GIT will detect a rename and show it properly with diffs and 
other stats)?  For historical reasons we need to keep $fcsr and $fir at 64 
bits in XML descriptions, as explained in commit 78b86327b530 ("mips-tdep: 
Make FCRs always 32-bit"), made specifically to address the inconsistency 
discovered in the context of your submission; none of any further FCRs 
added will have any historical implications though, so they ought to be 
32-bit as in hardware.

 You'll have to adjust the callers of `mips_collect_register_32bit' and 
`mips_supply_register_32bit' in `gdbserver' accordingly so that 
`use_64bit' is set according to the FPU rather than the CPU model then.  
I don't think you'll need to adjust anything in mips-linux-tdep.c, however 
please double-check.

> diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
> index 1e874e3..9913d6a 100644
> --- a/gdb/gdbserver/Makefile.in
> +++ b/gdb/gdbserver/Makefile.in
> @@ -357,7 +357,8 @@ clean:
>  	rm -f reg-tilegx.c reg-tilegx32.c
>  	rm -f arm-with-iwmmxt.c
>  	rm -f arm-with-vfpv2.c arm-with-vfpv3.c arm-with-neon.c
> -	rm -f mips-linux.c mips-dsp-linux.c
> +	rm -f mips-linux.c mips-dsp-linux.c mips-fpu64-linux.c
> +	rm -f mips-fpu64-dsp-linux.c
>  	rm -f mips64-linux.c mips64-dsp-linux.c
>  	rm -f nios2-linux.c
>  	rm -f powerpc-32.c powerpc-32l.c powerpc-64l.c powerpc-e500l.c

 This will then have to reflect the removal of mips64-fpu.xml of course.

> index a54b9e7..422fd90 100644
> --- a/gdb/gdbserver/configure.srv
> +++ b/gdb/gdbserver/configure.srv
> @@ -187,15 +187,20 @@ case "${target}" in
>  			;;
>    mips*-*-linux*)	srv_regobj="mips-linux.o"
>  			srv_regobj="${srv_regobj} mips-dsp-linux.o"
> +			srv_regobj="${srv_regobj} mips-fpu64-linux.o"
> +			srv_regobj="${srv_regobj} mips-fpu64-dsp-linux.o"
>  			srv_regobj="${srv_regobj} mips64-linux.o"
>  			srv_regobj="${srv_regobj} mips64-dsp-linux.o"
>  			srv_tgtobj="$srv_linux_obj linux-mips-low.o"
>  			srv_tgtobj="${srv_tgtobj} mips-linux-watch.o"
>  			srv_xmlfiles="mips-linux.xml"
>  			srv_xmlfiles="${srv_xmlfiles} mips-dsp-linux.xml"
> +			srv_xmlfiles="${srv_xmlfiles} mips-fpu64-linux.xml"
> +			srv_xmlfiles="${srv_xmlfiles} mips-fpu64-dsp-linux.xml"
>  			srv_xmlfiles="${srv_xmlfiles} mips-cpu.xml"
>  			srv_xmlfiles="${srv_xmlfiles} mips-cp0.xml"
>  			srv_xmlfiles="${srv_xmlfiles} mips-fpu.xml"
> +			srv_xmlfiles="${srv_xmlfiles} mips-fpu64.xml"
>  			srv_xmlfiles="${srv_xmlfiles} mips-dsp.xml"
>  			srv_xmlfiles="${srv_xmlfiles} mips64-linux.xml"
>  			srv_xmlfiles="${srv_xmlfiles} mips64-dsp-linux.xml"

 Likewise.

  Maciej

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 02/24]     Add MIPS32 FPU64 GDB target descriptions
  2016-10-12 12:42   ` Maciej W. Rozycki
@ 2016-10-12 13:58     ` James Hogan
  2016-10-12 16:30       ` Maciej W. Rozycki
  0 siblings, 1 reply; 37+ messages in thread
From: James Hogan @ 2016-10-12 13:58 UTC (permalink / raw)
  To: Maciej W. Rozycki
  Cc: Bhushan Attarde, gdb-patches, Matthew Fortune, Andrew Bennett,
	Jaydeep.Patil

[-- Attachment #1: Type: text/plain, Size: 13305 bytes --]

Hi Maciej,

On Wed, Oct 12, 2016 at 01:42:17PM +0100, Maciej W. Rozycki wrote:
> On Mon, 27 Jun 2016, Bhushan Attarde wrote:
> 
> >     Add a couple of new target descriptions for MIPS32 targets with 64-bit
> >     floating point registers, with and without DSP.
> > 
> >     These are identical to their 32-bit FPU counterparts except that the FP
> >     registers are 64-bits long to allow for debugging of F64=1 MIPS32 targets
> >     such as MIPS32r2 compatible cores, and they include the Config5 CP0
> >     register which has an FRE bit.
> 
>  Hmm, has Linux kernel support for CP0.Config5 accesses gone upstream 
> already?  Can you give me an upstream commit ID and/or reference to the 
> discussion where it has been approved if so?

I don't think it did go upstream yet.

> 
>  More importantly, what do we need CP0.Config5 access for in the first 
> place?  It looks to me like this bit is irrelevant to GDB as it does not 
> affect the native (raw) register format.  So the only use would be to let 
> the user running a debugging session switch between the FRE and NFRE modes 
> without the need to poke at CP1C.FRE or CP1C.NFRE registers with a CTC1 
> instruction, which by itself makes sense to me, but needs a further 
> consideration.

It allows the FRE bit to be read (I seem to remember this was the only
bit actually exposed through ptrace by the patch).

FRE simply causes certain instructions (all single precision FP
arithmetic instructions and FP word loads/stores) to trap to the kernel
so that it can emulate a variation/subset of FR=0, so the debugger would
use it to decide how to decode the single precision FP registers based
on the double precision FP registers (iirc).

> 
>  Additionally exposing CP0.Config5 may have security implications, 
> especially as parts of the register have not been defined yet in the 
> architectures and we'd have to force architecture maintainers somehow to 
> ask us every time they intend to add a bit to this register to check if 
> this has security implications and has to be avoided and/or explicitly 
> handled in software.

yes, as above it explicity only shows certain bits. I'm fine with the
api changing if necessary though since it isn't upstream.

cheers
James

> 
>  So overall it looks to me like we should avoid it.  What we ought to do 
> instead is -- since we need to extend structures anyway -- I think adding 
> all the remaining CP1C registers.  This would cover the earlier CP1C.UFR 
> and CP1C.UNFR registers as well as any future additions, which would be 
> further qualified with CP1.FIR bits to remove unimplemented registers from 
> the view.  Given the unusual semantics of these registers I'd be tempted 
> to map both pairs to the read register only and pretend it to be r/w with 
> the LSB directly mapping to CP0.Status.FR and CP0.Config5.FRE as with 
> CFC1.  Access would be r/o if user access to the selected bit was not 
> permitted.
> 
>  This would provide the necessary semantics and avoid any security 
> implications as GDB would only be able to poke/peek at the same bits the 
> debuggee itself could.
> 
>  This could be sorted out the same way in core files.
> 
>  Finally, do we need to have these bits recorded in a signal frame?
> 
> >     F64 targets have an FR bit in the status register to specify the effective
> >     register size, and the FRE bit is used with FR=1 to enable a compatibility
> >     mode which is similar to FR=0 but with usable odd doubles which don't
> >     alias with any other FP registers.
> 
>  This seems to contradict to how I read the architecture specification, 
> which IIUC states that CP0.Config5.FRE=1 merely causes all single FP 
> operations to trap.  All 32 64-bit registers are usable for doubles with 
> CP0.Status.FR=1 regardless of the state of CP0.Config5.FRE.  Have I missed 
> anything here?  Can you please elaborate and perhaps rephrase the sentence 
> so that the implications for GDB are more clearly seen?
> 
>  Further comments as to the change itself follow.
> 
> >     gdb/ChangeLog:
> > 
> >     	* features/Makefile (WHICH): Add mips-fpu64-linux and
> >     	mips-fpu64-dsp-linux and Sort microblaze out of the way
> 
>  Mid-sentence capitalisation issue here.
> 
> >         of mips/mips64
> 
>  Indentation and missing full stop.
> 
> >     	(mips-fpu64-expedite): Set.
> >     	(mips-fpu64-dsp-expedite): Set.
> >     	* features/mips-fpu64-dsp-linux.xml: New file.
> >     	* features/mips-fpu64-linux.xml: New file.
> >     	* features/mips-fpu64.xml: New file.
> >     	* features/mips-fpu64-dsp-linux.c: New generated file.
> >     	* features/mips-fpu64-linux.c: New generated file.
> >     	* regformats/mips-fpu64-dsp-linux.dat: New generated file.
> >     	* regformats/mips-fpu64-linux.dat: New generated file.
> > 
> >     gdb/gdbserver/ChangeLog:
> > 
> >     	* Makefile.in (clean): Delete mips-fpu64-linux.c and
> >     	mips-fpu64-dsp-linux.c.
> 
>  I think "Delete" is confusing here: are you deleting from the rule or 
> deleting files?  Please rephrase to make it unambiguous.  Maybe: "Add a 
> deletion of..."?
> 
> > diff --git a/gdb/features/Makefile b/gdb/features/Makefile
> > index 10173cf..b6baaf66 100644
> > --- a/gdb/features/Makefile
> > +++ b/gdb/features/Makefile
> > @@ -57,8 +57,8 @@ WHICH = aarch64 \
> >  	i386/x32 i386/x32-linux \
> >  	i386/x32-avx i386/x32-avx-linux \
> >  	i386/x32-avx512 i386/x32-avx512-linux \
> > -	mips-linux mips-dsp-linux \
> >  	microblaze-with-stack-protect \
> > +	mips-linux mips-dsp-linux mips-fpu64-linux mips-fpu64-dsp-linux \
> >  	mips64-linux mips64-dsp-linux \
> >  	nios2-linux \
> >  	rs6000/powerpc-32 \
> > @@ -100,11 +100,13 @@ i386/x32-avx-expedite = rbp,rsp,rip
> >  i386/x32-avx-linux-expedite = rbp,rsp,rip
> >  i386/x32-avx512-expedite = rbp,rsp,rip
> >  i386/x32-avx512-linux-expedite = rbp,rsp,rip
> > +microblaze-expedite = r1,rpc
> >  mips-expedite = r29,pc
> >  mips-dsp-expedite = r29,pc
> > +mips-fpu64-expedite = r29,pc
> > +mips-fpu64-dsp-expedite = r29,pc
> >  mips64-expedite = r29,pc
> >  mips64-dsp-expedite = r29,pc
> > -microblaze-expedite = r1,rpc
> >  nios2-linux-expedite = sp,pc
> >  powerpc-expedite = r1,pc
> >  rs6000/powerpc-cell32l-expedite = r1,pc,r0,orig_r3,r4
> 
>  Please split Microblaze changes off to a separate preparatory patch.  
> They can probably go in right away as obviously correct, but as a newcomer 
> please allow 48 hours for people to chime in before committing.
> 
>  Speaking of which -- I don't see you listed in gdb/MAINTAINERS, so can 
> you please clarify your status WRT the FSF copyright assignment?  Are you 
> covered by a company assignment?  If your paperwork has been cleared, then  
> I can commit your change on your behalf.
> 
> > diff --git a/gdb/features/mips-fpu64-dsp-linux.xml b/gdb/features/mips-fpu64-dsp-linux.xml
> > new file mode 100644
> > index 0000000..f0de5ce
> > --- /dev/null
> > +++ b/gdb/features/mips-fpu64-dsp-linux.xml
> > @@ -0,0 +1,20 @@
> > +<?xml version="1.0"?>
> > +<!-- Copyright (C) 2012-2013 Free Software Foundation, Inc.
> 
>  You need to list the current year in copyright notices for newly 
> submitted files, i.e.:
> 
> <!-- Copyright (C) 2016 Free Software Foundation, Inc.
> 
> Likewise throughout.
> 
> > diff --git a/gdb/features/mips-fpu64.xml b/gdb/features/mips-fpu64.xml
> > new file mode 100644
> > index 0000000..88dc9d9
> > --- /dev/null
> > +++ b/gdb/features/mips-fpu64.xml
> > @@ -0,0 +1,45 @@
> > +<?xml version="1.0"?>
> > +<!-- Copyright (C) 2007-2013 Free Software Foundation, Inc.
> > +
> > +     Copying and distribution of this file, with or without modification,
> > +     are permitted in any medium without royalty provided the copyright
> > +     notice and this notice are preserved.  -->
> > +
> > +<!DOCTYPE feature SYSTEM "gdb-target.dtd">
> > +<feature name="org.gnu.gdb.mips.fpu">
> > +  <reg name="f0" bitsize="64" type="ieee_double"/>
> > +  <reg name="f1" bitsize="64" type="ieee_double"/>
> > +  <reg name="f2" bitsize="64" type="ieee_double"/>
> > +  <reg name="f3" bitsize="64" type="ieee_double"/>
> > +  <reg name="f4" bitsize="64" type="ieee_double"/>
> > +  <reg name="f5" bitsize="64" type="ieee_double"/>
> > +  <reg name="f6" bitsize="64" type="ieee_double"/>
> > +  <reg name="f7" bitsize="64" type="ieee_double"/>
> > +  <reg name="f8" bitsize="64" type="ieee_double"/>
> > +  <reg name="f9" bitsize="64" type="ieee_double"/>
> > +  <reg name="f10" bitsize="64" type="ieee_double"/>
> > +  <reg name="f11" bitsize="64" type="ieee_double"/>
> > +  <reg name="f12" bitsize="64" type="ieee_double"/>
> > +  <reg name="f13" bitsize="64" type="ieee_double"/>
> > +  <reg name="f14" bitsize="64" type="ieee_double"/>
> > +  <reg name="f15" bitsize="64" type="ieee_double"/>
> > +  <reg name="f16" bitsize="64" type="ieee_double"/>
> > +  <reg name="f17" bitsize="64" type="ieee_double"/>
> > +  <reg name="f18" bitsize="64" type="ieee_double"/>
> > +  <reg name="f19" bitsize="64" type="ieee_double"/>
> > +  <reg name="f20" bitsize="64" type="ieee_double"/>
> > +  <reg name="f21" bitsize="64" type="ieee_double"/>
> > +  <reg name="f22" bitsize="64" type="ieee_double"/>
> > +  <reg name="f23" bitsize="64" type="ieee_double"/>
> > +  <reg name="f24" bitsize="64" type="ieee_double"/>
> > +  <reg name="f25" bitsize="64" type="ieee_double"/>
> > +  <reg name="f26" bitsize="64" type="ieee_double"/>
> > +  <reg name="f27" bitsize="64" type="ieee_double"/>
> > +  <reg name="f28" bitsize="64" type="ieee_double"/>
> > +  <reg name="f29" bitsize="64" type="ieee_double"/>
> > +  <reg name="f30" bitsize="64" type="ieee_double"/>
> > +  <reg name="f31" bitsize="64" type="ieee_double"/>
> > +
> > +  <reg name="fcsr" bitsize="32" group="float"/>
> > +  <reg name="fir" bitsize="32" group="float"/>
> > +</feature>
> 
>  This is AFAICT the same as mips64-fpu.xml, except for the sizes of `fcsr' 
> and `fir', wrongly set to 64 bits in the latter file.  I think we ought to 
> avoid the unnecessary duplication, and just use a single template for the 
> FPU, which is the same in the 64-bit FP case regardless of the machine 
> word width of the CPU.
> 
>  Can you therefore please just reuse mips64-fpu.xml here, which I think 
> should be renamed at the same time to mips-fpu64.xml, as with your 
> proposal (GIT will detect a rename and show it properly with diffs and 
> other stats)?  For historical reasons we need to keep $fcsr and $fir at 64 
> bits in XML descriptions, as explained in commit 78b86327b530 ("mips-tdep: 
> Make FCRs always 32-bit"), made specifically to address the inconsistency 
> discovered in the context of your submission; none of any further FCRs 
> added will have any historical implications though, so they ought to be 
> 32-bit as in hardware.
> 
>  You'll have to adjust the callers of `mips_collect_register_32bit' and 
> `mips_supply_register_32bit' in `gdbserver' accordingly so that 
> `use_64bit' is set according to the FPU rather than the CPU model then.  
> I don't think you'll need to adjust anything in mips-linux-tdep.c, however 
> please double-check.
> 
> > diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
> > index 1e874e3..9913d6a 100644
> > --- a/gdb/gdbserver/Makefile.in
> > +++ b/gdb/gdbserver/Makefile.in
> > @@ -357,7 +357,8 @@ clean:
> >  	rm -f reg-tilegx.c reg-tilegx32.c
> >  	rm -f arm-with-iwmmxt.c
> >  	rm -f arm-with-vfpv2.c arm-with-vfpv3.c arm-with-neon.c
> > -	rm -f mips-linux.c mips-dsp-linux.c
> > +	rm -f mips-linux.c mips-dsp-linux.c mips-fpu64-linux.c
> > +	rm -f mips-fpu64-dsp-linux.c
> >  	rm -f mips64-linux.c mips64-dsp-linux.c
> >  	rm -f nios2-linux.c
> >  	rm -f powerpc-32.c powerpc-32l.c powerpc-64l.c powerpc-e500l.c
> 
>  This will then have to reflect the removal of mips64-fpu.xml of course.
> 
> > index a54b9e7..422fd90 100644
> > --- a/gdb/gdbserver/configure.srv
> > +++ b/gdb/gdbserver/configure.srv
> > @@ -187,15 +187,20 @@ case "${target}" in
> >  			;;
> >    mips*-*-linux*)	srv_regobj="mips-linux.o"
> >  			srv_regobj="${srv_regobj} mips-dsp-linux.o"
> > +			srv_regobj="${srv_regobj} mips-fpu64-linux.o"
> > +			srv_regobj="${srv_regobj} mips-fpu64-dsp-linux.o"
> >  			srv_regobj="${srv_regobj} mips64-linux.o"
> >  			srv_regobj="${srv_regobj} mips64-dsp-linux.o"
> >  			srv_tgtobj="$srv_linux_obj linux-mips-low.o"
> >  			srv_tgtobj="${srv_tgtobj} mips-linux-watch.o"
> >  			srv_xmlfiles="mips-linux.xml"
> >  			srv_xmlfiles="${srv_xmlfiles} mips-dsp-linux.xml"
> > +			srv_xmlfiles="${srv_xmlfiles} mips-fpu64-linux.xml"
> > +			srv_xmlfiles="${srv_xmlfiles} mips-fpu64-dsp-linux.xml"
> >  			srv_xmlfiles="${srv_xmlfiles} mips-cpu.xml"
> >  			srv_xmlfiles="${srv_xmlfiles} mips-cp0.xml"
> >  			srv_xmlfiles="${srv_xmlfiles} mips-fpu.xml"
> > +			srv_xmlfiles="${srv_xmlfiles} mips-fpu64.xml"
> >  			srv_xmlfiles="${srv_xmlfiles} mips-dsp.xml"
> >  			srv_xmlfiles="${srv_xmlfiles} mips64-linux.xml"
> >  			srv_xmlfiles="${srv_xmlfiles} mips64-dsp-linux.xml"
> 
>  Likewise.
> 
>   Maciej

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 02/24]     Add MIPS32 FPU64 GDB target descriptions
  2016-10-12 13:58     ` James Hogan
@ 2016-10-12 16:30       ` Maciej W. Rozycki
  2016-10-12 18:05         ` James Hogan
  0 siblings, 1 reply; 37+ messages in thread
From: Maciej W. Rozycki @ 2016-10-12 16:30 UTC (permalink / raw)
  To: James Hogan
  Cc: Bhushan Attarde, gdb-patches, Matthew Fortune, Andrew Bennett,
	Jaydeep Patil, linux-mips

Hi James,

 Thanks for your input!

 Cc-ing linux-mips for the discussion about a ptrace(2) kernel API update; 
anyone interested in previous talk about this change please have a look 
at: <https://sourceware.org/ml/gdb-patches/2016-06/msg00441.html> and 
<https://sourceware.org/ml/gdb-patches/2016-10/msg00311.html> for the 
earlier messages.

> >  Hmm, has Linux kernel support for CP0.Config5 accesses gone upstream 
> > already?  Can you give me an upstream commit ID and/or reference to the 
> > discussion where it has been approved if so?
> 
> I don't think it did go upstream yet.

 Good!

> >  More importantly, what do we need CP0.Config5 access for in the first 
> > place?  It looks to me like this bit is irrelevant to GDB as it does not 
> > affect the native (raw) register format.  So the only use would be to let 
> > the user running a debugging session switch between the FRE and NFRE modes 
> > without the need to poke at CP1C.FRE or CP1C.NFRE registers with a CTC1 
> > instruction, which by itself makes sense to me, but needs a further 
> > consideration.
> 
> It allows the FRE bit to be read (I seem to remember this was the only
> bit actually exposed through ptrace by the patch).

 Then I think it makes sense even more not to create this artificial API 
and use the CP1C.FRE/CP1C.NFRE registers instead which do correspond to 
what hardware presents to user software.  Also with CP1C.UFR/CP1C.UNFR vs 
CP0.Status; while we want to retain the latter register in the view for 
historical reasons, it has always been read-only and I think it ought to 
remain such, with any writes to CP0.Status.FR executed via the former CP1C 
registers only.

> FRE simply causes certain instructions (all single precision FP
> arithmetic instructions and FP word loads/stores) to trap to the kernel
> so that it can emulate a variation/subset of FR=0, so the debugger would
> use it to decide how to decode the single precision FP registers based
> on the double precision FP registers (iirc).

 I don't think there is any value in it for GDB, I think all 64-bit FP 
registers ought to remain being presented as doubles and pairs of singles 
regardless of the mode selected (and also possibly fixed-point longs and 
pairs of fixed-point words).  We don't know what's emulated and what's not 
after all, and then the contents of FPRs are not interpreted by GDB itself 
anyhow except in user-supplied expressions or assignment requests, which 
for users' convenience I think should retain the maximum flexibility 
possible.

 So as I say it looks to me like the only, though obviously valid and 
wholeheartedly supported, use for CP1C.FRE/CP1C.NFRE would be for user's 
control of the execution environment.

> >  Additionally exposing CP0.Config5 may have security implications, 
> > especially as parts of the register have not been defined yet in the 
> > architectures and we'd have to force architecture maintainers somehow to 
> > ask us every time they intend to add a bit to this register to check if 
> > this has security implications and has to be avoided and/or explicitly 
> > handled in software.
> 
> yes, as above it explicity only shows certain bits. I'm fine with the
> api changing if necessary though since it isn't upstream.

 It sounds like a plan to me then -- any further questions or comments 
about the kernel API part, anyone?

  Maciej

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 02/24]     Add MIPS32 FPU64 GDB target descriptions
  2016-10-12 16:30       ` Maciej W. Rozycki
@ 2016-10-12 18:05         ` James Hogan
  2016-10-12 22:04           ` Maciej W. Rozycki
  0 siblings, 1 reply; 37+ messages in thread
From: James Hogan @ 2016-10-12 18:05 UTC (permalink / raw)
  To: Maciej W. Rozycki
  Cc: Bhushan Attarde, gdb-patches, Matthew Fortune, Andrew Bennett,
	Jaydeep Patil, linux-mips

[-- Attachment #1: Type: text/plain, Size: 5915 bytes --]

On Wed, Oct 12, 2016 at 05:29:53PM +0100, Maciej W. Rozycki wrote:
> Hi James,
> 
>  Thanks for your input!
> 
>  Cc-ing linux-mips for the discussion about a ptrace(2) kernel API update; 
> anyone interested in previous talk about this change please have a look 
> at: <https://sourceware.org/ml/gdb-patches/2016-06/msg00441.html> and 
> <https://sourceware.org/ml/gdb-patches/2016-10/msg00311.html> for the 
> earlier messages.
> 
> > >  Hmm, has Linux kernel support for CP0.Config5 accesses gone upstream 
> > > already?  Can you give me an upstream commit ID and/or reference to the 
> > > discussion where it has been approved if so?
> > 
> > I don't think it did go upstream yet.
> 
>  Good!
> 
> > >  More importantly, what do we need CP0.Config5 access for in the first 
> > > place?  It looks to me like this bit is irrelevant to GDB as it does not 
> > > affect the native (raw) register format.  So the only use would be to let 
> > > the user running a debugging session switch between the FRE and NFRE modes 
> > > without the need to poke at CP1C.FRE or CP1C.NFRE registers with a CTC1 
> > > instruction, which by itself makes sense to me, but needs a further 
> > > consideration.
> > 
> > It allows the FRE bit to be read (I seem to remember this was the only
> > bit actually exposed through ptrace by the patch).
> 
>  Then I think it makes sense even more not to create this artificial API 
> and use the CP1C.FRE/CP1C.NFRE registers instead which do correspond to 
> what hardware presents to user software.

well, barely. Linux at least doesn't enable Config5.UFE or Config5.UFR,
since FP mode changes must be done for all threads in the process, so
userland can't actually directly access those FCRs either.

> Also with CP1C.UFR/CP1C.UNFR vs 
> CP0.Status; while we want to retain the latter register in the view for 
> historical reasons, it has always been read-only and I think it ought to 
> remain such, with any writes to CP0.Status.FR executed via the former CP1C 
> registers only.
> 
> > FRE simply causes certain instructions (all single precision FP
> > arithmetic instructions and FP word loads/stores) to trap to the kernel
> > so that it can emulate a variation/subset of FR=0, so the debugger would
> > use it to decide how to decode the single precision FP registers based
> > on the double precision FP registers (iirc).
> 
>  I don't think there is any value in it for GDB, I think all 64-bit FP 
> registers ought to remain being presented as doubles and pairs of singles 
> regardless of the mode selected (and also possibly fixed-point longs and 
> pairs of fixed-point words).  We don't know what's emulated and what's not 
> after all, and then the contents of FPRs are not interpreted by GDB itself 
> anyhow except in user-supplied expressions or assignment requests, which 
> for users' convenience I think should retain the maximum flexibility 
> possible.

Well it technically depends on
test_tsk_thread_flag(target, TIF_HYBRID_FPREGS)

So it allows gdb to detect Linux's Hybrid FPU mode, and present the fp
regs (e.g. f0 or f1) more like below to the user depending on the fp
mode, which is surely much more intuitive from an assembly debugging
point of view.

Its also worth noting that "When software changes the value of this bit
[Status.FR], the contents of the floating-point registers are
UNPREDICTABLE". I.e. there is no architectural unifying register layout
between FR=0 / FR=1, only convention. Linux will I presume intentionally
save in old mode and restore in new mode on an fp mode change according
to its own convention (such that the valid mode changes don't clobber
register state).

(disclaimer: I haven't looked at this gdb patchset in detail as to
whether any of below has changed since I worked on it).

(1) Even singles and doubles always overlap one another, as do odd
singles and doubles when FR=1 (and FRE=0):
	/* (little endian) */
	union __gdb_builtin_mips_fp64 {
	  float  f32;
	  double f64;
	  int32  i32;
	  int64  i64;
	};

(2) Odd singles when FR=0 (there are no odd doubles):
	union __gdb_builtin_mips_fp32 {
	  float f32;
	  int32_t i32;
	};

(3) Odd singles and doubles when FR=1, FRE=1 don't overlap at all:
	struct __gdb_builtin_mips_fp96 {
		union {
			double f64;
			int64  i64;
		};
		union {
			float  f32;
			int32  i32;
		};
	};

i.e.

FR=0:
 (1) even
       double:	FEDCBA9876543210
       single:	        76543210
 (2) odd
       single:	FEDCBA98

FR=1, FRE=0:
 (1) even
       double:	FEDCBA9876543210
       single:	        76543210
 (1) odd
       double:	                0123456789ABCDEF
       single:	                        89ABCDEF

FR=1, FRE=1:
 (1) even
       double:	FEDCBA9876543210
       single:	        76543210   (Hybrid FPR emulation)
 (3) odd
       double:	                0123456789ABCDEF
       single:	FEDCBA98           (Hybrid FPR emulation)
)

Cheers
James

> 
>  So as I say it looks to me like the only, though obviously valid and 
> wholeheartedly supported, use for CP1C.FRE/CP1C.NFRE would be for user's 
> control of the execution environment.
> 
> > >  Additionally exposing CP0.Config5 may have security implications, 
> > > especially as parts of the register have not been defined yet in the 
> > > architectures and we'd have to force architecture maintainers somehow to 
> > > ask us every time they intend to add a bit to this register to check if 
> > > this has security implications and has to be avoided and/or explicitly 
> > > handled in software.
> > 
> > yes, as above it explicity only shows certain bits. I'm fine with the
> > api changing if necessary though since it isn't upstream.
> 
>  It sounds like a plan to me then -- any further questions or comments 
> about the kernel API part, anyone?
> 
>   Maciej

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 02/24]     Add MIPS32 FPU64 GDB target descriptions
  2016-10-12 18:05         ` James Hogan
@ 2016-10-12 22:04           ` Maciej W. Rozycki
  2016-10-13 10:09             ` Matthew Fortune
  0 siblings, 1 reply; 37+ messages in thread
From: Maciej W. Rozycki @ 2016-10-12 22:04 UTC (permalink / raw)
  To: James Hogan
  Cc: Bhushan Attarde, gdb-patches, Matthew Fortune, Andrew Bennett,
	Jaydeep Patil, linux-mips

On Wed, 12 Oct 2016, James Hogan wrote:

> >  Then I think it makes sense even more not to create this artificial API 
> > and use the CP1C.FRE/CP1C.NFRE registers instead which do correspond to 
> > what hardware presents to user software.
> 
> well, barely. Linux at least doesn't enable Config5.UFE or Config5.UFR,
> since FP mode changes must be done for all threads in the process, so
> userland can't actually directly access those FCRs either.

 Hmm, I didn't know that -- what was the reason for this design decision?  
Offhand the limitation does not appear necessary to me, each thread has 
its own distinct register set, so it does not appear to me that its mode 
of operation has to be the same across them all.  The current setting 
would still of course be inherited from the parent by any new threads 
created with clone(2).

 Anyway in that case the presented CP1C registers will have to be 
read-only.

> >  I don't think there is any value in it for GDB, I think all 64-bit FP 
> > registers ought to remain being presented as doubles and pairs of singles 
> > regardless of the mode selected (and also possibly fixed-point longs and 
> > pairs of fixed-point words).  We don't know what's emulated and what's not 
> > after all, and then the contents of FPRs are not interpreted by GDB itself 
> > anyhow except in user-supplied expressions or assignment requests, which 
> > for users' convenience I think should retain the maximum flexibility 
> > possible.
> 
> Well it technically depends on
> test_tsk_thread_flag(target, TIF_HYBRID_FPREGS)

 Sure, but the hardware representation is CP0.Config5.FRE/CP1C.FRE.

> So it allows gdb to detect Linux's Hybrid FPU mode, and present the fp
> regs (e.g. f0 or f1) more like below to the user depending on the fp
> mode, which is surely much more intuitive from an assembly debugging
> point of view.
> 
> Its also worth noting that "When software changes the value of this bit
> [Status.FR], the contents of the floating-point registers are
> UNPREDICTABLE". I.e. there is no architectural unifying register layout
> between FR=0 / FR=1, only convention. Linux will I presume intentionally
> save in old mode and restore in new mode on an fp mode change according
> to its own convention (such that the valid mode changes don't clobber
> register state).

 Well the contents might be unpredictable, but there sure will be some and 
GDB is supposed to present it.

> (disclaimer: I haven't looked at this gdb patchset in detail as to
> whether any of below has changed since I worked on it).
> 
> (1) Even singles and doubles always overlap one another, as do odd
> singles and doubles when FR=1 (and FRE=0):
> 	/* (little endian) */
> 	union __gdb_builtin_mips_fp64 {
> 	  float  f32;
> 	  double f64;
> 	  int32  i32;
> 	  int64  i64;
> 	};
> 
> (2) Odd singles when FR=0 (there are no odd doubles):
> 	union __gdb_builtin_mips_fp32 {
> 	  float f32;
> 	  int32_t i32;
> 	};
> 
> (3) Odd singles and doubles when FR=1, FRE=1 don't overlap at all:
> 	struct __gdb_builtin_mips_fp96 {
> 		union {
> 			double f64;
> 			int64  i64;
> 		};
> 		union {
> 			float  f32;
> 			int32  i32;
> 		};
> 	};
> 
> i.e.
> 
> FR=0:
>  (1) even
>        double:	FEDCBA9876543210
>        single:	        76543210
>  (2) odd
>        single:	FEDCBA98
> 
> FR=1, FRE=0:
>  (1) even
>        double:	FEDCBA9876543210
>        single:	        76543210
>  (1) odd
>        double:	                0123456789ABCDEF
>        single:	                        89ABCDEF
> 
> FR=1, FRE=1:
>  (1) even
>        double:	FEDCBA9876543210
>        single:	        76543210   (Hybrid FPR emulation)
>  (3) odd
>        double:	                0123456789ABCDEF
>        single:	FEDCBA98           (Hybrid FPR emulation)
> )

 I haven't got to this part so far and either way will have to think about 
it yet.  For one as I noted we do want to present vector (paired-single) 
data with FR=1, FRE=0 in addition to what you quoted above.  This was all 
implemented in an old MIPS UK patch originally written by Nigel Stephens 
and included with SDE, which I've never got to upstreaming; have you by 
any chance based your work on that?

 As to FR=1, FRE=1 your quoted representation of singles is a software 
convention only, so I'm not sure offhand how we might represent it in GDB 
to keep it reasonable; the 96-bit cooked FP register structure does not 
appeal to me at all TBH, but maybe it's the best we can do after all.

  Maciej

^ permalink raw reply	[flat|nested] 37+ messages in thread

* RE: [PATCH 02/24]     Add MIPS32 FPU64 GDB target descriptions
  2016-10-12 22:04           ` Maciej W. Rozycki
@ 2016-10-13 10:09             ` Matthew Fortune
  2016-10-21 19:17               ` Maciej W. Rozycki
  0 siblings, 1 reply; 37+ messages in thread
From: Matthew Fortune @ 2016-10-13 10:09 UTC (permalink / raw)
  To: Maciej Rozycki, James Hogan
  Cc: Bhushan Attarde, gdb-patches, Andrew Bennett, Jaydeep Patil, linux-mips

Maciej Rozycki <Maciej.Rozycki@imgtec.com> writes:
> On Wed, 12 Oct 2016, James Hogan wrote:
> 
> > >  Then I think it makes sense even more not to create this artificial
> > > API and use the CP1C.FRE/CP1C.NFRE registers instead which do
> > > correspond to what hardware presents to user software.
> >
> > well, barely. Linux at least doesn't enable Config5.UFE or
> > Config5.UFR, since FP mode changes must be done for all threads in the
> > process, so userland can't actually directly access those FCRs either.
> 
>  Hmm, I didn't know that -- what was the reason for this design
> decision?
> Offhand the limitation does not appear necessary to me, each thread has
> its own distinct register set, so it does not appear to me that its mode
> of operation has to be the same across them all.  The current setting
> would still of course be inherited from the parent by any new threads
> created with clone(2).
> 
>  Anyway in that case the presented CP1C registers will have to be read-
> only.

There is no need to support the CP1C.FRE/CP1C.NFRE CP1C.FR/CP1C.NFR
registers as they did not form part of the FR compatibility solution in the
end. They were added to the architecture as part of an earlier plan that
would have involved user-mode code switching mode on a per function basis.

They must not be enabled in Linux as use of them will lead to complete
chaos :-).

> > >  I don't think there is any value in it for GDB, I think all 64-bit
> > > FP registers ought to remain being presented as doubles and pairs of
> > > singles regardless of the mode selected (and also possibly
> > > fixed-point longs and pairs of fixed-point words).  We don't know
> > > what's emulated and what's not after all, and then the contents of
> > > FPRs are not interpreted by GDB itself anyhow except in
> > > user-supplied expressions or assignment requests, which for users'
> > > convenience I think should retain the maximum flexibility possible.
> >
> > Well it technically depends on
> > test_tsk_thread_flag(target, TIF_HYBRID_FPREGS)
> 
>  Sure, but the hardware representation is CP0.Config5.FRE/CP1C.FRE.

The FRE compatibility solution does require GDB to both know about and
modify the user-view of registers as the raw register data cannot be
interpreted by a user unassisted. My memory is a little rusty but I think
this already happens for FR=0 vs FR=1 in that GDB is provided with 32
64-bit registers and must present them as either:

FR=0
====
16 doubles by concatenating the low 32-bits of 2 consecutive registers
to form a double.
32* singles by showing the low 32-bits of each register (*odd registers
not being singles in mips V and below in FR=0.)

FR=1
====
32 doubles
32 singles
(32 128-bit)

FRE=1
=====
32 doubles
32 singles which are stored only in even numbered 64-bit registers with
the low 32-bit being an even numbered single and the high 32-bit being
an odd numbered single.
(32 128-bit)

GDB cannot show the FRE=1 state correctly without knowing which mode the
process is running in. I think this matches with comments from James
below.

> > So it allows gdb to detect Linux's Hybrid FPU mode, and present the fp
> > regs (e.g. f0 or f1) more like below to the user depending on the fp
> > mode, which is surely much more intuitive from an assembly debugging
> > point of view.
> >
> > Its also worth noting that "When software changes the value of this
> > bit [Status.FR], the contents of the floating-point registers are
> > UNPREDICTABLE". I.e. there is no architectural unifying register
> > layout between FR=0 / FR=1, only convention. Linux will I presume
> > intentionally save in old mode and restore in new mode on an fp mode
> > change according to its own convention (such that the valid mode
> > changes don't clobber register state).
> 
>  Well the contents might be unpredictable, but there sure will be some
> and GDB is supposed to present it.

The scheme we have guarantees that no FPU mode switch ever leaves the
register state in an unknown state which is another reason why users
cannot change mode directly. The kernel always performs the mode switch
and this happens with the FPU state in soft-context which is then
restored after the mode switch occurs.

> > (disclaimer: I haven't looked at this gdb patchset in detail as to
> > whether any of below has changed since I worked on it).
> >
> > (1) Even singles and doubles always overlap one another, as do odd
> > singles and doubles when FR=1 (and FRE=0):
> > 	/* (little endian) */
> > 	union __gdb_builtin_mips_fp64 {
> > 	  float  f32;
> > 	  double f64;
> > 	  int32  i32;
> > 	  int64  i64;
> > 	};
> >
> > (2) Odd singles when FR=0 (there are no odd doubles):
> > 	union __gdb_builtin_mips_fp32 {
> > 	  float f32;
> > 	  int32_t i32;
> > 	};
> >
> > (3) Odd singles and doubles when FR=1, FRE=1 don't overlap at all:
> > 	struct __gdb_builtin_mips_fp96 {
> > 		union {
> > 			double f64;
> > 			int64  i64;
> > 		};
> > 		union {
> > 			float  f32;
> > 			int32  i32;
> > 		};
> > 	};
> >
> > i.e.
> >
> > FR=0:
> >  (1) even
> >        double:	FEDCBA9876543210
> >        single:	        76543210
> >  (2) odd
> >        single:	FEDCBA98
> >
> > FR=1, FRE=0:
> >  (1) even
> >        double:	FEDCBA9876543210
> >        single:	        76543210
> >  (1) odd
> >        double:	                0123456789ABCDEF
> >        single:	                        89ABCDEF
> >
> > FR=1, FRE=1:
> >  (1) even
> >        double:	FEDCBA9876543210
> >        single:	        76543210   (Hybrid FPR emulation)
> >  (3) odd
> >        double:	                0123456789ABCDEF
> >        single:	FEDCBA98           (Hybrid FPR emulation)
> > )
> 
>  I haven't got to this part so far and either way will have to think
> about it yet.  For one as I noted we do want to present vector (paired-
> single) data with FR=1, FRE=0 in addition to what you quoted above.
> This was all implemented in an old MIPS UK patch originally written by
> Nigel Stephens and included with SDE, which I've never got to
> upstreaming; have you by any chance based your work on that?
> 
>  As to FR=1, FRE=1 your quoted representation of singles is a software
> convention only, so I'm not sure offhand how we might represent it in
> GDB to keep it reasonable; the 96-bit cooked FP register structure does
> not appeal to me at all TBH, but maybe it's the best we can do after
> all.

The whole FR compatibility scheme has some extremely intricate design
especially when it comes to FRE mode and I believe all tools have to play
along in order to get the end result to be seamless for users. If we
can do any simplification of GDB or the kernel interface then I'm open
to ideas.

A reference to the spec in case anyone doesn't know where it is:

https://dmz-portal.ba.imgtec.org/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking

Note that the spec does not include a definition of the ptrace extension
nor core dump extension (possibly not even designed yet).

While I remember the GDB patchset does need at least checking if not
extra work to cope with the way double precision type data is described
in dwarf for the various compile modes.

Matthew

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 01/24]     MIPS: Handle run-time reconfigurable FPR size
  2016-07-25 14:03 ` [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size Maciej W. Rozycki
@ 2016-10-18 17:37   ` Maciej W. Rozycki
  0 siblings, 0 replies; 37+ messages in thread
From: Maciej W. Rozycki @ 2016-10-18 17:37 UTC (permalink / raw)
  To: Bhushan Attarde
  Cc: gdb-patches, Matthew Fortune, James Hogan, Andrew Bennett, Jaydeep.Patil

Bhushan,

On Mon, 25 Jul 2016, Maciej W. Rozycki wrote:

> > @@ -8869,7 +8949,7 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
> >    mips_register_g_packet_guesses (gdbarch);
> >  
> >    /* Hook in OS ABI-specific overrides, if they have been registered.  */
> > -  info.tdep_info = tdesc_data;
> > +  ((struct gdbarch_tdep_info*)(info.tdep_info))->tdesc_data = tdesc_data;
> 
>  Missing space after the cast again, but why don't you need the same cast 
> to access `info.tdep_info->fp_register_size' above?  Have you verified 
> this change actually builds?
> 
>  Overall again I think it'll be best refactored to avoid these casts, e.g. 
> rename the existing null `tdep_info' to `null_tdep_info', and then add a 
> new `tdep_info' variable to keep a correctly typed pointer and use it 
> throughout.

 So to address my own concerns I have now proposed `struct gdbarch_info' 
restructuring, so that none of the casts are actually needed, and neither 
are auxiliary variables.  I forgot to cc you on that submission (sorry!); 
see here: <https://sourceware.org/ml/gdb-patches/2016-10/msg00516.html>. 

 With that in place and once you've resolved the obvious merge conflict 
you can use the following update to the original "MIPS: Handle run-time 
reconfigurable FPR size" change, which is what I've been using.  This also 
addresses my other concerns I have expressed in the review.

  Maciej

Index: binutils/gdb/mips-linux-tdep.c
===================================================================
--- binutils.orig/gdb/mips-linux-tdep.c	2016-10-18 07:51:21.000000000 +0100
+++ binutils/gdb/mips-linux-tdep.c	2016-10-18 07:55:18.734641371 +0100
@@ -1646,7 +1646,6 @@ mips_linux_init_abi (struct gdbarch_info
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   enum mips_abi abi = mips_abi (gdbarch);
-  struct tdesc_arch_data *tdesc_data = info.tdesc_data;
 
   linux_init_abi (info, gdbarch);
 
@@ -1738,7 +1737,7 @@ mips_linux_init_abi (struct gdbarch_info
   tdep->syscall_next_pc = mips_linux_syscall_next_pc;
   tdep->fp_register_size_fixed_p = 1;
 
-  if (((struct gdbarch_tdep_info*)(info.tdep_info))->tdesc_data)
+  if (info.tdep_info->tdesc_data)
     {
       const struct tdesc_feature *feature;
 
@@ -1753,7 +1752,7 @@ mips_linux_init_abi (struct gdbarch_info
       feature = tdesc_find_feature (info.target_desc,
 				    "org.gnu.gdb.mips.linux");
       if (feature != NULL)
-	tdesc_numbered_register (feature, (((struct gdbarch_tdep_info*)(info.tdep_info))->tdesc_data),
+	tdesc_numbered_register (feature, info.tdep_info->tdesc_data,
 				 MIPS_RESTART_REGNUM, "restart");
     }
 }
Index: binutils/gdb/mips-tdep.c
===================================================================
--- binutils.orig/gdb/mips-tdep.c	2016-10-18 07:51:21.000000000 +0100
+++ binutils/gdb/mips-tdep.c	2016-10-18 17:33:42.662895228 +0100
@@ -6233,7 +6233,7 @@ mips_read_fp_register_single (struct fra
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
   int fpsize = register_size (gdbarch, regno);
-  gdb_byte *raw_buffer = alloca (fpsize);
+  gdb_byte *raw_buffer = (gdb_byte *) alloca (fpsize);
 
   if (!deprecated_frame_register_read (frame, regno, raw_buffer))
     error (_("can't read register %d (%s)"),
@@ -6306,12 +6306,10 @@ mips_print_fp_register (struct ui_file *
 {				/* Do values for FP (float) regs.  */
   struct gdbarch *gdbarch = get_frame_arch (frame);
   int fpsize = register_size (gdbarch, regnum);
-  gdb_byte *raw_buffer;
+  gdb_byte *raw_buffer = (gdb_byte *) alloca (2 * fpsize);
   double doub, flt1;	/* Doubles extracted from raw hex data.  */
   int inv1, inv2;
 
-  raw_buffer = alloca (2 * fpsize);
-
   fprintf_filtered (file, "%s:", gdbarch_register_name (gdbarch, regnum));
   fprintf_filtered (file, "%*s",
 		    4 - (int) strlen (gdbarch_register_name (gdbarch, regnum)),
@@ -6462,7 +6460,7 @@ mips_print_float_info (struct gdbarch *g
     return;
 
   fprintf_filtered (file, "reg size: %d bits\n",
-		    register_size (gdbarch, mips_regnum (gdbarch)->fp0) * 8);
+		    mips_float_regsize (gdbarch) * 8);
 
   fputs_filtered ("cond    :", file);
   if (fcs & (1 << 23))
@@ -8930,7 +8928,7 @@ mips_gdbarch_init (struct gdbarch_info i
   mips_register_g_packet_guesses (gdbarch);
 
   /* Hook in OS ABI-specific overrides, if they have been registered.  */
-  ((struct gdbarch_tdep_info*)(info.tdep_info))->tdesc_data = tdesc_data;
+  info.tdep_info->tdesc_data = tdesc_data;
   gdbarch_init_osabi (info, gdbarch);
 
   /* The hook may have adjusted num_regs, fetch the final value and

^ permalink raw reply	[flat|nested] 37+ messages in thread

* RE: [PATCH 02/24]     Add MIPS32 FPU64 GDB target descriptions
  2016-10-13 10:09             ` Matthew Fortune
@ 2016-10-21 19:17               ` Maciej W. Rozycki
  2016-10-21 19:24                 ` Maciej W. Rozycki
  0 siblings, 1 reply; 37+ messages in thread
From: Maciej W. Rozycki @ 2016-10-21 19:17 UTC (permalink / raw)
  To: Matthew Fortune
  Cc: James Hogan, Bhushan Attarde, gdb-patches, Andrew Bennett,
	Jaydeep Patil, linux-mips

On Thu, 13 Oct 2016, Matthew Fortune wrote:

> >  Hmm, I didn't know that -- what was the reason for this design
> > decision?
> > Offhand the limitation does not appear necessary to me, each thread has
> > its own distinct register set, so it does not appear to me that its mode
> > of operation has to be the same across them all.  The current setting
> > would still of course be inherited from the parent by any new threads
> > created with clone(2).
> > 
> >  Anyway in that case the presented CP1C registers will have to be read-
> > only.
> 
> There is no need to support the CP1C.FRE/CP1C.NFRE CP1C.FR/CP1C.NFR
> registers as they did not form part of the FR compatibility solution in the
> end. They were added to the architecture as part of an earlier plan that
> would have involved user-mode code switching mode on a per function basis.

 I wonder in that case whether we shouldn't simply have a virtual $fre 
register represented.  It could be 1-bit, but I suspect this may not play 
well with the RSP, so we can make it wider at the raw level and only 
truncate it at the cooked level, just as we do with some other registers 
including in particular my recent $fcsr/$fir change.

 If we had such a dedicated virtual $fre, and we decided sometime to let 
the user actually write to it and switch the mode process-wide, then we 
could simply invoke the right prctl(2) call in response to the user's 
ptrace(2) request.

 NB the x86-64 target has such support with PTRACE_ARCH_PRCTL already and 
PTRACE_POKEUSR writes to $fs/$gs also invoke prctl(2).  So perhaps we just 
ought to go ahead and do the same.

> They must not be enabled in Linux as use of them will lead to complete
> chaos :-).

 Hmm, that's a bit too vague for me I am afraid to accept as an argument 
in a technical discussion, but James's note about mode switches needed 
process-wide at DSO load time has convinced me, so unless you want 
something to add beyond that, feel free not to expand here.

> > > Well it technically depends on
> > > test_tsk_thread_flag(target, TIF_HYBRID_FPREGS)
> > 
> >  Sure, but the hardware representation is CP0.Config5.FRE/CP1C.FRE.
> 
> The FRE compatibility solution does require GDB to both know about and
> modify the user-view of registers as the raw register data cannot be
> interpreted by a user unassisted. My memory is a little rusty but I think
> this already happens for FR=0 vs FR=1 in that GDB is provided with 32
> 64-bit registers and must present them as either:

 The change between FR=0 and FR=1 is different as there the raw register 
format changes (and consequently the cooked as well).  Whereas for FRE=0 
vs FRE=1 only the cooked format changes.  Strictly speaking we could 
ignore cooked format changes and only pass through the raw register 
contents, however I agree in that providing the user with the available 
numeric formats the contents of an FPR or an FPR pair can be interpreted 
as is appropriate.

> FR=0
> ====
> 16 doubles by concatenating the low 32-bits of 2 consecutive registers
> to form a double.
> 32* singles by showing the low 32-bits of each register (*odd registers
> not being singles in mips V and below in FR=0.)
> 
> FR=1
> ====
> 32 doubles
> 32 singles
> (32 128-bit)
> 
> FRE=1
> =====
> 32 doubles
> 32 singles which are stored only in even numbered 64-bit registers with
> the low 32-bit being an even numbered single and the high 32-bit being
> an odd numbered single.
> (32 128-bit)
> 
> GDB cannot show the FRE=1 state correctly without knowing which mode the
> process is running in. I think this matches with comments from James
> below.

 Fair enough although arguably the native and FRE=1 states could be 
presented both at a time for the user to pick whichever he founds more 
convenient.  For example we present FR=0 singles for both even and odd FPR 
indices even on hardware which does not support single arithmetics on FPRs 
at odd indices, i.e. all legacy ISAs, up to MIPS IV inclusive.

> >  Well the contents might be unpredictable, but there sure will be some
> > and GDB is supposed to present it.
> 
> The scheme we have guarantees that no FPU mode switch ever leaves the
> register state in an unknown state which is another reason why users
> cannot change mode directly. The kernel always performs the mode switch
> and this happens with the FPU state in soft-context which is then
> restored after the mode switch occurs.

 Noted, though GDB does not actually care -- it serves as a pass-through 
really, or at least that's the intent.

> >  I haven't got to this part so far and either way will have to think
> > about it yet.  For one as I noted we do want to present vector (paired-
> > single) data with FR=1, FRE=0 in addition to what you quoted above.
> > This was all implemented in an old MIPS UK patch originally written by
> > Nigel Stephens and included with SDE, which I've never got to
> > upstreaming; have you by any chance based your work on that?
> > 
> >  As to FR=1, FRE=1 your quoted representation of singles is a software
> > convention only, so I'm not sure offhand how we might represent it in
> > GDB to keep it reasonable; the 96-bit cooked FP register structure does
> > not appeal to me at all TBH, but maybe it's the best we can do after
> > all.
> 
> The whole FR compatibility scheme has some extremely intricate design
> especially when it comes to FRE mode and I believe all tools have to play
> along in order to get the end result to be seamless for users. If we
> can do any simplification of GDB or the kernel interface then I'm open
> to ideas.

 I'll give it some thought yet and encourage everyone interested to do so 
as well.

> A reference to the spec in case anyone doesn't know where it is:
> 
> https://dmz-portal.ba.imgtec.org/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking
> 
> Note that the spec does not include a definition of the ptrace extension
> nor core dump extension (possibly not even designed yet).

 Thanks for the clarification.

> While I remember the GDB patchset does need at least checking if not
> extra work to cope with the way double precision type data is described
> in dwarf for the various compile modes.

 Noted, though with the cooked register view as outlined above it looks 
to me like register references are supposed to match with no extra effort.

 I'll see if it's worthwhile to push the original MIPS UK work first 
though.  It's been in use for over 10 years now, with our own SDE and then 
CodeSourcery toolchains, although regrettably serving non-XML-described 
targets only:

(gdb) show mips abi
The MIPS ABI is set automatically (currently "n64").
(gdb) show endian
The target endianness is set automatically (currently big endian)
(gdb) ptype $f0
type = union __gdb_builtin_type_mips_double_float_reg {
    double d;
    int64_t l;
    float s __attribute__ ((vector_size(2)));
    int32_t w __attribute__ ((vector_size(2)));
}
(gdb) info registers $f0
f0:  0xffffffffffffffff flt: -nan              dbl: -nan
(gdb) print $f0
$2 = {d = -nan(0xfffffffffffff), l = -1, s = {-nan(0x7fffff), -nan(0x7fffff)},
  w = {-1, -1}}
(gdb) set $f0.s[1] = -1
(gdb) info registers $f0
f0:  0xffffffffbf800000 flt: -1                dbl: -nan
(gdb) print $f0
$5 = {d = -nan(0xfffffbf800000), l = -1082130432, s = {-nan(0x7fffff), -1},
  w = {-1, -1082130432}}
(gdb) 

 Questions or comments?

  Maciej

^ permalink raw reply	[flat|nested] 37+ messages in thread

* RE: [PATCH 02/24]     Add MIPS32 FPU64 GDB target descriptions
  2016-10-21 19:17               ` Maciej W. Rozycki
@ 2016-10-21 19:24                 ` Maciej W. Rozycki
  0 siblings, 0 replies; 37+ messages in thread
From: Maciej W. Rozycki @ 2016-10-21 19:24 UTC (permalink / raw)
  To: Matthew Fortune
  Cc: James Hogan, Bhushan Attarde, gdb-patches, Andrew Bennett,
	Jaydeep Patil, linux-mips

On Fri, 21 Oct 2016, Maciej W. Rozycki wrote:

>  If we had such a dedicated virtual $fre, and we decided sometime to let 
> the user actually write to it and switch the mode process-wide, then we 
> could simply invoke the right prctl(2) call in response to the user's 
> ptrace(2) request.

 Or we could call it $fp_mode and map it directly to prctl(PR_GET_FP_MODE) 
and prctl(PR_SET_FP_MODE, ...).

  Maciej

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 03/24]     regcache: handle invalidated regcache
  2016-06-27 14:50 ` [PATCH 03/24] regcache: handle invalidated regcache Bhushan Attarde
@ 2016-10-21 22:42   ` Maciej W. Rozycki
  0 siblings, 0 replies; 37+ messages in thread
From: Maciej W. Rozycki @ 2016-10-21 22:42 UTC (permalink / raw)
  To: Bhushan Attarde
  Cc: gdb-patches, Matthew.Fortune, James.Hogan, Andrew.Bennett, Jaydeep.Patil

On Mon, 27 Jun 2016, Bhushan Attarde wrote:

>     When registers are marked as change, set a new regcache_invalidated
>     variable which is used by get_thread_regcache to decide whether to
>     recreate the gdbarch.

 Can you please be a bit more specific as to why this change is needed?

> 	gdb/ChangeLog:
> 		* regcache.c (regcache_invalidated): New variable.
> 		(set_current_thread_ptid_arch): Use regcache_invalidated to
> 		set registers_changed_p.
> 		(get_thread_regcache): Reset regcache_invalidated to 0.
> 		(registers_changed_ptid): Set regcache_invalidated to 1.

 Single-tab indentation please.

 But overall it looks like a bug fix to me, applying to 01/24 and 
addressing the assumption made there that there is only a single thread 
being debugged.  Which may have been OK for the majority of bare-metal 
cases, but certainly not for OS debugging.  So please fold this change 
into 01/24.

 But I have a concern about the implementation too.

> diff --git a/gdb/regcache.c b/gdb/regcache.c
> index c3405b6..3cbec6e 100644
> --- a/gdb/regcache.c
> +++ b/gdb/regcache.c
> @@ -489,6 +489,7 @@ struct regcache_list
>  };
>  
>  static struct regcache_list *current_regcache;
> +static int regcache_invalidated = 1;
>  
>  struct regcache *
>  get_thread_arch_aspace_regcache (ptid_t ptid, struct gdbarch *gdbarch,
> @@ -547,7 +548,7 @@ set_current_thread_ptid_arch (ptid_t ptid)
>  struct regcache *
>  get_thread_regcache (ptid_t ptid)
>  {
> -  int registers_changed_p = current_regcache == NULL;
> +  int registers_changed_p = current_regcache == NULL || regcache_invalidated;
>    struct regcache *new_regcache;
>  
>    set_current_thread_ptid_arch (ptid);
> @@ -560,6 +561,7 @@ get_thread_regcache (ptid_t ptid)
>        registers_changed ();
>        set_current_thread_ptid_arch (ptid);
>        new_regcache = get_thread_arch_regcache (ptid, current_thread_arch);
> +      regcache_invalidated = 0;
>      }
>  
>    return new_regcache;
> @@ -646,6 +648,7 @@ registers_changed_ptid (ptid_t ptid)
>  	 forget about any frames we have cached, too.  */
>        reinit_frame_cache ();
>      }
> +  regcache_invalidated = 1;
>  }

 This uses a global `regcache_invalidated' flag for what looks to me like 
a thread-specific case, i.e. you really want to set `registers_changed_p' 
above only if `ptid' thread's registers have changed.  Or in other words 
if the old regcache was gone and a new one has been allocated for `ptid' 
requested.  Yes, with the MIPS FPU topology changes in particular this may 
not matter much, but let's get this piece right for the general case, like 
multiprocess scenarios perhaps.

 So it looks to me like a better approach will be to either scan the 
regcache list from `current_regcache' to see if there's a match for `ptid' 
or to make `get_thread_arch_regcache' return additional status of the scan 
it already does.  I have no clear preference between these two choices, so 
please pick up whichever you like better or maybe a general maintainer can 
speak out.

  Maciej

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size
  2016-06-27 14:50 [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size Bhushan Attarde
                   ` (20 preceding siblings ...)
  2016-07-25 14:03 ` [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size Maciej W. Rozycki
@ 2016-11-08 19:46 ` Yao Qi
  2016-11-10 12:43   ` Maciej W. Rozycki
  21 siblings, 1 reply; 37+ messages in thread
From: Yao Qi @ 2016-11-08 19:46 UTC (permalink / raw)
  To: Bhushan Attarde
  Cc: gdb-patches, Maciej.Rozycki, Matthew.Fortune, James.Hogan,
	Andrew.Bennett, Jaydeep.Patil

Hi Bhushan,

On Mon, Jun 27, 2016 at 3:49 PM, Bhushan Attarde
<bhushan.attarde@imgtec.com> wrote:
>     Many MIPS architecture processors can reconfigure the size of their
>     floating-point registers at the run time.  The file comprising 32
>     registers can be either 32-bit or 64-bit wide depending on whether CP0
>     Status register's bit FR is zero or one, respectively.  Fortunately access
>     to Status is available on all targets.
>
>     Here's a change to handle this property.  It requires the generic register
>     access code to raise the target backend's attention whenever a new
>     register set has been retrieved so that it can examine the state of
>     CP0.Status.FR and act accordingly.  I have added this hook to
>     get_thread_regcache, the backend has then an opportunity to switch gdbarch
>     as necessary and let the caller know if it did so.  If that indeed
>     happened, then the register cache originally retrieved is then discarded
>     and another one obtained using the newly-selected gdbarch.  This new
>     register cache is not revalidated.
>
>

>     This is implemented by retaining the raw register size for the FPRs at its
>     native size (64-bits; this is required for remote packet offsets to work
>     out correctly) and then truncating the cooked register size or not as
>     required.  I have skipped `maintenance print registers' dumps here for
>     brevity, the types flip between "double" and "float" as expected.
>

If I understand you correctly, 64-bits are still transferred in remote protocol
if FPRs are 32-bit.

>      This change supports bare-iron, Linux and IRIX targets.  For Linux and
>     IRIX the width of the floating-point registers is set by the ABI of the
>     program being run by the OS kernel and the kernel is responsible for
>     setting CP0.Status.FR correctly; the image of Status accessible via
>     ptrace(2) is read-only.  Therefore the respective backends mark the width
>     as fixed and cause the run-time check to be skipped for efficiency.  I
>     have verified that the Linux target does that correctly; the change for
>     IRIX is the same and is expected to be all right, but I have no access to
>     such a system (I will appreciate anyone verifying that).
>
>      The change currently supports 64-bit processors only as GDB has no way to
>     access upper halves of floating-point registers on 32-bit processors that
>     have a 64-bit FPU (i.e. MIPS32r2 and newer processors); this is mentioned
>     in the explanatory notes included with the change itself.
>
>      The change also supports both XML and non-XML targets, but currently
>     bare-iron targets for which this update has any significant meaning do not
>     really support XML.  Any XML target is supposed to always provide an FPU
>     description that matches the current setting of CP0.Status.FR, the new
>     code verifies this is always the case and rejects the description as
>     invalid otherwise.

How do I understand "Any XML target is supposed to always provide
an FPU description that matches the current setting of CP0.Status.FR"?
I don't see how it is done in current GDB/GDBserver.

"reconfigure FPRs" is a target description change to me, instead of a
regcache change.  I'd like GDB can deal with "target description of
process is changed in runtime" in general, because this requirement
exists in other places as well,

 - x86 kernel booting, the arch is 16-bit at the beginning, and switch to
   32-bit or 64-bit later,
   https://sourceware.org/ml/gdb/2016-11/msg00003.html
 - ARM SVE vector registers length can be changed,

There are two different ways to support handling target description
change in general.  Other thoughts are welcome too.

1)
 - Implement target hook to_thread_architecture in ARCH-linux-nat.c,
   in which we can use ptrace to read the register A which indicates
   the target description is changed or not.  In MIPS, register A is
   CP0.Status.  Create target info and return the right gdbarch.
   [In MIPS, we have one gdbarch for 32-bit FPR and one gdbarch for
   64-bit FPR]
 - Add register A to expedited registers, which is included in the stop
   reply from GDBserver.
 - Add new gdbarch method target_description_changed_p, and its
   parameter is a vector of expedited registers got in
   remote.c:process_stop_reply.  In default, it returns false.  In
   MIPS, we can tell whether target description is changed by the
   value of  and current gdbarch.
 - In remote.c:process_stop_reply, if
   gdbarch_target_description_changed_p returns true, invalidate all
   regcaches, request target description from gdbserver again, and get
   the updated target description.

2)
 - Add enum TARGET_WAITKIND_ARCH_CHANGED,
 - In ARCH-linux-nat.c, interpret/override linux_nat_wait.  If
   linux_nat_wait returns, and there is a real event of stop, call
   ptrace to get the register A value, if it is different from what we
   remember in current gdbarch, mark the event pending and return
   TARGET_WAITKIND_ARCH_CHANGED,
 - In remote, add a new stop reply, T00arch, for example,
   https://sourceware.org/gdb/onlinedocs/gdb/Stop-Reply-Packets.html
   If remote.c:process_stop_reply sees T00arch, return
   TARGET_WAITKIND_ARCH_CHANGED.
 - In gdb core, if TARGET_WAITKIND_ARCH_CHANGED is reported by
   target_wait, call target_find_description, to update target
   description.
 - In gdbserver, add target method target_stopped_by_changed_arch,
   and use it in remote-utils.c:prepare_resume_reply.  Get register A
   value by ptrace too, and return true if it is different from the
   knowledge in process_info.tdesc.

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size
  2016-11-08 19:46 ` Yao Qi
@ 2016-11-10 12:43   ` Maciej W. Rozycki
  2016-11-11 12:29     ` Yao Qi
  0 siblings, 1 reply; 37+ messages in thread
From: Maciej W. Rozycki @ 2016-11-10 12:43 UTC (permalink / raw)
  To: Yao Qi
  Cc: Bhushan Attarde, gdb-patches, Matthew Fortune, James Hogan,
	Andrew Bennett, Jaydeep Patil

Yao,

 I'll chime in in Bhushan's stead a bit as I've beaten the oddities of the 
MIPS FPU to death throughout my dealings with the architecture (Bhushan, 
you're of course welcome to reply too if you have anything to add).

On Tue, 8 Nov 2016, Yao Qi wrote:

> >     This is implemented by retaining the raw register size for the FPRs at its
> >     native size (64-bits; this is required for remote packet offsets to work
> >     out correctly) and then truncating the cooked register size or not as
> >     required.  I have skipped `maintenance print registers' dumps here for
> >     brevity, the types flip between "double" and "float" as expected.
> >
> 
> If I understand you correctly, 64-bits are still transferred in remote protocol
> if FPRs are 32-bit.

 Nope.  In the FR=0 mode existing XML-described stubs present a file of 32 
32-bit FPRs; this applies to MIPS32 targets only as so far we've had an 
assumption that MIPS32 <=> FR=0 and MIPS64 <=> FR=1.  I think switching 
the view at this time would be an undesireable complication, as it would 
be yet another variant we'd have to handle forever along with the new one.

 FWIW I think the FR=0 mode should have been chosen to present the FPR 
file as 16 64-bit FPRs instead, with the cooked register view used to 
access register halves if required, but then I think a further 
complication would arise with non-XML-described stubs.

> >      The change also supports both XML and non-XML targets, but currently
> >     bare-iron targets for which this update has any significant meaning do not
> >     really support XML.  Any XML target is supposed to always provide an FPU
> >     description that matches the current setting of CP0.Status.FR, the new
> >     code verifies this is always the case and rejects the description as
> >     invalid otherwise.
> 
> How do I understand "Any XML target is supposed to always provide
> an FPU description that matches the current setting of CP0.Status.FR"?
> I don't see how it is done in current GDB/GDBserver.

 I do hope the last patch which adds `gdbserver' features en masse, which 
I didn't get to to looking through yet, has it (although I think the 
individual features should be included along with corresponding base 
target and native support instead).

> "reconfigure FPRs" is a target description change to me, instead of a
> regcache change.

 The regcache change is partly historic, because parts of the series 
(dating back to 2005) were implemented even before we had XML 
descriptions, and an FR transition is also supposed to work with 
non-XML-described MIPS64 bare-metal targets (where the FPR file is 
presented as 32 64-bit FPRs regardless of the FR setting).  I do agree a 
target description should take precedence where available, and certainly 
with Linux targets where you cannot get a MIPS64 FR=0 configuration or a 
non-XML-described MIPS32 FR=1 configuration).

 What do you propose if we don't have a target description though?  We 
can't handle MIPS32 FR=1, because stubs won't transfer the upper halves of 
FPRs, but we can handle MIPS64 FR=0, because we can simply ignore the 
irrelevant upper halves.

> There are two different ways to support handling target description
> change in general.  Other thoughts are welcome too.
> 
> 1)
>  - Implement target hook to_thread_architecture in ARCH-linux-nat.c,
>    in which we can use ptrace to read the register A which indicates
>    the target description is changed or not.  In MIPS, register A is
>    CP0.Status.  Create target info and return the right gdbarch.
>    [In MIPS, we have one gdbarch for 32-bit FPR and one gdbarch for
>    64-bit FPR]
>  - Add register A to expedited registers, which is included in the stop
>    reply from GDBserver.

 I think I'd prefer this to be the $fp_mode register if available (as 
it'll include the FRE setting as well), and the $status register 
otherwise.  Linux kernels which support the FRE setting will always make 
$fp_mode available, as it'll be a part of the same change (unless someone 
sneaks a broken patch through behind my back, as I still yet have to see 
the kernel parts of this framework, let alone review them).

>  - Add new gdbarch method target_description_changed_p, and its
>    parameter is a vector of expedited registers got in
>    remote.c:process_stop_reply.  In default, it returns false.  In
>    MIPS, we can tell whether target description is changed by the
>    value of  and current gdbarch.
>  - In remote.c:process_stop_reply, if
>    gdbarch_target_description_changed_p returns true, invalidate all
>    regcaches, request target description from gdbserver again, and get
>    the updated target description.
> 
> 2)
>  - Add enum TARGET_WAITKIND_ARCH_CHANGED,
>  - In ARCH-linux-nat.c, interpret/override linux_nat_wait.  If
>    linux_nat_wait returns, and there is a real event of stop, call
>    ptrace to get the register A value, if it is different from what we
>    remember in current gdbarch, mark the event pending and return
>    TARGET_WAITKIND_ARCH_CHANGED,
>  - In remote, add a new stop reply, T00arch, for example,
>    https://sourceware.org/gdb/onlinedocs/gdb/Stop-Reply-Packets.html
>    If remote.c:process_stop_reply sees T00arch, return
>    TARGET_WAITKIND_ARCH_CHANGED.
>  - In gdb core, if TARGET_WAITKIND_ARCH_CHANGED is reported by
>    target_wait, call target_find_description, to update target
>    description.
>  - In gdbserver, add target method target_stopped_by_changed_arch,
>    and use it in remote-utils.c:prepare_resume_reply.  Get register A
>    value by ptrace too, and return true if it is different from the
>    knowledge in process_info.tdesc.

 The rest looks like a good plan to me, although I think I like your #1 
proposal a bit better.

  Maciej

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size
  2016-11-10 12:43   ` Maciej W. Rozycki
@ 2016-11-11 12:29     ` Yao Qi
  2016-12-02  2:31       ` Maciej W. Rozycki
  0 siblings, 1 reply; 37+ messages in thread
From: Yao Qi @ 2016-11-11 12:29 UTC (permalink / raw)
  To: Maciej W. Rozycki
  Cc: Bhushan Attarde, gdb-patches, Matthew Fortune, James Hogan,
	Andrew Bennett, Jaydeep Patil

On Thu, Nov 10, 2016 at 12:42:53PM +0000, Maciej W. Rozycki wrote:
> 
> > >     This is implemented by retaining the raw register size for the FPRs at its
> > >     native size (64-bits; this is required for remote packet offsets to work
> > >     out correctly) and then truncating the cooked register size or not as
> > >     required.  I have skipped `maintenance print registers' dumps here for
> > >     brevity, the types flip between "double" and "float" as expected.
> > >
> > 
> > If I understand you correctly, 64-bits are still transferred in remote protocol
> > if FPRs are 32-bit.
> 
>  Nope.  In the FR=0 mode existing XML-described stubs present a file of 32 
> 32-bit FPRs; this applies to MIPS32 targets only as so far we've had an 
> assumption that MIPS32 <=> FR=0 and MIPS64 <=> FR=1.  I think switching 
> the view at this time would be an undesireable complication, as it would 
> be yet another variant we'd have to handle forever along with the new one.

Yeah, there are different variants.  Let me be specific, with this patch
applied, on MIPS64, FR=0, how many bits needed for each FPR in 'g' packet?
I ask this question for this sentence "This is implemented by retaining the
raw register size for the FPRs at its native size (64-bits; this is required for
remote packet offsets to work out correctly) and then truncating the cooked
register size or not as required." in Bhushan's mail.
IIUC, with this patch applied, on MIPS64, FR=0, FPR is 32-bit, but 64-bit
space is used in 'g' packet.  No?

> 
>  FWIW I think the FR=0 mode should have been chosen to present the FPR 
> file as 16 64-bit FPRs instead, with the cooked register view used to 
> access register halves if required, but then I think a further 
> complication would arise with non-XML-described stubs.
> 
> > >      The change also supports both XML and non-XML targets, but currently
> > >     bare-iron targets for which this update has any significant meaning do not
> > >     really support XML.  Any XML target is supposed to always provide an FPU
> > >     description that matches the current setting of CP0.Status.FR, the new
> > >     code verifies this is always the case and rejects the description as
> > >     invalid otherwise.
> > 
> > How do I understand "Any XML target is supposed to always provide
> > an FPU description that matches the current setting of CP0.Status.FR"?
> > I don't see how it is done in current GDB/GDBserver.
> 
>  I do hope the last patch which adds `gdbserver' features en masse, which 
> I didn't get to to looking through yet, has it (although I think the 
> individual features should be included along with corresponding base 
> target and native support instead).

Oh, it must be this patch
https://sourceware.org/ml/gdb-patches/2016-06/msg00511.html

> 
> > "reconfigure FPRs" is a target description change to me, instead of a
> > regcache change.
> 
>  The regcache change is partly historic, because parts of the series 
> (dating back to 2005) were implemented even before we had XML 
> descriptions, and an FR transition is also supposed to work with 
> non-XML-described MIPS64 bare-metal targets (where the FPR file is 
> presented as 32 64-bit FPRs regardless of the FR setting).  I do agree a 
> target description should take precedence where available, and certainly 
> with Linux targets where you cannot get a MIPS64 FR=0 configuration or a 
> non-XML-described MIPS32 FR=1 configuration).
> 
>  What do you propose if we don't have a target description though?  We 
> can't handle MIPS32 FR=1, because stubs won't transfer the upper halves of 
> FPRs, but we can handle MIPS64 FR=0, because we can simply ignore the 
> irrelevant upper halves.

Why stubs doesn't transfer the upper bits of PFRs in case of MIPS32 FR=1?
because of keeping backward compatibility?  Does
register_remote_g_packet_guess help?

> 
> > There are two different ways to support handling target description
> > change in general.  Other thoughts are welcome too.
> > 
> > 1)
> >  - Implement target hook to_thread_architecture in ARCH-linux-nat.c,
> >    in which we can use ptrace to read the register A which indicates
> >    the target description is changed or not.  In MIPS, register A is
> >    CP0.Status.  Create target info and return the right gdbarch.
> >    [In MIPS, we have one gdbarch for 32-bit FPR and one gdbarch for
> >    64-bit FPR]
> >  - Add register A to expedited registers, which is included in the stop
> >    reply from GDBserver.
> 
>  I think I'd prefer this to be the $fp_mode register if available (as 
> it'll include the FRE setting as well), and the $status register 
> otherwise.  Linux kernels which support the FRE setting will always make 
> $fp_mode available, as it'll be a part of the same change (unless someone 
> sneaks a broken patch through behind my back, as I still yet have to see 
> the kernel parts of this framework, let alone review them).

If we have $fp_mode, that is better.

> 
>  The rest looks like a good plan to me, although I think I like your #1 
> proposal a bit better.
> 

Thanks for your feedback, Maciej.  I personally like #1 better too :)

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size
  2016-11-11 12:29     ` Yao Qi
@ 2016-12-02  2:31       ` Maciej W. Rozycki
  0 siblings, 0 replies; 37+ messages in thread
From: Maciej W. Rozycki @ 2016-12-02  2:31 UTC (permalink / raw)
  To: Yao Qi
  Cc: Bhushan Attarde, gdb-patches, Matthew Fortune, James Hogan,
	Andrew Bennett, Jaydeep Patil

On Fri, 11 Nov 2016, Yao Qi wrote:

> > > >     This is implemented by retaining the raw register size for the FPRs at its
> > > >     native size (64-bits; this is required for remote packet offsets to work
> > > >     out correctly) and then truncating the cooked register size or not as
> > > >     required.  I have skipped `maintenance print registers' dumps here for
> > > >     brevity, the types flip between "double" and "float" as expected.
> > > >
> > > 
> > > If I understand you correctly, 64-bits are still transferred in remote protocol
> > > if FPRs are 32-bit.
> > 
> >  Nope.  In the FR=0 mode existing XML-described stubs present a file of 32 
> > 32-bit FPRs; this applies to MIPS32 targets only as so far we've had an 
> > assumption that MIPS32 <=> FR=0 and MIPS64 <=> FR=1.  I think switching 
> > the view at this time would be an undesireable complication, as it would 
> > be yet another variant we'd have to handle forever along with the new one.
> 
> Yeah, there are different variants.  Let me be specific, with this patch
> applied, on MIPS64, FR=0, how many bits needed for each FPR in 'g' packet?
> I ask this question for this sentence "This is implemented by retaining the
> raw register size for the FPRs at its native size (64-bits; this is required for
> remote packet offsets to work out correctly) and then truncating the cooked
> register size or not as required." in Bhushan's mail.
> IIUC, with this patch applied, on MIPS64, FR=0, FPR is 32-bit, but 64-bit
> space is used in 'g' packet.  No?

 Pre-XML stubs have a uniform register width so with a MIPS64 debuggee 
FPRs will be 64-bit whether FR=1 or FR=0; this patch cannot and does not 
attempt to change this, so in that case FPRs need to be explicitly 
truncated at the cooked level, which is arranged by this patch in 
`mips_register_type'.

 XML-described stubs are enforced by this patch to match `g' packet space 
with the actual FPR width, however no XML-described stub is currently 
known to support FR tracking.

 NB all this only applies to bare-metal stubs rather than our `gdbserver' 
as MIPS64/FR=0 is not a supported Linux execution model.

> >  FWIW I think the FR=0 mode should have been chosen to present the FPR 
> > file as 16 64-bit FPRs instead, with the cooked register view used to 
> > access register halves if required, but then I think a further 
> > complication would arise with non-XML-described stubs.
> > 
> > > >      The change also supports both XML and non-XML targets, but currently
> > > >     bare-iron targets for which this update has any significant meaning do not
> > > >     really support XML.  Any XML target is supposed to always provide an FPU
> > > >     description that matches the current setting of CP0.Status.FR, the new
> > > >     code verifies this is always the case and rejects the description as
> > > >     invalid otherwise.
> > > 
> > > How do I understand "Any XML target is supposed to always provide
> > > an FPU description that matches the current setting of CP0.Status.FR"?
> > > I don't see how it is done in current GDB/GDBserver.
> > 
> >  I do hope the last patch which adds `gdbserver' features en masse, which 
> > I didn't get to to looking through yet, has it (although I think the 
> > individual features should be included along with corresponding base 
> > target and native support instead).
> 
> Oh, it must be this patch
> https://sourceware.org/ml/gdb-patches/2016-06/msg00511.html

 Correct.

> > > "reconfigure FPRs" is a target description change to me, instead of a
> > > regcache change.
> > 
> >  The regcache change is partly historic, because parts of the series 
> > (dating back to 2005) were implemented even before we had XML 
> > descriptions, and an FR transition is also supposed to work with 
> > non-XML-described MIPS64 bare-metal targets (where the FPR file is 
> > presented as 32 64-bit FPRs regardless of the FR setting).  I do agree a 
> > target description should take precedence where available, and certainly 
> > with Linux targets where you cannot get a MIPS64 FR=0 configuration or a 
> > non-XML-described MIPS32 FR=1 configuration).
> > 
> >  What do you propose if we don't have a target description though?  We 
> > can't handle MIPS32 FR=1, because stubs won't transfer the upper halves of 
> > FPRs, but we can handle MIPS64 FR=0, because we can simply ignore the 
> > irrelevant upper halves.
> 
> Why stubs doesn't transfer the upper bits of PFRs in case of MIPS32 FR=1?
> because of keeping backward compatibility?  Does
> register_remote_g_packet_guess help?

 Pre-XML stubs have a uniform register width matching the architecture, 
and then a fixed register layout as defined by the enum in mips-tdep.h.  
Consequently there is simply no room there for the upper halves of 
MIPS32/FR=1 FPRs, so no legacy stub ever gives access to them, because all 
registers transferred are 32-bit.  Using `register_remote_g_packet_guess' 
won't help with such missing data.

 With an XML-described stub we can of course supply whole FPRs however we 
wish, although I think there's still value in keeping the MIPS32/FR=0 
packet format the same (i.e. as defined by mips-tdep.h) so that 
communication continues working with legacy pre-XML GDB clients.  Of 
course once we switch to MIPS32/FR=1, then communication will break, but 
pre-XML GDB clients don't support the cooked MIPS32/FR=1 register format 
anyway.

 Did I answer your questions?

  Maciej

^ permalink raw reply	[flat|nested] 37+ messages in thread

end of thread, other threads:[~2016-12-02  2:31 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-27 14:50 [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size Bhushan Attarde
2016-06-27 14:50 ` [PATCH 10/24] MIPS: override fscr/fir types and print control registers specially Bhushan Attarde
2016-06-27 14:50 ` [PATCH 08/24] MIPS: Convert FP mode to enum and put fp registers into fp reggroup Bhushan Attarde
2016-06-27 14:50 ` [PATCH 06/24] mips-linux-nat: pick fp64 target description when appropriate Bhushan Attarde
2016-06-27 14:50 ` [PATCH 03/24] regcache: handle invalidated regcache Bhushan Attarde
2016-10-21 22:42   ` Maciej W. Rozycki
2016-06-27 14:50 ` [PATCH 11/24] MIPS: Add support for hybrid fp32/fp64 mode Bhushan Attarde
2016-06-27 14:51 ` [PATCH 04/24] Add MIPS Config5 register related support Bhushan Attarde
2016-06-27 14:51 ` [PATCH 22/24] Support all new ABIs when detecting if an FPU is present Bhushan Attarde
2016-06-27 14:51 ` [PATCH 24/24] MIPS R6 forbidden slot support Bhushan Attarde
2016-06-27 14:51 ` [PATCH 09/24] MIPS: Enhance cooked FP format Bhushan Attarde
2016-06-27 14:51 ` [PATCH 20/24] Drop FP and MSA control registers from default info registers Bhushan Attarde
2016-06-27 14:51 ` [PATCH 23/24] MIPS R6 opcode table shuffle for LDC2/SDC2 Bhushan Attarde
2016-06-27 14:51 ` [PATCH 02/24] Add MIPS32 FPU64 GDB target descriptions Bhushan Attarde
2016-10-12 12:42   ` Maciej W. Rozycki
2016-10-12 13:58     ` James Hogan
2016-10-12 16:30       ` Maciej W. Rozycki
2016-10-12 18:05         ` James Hogan
2016-10-12 22:04           ` Maciej W. Rozycki
2016-10-13 10:09             ` Matthew Fortune
2016-10-21 19:17               ` Maciej W. Rozycki
2016-10-21 19:24                 ` Maciej W. Rozycki
2016-06-27 14:51 ` [PATCH 21/24] MIPSR6 support for GDB Bhushan Attarde
2016-07-29 21:10   ` Maciej W. Rozycki
2016-06-27 14:51 ` [PATCH 13/24] Add MIPS MSA GDB target descriptions Bhushan Attarde
2016-06-27 14:51 ` [PATCH 14/24] Implement core MSA stuff Bhushan Attarde
2016-06-27 14:51 ` [PATCH 07/24] MIPS: Make Linux restart register more dynamic Bhushan Attarde
2016-06-27 14:51 ` [PATCH 19/24] Add MIPS MSA vector branch instruction support Bhushan Attarde
2016-06-27 14:51 ` [PATCH 05/24] MIPS: Add config5 to MIPS GDB target descriptions Bhushan Attarde
2016-06-27 14:51 ` [PATCH 18/24] mips-linux-nat: get msa registers Bhushan Attarde
2016-06-27 14:51 ` [PATCH 12/24] o32 sigframe unwinding with FR1 Bhushan Attarde
2016-07-25 14:03 ` [PATCH 01/24] MIPS: Handle run-time reconfigurable FPR size Maciej W. Rozycki
2016-10-18 17:37   ` Maciej W. Rozycki
2016-11-08 19:46 ` Yao Qi
2016-11-10 12:43   ` Maciej W. Rozycki
2016-11-11 12:29     ` Yao Qi
2016-12-02  2:31       ` Maciej W. Rozycki

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).