http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58390
Georg-Johann Lay <gjl at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|UNCONFIRMED |RESOLVED
CC| |gjl at gcc dot gnu.org
Resolution|--- |INVALID
--- Comment #1 from Georg-Johann Lay <gjl at gcc dot gnu.org> ---
(In reply to semicontinuity from comment #0)
> Trying to speed up the following code, I've placed 'address' variable to the
> r2:r3 (and added -ffixed-r2 -ffixed-r3):
>
> // -------------------------------------------------------------------------
> //void* address; // placed in memory (OK)
> //register void* address asm("r30"); // placed in r30:r31 (OK)
> register void* address asm("r2"); // placed in r2:r3 or any other register
> (NOT OK)
>
> void test(void) {
> char flag = 1;
>
> goto *address; // address is computed properly beforehand
>
> for(;;) {
>
> asm volatile("nop\t\n");
>
>
> flag = 0;
> L1: (void)&&L1;
> if (flag==0) { address = &&L1; return; }
>
> asm volatile("nop\t\n");
>
> flag = 0;
> L2: (void)&&L2;
> if (flag==0) { address = &&L2; return; }
>
> }
> }
>
>
> int main(void) {
>
> for(;;) {
> test();
> }
>
> return 0;
> }
> // -------------------------------------------------------------------------
>
> If 'address' variable is placed in memory or in r30:r31, the generated code
> is OK:
> // -------------------------------------------------------------------------
> 0000003c <test>:
> register void* address asm("r30");
>
> void test(void) {
> 3c: 09 94 ijmp
>
> goto *address; // address is computed properly
>
> for(;;) {
>
> asm volatile("nop\t\n");
> 3e: 00 00 nop
> // -------------------------------------------------------------------------
>
> ijmp is generated for computed goto, address is already in r30:r31 for ijmp.
>
>
> If 'address' variable is placed in memory or in r2:r3, the generated code is
> NOT OK:
>
> // -------------------------------------------------------------------------
> 0000003c <test>:
> register void* address asm("r2");
>
> void test(void) {
> 3c: 2f 92 push r2
> 3e: 3f 92 push r3
> 40: 08 95 ret
>
> goto *address; // address is computed properly
>
> for(;;) {
>
> asm volatile("nop\t\n");
> 42: 00 00 nop
> // -------------------------------------------------------------------------
>
> No ijmp is generated. Instead, push r2, push r3 and ret. No pops are
> generated.
This PUSH/PUSH/RET sequence is in order because is acts exactly like an IJMP
for targets with 16-bit PC. This is the case for ATmega8535 as of
-mmcu=atmega8535.
FYI, reserving r30/r31 (Z-reg) might break code because there are situations
where the compiler cannot generate code without using Z, e.g. when reading from
flash by means of LPM. Or indirect addressing when a frame pointer is needed
and Y cannot be used for addressing.