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


On Wed, May 12, 2004 at 12:13:17PM -0400, Ian Lance Taylor wrote:
> 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.

  This is only true if GCC can ignore "register asm()", can it? If thats
  the case than this is surprsing. Why does it work with the bar call
  removed? That shouldn't change anything.

> 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.

  Yes, the constraine did only say "r". If I use "a" GCC puts the value
  into "A2" which isn't any better.

> However, since you assumed that the input would be in A6, that didn't
> work.

  I need all values in exactly the registers as specified. "register asm()"
  was helpful to let the compiler choose an appropriate addressing mode.

> 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.

  Well, GCC might insert the correct address register but that would help
  since the value _must_ be in A6.

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

  Doesn't help.

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

  I changed __v1 and __v2 to d2 and a2. GCC uses these registers (which are
  not clobbered) but for _bn it uses d3 now.

  Gunther


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