Das push muss doch vor dem ldi stehen, sonst zerstört die ISR R24. Ausserdem "weiß" GCC nicht, welche Register eine Funktion verwendet, bzw. es wird davon ausgegangen, daß die Werte in R18-R27 und Z zerstört werden (siehe Registerverwendung).
Jedenfalls scheint das ganze komplizierter zu sein, als es auf den ersten Blick erscheint...
So könnte es gehen, zumindest für 2 ISRs:
Code:
// Jump to Symbol sym
#define jump(sym) \
__asm__ __volatile ("rjmp " #sym)
// Set T-Flag
#define set() \
__asm__ __volatile ("set")
// Clear T-Flag
#define clt() \
__asm__ __volatile ("clt")
// Load Bit n with T-Flag
#define bld(n) \
({ \
unsigned char _x; \
__asm__ __volatile ("bld %0, %1" : "=r" (_x) : "M" (n)); \
_x & (1 << (n)); \
})
char blah;
SIGNAL (foo)
{
if (bld(0) & 1)
blah = 1;
else
blah = -1;
}
void __attribute__ ((naked))
SIG_INTERRUPT0()
{
clt();
jump (foo);
}
void __attribute__ ((naked))
SIG_INTERRUPT1()
{
set();
jump (foo);
}
Das ergibt
Code:
0000005c <foo>:
5c: 1f 92 push r1
5e: 0f 92 push r0
60: 0f b6 in r0, 0x3f ; 63
62: 0f 92 push r0
64: 11 24 eor r1, r1
66: 8f 93 push r24
;;;;;;;;;;;;; Prolog Ende
68: 80 f9 bld r24, 0
6a: 80 ff sbrs r24, 0
6c: 02 c0 rjmp .+4 ; 0x72
6e: 81 e0 ldi r24, 0x01 ; 1
70: 01 c0 rjmp .+2 ; 0x74
72: 8f ef ldi r24, 0xFF ; 255
74: 80 93 7b 00 sts 0x007B, r24
;;;;;;;;;;;;; Epilog Anfang
78: 8f 91 pop r24
7a: 0f 90 pop r0
7c: 0f be out 0x3f, r0 ; 63
7e: 0f 90 pop r0
80: 1f 90 pop r1
82: 18 95 reti
00000084 <__vector_1>:
84: e8 94 clt
86: ea cf rjmp .-44 ; 0x5c
00000088 <__vector_2>:
88: 68 94 set
8a: e8 cf rjmp .-48 ; 0x5c
Das geht aber nur mit 2 ISRs
Ausserdem wird das T-Flag durch die ISR zerstört. Weiter tragisch ist das nicht, weil es nicht von GCC verwendet wird. Aber sonstwo kann man es auch nicht mehr verwenden.
Das in einem globalen Register zu merken geht auch nicht. Das Register kann nur R16-R31 sein, weil R0-R15 kein andi, ori kennen. Und von den Registern kann man keines global machen, ausser evtl. R26, R27, was aber überall zu deutlich mieserem Code führen durfte!
Lesezeichen