Paulo Marques wrote:
[...]
a = (c * 65534) >> 16;
b = c - (a * 10);
leaving you with no divisions to perform.
The main problem is that the first multiplication should be done with
some hand optimized assembly to perform a 8x16 bit multiplication,
leaving just the upper 8 bits of a 24 bit result, but it should be
doable with just 2 mul instructions and one 16 bit addition.
Actually after a few more digging, we can do this all in plain C, by
using a smaller reciprocal multiplier:
unsigned char a,b,c;
unsigned int r;
r = c * 205;
a = r / 2048;
b = c - (a * 10);
generates this code with avr-gcc 4.2.1:
r = c * 205;
a = r / 2048;
d8: 2d ec ldi r18, 0xCD ; 205
da: 82 9f mul r24, r18
dc: 90 01 movw r18, r0
de: 11 24 eor r1, r1
e0: 23 2f mov r18, r19
e2: 33 27 eor r19, r19
e4: 26 95 lsr r18
e6: 26 95 lsr r18
e8: 26 95 lsr r18
b = c - (a * 10);
ea: 9a e0 ldi r25, 0x0A ; 10
ec: 92 9f mul r25, r18
ee: 90 2d mov r25, r0
f0: 11 24 eor r1, r1
f2: 89 1b sub r24, r25
This is slightly larger than 22 bytes (28 bytes), but it should execute
in just 16 cycles. We could certainly improve the size a little with
hand optimized assembly, though.
--
Paulo Marques
Software Development Department - Grupo PIE, S.A.
Phone: +351 252 290600, Fax: +351 252 290601
Web: www.grupopie.com
"God is real, unless declared integer."
_______________________________________________
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list