Look for FIR in the last FreeBSD/mips floating-point register.
authorJohn Baldwin <jhb@FreeBSD.org>
Tue, 29 Aug 2017 22:04:09 +0000 (15:04 -0700)
committerJohn Baldwin <jhb@FreeBSD.org>
Tue, 29 Aug 2017 22:04:09 +0000 (15:04 -0700)
FreeBSD/mips kernels were recently changed to include the floating
point implementation revision register in the floating point register
set exported in process cores and via ptrace() (r318067).  This change
will first ship in FreeBSD 12.0 when it is eventually released.  The
space used to hold FIR was previously reserved in 'struct fpreg' as a
zero-filled dummy for padding, so 'struct fpreg' has not changed in
size.  Since FIR should be non-zero on all MIPS processors supported
by FreeBSD, ignore a value of 0 from 'struct fpreg' and only report
non-zero values as a valid FIR register.

gdb/ChangeLog:

* mips-fbsd-nat.c (getfpregs_supplies): Return true for FIR.
* mips-fbsd-tdep.c (mips_fbsd_supply_fpregs): Split supply of FSR
out of loop and add supply of FIR.
(mips_fbsd_collect_fpregs): Split collect of FSR out of loop and
add collect of FIR.

gdb/ChangeLog
gdb/mips-fbsd-nat.c
gdb/mips-fbsd-tdep.c

index 926c96656e17ba25de172f989f41292dff19e76a..5559bc2907a5eb5fb11ded8756530471fc56a11f 100644 (file)
@@ -1,3 +1,11 @@
+2017-08-29  John Baldwin  <jhb@FreeBSD.org>
+
+       * mips-fbsd-nat.c (getfpregs_supplies): Return true for FIR.
+       * mips-fbsd-tdep.c (mips_fbsd_supply_fpregs): Split supply of FSR
+       out of loop and add supply of FIR.
+       (mips_fbsd_collect_fpregs): Split collect of FSR out of loop and
+       add collect of FIR.
+
 2017-08-28  Simon Marchi  <simon.marchi@ericsson.com>
 
        PR gdb/21827
index 53817d7cd763640d5bd02f640a68086a79240e5c..c3811865354678f2876ccb02eea85612944a0309 100644 (file)
@@ -46,7 +46,7 @@ static bool
 getfpregs_supplies (struct gdbarch *gdbarch, int regnum)
 {
   return (regnum >= mips_regnum (gdbarch)->fp0
-         && regnum < mips_regnum (gdbarch)->fp_implementation_revision);
+         && regnum <= mips_regnum (gdbarch)->fp_implementation_revision);
 }
 
 /* Fetch register REGNUM from the inferior.  If REGNUM is -1, do this
index 44b960d4d2b453c99905ac96ca85b51d4aa58965..feb18e1a7aca976a26d57dc9f6080a1c447e3adb 100644 (file)
@@ -39,7 +39,8 @@
 
 /* Number of registers in `struct fpreg' from <machine/reg.h>.  The
    first 32 hold floating point registers.  33 holds the FSR.  The
-   34th is a dummy for padding.  */
+   34th holds FIR on FreeBSD 12.0 and newer kernels.  On older kernels
+   it was a zero-filled dummy for padding.  */
 #define MIPS_FBSD_NUM_FPREGS   34
 
 /* Supply a single register.  The register size might not match, so use
@@ -72,14 +73,23 @@ mips_fbsd_supply_fpregs (struct regcache *regcache, int regnum,
 {
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
   const gdb_byte *regs = (const gdb_byte *) fpregs;
-  int i, fp0num, fsrnum;
+  int i, fp0num;
 
   fp0num = mips_regnum (gdbarch)->fp0;
-  fsrnum = mips_regnum (gdbarch)->fp_control_status;
-  for (i = fp0num; i <= fsrnum; i++)
-    if (regnum == i || regnum == -1)
-      mips_fbsd_supply_reg (regcache, i,
-                           regs + (i - fp0num) * regsize, regsize);
+  for (i = 0; i <= 32; i++)
+    if (regnum == fp0num + i || regnum == -1)
+      mips_fbsd_supply_reg (regcache, fp0num + i,
+                           regs + i * regsize, regsize);
+  if (regnum == mips_regnum (gdbarch)->fp_control_status || regnum == -1)
+    mips_fbsd_supply_reg (regcache, mips_regnum (gdbarch)->fp_control_status,
+                         regs + 32 * regsize, regsize);
+  if ((regnum == mips_regnum (gdbarch)->fp_implementation_revision
+       || regnum == -1)
+      && extract_unsigned_integer (regs + 33 * regsize, regsize,
+                                  gdbarch_byte_order (gdbarch)) != 0)
+    mips_fbsd_supply_reg (regcache,
+                         mips_regnum (gdbarch)->fp_implementation_revision,
+                         regs + 33 * regsize, regsize);
 }
 
 /* Supply the general-purpose registers stored in GREGS to REGCACHE.
@@ -109,14 +119,21 @@ mips_fbsd_collect_fpregs (const struct regcache *regcache, int regnum,
 {
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
   gdb_byte *regs = (gdb_byte *) fpregs;
-  int i, fp0num, fsrnum;
+  int i, fp0num;
 
   fp0num = mips_regnum (gdbarch)->fp0;
-  fsrnum = mips_regnum (gdbarch)->fp_control_status;
-  for (i = fp0num; i <= fsrnum; i++)
-    if (regnum == i || regnum == -1)
-      mips_fbsd_collect_reg (regcache, i,
-                            regs + (i - fp0num) * regsize, regsize);
+  for (i = 0; i < 32; i++)
+    if (regnum == fp0num + i || regnum == -1)
+      mips_fbsd_collect_reg (regcache, fp0num + i,
+                            regs + i * regsize, regsize);
+  if (regnum == mips_regnum (gdbarch)->fp_control_status || regnum == -1)
+    mips_fbsd_collect_reg (regcache, mips_regnum (gdbarch)->fp_control_status,
+                          regs + 32 * regsize, regsize);
+  if (regnum == mips_regnum (gdbarch)->fp_implementation_revision
+      || regnum == -1)
+    mips_fbsd_collect_reg (regcache,
+                          mips_regnum (gdbarch)->fp_implementation_revision,
+                          regs + 33 * regsize, regsize);
 }
 
 /* Collect the general-purpose registers from REGCACHE and store them