This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] S/390: Addends of larl operand must be in -/+2GB range


Hello,

the attached patch fixes a problem with addends to larl 
(load address relative long) operands getting too large.

The patch consists of what Michael proposed in the PR 
plus the changes proposed by Ulrich.

I'm about to test the patch for gcc 4.1 4.2 and mainline.

Ok for these 3 - in case there are no testsuite regressions?

Michael, thanks for looking into this.


Bye,

-Andreas-


2006-11-24  Michael Matz  <matz@suse.de>
            Andreas Krebbel  <krebbel1@de.ibm.com>

	PR target/29319
	* config/s390/s390.c (legitimize_pic_address): Check addend of larl
	operand to be in range of -/+2GB.
	* config/s390/predicates.md (larl_operand): Likewise.


2006-11-24  Michael Matz  <matz@suse.de>
            Andreas Krebbel  <krebbel1@de.ibm.com>

	PR target/29319
	* gcc.dg/20061124-2.c: New testcase.


Index: gcc/config/s390/s390.c
===================================================================
*** gcc/config/s390/s390.c.orig	2006-11-24 13:39:20.000000000 +0100
--- gcc/config/s390/s390.c	2006-11-24 15:52:21.000000000 +0100
*************** legitimize_pic_address (rtx orig, rtx re
*** 3002,3008 ****
  		|| (GET_CODE (op0) == SYMBOL_REF && SYMBOL_REF_LOCAL_P (op0)))
  	      && GET_CODE (op1) == CONST_INT)
  	    {
!               if (TARGET_CPU_ZARCH && larl_operand (op0, VOIDmode))
                  {
                    if (INTVAL (op1) & 1)
                      {
--- 3002,3011 ----
  		|| (GET_CODE (op0) == SYMBOL_REF && SYMBOL_REF_LOCAL_P (op0)))
  	      && GET_CODE (op1) == CONST_INT)
  	    {
!               if (TARGET_CPU_ZARCH
! 		  && larl_operand (op0, VOIDmode)
! 		  && INTVAL (op1) < (HOST_WIDE_INT)1 << 31
! 		  && INTVAL (op1) >= -((HOST_WIDE_INT)1 << 31))
                  {
                    if (INTVAL (op1) & 1)
                      {
*************** legitimize_pic_address (rtx orig, rtx re
*** 3012,3018 ****
  
                        if (!DISP_IN_RANGE (INTVAL (op1)))
                          {
!                           int even = INTVAL (op1) - 1;
                            op0 = gen_rtx_PLUS (Pmode, op0, GEN_INT (even));
  			  op0 = gen_rtx_CONST (Pmode, op0);
                            op1 = const1_rtx;
--- 3015,3021 ----
  
                        if (!DISP_IN_RANGE (INTVAL (op1)))
                          {
!                           HOST_WIDE_INT even = INTVAL (op1) - 1;
                            op0 = gen_rtx_PLUS (Pmode, op0, GEN_INT (even));
  			  op0 = gen_rtx_CONST (Pmode, op0);
                            op1 = const1_rtx;
Index: gcc/config/s390/predicates.md
===================================================================
*** gcc/config/s390/predicates.md.orig	2006-11-24 15:44:13.000000000 +0100
--- gcc/config/s390/predicates.md	2006-11-24 15:52:32.000000000 +0100
***************
*** 126,133 ****
        if (GET_CODE (XEXP (op, 1)) != CONST_INT
            || (INTVAL (XEXP (op, 1)) & 1) != 0)
          return false;
!       if (INTVAL (XEXP (op, 1)) >= (HOST_WIDE_INT)1 << 32
! 	  || INTVAL (XEXP (op, 1)) < -((HOST_WIDE_INT)1 << 32))
          return false;
        op = XEXP (op, 0);
      }
--- 126,133 ----
        if (GET_CODE (XEXP (op, 1)) != CONST_INT
            || (INTVAL (XEXP (op, 1)) & 1) != 0)
          return false;
!       if (INTVAL (XEXP (op, 1)) >= (HOST_WIDE_INT)1 << 31
! 	  || INTVAL (XEXP (op, 1)) < -((HOST_WIDE_INT)1 << 31))
          return false;
        op = XEXP (op, 0);
      }
Index: gcc/testsuite/gcc.dg/20061124-2.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/20061124-2.c	2006-11-24 15:59:37.000000000 +0100
***************
*** 0 ****
--- 1,32 ----
+ { dg-compile }
+ { dg-options "-O1 -fPIC" }
+ 
+ /* PR target/29319 */
+ 
+ extern void abort(void);
+ 
+ static char l_info[100];
+ 
+ void bug1 (unsigned long tag)
+ {
+   char *info = l_info;
+   info[tag - 0x100000000 + 1] = 1;
+ }
+ 
+ void bug2 (unsigned long tag)
+ {
+   char *info = l_info;
+   info[tag - 0x100000000 + 1] = 2;
+ }
+ 
+ int main()
+ {
+   unsigned i;
+   for (i = 0; i < sizeof(l_info); i++)
+     l_info[i] = 0;
+   bug1(0x100000000);
+   bug2(0x100000000);
+   if (l_info[2] != 2 || l_info[1] != 1)
+     abort();
+   return 0;
+ }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]