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: decl_conflicts_with_clobbers_p problem


On Thu, Mar 13, 2003 at 06:04:53PM +0100, Hans-Peter Nilsson wrote:
> > #define SendIO(ioRequest) \
> > 	LP1NR(0x1ce, SendIO, struct IORequest *, ioRequest, a1, \
> > 	, EXEC_BASE_NAME)
> 
> If you have control over the system, I suggest consider passing
> all parameters in the same register to avoid confusion, for
> programmers more than for GCC. ;-)

  The progammer cannot (hopefully! :) get confused because he includes an
  appropriate header for the system module where all the magic is done.
  That header is generated from a description file listing all module
  functions with their arguments and into which register they belong.

>  But I assume you don't.

  ;-)

> Still, consider a solution where you do not need to specify
> matching register name *and* system call in the macro.  It's a
> recipe for bugs.

  AFAIK, it was done to be able to use these generic LP* macros. There
  are much macros like that taking more arguments.

> Instead parametrize the register name on the syscall name.

  This is tedious because every function has a different requirement.
  The example function used "a1" other might use "d0", "d1" or "d0"
  and "a0" or ... The system ABI defines "d0", "d1", "a0" and "a1" as
  scratch registers, thats why they are listed in the clobber list.

> > The clobber list contains all registers that can be changed by a system
> > function as defined by the system ABI.
> 
> The clobber list must not contain inputs nor outputs.

  I have read the paragraph about extended asm in the manual again.

> > In this example the system function
> > expects its argument in register "a1". Thus the value for _n1 is bound to
> > register "a1" and passed as an input to the asm() statement.
> 
> With the actual register name *as a parameter*, it seems.

  Yes.

> No, you can't parametrize it simply like that.

  Thats unfortunate :-(

> Why not use different macros, since you list the register at the point of
> the macro call anyway?

  Because it was meant to be generic macros.

> Or without code changes elsewhere than
> the macro definition, use a trick like
>  #define LP1NR(offs, name, t1, v1, r1, bt, bn) LP1NR_##r1 (offs, name, t1, v1, bt, bn)
> and define different
>  #define LP1NR_a1(offs, name, t1, v1, r1, bt, bn) ...
>  #define LP1NR_d0(offs, name, t1, v1, r1, bt, bn) ...
> with contents where each different "r1" is listed as output and
> not in the clobber list?  Or just parametrize the clobber list?

  This would result in a lot of macros because the arguments are in a
  "random" order and unpredictable.
  
> The manual (Node "Extended Asm", "Assembler Instructions with C
> Expression Operands") says: "you may not write a clobber
> description in a way that overlaps with an input or output
> operand" and "there is no way for you to specify that an input
> operand is modified without also specifying it as an output
> operand".  It said this *before* the decl_conflicts_with_clobbers_p
> change.

  Yes, you are right. That was in the documentation before. Now I realize
  that the topic is wrong. Actually its a question about "extended asm".
  decl_conflicts_with_clobbers_p() does "only" catch that error now.

> No; the declaration *does* conflict with the clobbers, so the
> function does its job.

  Yes. Regarding the documentation, it does only state overlaps are
  invalid. I understand that for output operands (the system uses "d0"
  to return a result which might be used as an input too). But why is
  this also required for input operands? The registers listed in the
  clobbers are scratch registers in the ABI. I was under the impression
  clobbers mean registers that are undefined *after* the asm. I don't
  understand the conflict with inputs.

> You *have* to list the register that is changed as output.  This
> is not really a change; your asm was in error before too, GCC
> just didn't notice; it'd silently generated wrong code instead.

  Yes, according the (3.x?) documentation the asm is wrong. However, I have
  never seen incorrect code beeing generated (which doesn't prove anything,
  granted) and I have used GCC alot on the system in question where these
  asm statements are required.
  (Well, its posible to use stubs but make the calls "inline" is much morf
   efficient).

> In your later email, you listed your "inputs" *only* as asm
> outputs.  That is also wrong.

  You mean the example with the additional local register variables only
  used in the output line? GCC accepted it. I hoped that this would fulfill
  the constraints of extended asm statements :-(

> Here's an example LP1NR_a1, which I hope is right.  I removed the "name"
> parameter since it seemed unnecessary and just confusing:

  It is meant to make the variable names unique and to not shadow outer
  variables. Using the function name seems to be good idea for that. Maybe
  thats not an issue.

> #define LP1NR_a1(offs, name, t1, v1, bt, bn)			\
> ({								\
>    t1 _v1 = (v1);						\
>    {								\
>       register void *const _bn __asm("a6") = (bn);		\
>       register t1 _n1 __asm("a1") = _v1;			\
>       __asm volatile ("jsr a6@(-"#offs":W)"			\
>       : "=r" (_n1)						\
>       : "r" (_bn), "0" (_n1)					\
>       : "d0", "d1", "a0", "fp0", "fp1", "cc", "memory");	\
>    }								\
> })

  Since I don't know that _n1 is bound to "a1" thats not a solution.

> Or perhaps it would be sufficient to just change the clobber
> list into a macro:
> 
> #define LP1NR(offs, name, t1, v1, r1, bt, bn)			\
> ({								\
>    t1 _##name##_v1 = (v1);					\
>    {								\
>       register void *const _##name##_bn __asm("a6") = (bn);	\
>       register t1 _n1 __asm(#r1) = _##name##_v1;		\
>       __asm volatile ("jsr a6@(-"#offs":W)"			\
>       : /* no output */					\
>       : "r" (_##name##_bn), "rf"(_n1)				\
>       : CLOBBER_LIST_EXCLUDING_##r1;				\
>    }								\
> })
> 
> with
> #define CLOBBER_LIST_EXCLUDING_a1 \
>  "d0", "d1", "a0", "fp0", "fp1", "cc", "memory"

  As already said, this doesn't work either since I have no control over the
  registers passed. There can be non-scratch ones too.

  I guess creating an appropriate macro for every function is the only
  viable solution.

  Gunther


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