diff options
author | Ian Lance Taylor <ian@wasabisystems.com> | 2004-01-27 14:48:02 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2004-01-27 14:48:02 +0000 |
commit | b034930ffb2b6c44a85d7316b622cf4cc4df2737 (patch) | |
tree | 881e0f5d7ed2e65c7a43845def0bdf3df46207b3 /gcc | |
parent | be446dfc6bb52f0aecbc0c7fc71b7a8fbb35be4b (diff) | |
download | gcc-b034930ffb2b6c44a85d7316b622cf4cc4df2737.zip gcc-b034930ffb2b6c44a85d7316b622cf4cc4df2737.tar.gz gcc-b034930ffb2b6c44a85d7316b622cf4cc4df2737.tar.bz2 |
arm.c (output_return_instruction): Only restore IP into SP if frame_pointer_needed.
* config/arm/arm.c (output_return_instruction): Only restore IP
into SP if frame_pointer_needed.
* gcc.dg/arm-mmx-1.c: New test.
From-SVN: r76710
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 28 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/arm-mmx-1.c | 26 |
4 files changed, 54 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 58a742c..119c20a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2004-01-27 Ian Lance Taylor <ian@wasabisystems.com> + + * config/arm/arm.c (output_return_instruction): Only restore IP + into SP if frame_pointer_needed. + 2004-01-27 Eric Botcazou <ebotcazou@libertysurf.fr> * config/sparc/sparc.c (function_arg_pass_by_reference): Return 1 diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 768678d..b70e68b 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -8260,15 +8260,25 @@ output_return_instruction (rtx operand, int really_return, int reverse) return_reg = reg_names[LR_REGNUM]; if ((live_regs_mask & (1 << IP_REGNUM)) == (1 << IP_REGNUM)) - /* There are two possible reasons for the IP register being saved. - Either a stack frame was created, in which case IP contains the - old stack pointer, or an ISR routine corrupted it. If this in an - ISR routine then just restore IP, otherwise restore IP into SP. */ - if (! IS_INTERRUPT (func_type)) - { - live_regs_mask &= ~ (1 << IP_REGNUM); - live_regs_mask |= (1 << SP_REGNUM); - } + { + /* There are three possible reasons for the IP register + being saved. 1) a stack frame was created, in which case + IP contains the old stack pointer, or 2) an ISR routine + corrupted it, or 3) it was saved to align the stack on + iWMMXt. In case 1, restore IP into SP, otherwise just + restore IP. */ + if (frame_pointer_needed) + { + live_regs_mask &= ~ (1 << IP_REGNUM); + live_regs_mask |= (1 << SP_REGNUM); + } + else + { + if (! IS_INTERRUPT (func_type) + && ! TARGET_REALLY_IWMMXT) + abort (); + } + } /* On some ARM architectures it is faster to use LDR rather than LDM to load a single register. On other architectures, the diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 330d38a..a898442 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2004-01-27 Ian Lance Taylor <ian@wasabisystems.com> + + * gcc.dg/arm-mmx-1.c: New test. + 2004-01-27 Eric Botcazou <ebotcazou@libertysurf.fr> * gcc.dg/20040127-1.c: New test. diff --git a/gcc/testsuite/gcc.dg/arm-mmx-1.c b/gcc/testsuite/gcc.dg/arm-mmx-1.c new file mode 100644 index 0000000..4f95d8d1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/arm-mmx-1.c @@ -0,0 +1,26 @@ +/* Verify that if IP is saved to ensure stack alignment, we don't load + it into sp. */ +/* { dg-do compile { target arm*-*-* strongarm*-*-* xscale*-*-*} } */ +/* { dg-options "-O -mno-apcs-frame -mcpu=iwmmxt" } */ +/* { dg-final { scan-assembler "ldmfd\[ ]sp!.*ip,\[ ]*pc" } } */ + +/* This function uses all the call-saved registers, namely r4, r5, r6, + r7, r8, r9, sl, fp. Since we also save pc, that leaves an odd + number of registers, and the compiler will push ip to align the + stack. Make sure that we restore ip into ip, not into sp as is + done when using a frame pointer. The -mno-apcs-frame option + permits the frame pointer to be used as an ordinary register. */ +int +foo(int *a, int *b, int *c, int *d, int *tot) +{ + int i, j, k, l, m, n, o; + + *tot = 0; + for (i = *a; i < *b; i += *c) + for (j = *a; j < *b; j += *d) + for (k = *a; k < *c; k += *d) + for (l = *b; k < *c; k += *d) + for (m = *d; k < *c; k += *b) + *tot += i + j + k + l + m; + return *tot; +} |