Code: #include <avr/io.h> register uint8_t test asm("r2"); int main(void) { test = TCNT0; } Compiled with -Os results in the following instruction sequence: 00000092 <main>: 92: 82 b7 in r24, 0x32 ; 50 94: 28 2e mov r2, r24 96: 08 95 ret This is particularly nasty for naked interrupts, where one would expect the compiler to generate just a single instruction: in r2, 0x32 Apparently the compiler behaves correctly when opposite transfer is requested, generating single OUT opcode.
This bug is invalid. Your test code is in main() which returns an int. The return value is stored in r24. So the code is correct to store the value in both r2 (test) and r24. See the avr-libc user manual, FAQ, for more information on the calling convention: http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_reg_usage Perhaps you need to try this in a function that has void return.
I can't see how register usage and calling convention affect this. As I said before, this behaviour bit me in a naked interrupt handler, with no arguments and no return value. I'm attaching a fixed test case where functions have no arguments and void return type. #include <avr/io.h> register uint8_t test asm("r2"); void fun1(void) { test = TCNT0; } void fun2(void) { TCNT0 = test; } Compile with -Os. Generated instruction sequence: 00000000 <fun1>: 0: 82 b7 in r24, 0x32 ; 50 2: 28 2e mov r2, r24 4: 08 95 ret 00000006 <fun2>: 6: 22 be out 0x32, r2 ; 50 8: 08 95 ret
Created attachment 17545 [details] Second test case with void functions.
This might be the case hard registers are not always copy propogated except into inline-asm. Can you provide the preprocessed source?
Created attachment 17553 [details] Preprocessed source of test case Created with "avr-gcc -v -save-temps -mmcu=attiny13 -Os -c test.c -o test.o"
Confirmed on 4.3.2.