http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47675
Summary: [avr] problems with asm when all registers on clobber list Product: gcc Version: 4.5.2 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: kice...@gmail.com I've noticed that, when i use a big asm routine that uses *all* of registers (r0 to r31) g++ doesn't handle it. example: class A { int d; public: A():d(0){} void test(void) { asm volatile("nop" :::"r0","r1","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12","r13","r14","r15","r16","r17","r18","r19","r20","r21","r22","r23","r24","r25","r26","r27","r28","r29","r30","r31"); d++; } int getD() const { return d; } }; int f(A *a, A* b) { a->test(); return a->getD(); } and the interesting part of the output is: 26: cd b7 in r28, 0x3d ; 61 28: de b7 in r29, 0x3e ; 62 2a: 9a 83 std Y+2, r25 ; 0x02 2c: 89 83 std Y+1, r24 ; 0x01 2e: 00 00 nop 30: e9 81 ldd r30, Y+1 ; 0x01 32: fa 81 ldd r31, Y+2 ; 0x02 34: 20 81 ld r18, Z 36: 31 81 ldd r19, Z+1 ; 0x01 as you may see, just after nop execution, Y register is used (to restore Z register). The solution is to leave at least 2 register untouched (let's say I remove r20 and r21 from the clobber list) and the output is right: 24: 48 2f mov r20, r24 26: 59 2f mov r21, r25 28: 00 00 nop 2a: e4 2f mov r30, r20 2c: f5 2f mov r31, r21 2e: 20 81 ld r18, Z 30: 31 81 ldd r19, Z+1 ; 0x01 (here Z register is being restored from untouched r21:r20). For this moment gcc saves (pushes) all the registers at the begining of function (not the begining of asm routine) and restores them at the end of function (not asm routine). Maybe the solution is to restore clobbered registers just after the end of asm routine?