From patchwork Sun Jul 18 12:12:53 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 59164 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 268EAB6EFE for ; Sun, 18 Jul 2010 22:13:07 +1000 (EST) Received: (qmail 31994 invoked by alias); 18 Jul 2010 12:13:05 -0000 Received: (qmail 31983 invoked by uid 22791); 18 Jul 2010 12:13:04 -0000 X-SWARE-Spam-Status: No, hits=-1.7 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, TW_SR, T_TO_NO_BRKTS_FREEMAIL X-Spam-Check-By: sourceware.org Received: from mail-wy0-f175.google.com (HELO mail-wy0-f175.google.com) (74.125.82.175) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sun, 18 Jul 2010 12:12:58 +0000 Received: by wye20 with SMTP id 20so4189438wye.20 for ; Sun, 18 Jul 2010 05:12:56 -0700 (PDT) Received: by 10.227.32.140 with SMTP id c12mr2888512wbd.6.1279455175977; Sun, 18 Jul 2010 05:12:55 -0700 (PDT) Received: from localhost (rsandifo.gotadsl.co.uk [82.133.89.107]) by mx.google.com with ESMTPS id a1sm31765669wbb.8.2010.07.18.05.12.54 (version=TLSv1/SSLv3 cipher=RC4-MD5); Sun, 18 Jul 2010 05:12:55 -0700 (PDT) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, rdsandiford@googlemail.com Subject: [committed] Fix SCmode return values for hard-float MIPS16 Date: Sun, 18 Jul 2010 13:12:53 +0100 Message-ID: <87bpa5rnsq.fsf@firetop.home> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) MIME-Version: 1.0 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 On o64, an SCmode value is returned in either ($f0, $f2) (for hard float) or as a 64-bit value packed into $2 (for soft-float). MIPS16 code needs stubs for converting the former to the latter, but they were missing a zero-extension of the low-half of $2. This meant that a negative component in the low half would fill out the high half, turning it into a negative NaN. The bug occured in both mips.c and mips16.S. The mips.c one caused a failure in gcc.c-torture/execute with -mflip-mips16. I then wrote the attached test to confirm that the same failure occured with mips16.S stubs. Tested on mipsisa64-elfoabi and applied. Richard gcc/ * config/mips/mips.c (mips16_build_call_stub): Zero-extend the low half of a single-register SCmode return value before ORing it with the high half. * config/mips/mips16.S (MERGE_GPRf): Likewise. gcc/testsuite/ * gcc.target/mips/mips16-attributes-4.c: New test. Index: gcc/config/mips/mips.c =================================================================== --- gcc/config/mips/mips.c 2010-07-18 13:03:50.000000000 +0100 +++ gcc/config/mips/mips.c 2010-07-18 13:03:52.000000000 +0100 @@ -6318,19 +6318,28 @@ mips16_build_call_stub (rtx retval, rtx switch (GET_MODE (retval)) { case SCmode: - mips_output_32bit_xfer ('f', GP_RETURN + 1, - FP_REG_FIRST + MAX_FPRS_PER_FMT); - /* Fall though. */ - case SFmode: - mips_output_32bit_xfer ('f', GP_RETURN, FP_REG_FIRST); + mips_output_32bit_xfer ('f', GP_RETURN + TARGET_BIG_ENDIAN, + TARGET_BIG_ENDIAN + ? FP_REG_FIRST + MAX_FPRS_PER_FMT + : FP_REG_FIRST); + mips_output_32bit_xfer ('f', GP_RETURN + TARGET_LITTLE_ENDIAN, + TARGET_LITTLE_ENDIAN + ? FP_REG_FIRST + MAX_FPRS_PER_FMT + : FP_REG_FIRST); if (GET_MODE (retval) == SCmode && TARGET_64BIT) { /* On 64-bit targets, complex floats are returned in a single GPR, such that "sd" on a suitably-aligned target would store the value correctly. */ fprintf (asm_out_file, "\tdsll\t%s,%s,32\n", + reg_names[GP_RETURN + TARGET_BIG_ENDIAN], + reg_names[GP_RETURN + TARGET_BIG_ENDIAN]); + fprintf (asm_out_file, "\tdsll\t%s,%s,32\n", reg_names[GP_RETURN + TARGET_LITTLE_ENDIAN], reg_names[GP_RETURN + TARGET_LITTLE_ENDIAN]); + fprintf (asm_out_file, "\tdsrl\t%s,%s,32\n", + reg_names[GP_RETURN + TARGET_BIG_ENDIAN], + reg_names[GP_RETURN + TARGET_BIG_ENDIAN]); fprintf (asm_out_file, "\tor\t%s,%s,%s\n", reg_names[GP_RETURN], reg_names[GP_RETURN], @@ -6338,6 +6347,10 @@ mips16_build_call_stub (rtx retval, rtx } break; + case SFmode: + mips_output_32bit_xfer ('f', GP_RETURN, FP_REG_FIRST); + break; + case DCmode: mips_output_64bit_xfer ('f', GP_RETURN + (8 / UNITS_PER_WORD), FP_REG_FIRST + MAX_FPRS_PER_FMT); Index: gcc/config/mips/mips16.S =================================================================== --- gcc/config/mips/mips16.S 2010-07-18 13:03:50.000000000 +0100 +++ gcc/config/mips/mips16.S 2010-07-18 13:03:52.000000000 +0100 @@ -61,9 +61,11 @@ see the files COPYING3 and COPYING.RUNTI and so that its low 32 bits contain LOW_FPR. */ #define MERGE_GPRf(GPR, HIGH_FPR, LOW_FPR) \ .set noat; \ - mfc1 GPR, HIGH_FPR; \ mfc1 $1, LOW_FPR; \ + mfc1 GPR, HIGH_FPR; \ + dsll $1, $1, 32; \ dsll GPR, GPR, 32; \ + dsrl $1, $1, 32; \ or GPR, GPR, $1; \ .set at Index: gcc/testsuite/gcc.target/mips/mips16-attributes-4.c =================================================================== --- /dev/null 2010-07-18 09:23:39.222094797 +0100 +++ gcc/testsuite/gcc.target/mips/mips16-attributes-4.c 2010-07-18 13:03:52.000000000 +0100 @@ -0,0 +1,17 @@ +/* { dg-do run } */ +/* { dg-options "(-mips16)" } */ + +extern void abort (void); + +__complex float f = { -1.0 + -1.0i }; +__complex float __attribute__((nomips16)) foo (void) { return f; } +__complex float (*volatile foop) (void) = foo; +__complex float __attribute__((mips16, noinline)) bar (void) { return foop (); } + +int +main (void) +{ + if (bar () != f) + abort (); + return 0; +}