This is the mail archive of the gcc@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]

Re: [m68k] asm regression with 3.3/3.4/3.5


Gunther Nikl <gni@gecko.de> writes:

> The following testcase case fails with GCC 3.3 and later when compiled with
> -O. GCC 2.95.2 generates working code. I think its a GCC3 bug. Initially the
> bug was noticed with m68k-amigaos. However, a 3.3 m68k-linux cross-compiler
> shows the same bug (there A6 has to be replaced with eg. A5 in the testcase;
> with m68k-amigaos A6 is a free register and A5 is the framepointer)
> For me this is a serious bug which could be triggered at random places.
> I would appriciate any help finding this bug.
> 
> -- cut --
> #define osfunc(v1,v2)					\
> ({							\
>  int _v1 = (v1);					\
>  int _v2 = (v2);					\
>  {							\
>    register int _d0 __asm("d0") = 0xDEADBEAF;		\
>    register int _d1 __asm("d1") = 0xDEADBEAF;		\
>    register int _a0 __asm("a0") = 0xDEADBEAF;		\
>    register int _a1 __asm("a1") = 0xDEADBEAF;		\
>    register void *const _bn __asm("a6") = (base);	\
>    register int __v1 __asm("d0") = (_v1);		\
>    register int __v2 __asm("a0") = (_v2);		\
>    __asm volatile ("jsr a6@(-0x84:W)"			\
>    : "=r" (_d0), "=r" (_d1), "=r" (_a0), "=r" (_a1)	\
>    : "r" (_bn), "rf" (__v1), "rf" (__v2)		\
>    : "fp0", "fp1", "cc", "memory");			\
>   }							\
> })
> 
> void bar(void);
> 
> void foo(void *base) {
>   for (;;) {
>     osfunc(1,2);
>     bar();
>   }
> }
> -- cut --
> 
> GCC 2.95.2 generates:
> 
> _foo:	movel a6,sp@-
> 	movel d2,sp@-
> 	movel sp@(12),d2
> L3:	movel d2,a6
> 	moveq #1,d0
> 	movew #2,a0
> #APP
> 	jsr a6@(-0x84:W)
> #NO_APP
> 	jbsr _bar
> 	jra L3
> 
> but GCC 3.3 and all later versions generate:
> 
> _foo:	movel d2,sp@-
> 	movel sp@(8),d2
> L2:	moveq #1,d0
> 	movew #2,a0
> #APP
> 	jsr a6@(-0x84:W)
> #NO_APP
> 	jbsr _bar
> 	jra L2
> 
> GCC3 "forgets" to load A6 and it doesn't save the register at all. It seems
> that GCC3 thinks A6 isn't used at all.

gcc outsmarted you.  To put it another way, gcc acted reasonably
within the constraints as you described me.

In the asm statement, you said that the input _bn could be in any
register.  You didn't say that it had to be in A6.  gcc was clever
enough to see that it could replace all the uses of _bn with base,
provided it put base in a register (constraint "r").  It decided to
store base in D2.  It even correctly did this in the asm statement.
However, since you assumed that the input would be in A6, that didn't
work.

If you change the statement to this:

   __asm volatile ("jsr %4@(-0x84:W)"			\
   : "=r" (_d0), "=r" (_d1), "=r" (_a0), "=r" (_a1)	\
   : "a" (_bn), "rf" (__v1), "rf" (__v2)		\
   : "fp0", "fp1", "cc", "memory");			\

It should work.  This says that you need an address register for _bn
(by using a constraint of "a") and then it uses whatever address
register gcc chooses in the jsr statement.  It could be any address
register, but it should work.

If you must use A6 for other reasons--if the subroutine expects
it--then you need to declare _bn to be volatile.

Similar issues did not arise for the other register input variables,
because they are clobbered by the asm statement.

Ian


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