This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
SH patch applied: fix target/21255
- From: Joern RENNECKE <joern dot rennecke at st dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 31 Aug 2005 20:54:43 +0100
- Subject: SH patch applied: fix target/21255
2005-08-31 J"orn Rennecke <joern.rennecke@st.com>
gcc:
PR target/21255
* sh.c (print_operand, %R and %S): Add handling of floating point
registers, memory, constants and invalid operands.
gcc/testsuite:
PR target/21255
* gcc.dg/pr21255-1.c: New test.
* gcc.dg/pr21255-2-mb.c: Likewise.
* gcc.dg/pr21255-2-ml.c: Likewise.
* gcc.dg/pr21255-3.c: Likewise.
* gcc.dg/pr21255-4.c: Likewise.
Index: config/sh/sh.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.c,v
retrieving revision 1.345
diff -p -r1.345 sh.c
*** config/sh/sh.c 23 Aug 2005 13:06:55 -0000 1.345
--- config/sh/sh.c 31 Aug 2005 18:49:49 -0000
*************** print_operand (FILE *stream, rtx x, int
*** 734,744 ****
x = mark_constant_pool_use (x);
output_addr_const (stream, x);
break;
case 'R':
! fputs (reg_names[REGNO (x) + LSW], (stream));
break;
case 'S':
! fputs (reg_names[REGNO (x) + MSW], (stream));
break;
case 'T':
/* Next word of a double. */
--- 734,799 ----
x = mark_constant_pool_use (x);
output_addr_const (stream, x);
break;
+ /* N.B.: %R / %S / %T adjust memory addresses by four.
+ For SHMEDIA, that means they can be used to access the first and
+ second 32 bit part of a 64 bit (or larger) value that
+ might be held in floating point registers or memory.
+ While they can be used to access 64 bit parts of a larger value
+ held in general purpose registers, that won't work with memory -
+ neither for fp registers, since the frxx names are used. */
case 'R':
! if (REG_P (x) || GET_CODE (x) == SUBREG)
! {
! regno = true_regnum (x);
! regno += FP_REGISTER_P (regno) ? 1 : LSW;
! fputs (reg_names[regno], (stream));
! }
! else if (MEM_P (x))
! {
! x = adjust_address (x, SImode, 4 * LSW);
! print_operand_address (stream, XEXP (x, 0));
! }
! else
! {
! rtx sub = NULL_RTX;
!
! mode = GET_MODE (x);
! if (mode == VOIDmode)
! mode = DImode;
! if (GET_MODE_SIZE (mode) >= 8)
! sub = simplify_subreg (SImode, x, mode, 4 * LSW);
! if (sub)
! print_operand (stream, sub, 0);
! else
! output_operand_lossage ("invalid operand to %%R");
! }
break;
case 'S':
! if (REG_P (x) || GET_CODE (x) == SUBREG)
! {
! regno = true_regnum (x);
! regno += FP_REGISTER_P (regno) ? 0 : MSW;
! fputs (reg_names[regno], (stream));
! }
! else if (MEM_P (x))
! {
! x = adjust_address (x, SImode, 4 * MSW);
! print_operand_address (stream, XEXP (x, 0));
! }
! else
! {
! rtx sub = NULL_RTX;
!
! mode = GET_MODE (x);
! if (mode == VOIDmode)
! mode = DImode;
! if (GET_MODE_SIZE (mode) >= 8)
! sub = simplify_subreg (SImode, x, mode, 4 * MSW);
! if (sub)
! print_operand (stream, sub, 0);
! else
! output_operand_lossage ("invalid operand to %%S");
! }
break;
case 'T':
/* Next word of a double. */
*** /dev/null 2004-06-24 19:04:38.000000000 +0100
--- testsuite/gcc.dg/pr21255-1.c 2005-08-31 19:05:05.000000000 +0100
***************
*** 0 ****
--- 1,15 ----
+ /* { dg-do compile { target "sh*-*-*" } } */
+ /* { dg-options "-O2 -fomit-frame-pointer" } */
+ /* { dg-final { scan-assembler "mov fr4,fr.; mov fr5,fr." } } */
+ double
+ f (double d)
+ {
+ double r;
+
+ #if defined (__SH_FPU_DOUBLE__) && !TARGET_SHMEDIA
+ asm ("mov %S1,%S0; mov %R1,%R0" : "=f" (r) : "f" (d));
+ #else
+ asm ("mov fr4,fr4; mov fr5,fr5");
+ #endif
+ return r;
+ }
*** /dev/null 2004-06-24 19:04:38.000000000 +0100
--- testsuite/gcc.dg/pr21255-2-mb.c 2005-08-31 19:20:33.000000000 +0100
***************
*** 0 ****
--- 1,19 ----
+ /* { dg-do compile { target "sh*-*-*" } } */
+ /* { dg-options "-mb -O2 -fomit-frame-pointer" } */
+ /* { dg-final { scan-assembler "mov @r.,r.; mov @\\(4,r.\\),r." } } */
+ double d;
+
+ double
+ f (void)
+ {
+ double r;
+
+ /* If -ml from the target options is passed after -mb from dg-options, we
+ end up with th reverse endianness. */
+ #if TARGET_SHMEDIA || defined (__LITTLE_ENDIAN__)
+ asm ("mov @r1,r3; mov @(4,r1),r4");
+ #else
+ asm ("mov %S1,%S0; mov %R1,%R0" : "=&r" (r) : "m" (d));
+ #endif
+ return r;
+ }
*** /dev/null 2004-06-24 19:04:38.000000000 +0100
--- testsuite/gcc.dg/pr21255-2-ml.c 2005-08-31 19:19:46.000000000 +0100
***************
*** 0 ****
--- 1,19 ----
+ /* { dg-do compile { target "sh*-*-*" } } */
+ /* { dg-options "-ml -O2 -fomit-frame-pointer" } */
+ /* { dg-final { scan-assembler "mov @\\(4,r.\\),r.; mov @r.,r." } } */
+ double d;
+
+ double
+ f (void)
+ {
+ double r;
+
+ /* If -mb from the target options is passed after -ml from dg-options, we
+ end up with th reverse endianness. */
+ #if TARGET_SHMEDIA || defined (__BIG_ENDIAN__)
+ asm ("mov @(4,r1),r4; mov @r1,r3");
+ #else
+ asm ("mov %S1,%S0; mov %R1,%R0" : "=&r" (r) : "m" (d));
+ #endif
+ return r;
+ }
*** /dev/null 2004-06-24 19:04:38.000000000 +0100
--- testsuite/gcc.dg/pr21255-3.c 2005-08-31 18:32:32.000000000 +0100
***************
*** 0 ****
--- 1,13 ----
+ /* { dg-do compile { target "sh*-*-*" } } */
+ /* { dg-options "-O2 -fomit-frame-pointer" } */
+ /* { dg-final { scan-assembler "mov #?0,r.*; mov #?20,r" } } */
+ /* { dg-final { scan-assembler "mov #?1077149696,r.*; mov #?0,r" } } */
+ double
+ f ()
+ {
+ double r;
+
+ asm ("mov %S1,%S0; mov %R1,%R0" : "=r" (r) : "i" (20));
+ asm ("mov %S1,%S0; mov %R1,%R0" : "+r" (r) : "i" (20.));
+ return r;
+ }
*** /dev/null 2004-06-24 19:04:38.000000000 +0100
--- testsuite/gcc.dg/pr21255-4.c 2005-08-31 19:35:50.000000000 +0100
***************
*** 0 ****
--- 1,13 ----
+ /* { dg-do compile { target "sh*-*-*" } } */
+ /* { dg-options "-O2 -fomit-frame-pointer" } */
+
+ double
+ f ()
+ {
+ double r;
+
+ asm ("mov %S1,%S0; mov %R1,%R0" : "=r" (r) : "i" (f));
+ /* { dg-error "invalid operand to %S" "" {target "sh*-*-*" } 9 } */
+ /* { dg-error "invalid operand to %R" "" {target "sh*-*-*" } 9 } */
+ return r;
+ }