more than 10 operands in `asm'
Richard Earnshaw
rearnsha@arm.com
Wed Nov 4 03:10:00 GMT 1998
> Hope this isn't a FAQ...
>
> I suppose we've all seen the "more than 10 operands in `asm'" error
> message from time to time.
>
> How about upping the limit from 10 to something more reasonable?
>
> On Alpha we have 32 each of integer and float registers. On ARM we
> can run out with a single instruction!:
>
> U32 a,b,c,d,e,f,g,h,i, *p;
>
> asm ( "ldmia %0!, { %2,%3,%4,%5,%6,%7,%8,%9,%10 }"
> : "=r"(p)
> : "0"(p), "r"(a), "r"(b), "r"(c), "r"(d), "r"(e), "r"(f), "r"(g)
> , "r"(h), "r"(i)
> : "memory"
> );
>
> A limit of 10 often restricts inline ASM to trivial snippets of code,
> especially as in & out registers get counted twice. The patch is
> probably a one-liner somewhere.
>
This would rarely be a good idea, particularly on an ARM. If you try to
pass this many arguments to an ASM, all in registers, it is almost certain
to cause the compiler to fail since it won't be able to work out how to
marshall the arguments in the way that is necessary. Further, if there
are any other variables in your function, they would all get forced out
into the stack if they happened to be live across the asm (since you have
used all the available registers for your asm). You will almost certainly
get better overall code by breaking the instruction down into asms that do
smaller amounts of work. If that can't be done for some reason, you would
probably be better off coding it as a separate function and doing it
entirely in assembler.
I guess the limit of 10 operands is pretty arbitrary, but it should be
taken as an indication that if you want to violate it, you are probably
not doing things the best way.
Now to some ARM specific reasons why this would be a bad thing.
1) Load/store multiple instructions push arguments sequentially by
register number, so your above example almost certainly wouldn't give you
what you would expect. By way of example, if you write:
stmfd sp!, {r1, r0, r4, r2, r3}
your stack will be
+-----------+
| r4 |
+-----------+
| r3 |
+-----------+
| r2 |
+-----------+
| r1 |
+-----------+
| r0 | <---- New value of sp points here
+-----------+
So in practice, it is rarely possible to use ldm/stm from an ASM on the
ARM, because it is not possible to control the register allocation. Note
this is still the case internally to the compiler which is why load/store
multiple instructions don't get used in generated code as often as they
might.
Note, gas will emit a warning if you try to assemble an ldm/stm with
out-of-order registers.
2) Using long ldm/stm sequences can push up the interrupt latency; this
might not be an issue unless you are in an RTOS enviornment.
3) Your example uses ldmia, but your arguments are coded as though you
intended stmia (I guess this is just a typo).
Richard.
More information about the Gcc-bugs
mailing list