This is the mail archive of the gdb-cvs@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] MIPS/Linux: Correct o32 core file FGR interpretation


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=d8dab6c3bbe6432ff20237e621f2f3a3d30d4d4b

commit d8dab6c3bbe6432ff20237e621f2f3a3d30d4d4b
Author: Maciej W. Rozycki <macro@mips.com>
Date:   Fri May 25 12:37:45 2018 +0100

    MIPS/Linux: Correct o32 core file FGR interpretation
    
    Our interpretation of the layout of floating-point general registers
    (FGRs) in o32 MIPS/Linux core files is different from how the kernel
    makes them, affecting the CP0 Status.FR=0 aka FP32 mode (we don't
    currently support the CP0 Status.FR=1 aka FP64 mode with the o32 ABI).
    
    In the FP32 mode pairs of consecutive even/odd-numbered 32-bit registers
    are placed together as 64-bit values in even-indexed 64-bit slots
    corresponding to the even index, leaving the odd-indexed 64-bit slots
    unused.  These 64-bit values are stored according to the endianness in
    effect, which is how the MIPS II SDC1 instruction would store them.
    
    It has always been like that with the Linux kernel for MIPS II and
    higher ISA processors, which are the vast majority ever supported, as it
    is indeed SDC1 that the kernel uses to store FGRs in a floating-point
    context.
    
    With MIPS I processors, which lack the SDC1 instruction, a layout that
    we expect used to be used long ago, but it was corrected for consistency
    with newer processors back in 2002, with `linux-mips.org' (LMO) commit
    42533948caac ("Major pile of FP emulator changes."), the fix corrected
    with LMO commit 849fa7a50dff ("R3k FPU ptrace() handling fixes."), and
    then broken and fixed over and over again, until last time fixed with
    commit 80cbfad79096 ("MIPS: Correct MIPS I FP context layout").
    
    Consequently the values we see in FP32 core files or produce with the
    `gcore' command are different from those obtained from the same FP
    context of a live process, e.g. with a big-endian configuration these
    live values:
    
    (gdb) info registers float
    f0:  0x4b5c6d7e flt: 14445950          dbl: 1.7446153562345001e-274
    f1:  0x0718293a flt: 1.14473244e-34
    f2:  0xc3d4e5f6 flt: -425.79657        dbl: -1.046160437414959e-233
    f3:  0x8f90a1b2 flt: -1.42617791e-29
    f4:  0x4c5d6e7f flt: 58046972          dbl: 1.1908587841220294e-269
    f5:  0x08192a3b flt: 4.60914044e-34
    f6:  0xc4d5e6f7 flt: -1711.21765       dbl: -6.2784661835068965e-306
    f7:  0x8091a2b3 flt: -1.33745124e-38
    f8:  0x45566778 flt: 3430.4668         dbl: 1.6530355595710607e-303
    f9:  0x01122334 flt: 2.68412219e-38
    f10: 0xcddeeff0 flt: -467533312        dbl: -2.1174864564135575e-262
    f11: 0x899aabbc flt: -3.72356497e-33
    f12: 0x46576879 flt: 13786.1182        dbl: 1.143296486773654e-298
    f13: 0x02132435 flt: 1.08102453e-37
    f14: 0xcedfe0f1 flt: -1.87803046e+09   dbl: -1.4399511533369862e-257
    f15: 0x8a9bacbd flt: -1.4990934e-32
    f16: 0x4758697a flt: 55401.4766        dbl: 7.8856820439568725e-294
    f17: 0x03142536 flt: 4.3536007e-37
    f18: 0xcfd0e1f2 flt: -7.00893696e+09   dbl: -9.7791926757340559e-253
    f19: 0x8b9cadbe flt: -6.03504325e-32
    f20: 0x48596a7b flt: 222633.922        dbl: 5.4255001483306113e-289
    f21: 0x04152637 flt: 1.75324132e-36
    f22: 0xc0d1e2f3 flt: -6.55895376       dbl: -6.6332401002310683e-248
    f23: 0x8c9daebf flt: -2.42948516e-31
    f24: 0x495a6b7c flt: 894647.75         dbl: 3.7244369058749787e-284
    f25: 0x05162738 flt: 7.06016945e-36
    f26: 0xc1d2e3f4 flt: -26.3613052       dbl: -4.4941535759306202e-243
    f27: 0x8d9eafb0 flt: -9.77979703e-31
    f28: 0x4a5b6c7d flt: 3595039.25        dbl: 2.5514593711161396e-279
    f29: 0x06172839 flt: 2.84294945e-35
    f30: 0xc2d3e4f5 flt: -105.947182       dbl: -3.035646690850097e-238
    f31: 0x8e9fa0b1 flt: -3.93512664e-30
    fcsr: 0x0
    fir: 0xf30000
    (gdb)
    
    show up in a core file as these:
    
    (gdb) info registers float
    f0:  0x0718293a flt: 1.14473244e-34    dbl: nan
    f1:  0x7ff80000 flt: nan
    f2:  0x8f90a1b2 flt: -1.42617791e-29   dbl: nan
    f3:  0x7ff80000 flt: nan
    f4:  0x08192a3b flt: 4.60914044e-34    dbl: nan
    f5:  0x7ff80000 flt: nan
    f6:  0x8091a2b3 flt: -1.33745124e-38   dbl: nan
    f7:  0x7ff80000 flt: nan
    f8:  0x01122334 flt: 2.68412219e-38    dbl: nan
    f9:  0x7ff80000 flt: nan
    f10: 0x899aabbc flt: -3.72356497e-33   dbl: nan
    f11: 0x7ff80000 flt: nan
    f12: 0x02132435 flt: 1.08102453e-37    dbl: nan
    f13: 0x7ff80000 flt: nan
    f14: 0x8a9bacbd flt: -1.4990934e-32    dbl: nan
    f15: 0x7ff80000 flt: nan
    f16: 0x03142536 flt: 4.3536007e-37     dbl: nan
    f17: 0x7ff80000 flt: nan
    f18: 0x8b9cadbe flt: -6.03504325e-32   dbl: nan
    f19: 0x7ff80000 flt: nan
    f20: 0x04152637 flt: 1.75324132e-36    dbl: nan
    f21: 0x7ff80000 flt: nan
    f22: 0x8c9daebf flt: -2.42948516e-31   dbl: nan
    f23: 0x7ff80000 flt: nan
    f24: 0x05162738 flt: 7.06016945e-36    dbl: nan
    f25: 0x7ff80000 flt: nan
    f26: 0x8d9eafb0 flt: -9.77979703e-31   dbl: nan
    f27: 0x7ff80000 flt: nan
    f28: 0x06172839 flt: 2.84294945e-35    dbl: nan
    f29: 0x7ff80000 flt: nan
    f30: 0x8e9fa0b1 flt: -3.93512664e-30   dbl: nan
    f31: 0x7ff80000 flt: nan
    (gdb)
    
    Notice how values from odd-numbered registers are shown in corresponding
    even-numbered registers and how dummy 0x7ff80000 NaN values, which the
    kernel places in unused slots, are reported in odd-numbered registers.
    
    Correct our intepretation then, to match the kernel's.  As it happens
    the o32 FGR core file representation matches that used by the `ptrace'
    PTRACE_GETFPREGS request, which means our 64-bit handlers can be readily
    used, as they already correctly handle the differences between o32 FP32
    mode vs n32/n64 representations.
    
    Adjust comments accordingly throughout, in particular remove a reference
    to the r3000/tx39 MIPS I processor peculiarity, long irrelevant.
    
    Add a test case to verify correctness.  Avoid GCC bugs and limitations
    in the test case where possible; the test case still fails to build with
    GCC 8 and the o32 FP64 mode (i.e. with `-mips32r2 -mfp64' options)
    giving:
    
    mips-fpregset-core.c: In function 'main':
    mips-fpregset-core.c:66:3: error: inconsistent operand constraints in an 'asm'
       asm (
       ^~~
    
    (GCC PR target/85909), but that is not a concern for us as yet, because
    as noted above we do not currently support the o32 FP64 mode anyway.
    
    	gdb/
    	* mips-linux-tdep.h (mips_supply_fpregset, mips_fill_fpregset):
    	Remove prototypes.
    	* mips-linux-nat.c (supply_fpregset): Always call
    	`mips64_supply_fpregset' rather than `mips_supply_fpregset'.
    	(fill_fpregset): Always call `mips64_fill_fpregset' rather than
    	`mips_fill_fpregset'.
    	* mips-linux-tdep.c (mips_supply_fpregset)
    	(mips_supply_fpregset_wrapper, mips_fill_fpregset)
    	(mips_fill_fpregset_wrapper): Remove functions.
    	(mips64_supply_fpregset, mips64_fill_fpregset): Update comments.
    	(mips_linux_fpregset): Remove variable.
    	(mips_linux_iterate_over_regset_sections): Use
    	`mips64_linux_fpregset' in place of `mips_linux_fpregset'.
    	(mips_linux_o32_sigframe_init): Remove comment.
    
    	gdb/testsuite/
    	* gdb.arch/mips-fpregset-core.exp: New test.
    	* gdb.arch/mips-fpregset-core.c: New test source.

Diff:
---
 gdb/ChangeLog                                 |  17 +++
 gdb/gdbserver/ChangeLog                       |   5 +
 gdb/mips-linux-nat.c                          |  12 +-
 gdb/mips-linux-tdep.c                         | 109 +++---------------
 gdb/mips-linux-tdep.h                         |   2 -
 gdb/testsuite/gdb.arch/mips-fpregset-core.c   |  82 ++++++++++++++
 gdb/testsuite/gdb.arch/mips-fpregset-core.exp | 154 ++++++++++++++++++++++++++
 7 files changed, 273 insertions(+), 108 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 4f42528..070c991 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,20 @@
+2018-05-25  Maciej W. Rozycki  <macro@mips.com>
+
+	* mips-linux-tdep.h (mips_supply_fpregset, mips_fill_fpregset):
+	Remove prototypes.
+	* mips-linux-nat.c (supply_fpregset): Always call
+	`mips64_supply_fpregset' rather than `mips_supply_fpregset'.
+	(fill_fpregset): Always call `mips64_fill_fpregset' rather than
+	`mips_fill_fpregset'.
+	* mips-linux-tdep.c (mips_supply_fpregset)
+	(mips_supply_fpregset_wrapper, mips_fill_fpregset)
+	(mips_fill_fpregset_wrapper): Remove functions.
+	(mips64_supply_fpregset, mips64_fill_fpregset): Update comments.
+	(mips_linux_fpregset): Remove variable.
+	(mips_linux_iterate_over_regset_sections): Use
+	`mips64_linux_fpregset' in place of `mips_linux_fpregset'.
+	(mips_linux_o32_sigframe_init): Remove comment.
+
 2018-05-25  Pedro Alves  <palves@redhat.com>
 
 	* remote.c (struct vCont_action_support, MAXTHREADLISTRESULTS)
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 7aa5946..0224818 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,8 @@
+2018-05-25  Maciej W. Rozycki  <macro@mips.com>
+
+	* gdb.arch/mips-fpregset-core.exp: New test.
+	* gdb.arch/mips-fpregset-core.c: New test source.
+
 2018-05-23  Erik Kurzinger  <ekurzinger@nvidia.com>
 
 	PR server/23198
diff --git a/gdb/mips-linux-nat.c b/gdb/mips-linux-nat.c
index a9f0b79..3683107 100644
--- a/gdb/mips-linux-nat.c
+++ b/gdb/mips-linux-nat.c
@@ -224,22 +224,14 @@ fill_gregset (const struct regcache *regcache,
 void
 supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
 {
-  if (mips_isa_regsize (regcache->arch ()) == 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 (regcache->arch ()) == 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);
 }
 
 
diff --git a/gdb/mips-linux-tdep.c b/gdb/mips-linux-tdep.c
index 175b402..e580424 100644
--- a/gdb/mips-linux-tdep.c
+++ b/gdb/mips-linux-tdep.c
@@ -233,82 +233,6 @@ mips_fill_gregset_wrapper (const struct regset *regset,
   mips_fill_gregset (regcache, (mips_elf_gregset_t *)gregs, regnum);
 }
 
-/* Likewise, unpack an elf_fpregset_t.  */
-
-void
-mips_supply_fpregset (struct regcache *regcache,
-		      const mips_elf_fpregset_t *fpregsetp)
-{
-  struct gdbarch *gdbarch = regcache->arch ();
-  int regi;
-
-  for (regi = 0; regi < 32; regi++)
-    regcache_raw_supply (regcache,
-			 gdbarch_fp0_regnum (gdbarch) + regi,
-			 *fpregsetp + regi);
-
-  regcache_raw_supply (regcache,
-		       mips_regnum (gdbarch)->fp_control_status,
-		       *fpregsetp + 32);
-
-  /* FIXME: how can we supply FCRIR?  The ABI doesn't tell us.  */
-  regcache->raw_supply_zeroed
-    (mips_regnum (gdbarch)->fp_implementation_revision);
-}
-
-static void
-mips_supply_fpregset_wrapper (const struct regset *regset,
-			      struct regcache *regcache,
-			      int regnum, const void *gregs, size_t len)
-{
-  gdb_assert (len >= sizeof (mips_elf_fpregset_t));
-
-  mips_supply_fpregset (regcache, (const mips_elf_fpregset_t *)gregs);
-}
-
-/* Likewise, pack one or all floating point registers into an
-   elf_fpregset_t.  */
-
-void
-mips_fill_fpregset (const struct regcache *regcache,
-		    mips_elf_fpregset_t *fpregsetp, int regno)
-{
-  struct gdbarch *gdbarch = regcache->arch ();
-  char *to;
-
-  if ((regno >= gdbarch_fp0_regnum (gdbarch))
-      && (regno < gdbarch_fp0_regnum (gdbarch) + 32))
-    {
-      to = (char *) (*fpregsetp + regno - gdbarch_fp0_regnum (gdbarch));
-      regcache_raw_collect (regcache, regno, to);
-    }
-  else if (regno == mips_regnum (gdbarch)->fp_control_status)
-    {
-      to = (char *) (*fpregsetp + 32);
-      regcache_raw_collect (regcache, regno, to);
-    }
-  else if (regno == -1)
-    {
-      int regi;
-
-      for (regi = 0; regi < 32; regi++)
-	mips_fill_fpregset (regcache, fpregsetp,
-			    gdbarch_fp0_regnum (gdbarch) + regi);
-      mips_fill_fpregset (regcache, fpregsetp,
-			  mips_regnum (gdbarch)->fp_control_status);
-    }
-}
-
-static void
-mips_fill_fpregset_wrapper (const struct regset *regset,
-			    const struct regcache *regcache,
-			    int regnum, void *gregs, size_t len)
-{
-  gdb_assert (len >= sizeof (mips_elf_fpregset_t));
-
-  mips_fill_fpregset (regcache, (mips_elf_fpregset_t *)gregs, regnum);
-}
-
 /* Support for 64-bit ABIs.  */
 
 /* Figure out where the longjmp will land.
@@ -473,7 +397,16 @@ mips64_fill_gregset_wrapper (const struct regset *regset,
   mips64_fill_gregset (regcache, (mips64_elf_gregset_t *)gregs, regnum);
 }
 
-/* Likewise, unpack an elf_fpregset_t.  */
+/* Likewise, unpack an elf_fpregset_t.  Linux only uses even-numbered
+   FPR slots in the Status.FR=0 mode, storing even-odd FPR pairs as the
+   SDC1 instruction would.  When run on MIPS I architecture processors
+   all FPR slots used to be used, unusually, holding the respective FPRs
+   in the first 4 bytes, but that was corrected for consistency, with
+   `linux-mips.org' (LMO) commit 42533948caac ("Major pile of FP emulator
+   changes."), the fix corrected with LMO commit 849fa7a50dff ("R3k FPU
+   ptrace() handling fixes."), and then broken and fixed over and over
+   again, until last time fixed with commit 80cbfad79096 ("MIPS: Correct
+   MIPS I FP context layout").  */
 
 void
 mips64_supply_fpregset (struct regcache *regcache,
@@ -482,8 +415,6 @@ mips64_supply_fpregset (struct regcache *regcache,
   struct gdbarch *gdbarch = regcache->arch ();
   int regi;
 
-  /* See mips_linux_o32_sigframe_init for a description of the
-     peculiar FP register layout.  */
   if (register_size (gdbarch, gdbarch_fp0_regnum (gdbarch)) == 4)
     for (regi = 0; regi < 32; regi++)
       {
@@ -523,7 +454,8 @@ mips64_supply_fpregset_wrapper (const struct regset *regset,
 }
 
 /* Likewise, pack one or all floating point registers into an
-   elf_fpregset_t.  */
+   elf_fpregset_t.  See `mips_supply_fpregset' for an explanation
+   of the layout.  */
 
 void
 mips64_fill_fpregset (const struct regcache *regcache,
@@ -535,8 +467,6 @@ mips64_fill_fpregset (const struct regcache *regcache,
   if ((regno >= gdbarch_fp0_regnum (gdbarch))
       && (regno < gdbarch_fp0_regnum (gdbarch) + 32))
     {
-      /* See mips_linux_o32_sigframe_init for a description of the
-	 peculiar FP register layout.  */
       if (register_size (gdbarch, regno) == 4)
 	{
 	  int regi = regno - gdbarch_fp0_regnum (gdbarch);
@@ -597,11 +527,6 @@ static const struct regset mips64_linux_gregset =
     NULL, mips64_supply_gregset_wrapper, mips64_fill_gregset_wrapper
   };
 
-static const struct regset mips_linux_fpregset =
-  {
-    NULL, mips_supply_fpregset_wrapper, mips_fill_fpregset_wrapper
-  };
-
 static const struct regset mips64_linux_fpregset =
   {
     NULL, mips64_supply_fpregset_wrapper, mips64_fill_fpregset_wrapper
@@ -617,7 +542,7 @@ mips_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
     {
       cb (".reg", sizeof (mips_elf_gregset_t), &mips_linux_gregset,
 	  NULL, cb_data);
-      cb (".reg2", sizeof (mips_elf_fpregset_t), &mips_linux_fpregset,
+      cb (".reg2", sizeof (mips64_elf_fpregset_t), &mips64_linux_fpregset,
 	  NULL, cb_data);
     }
   else
@@ -1076,14 +1001,6 @@ mips_linux_o32_sigframe_init (const struct tramp_frame *self,
 			     (regs_base + SIGCONTEXT_REGS
 			      + ireg * SIGCONTEXT_REG_SIZE));
 
-  /* 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
-     32 eight byte slots.  For everything else, the registers are saved
-     using double precision; only the even-numbered slots are initialized,
-     and the high bits are the odd-numbered register.  Assume the latter
-     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))
       trad_frame_set_reg_addr (this_cache,
diff --git a/gdb/mips-linux-tdep.h b/gdb/mips-linux-tdep.h
index 83636fa..a87d555 100644
--- a/gdb/mips-linux-tdep.h
+++ b/gdb/mips-linux-tdep.h
@@ -52,8 +52,6 @@ typedef mips_elf_fpreg_t mips_elf_fpregset_t[ELF_NFPREG];
 
 void mips_supply_gregset (struct regcache *, const mips_elf_gregset_t *);
 void mips_fill_gregset (const struct regcache *, mips_elf_gregset_t *, int);
-void mips_supply_fpregset (struct regcache *, const mips_elf_fpregset_t *);
-void mips_fill_fpregset (const struct regcache *, mips_elf_fpregset_t *, int);
 
 /* 64-bit support.  */
 
diff --git a/gdb/testsuite/gdb.arch/mips-fpregset-core.c b/gdb/testsuite/gdb.arch/mips-fpregset-core.c
new file mode 100644
index 0000000..f0ac31b
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/mips-fpregset-core.c
@@ -0,0 +1,82 @@
+/* This test is part of GDB, the GNU debugger.
+
+   Copyright 2018 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <stdint.h>
+
+int __attribute__ ((nomips16))
+main (void)
+{
+  /* We need to use a complex type to avoid hitting GCC's limit of
+     the number of `asm' operands:
+
+     mips-fpregset-core.f: In function 'main':
+     mips-fpregset-core.f:66:3: error: more than 30 operands in 'asm'
+        asm (
+        ^~~
+
+     and still have complete 32 FGR coverage with FP64 ABIs.  Using
+     a complex type breaks o32 GCC though, so use plain `double' with
+     FP32.  */
+#if _MIPS_FPSET == 32
+  typedef double _Complex float_t;
+#else
+  typedef double float_t;
+#endif
+  union
+    {
+      uint64_t i[32];
+      float_t f[256 / sizeof (float_t)];
+    }
+  u =
+    { .i =
+      {
+	0x0112233445566778, 0x899aabbccddeeff0,
+	0x0213243546576879, 0x8a9bacbdcedfe0f1,
+	0x031425364758697a, 0x8b9cadbecfd0e1f2,
+	0x0415263748596a7b, 0x8c9daebfc0d1e2f3,
+	0x05162738495a6b7c, 0x8d9eafb0c1d2e3f4,
+	0x061728394a5b6c7d, 0x8e9fa0b1c2d3e4f5,
+	0x0718293a4b5c6d7e, 0x8f90a1b2c3d4e5f6,
+	0x08192a3b4c5d6e7f, 0x8091a2b3c4d5e6f7,
+	0x091a2b3c4d5e6f70, 0x8192a3b4c5d6e7f8,
+	0x0a1b2c3d4e5f6071, 0x8293a4b5c6d7e8f9,
+	0x0b1c2d3e4f506172, 0x8394a5b6c7d8e9fa,
+	0x0c1d2e3f40516273, 0x8495a6b7c8d9eafb,
+	0x0d1e2f3041526374, 0x8596a7b8c9daebfc,
+	0x0e1f203142536475, 0x8697a8b9cadbecfd,
+	0x0f10213243546576, 0x8798a9bacbdcedfe,
+	0x0011223344556677, 0x8899aabbccddeeff
+      }
+    };
+
+  asm (
+    ".globl\tbreak_here\n\t"
+    ".aent\tbreak_here\n"
+    "break_here:\n\t"
+    "lb\t$0,0($0)\n"
+    :
+    : [f0] "f" (u.f[0]), [f2] "f" (u.f[1]),
+      [f4] "f" (u.f[2]), [f6] "f" (u.f[3]),
+      [f8] "f" (u.f[4]), [f10] "f" (u.f[5]),
+      [f12] "f" (u.f[6]), [f14] "f" (u.f[7]),
+      [f16] "f" (u.f[8]), [f18] "f" (u.f[9]),
+      [f20] "f" (u.f[10]), [f22] "f" (u.f[11]),
+      [f24] "f" (u.f[12]), [f26] "f" (u.f[13]),
+      [f28] "f" (u.f[14]), [f30] "f" (u.f[15]));
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.arch/mips-fpregset-core.exp b/gdb/testsuite/gdb.arch/mips-fpregset-core.exp
new file mode 100644
index 0000000..49fcb79
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/mips-fpregset-core.exp
@@ -0,0 +1,154 @@
+# Copyright 2018 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test MIPS Floating Point General Register handling in core files.
+
+if { ![istarget "mips*-*-*"] } then {
+    verbose "Skipping MIPS Floating Point General Register tests."
+    return
+}
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" ${testfile}] } {
+    return
+}
+
+# Procedure to get current content of all floating-point registers.
+proc mips_fpregset_core_fetch_float_registers { test } {
+    global gdb_prompt
+
+    set all_registers_lines {}
+    set bad -1
+    # Former trailing `\[\r\n\]+' may eat just \r leaving \n in the buffer
+    # corrupting the next matches.
+    if { [gdb_test_multiple "info registers float" $test {
+	-re "info registers float\r\n" {
+	    exp_continue
+	}
+	-ex "The program has no registers now" {
+	    set bad 1
+	    exp_continue
+	}
+	-re "^\(?:fcsr\|fir\):\[ \t\]+\[^\r\n\]+\r\n" {
+	    # Filter out control registers.  They may or may not be a part
+	    # of the float group depending on whether XML descriptions are
+	    # used or not.
+	    exp_continue
+	}
+	-re "^\[^ \t\]+\[ \t\]+\[^\r\n\]+\r\n" {
+	    lappend all_registers_lines $expect_out(0,string)
+	    exp_continue
+	}
+	-re "$gdb_prompt $" {
+	    incr bad
+	}
+	-re "^\[^\r\n\]+\r\n" {
+	    if { !$bad } {
+		warning "Unrecognized output: $expect_out(0,string)"
+		set bad 1
+	    }
+	    exp_continue
+	}
+    }] != 0 } {
+	return {}
+    }
+
+    if { $bad } {
+	fail $test
+	return {}
+    }
+
+    pass $test
+    return $all_registers_lines
+}
+
+# Generate a native core file.
+
+set corefile [core_find $binfile]
+set core_supported [expr {$corefile != ""}]
+
+# Generate a core file with "gcore".
+
+clean_restart ${binfile}
+
+runto break_here
+
+# Check if we have an FPU available.
+gdb_test_multiple "show mipsfpu" "check for MIPS floating-point coprocessor" {
+    -re "The MIPS floating-point coprocessor\
+	 .*\(absent\|unknown\).*$gdb_prompt $" {
+        unsupported "no MIPS floating-point coprocessor in the processor"
+        return
+    }
+    -re "The MIPS floating-point coprocessor .*$gdb_prompt $" {
+        verbose "MIPS floating-point coprocessor check successful."
+    }
+    default {
+        fail
+        return
+    }
+}
+
+# Save live FGR register contents.
+set live_fgr_contents [mips_fpregset_core_fetch_float_registers \
+    "retrieve live FGR register contents"]
+
+set gcorefile [standard_output_file gcore.test]
+set gcore_supported [gdb_gcore_cmd "$gcorefile" "gcore"]
+
+# Restart gdb and load COREFILE as a core file.  SUPPORTED is true iff
+# the core was generated successfully; otherwise, the tests are marked
+# unsupported.
+#
+proc mips_fpregset_core_test { supported corefile } {
+    upvar live_fgr_contents live_fgr_contents
+    upvar target_triplet target_triplet
+    upvar host_triplet host_triplet
+    upvar binfile binfile
+
+    clean_restart ${binfile}
+
+    set test "load core file"
+    if { $supported } {
+	set core_loaded [gdb_core_cmd $corefile $test]
+    } else {
+	set core_loaded 0
+	unsupported $test
+    }
+
+    if { $core_loaded == 1 } {
+	set test "core file FGR register contents"
+	set core_fgr_contents \
+	    [mips_fpregset_core_fetch_float_registers "retrieve $test"]
+	if { $core_fgr_contents == $live_fgr_contents } then {
+	    pass $test
+	} else {
+	    fail $test
+	}
+    } else {
+	unsupported $test
+    }
+}
+
+with_test_prefix "native" {
+    mips_fpregset_core_test $core_supported $corefile
+}
+
+with_test_prefix "gcore" {
+    mips_fpregset_core_test $gcore_supported $gcorefile
+}
+
+gdb_exit


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]