Наверно ещё рано идти в багтрекер, возникает вопрос зачем это сделано и нельзя ли отключить.
u16_t u_mul_u16_u88_rough(u16_t x, u16_t m)
{
union { u16_t s; u8_t b[2]; } um;
u16_t r = 0;
u8_t i = 1;
um.s = m;
do {
if (um.b[0] & i) {
r += x;
}
r >>= 1;
i <<= 1;
}
while (i != 0);
i = 1;
do {
if (um.b[1] & i) {
r += x;
}
x <<= 1;
i <<= 1;
}
while (i != 0);
return r;
}
$ avr-gcc -c util.c -Wall -pipe -std=c99 -Os -fconserve-stack -fno-strict-aliasing -mmcu=atmega16 -S
.global u_mul_u16_u88_rough
.type u_mul_u16_u88_rough, @function
u_mul_u16_u88_rough:
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
ldi r20,lo8(8)
ldi r21,hi8(8)
ldi r30,lo8(1)
ldi r18,lo8(0)
ldi r19,hi8(0)
.L29:
mov r31,r30
and r31,r22
breq .L28
add r18,r24
adc r19,r25
.L28:
lsr r19
ror r18
lsl r30
subi r20,lo8(-(-1))
sbci r21,hi8(-(-1))
brne .L29
ldi r20,lo8(8)
ldi r21,hi8(8)
ldi r22,lo8(1)
.L32:
mov r30,r22
and r30,r23
breq .L30
add r18,r24
adc r19,r25
.L30:
lsl r22
subi r20,lo8(-(-1))
sbci r21,hi8(-(-1))
breq .L31
lsl r24
rol r25
rjmp .L32
.L31:
movw r24,r18
/* epilogue start */
ret
Добавляется новый счетчик цикла в регистрах r20/r21 который, только не ясно зачем. На x86 тоже происходит что-то похожее. Но зачем? инструкция сдвига или сложения уже ставит флаги и следующей инструкцией уже может быть условный переход.
Если передать i как параметр функции то первый цикл становиться таким.
ldi r18,lo8(0)
ldi r19,hi8(0)
.L29:
mov r21,r20
and r21,r22
breq .L28
add r18,r24
adc r19,r25
.L28:
lsr r19
ror r18
lsl r20
brne .L29
Вот так и надо, было.