Q:

AVR: problem with inline assembler

WinAVR seems to produce a lot of useless code, e.g. for following C method
ISR(INT0_vect) {
    TCCR1B = 0x09;
}

it produces (-Os)
PUSH      R1             Push register on stack
PUSH      R0             Push register on stack
IN        R0,0x3F        In from I/O location
PUSH      R0             Push register on stack
CLR       R1             Clear Register
PUSH      R24            Push register on stack
LDI       R24,0x09       Load immediate
STS       0x0081,R24     Store direct to data space
POP       R24            Pop register from stack
POP       R0             Pop register from stack
OUT       0x3F,R0        Out to I/O location
POP       R0             Pop register from stack
POP       R1             Pop register from stack
RETI                     Interrupt return

although
PUSH      R0            Push register on stack
LDI       R0,0x09       Load immediate
STS       0x0081,R0     Store direct to data space
POP       R0            Pop register from stack
RETI                    Interrupt return

should be sufficient. Because these extra commands take time, my question: how to tell the compiler to produce only the required code? Or is there a tool which can optimize the byte code directly?
UPDATE:
I've tried
ISR(INT0_vect, ISR_NAKED) {
    asm volatile(
    "push r0             \n\t"
    "ldi  r0, %[value]   \n\t"
    "sts  %[ioReg], r0   \n\t"
    "pop  r0             \n\t"
    "reti                \n\t"
    : // output
    : // input
       [ioReg] "M" (_SFR_IO_ADDR(TCCR1B)),
       [value] "M" (0 << ICNC1
                  | 0 << ICES1 
                  | 0 << WGM13 
                  | 1 << WGM12
                  | 0 << CS12
                  | 0 << CS11 
                  | 1 << CS10)
    );
}

but the compiler complains:
c:\temp/ccjBxDFz.s: Assembler messages:
c:\temp/ccjBxDFz.s:30: Error: register number above 15 required

I've read a lot of AVR inline assembler documentation/tutorials, but can't get it to compile.

A:

The problem was the usage of r0. With r16 it works:
ISR(INT0_vect, ISR_NAKED) {
    asm volatile(
    "push r16             \n\t"
    "ldi  r16, %[value]   \n\t"
    "sts  %[ioReg], r16   \n\t"
    "pop  r16             \n\t"
    "reti                 \n\t"
    : // output
    : // input
       [ioReg] "M" (_SFR_IO_ADDR(TCCR1B)),
       [value] "M" (0 << ICNC1
                  | 0 << ICES1 
                  | 0 << WGM13 
                  | 1 << WGM12
                  | 0 << CS12
                  | 0 << CS11 
                  | 1 << CS10)
    );
}

