Sziasztok!
Adott AVR8 alatt egy egyszeru problema: ossze kellene szorozni egy 32bites es egy 8bites szamot. Ha csinalok erre egy ilyesmit, hogy
static inline uint32_t mul32x8(uint32_t a,uint8_t b)
{
return(a*b);
}
akkor ez nagyon lassu lesz. Tobbek kozott azert mert 32x32bites szorzasra alakitja es egy avr-libc konyvtarban implementalt (valami __mul32... jellegu nevvel megaldott) fuggvenyt hiv. Es ez ugye egy RISC architektura alatt (plane 8 biten) koltseges. Marmint mind az a luxus hogy 8bit helyett 32bittel dolgozunk, mind a fuggvenyhivas.
Nosza, irjuk meg asm-ben. Halistennek a linuxos avr-gcc fejleszteseben is tevekenyen ott van az Atmel, a referenciadoksi is nagyon jo, igy szepen el lehet indulni. Ossze is sikerult dobni egy ilyet:
static inline uint32_t mul32x8(uint32_t a,uint8_t b)
{
uint32_t prod;
__asm__
(
" mul %A[a], %[b] \n\t"
" mov %A[p], r0 \n\t"
" mov %B[p], r1 \n\t"
" eor %C[p], %C[p] \n\t"
" eor %D[p], %D[p] \n\t"
" mul %B[a], %[b] \n\t"
" add %B[p], r0 \n\t"
" adc %C[p], r1 \n\t"
" mul %C[a], %[b] \n\t"
" add %C[p], r0 \n\t"
" adc %D[p], r1 \n\t"
" mul %D[a], %[b] \n\t"
" add %D[p], r0 \n\t"
: [p] "=&d" (prod)
: [a] "d" (a), [b] "d" (b)
: "r0", "r1", "cc"
);
return(prod);
}
Offline debugger szerint is megy, jo kodot is general (avr-objdump -d), elesben is majdnem mukodik, csak neha nem. Akkor viszont valahogy ugy kifagyasztja az MCU-t hogy WDR-ig se sikerul eljutnia :] Akkor nem mukodik (neha), ha ket egymas koveto" szorzas van, kis egyeb aritmetikaval (pl osszeadas). Igy felmerul a lehetoseg, hogy optimalizacio (-O3) soran valamit a parameter-regiszterekkel (lasd [p], [a], [b]) igencsak osszekavar itten.
Szoval a lenyegi kerdes: van-e valakinek tapasztalata hogy gcc inline asm mellett az output es/vagy input parametereknel az egyes regisztereket hogyan erdemes es/vagy ajanlott beallitani? Esetleg pont AVR8 alatt? A "d" itten kvazi hasrautes szeru" volt, de ha pl =&d helyett csak =d-t adok meg outputkent akkor az -O3-as kod mar debugger szinten nem lesz jo. A clobber szekcioban meg az r0, r1 es a flags-on kivul mast csakcsak nem kell megadni (a mul explicite csak az r0,r1-et bantja, a tobbi meg csak a parametereit es a cc-t). De valszeg a kiakada's azert van mert itten rosszul adok meg valamit... Lehet hogy "d" helyett "a" kene? A referencia szepen osszefoglalja az opciokat (r, d, a, l, ...) de hogy ebben az esetben mi a banat baja lehet azt nem tudom...
thx, A
Hozzászólások
Úgy rémlik, hogy az r1 a __zero_reg__, a libc sok helyen feltételezi, hogy 0 van benne, emiatt, ha megváltoztattuk, akkor illendő törölni a használat végén.
Koszi, igen, lehet hogy ez lesz az! Lasd pl itten.
Ettol fuggetlenul kerdes, hogy a clobber erre nem ad-e valami automatikus megodast. Merthogy annak pont az a celja hogy explicit jelezzuk hogy milyen regisztereket piszkaltunk meg az asm kodban. Illetve ezzel fenntartho (lenne) a ko'd "hordozhatosaga is" (maramennyiben asm eseten erdemes ilyesmirol beszelni...:]).
Igen, ez volt az! Egy
sor a ve'ge'n megoldotta a dolgot. Ugylatszik a clobber szekcioban felsorolt r1 az nem segit, vagyis onmagaban keve's.