Hallo,
wieder so eine Sache, die sich mir nicht erschließt:
MODULATE_A ist hier ein Bitfeld von einem Bit Breite, das auf ein SFR
außerhalb des I/O-Bereiches zeigt (hier TIMSK, Details im Anhang).
Dann nehme man folgende Schnippsel her:
1 | /* Variante A */
|
2 | if (phase_a > 0)
|
3 | MODULATE_A = 1;
|
4 | else
|
5 | MODULATE_A = 0;
|
und
1 | /* Variante B */
|
2 | MODULATE_A = (phase_a > 0);
|
Da fällt auf (avr-gcc 4.5.1, -Os): Bei Variante A werden schlicht und
ergreifend zwei Masken erzeugt und mit ori und andi verarbeitet:
1 | 520: 49 b7 in r20, 0x39 ; 57
|
2 | 522: 88 23 and r24, r24
|
3 | 524: 11 f0 breq .+4 ; 0x52a <__stack+0xcb>
|
4 | 526: 48 60 ori r20, 0x08 ; 8
|
5 | 528: 01 c0 rjmp .+2 ; 0x52c <__stack+0xcd>
|
6 | 52a: 47 7f andi r20, 0xF7 ; 247
|
7 | 52c: 49 bf out 0x39, r20 ; 57
|
Wohingegen der GCC sich bei zweiter Variante mit obskuren Operationen
abquält:
1 | 4fe: 41 e0 ldi r20, 0x01 ; 1
|
2 | 500: 88 23 and r24, r24
|
3 | 502: 09 f4 brne .+2 ; 0x506 <__stack+0xa7>
|
4 | 504: 40 e0 ldi r20, 0x00 ; 0
|
5 | 506: 42 95 swap r20
|
6 | 508: 40 7f andi r20, 0xF0 ; 240
|
7 | 50a: 89 b7 in r24, 0x39 ; 57
|
8 | 50c: 8f 7e andi r24, 0xEF ; 239
|
9 | 50e: 84 2b or r24, r20
|
10 | 510: 89 bf out 0x39, r24 ; 57
|
Woher kommt das denn? Je nachdem, welches Bit gemeint ist (hier OCIE1A)
schiebt und rotiert und addiert er sich einen zurecht und macht
eigentlich alles, nur nicht das schicke, schlanke ori/andi von zuvor.
Danke und Gruß,
Sven