Odpovídáte na názor ke článku Počítání s přetečením v C.
Dekuji vsem diskutujicim za podmente pripominky, diky teto diskuzi jsem zjistil, ze gcc-avr podporuje i long long aritmetiku. Jaksi me nenapadlo, ze je to vlastne standard. Dal jsem zjistil, ze tento processor je osmibitovy a ne 32 bitovy - nejak jsem si prilis zvykl na ARM. Pak jsem zjistil, ze gcc-avr preklada naprosto nesmyslnym zpusobem i naprosto jednoduche long long scitani, viz [25]. Ale program fungoval, dokonce lepe nez na PIC, kde jsem to mel v assembleru. Ale nedalo mi to, pustil jsem se do optimalizaci. Nakonec jsem prepsal funkci sum do assembleru a rozepsal cykly ve volajici funkci, aby nerotovala 64 bitove, ale vzala si to byte po byte a rotovala po 8mi bitech. Doba vypoctu sla asi na ctvrtinu.
Pritom jsem jeste zjistil, ze gcc-avr nedokaze odkazovat na registry long long. Odkazy se delaji %A pro nejnizsi byte, %B pro dalsi a tak dale az po %D, ktery odkazuje na nejvyssi registr longu. Ale jaksi zapomneli podporovat %E az %G. Takze temporary registry jsem musel udelat dva longove misto jednoho long long.
No a ted ta funkce na scitani, secte dve unsigned long long cisla, a v navratove hodnote vrati carry:
typedef unsigned long long ull;
unsigned char sum(ull *r, const ull *a) // *r+=*a, returns carry
{
unsigned long int r1;
unsigned long int r2;
asm volatile(
"movw %[z],%[r]" LF
"movw %[y],%[a]" LF
"ld %A[tmp1],Z" LF
"ldd %B[tmp1],Z+1" LF
"ldd %C[tmp1],Z+2" LF
"ldd %D[tmp1],Z+3" LF
"ldd %A[tmp2],Z+4" LF
"ldd %B[tmp2],Z+5" LF
"ldd %C[tmp2],Z+6" LF
"ldd %D[tmp2],Z+7" LF
"ld __tmp_reg__, Y" LF
"add %A[tmp1], __tmp_reg__" LF
"ldd __tmp_reg__, Y+1" LF
"adc %B[tmp1], __tmp_reg__" LF
"ldd __tmp_reg__, Y+2" LF
"adc %C[tmp1], __tmp_reg__" LF
"ldd __tmp_reg__, Y+3" LF
"adc %D[tmp1], __tmp_reg__" LF
"ldd __tmp_reg__, Y+4" LF
"adc %A[tmp2], __tmp_reg__" LF
"ldd __tmp_reg__, Y+5" LF
"adc %B[tmp2], __tmp_reg__" LF
"ldd __tmp_reg__, Y+6" LF
"adc %C[tmp2], __tmp_reg__" LF
"ldd __tmp_reg__, Y+7" LF
"adc %D[tmp2], __tmp_reg__" LF
"st Z, %A[tmp1]" LF
"std Z+1, %B[tmp1]" LF
"std Z+2, %C[tmp1]" LF
"std Z+3, %D[tmp1]" LF
"std Z+4, %A[tmp2]" LF
"std Z+5, %B[tmp2]" LF
"std Z+6, %C[tmp2]" LF
"std Z+7, %D[tmp2]" LF
"clr %A[tmp1]" LF
"rol %A[tmp1]" LF // carry -> tmp1
:[z]"=z"(r), [y]"=y"(a), [tmp1]"=r"(r1), [tmp2]"=r"(r2)
:[r]"r"(r), [a]"r"(a)
);
return r1;
}