From patchwork Thu May 26 16:56:34 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julian Brown X-Patchwork-Id: 97597 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id AA72FB6F90 for ; Fri, 27 May 2011 02:56:59 +1000 (EST) Received: (qmail 1488 invoked by alias); 26 May 2011 16:56:58 -0000 Received: (qmail 1479 invoked by uid 22791); 26 May 2011 16:56:56 -0000 X-SWARE-Spam-Status: No, hits=-1.6 required=5.0 tests=AWL, BAYES_00, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 26 May 2011 16:56:40 +0000 Received: (qmail 2886 invoked from network); 26 May 2011 16:56:39 -0000 Received: from unknown (HELO rex.config) (julian@127.0.0.2) by mail.codesourcery.com with ESMTPA; 26 May 2011 16:56:39 -0000 Date: Thu, 26 May 2011 17:56:34 +0100 From: Julian Brown To: gcc-patches@gcc.gnu.org Subject: [PATCH] ARM fixed-point support [5.5/6]: argument & return padding for libcalls Message-ID: <20110526175634.4bcab9b5@rex.config> Mime-Version: 1.0 X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org 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. commit e3b8b63431fc1d701ac5d3cafd19c24e6d3b5c6e Author: Julian Brown 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; }