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.