public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] ARM fixed-point support [5.5/6]: argument & return padding for libcalls
@ 2011-05-26 17:51 Julian Brown
  2011-06-30 13:51 ` Richard Earnshaw
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Julian Brown @ 2011-05-26 17:51 UTC (permalink / raw)
  To: gcc-patches

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

This patch allows padding to be specified per-target for libcalls. This
hasn't been traditionally important, because libcalls haven't accepted
quantities which might need padding, but that's no longer true with the
new(-ish) fixed-point support helper functions.

Tested (alongside other fixed-point support patches) with cross to ARM
EABI in both big & little-endian mode (the target-specific part is to
avoid a behaviour change for half-float types on ARM). OK to apply?

Thanks,

Julian

ChangeLog

    gcc/
    * calls.c (emit_library_call_value_1): Support padding for libcall
    arguments and return values.
    * config/arm/arm.c (arm_pad_arg_upward): Pad half-float values
    downwards in big-endian mode.

[-- Attachment #2: libcall-padding-3.diff --]
[-- Type: text/x-patch, Size: 3350 bytes --]

commit e3b8b63431fc1d701ac5d3cafd19c24e6d3b5c6e
Author: Julian Brown <julian@henry8.codesourcery.com>
Date:   Thu May 26 09:06:44 2011 -0700

    Support target-specific padding for libcalls.

diff --git a/gcc/calls.c b/gcc/calls.c
index 44a16ff..9d5d294 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -3794,13 +3794,41 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
       rtx val = argvec[argnum].value;
       rtx reg = argvec[argnum].reg;
       int partial = argvec[argnum].partial;
-
+      int size = 0;
+      
       /* Handle calls that pass values in multiple non-contiguous
 	 locations.  The PA64 has examples of this for library calls.  */
       if (reg != 0 && GET_CODE (reg) == PARALLEL)
 	emit_group_load (reg, val, NULL_TREE, GET_MODE_SIZE (mode));
       else if (reg != 0 && partial == 0)
-	emit_move_insn (reg, val);
+        {
+	  emit_move_insn (reg, val);
+#ifdef BLOCK_REG_PADDING
+	  size = GET_MODE_SIZE (argvec[argnum].mode);
+
+	  /* Copied from load_register_parameters.  */
+
+	  /* Handle case where we have a value that needs shifting
+	     up to the msb.  eg. a QImode value and we're padding
+	     upward on a BYTES_BIG_ENDIAN machine.  */
+	  if (size < UNITS_PER_WORD
+	      && (argvec[argnum].locate.where_pad
+		  == (BYTES_BIG_ENDIAN ? upward : downward)))
+	    {
+	      rtx x;
+	      int shift = (UNITS_PER_WORD - size) * BITS_PER_UNIT;
+
+	      /* Assigning REG here rather than a temp makes CALL_FUSAGE
+		 report the whole reg as used.  Strictly speaking, the
+		 call only uses SIZE bytes at the msb end, but it doesn't
+		 seem worth generating rtl to say that.  */
+	      reg = gen_rtx_REG (word_mode, REGNO (reg));
+	      x = expand_shift (LSHIFT_EXPR, word_mode, reg, shift, reg, 1);
+	      if (x != reg)
+		emit_move_insn (reg, x);
+	    }
+#endif
+	}
 
       NO_DEFER_POP;
     }
@@ -3866,6 +3894,15 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
 	       valreg,
 	       old_inhibit_defer_pop + 1, call_fusage, flags, & args_so_far);
 
+  /* Right-shift returned value if necessary.  */
+  if (!pcc_struct_value
+      && TYPE_MODE (tfom) != BLKmode
+      && targetm.calls.return_in_msb (tfom))
+    {
+      shift_return_value (TYPE_MODE (tfom), false, valreg);
+      valreg = gen_rtx_REG (TYPE_MODE (tfom), REGNO (valreg));
+    }
+
   /* For calls to `setjmp', etc., inform function.c:setjmp_warnings
      that it should complain if nonvolatile values are live.  For
      functions that cannot return, inform flow that control does not
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 7d52b0e..cd32fe3 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -11375,6 +11375,15 @@ arm_pad_arg_upward (enum machine_mode mode, const_tree type)
   if (type && BYTES_BIG_ENDIAN && INTEGRAL_TYPE_P (type))
     return false;
 
+  /* Half-float values are only passed to libcalls, not regular functions.
+     They should be passed and returned as "short"s (see RTABI).  To achieve
+     that effect in big-endian mode, pad downwards so the value is passed in
+     the least-significant end of the register.  ??? This needs to be here
+     rather than in arm_pad_reg_upward due to peculiarity in the handling of
+     libcall arguments.  */
+  if (BYTES_BIG_ENDIAN && mode == HFmode)
+    return false;
+
   return true;
 }
 

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

end of thread, other threads:[~2011-08-25 17:57 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-26 17:51 [PATCH] ARM fixed-point support [5.5/6]: argument & return padding for libcalls Julian Brown
2011-06-30 13:51 ` Richard Earnshaw
2011-08-01 13:39 ` H.J. Lu
2011-08-01 13:52   ` H.J. Lu
2011-08-01 13:55     ` H.J. Lu
2011-08-01 14:24       ` Julian Brown
2011-08-07 18:50 ` Richard Sandiford
2011-08-18 21:37   ` Andrew Pinski
2011-08-24 18:09   ` Julian Brown
2011-08-25  7:35     ` Julian Brown
2011-08-25 18:46       ` RFA: PR 50061/50113: BLOCK_REG_PADDING " Richard Sandiford

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