Hallo!
Es geht hier um den AVR-GCC.
Ich müsste folgendes realisieren:
1
uint32_ta;
2
uint8_tb;
3
4
b=(a&0x3FC00000)>>22;
Der Compiler macht dann genau das, was man erwartet- eine Schleife mit
22 Durchläufen und benutzt dabei alle vier Register, die für den 32Bit-
Integer benutzt werden.
Rein logisch könnte man ja auch die oberen 16Bit von a "abknipsen" und
nur um sechs stellen schieben, so dass auch im assembler nur die beiden
oberen Register von a angesprochen werden.
Geht das oder kommt man da um den inline- assembler nicht herum?
Danke,
Heiko.
10 Takte, gcc 4.3.3:
b = ((unsigned)(a >> 16) << 2) >> 8;
Varianten über Speicher haben Nachteile. Der übrige Code, der auf die
Variablen zugreift, wird aufwendiger weil nicht in Register. Und es
erwingt oft einen teuren Stackframe.
A. K. wrote:
> 10 Takte, gcc 4.3.3:> b = ((unsigned)(a >> 16) << 2) >> 8;>> Varianten über Speicher haben Nachteile. Der übrige Code, der auf die> Variablen zugreift, wird aufwendiger weil nicht in Register. Und es> erwingt oft einen teuren Stackframe.
Kommt drauf an, ob der Wert auto/parameter ist oder nicht.
> arm-none-eabi-gcc -O2 -S dummy.c> Sorry ;)
Und?
Heiko L. wrote:
> Es geht hier um den AVR-GCC.
Oder hast du per avr-gcc -B... nen anderen cc1 reingestöpselt? ;-)
Johann
A. K. wrote:
> 10 Takte, gcc 4.3.3:> b = ((unsigned)(a >> 16) << 2) >> 8;>> Varianten über Speicher haben Nachteile. Der übrige Code, der auf die> Variablen zugreift, wird aufwendiger weil nicht in Register. Und es> erwingt oft einen teuren Stackframe.
Das braucht bei mir 19 Takte (a ist eine globale Variable im ram -> 4
mal LDS...), also einen Takt weniger als die "Pointer- Version", aber
immerhin!
Jetzt habe ich noch etwas probiert:
1
b=(*((uint16_t*)&a+1)<<2)>>8;
17 Takte!
Diese Version profitiert wohl einmal davon, dass hier wirklich nur das
"high word" aus dem Speicher geholt wird (a ist global) und dann von dem
einen "2er shift", der "8er shift" wird ja zu einer "Kopieraktion".
Danke!