public inbox for gdb-cvs@sourceware.org
help / color / mirror / Atom feed
* [binutils-gdb] gdb/riscv: Apply NaN boxing when writing return values into registers
@ 2020-03-25 11:35 Andrew Burgess
  0 siblings, 0 replies; only message in thread
From: Andrew Burgess @ 2020-03-25 11:35 UTC (permalink / raw)
  To: gdb-cvs

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

commit dd8953924b0966e363c27ee38a0663c08f742fa0
Author: Andrew Burgess <andrew.burgess@embecosm.com>
Date:   Fri Mar 13 15:50:28 2020 +0000

    gdb/riscv: Apply NaN boxing when writing return values into registers
    
    When setting up function parameters we already perform NaN boxing, as
    required by the RISC-V ABI, however, we don't do this when writing
    values into registers as part of setting up a return value.
    
    This commit moves the NaN boxing code into a small helper function,
    and then makes use of this function when setting up function
    parameters, and also when setting up return values.
    
    This should resolve this failure:
    
      FAIL: gdb.base/return-nodebug.exp: float: full width of the returned result
    
    gdb/ChangeLog:
    
            PR gdb/25489
            * riscv-tdep.c (riscv_arg_info::c_offset): Update comment.
            (riscv_regcache_cooked_write): New function.
            (riscv_push_dummy_call): Use new function.
            (riscv_return_value): Likewise.

Diff:
---
 gdb/ChangeLog    |  8 +++++++
 gdb/riscv-tdep.c | 69 ++++++++++++++++++++++++++++++++------------------------
 2 files changed, 48 insertions(+), 29 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index ced1b6d43fa..7d627b55ad4 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,11 @@
+2020-03-25  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+	PR gdb/25534
+	* riscv-tdep.c (riscv_arg_info::c_offset): Update comment.
+	(riscv_regcache_cooked_write): New function.
+	(riscv_push_dummy_call): Use new function.
+	(riscv_return_value): Likewise.
+
 2020-03-24  Simon Marchi  <simon.marchi@polymtl.ca>
 
 	* fbsd-nat.c (fbsd_nat_target::follow_fork): Change bool to int.
diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c
index 2978b9e2d57..0423e6abf30 100644
--- a/gdb/riscv-tdep.c
+++ b/gdb/riscv-tdep.c
@@ -1727,8 +1727,9 @@ struct riscv_arg_info
        will go.  */
     int c_length;
 
-    /* The offset within CONTENTS for this part of the argument.  Will
-       always be 0 for the first part.  For the second part of the
+    /* The offset within CONTENTS for this part of the argument.  This can
+       be non-zero even for the first part (the first field of a struct can
+       have a non-zero offset due to padding).  For the second part of the
        argument, this might be the C_LENGTH value of the first part,
        however, if we are passing a structure in two registers, and there's
        is padding between the first and second field, then this offset
@@ -2417,6 +2418,26 @@ riscv_print_arg_location (ui_file *stream, struct gdbarch *gdbarch,
     }
 }
 
+/* Wrapper around REGCACHE->cooked_write.  Places the LEN bytes of DATA
+   into a buffer that is at least as big as the register REGNUM, padding
+   out the DATA with either 0x00, or 0xff.  For floating point registers
+   0xff is used, for everyone else 0x00 is used.  */
+
+static void
+riscv_regcache_cooked_write (int regnum, const gdb_byte *data, int len,
+			     struct regcache *regcache, int flen)
+{
+  gdb_byte tmp [sizeof (ULONGEST)];
+
+  /* FP values in FP registers must be NaN-boxed.  */
+  if (riscv_is_fp_regno_p (regnum) && len < flen)
+    memset (tmp, -1, sizeof (tmp));
+  else
+    memset (tmp, 0, sizeof (tmp));
+  memcpy (tmp, data, len);
+  regcache->cooked_write (regnum, tmp);
+}
+
 /* Implement the push dummy call gdbarch callback.  */
 
 static CORE_ADDR
@@ -2526,18 +2547,13 @@ riscv_push_dummy_call (struct gdbarch *gdbarch,
 	{
 	case riscv_arg_info::location::in_reg:
 	  {
-	    gdb_byte tmp [sizeof (ULONGEST)];
-
 	    gdb_assert (info->argloc[0].c_length <= info->length);
-	    /* FP values in FP registers must be NaN-boxed.  */
-	    if (riscv_is_fp_regno_p (info->argloc[0].loc_data.regno)
-		&& info->argloc[0].c_length < call_info.flen)
-	      memset (tmp, -1, sizeof (tmp));
-	    else
-	      memset (tmp, 0, sizeof (tmp));
-	    memcpy (tmp, (info->contents + info->argloc[0].c_offset),
-		    info->argloc[0].c_length);
-	    regcache->cooked_write (info->argloc[0].loc_data.regno, tmp);
+
+	    riscv_regcache_cooked_write (info->argloc[0].loc_data.regno,
+					 (info->contents
+					  + info->argloc[0].c_offset),
+					 info->argloc[0].c_length,
+					 regcache, call_info.flen);
 	    second_arg_length =
 	      (((info->argloc[0].c_length + info->argloc[0].c_offset) < info->length)
 	       ? info->argloc[1].c_length : 0);
@@ -2569,19 +2585,13 @@ riscv_push_dummy_call (struct gdbarch *gdbarch,
 	    {
 	    case riscv_arg_info::location::in_reg:
 	      {
-		gdb_byte tmp [sizeof (ULONGEST)];
-
 		gdb_assert ((riscv_is_fp_regno_p (info->argloc[1].loc_data.regno)
 			     && second_arg_length <= call_info.flen)
 			    || second_arg_length <= call_info.xlen);
-		/* FP values in FP registers must be NaN-boxed.  */
-		if (riscv_is_fp_regno_p (info->argloc[1].loc_data.regno)
-		    && second_arg_length < call_info.flen)
-		  memset (tmp, -1, sizeof (tmp));
-		else
-		  memset (tmp, 0, sizeof (tmp));
-		memcpy (tmp, second_arg_data, second_arg_length);
-		regcache->cooked_write (info->argloc[1].loc_data.regno, tmp);
+		riscv_regcache_cooked_write (info->argloc[1].loc_data.regno,
+					     second_arg_data,
+					     second_arg_length,
+					     regcache, call_info.flen);
 	      }
 	      break;
 
@@ -2701,9 +2711,9 @@ riscv_return_value (struct gdbarch  *gdbarch,
 	      if (writebuf)
 		{
 		  const gdb_byte *ptr = writebuf + info.argloc[0].c_offset;
-		  regcache->cooked_write_part (regnum, 0,
+		  riscv_regcache_cooked_write (regnum, ptr,
 					       info.argloc[0].c_length,
-					       ptr);
+					       regcache, call_info.flen);
 		}
 
 	      /* A return value in register can have a second part in a
@@ -2730,10 +2740,11 @@ riscv_return_value (struct gdbarch  *gdbarch,
 
 		      if (writebuf)
 			{
-			  writebuf += info.argloc[1].c_offset;
-			  regcache->cooked_write_part (regnum, 0,
-						       info.argloc[1].c_length,
-						       writebuf);
+			  const gdb_byte *ptr
+			    = writebuf + info.argloc[1].c_offset;
+			  riscv_regcache_cooked_write
+			    (regnum, ptr, info.argloc[1].c_length,
+			     regcache, call_info.flen);
 			}
 		      break;


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2020-03-25 11:35 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-25 11:35 [binutils-gdb] gdb/riscv: Apply NaN boxing when writing return values into registers Andrew Burgess

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).