Oops, I meant to include this last time. Note how the mod-10 reduction works, subtracting 30s until the remainder goes negative, then adding back 10s until it goes positive again. That takes an average of 12.2 cycles (averaged over all inputs 00..99).
#define __zero_reg__ r1 #define __tmp_reg__ r0 .macro DEFUN name .global \name .func \name \name: .endm .macro ENDF name .size \name, .-\name .endfunc .endm #if defined (__AVR_HAVE_JMP_CALL__) #define XCALL call #define XJMP jmp #else #define XCALL rcall #define XJMP rjmp #endif .macro wmov r_dest, r_src #if defined (__AVR_HAVE_MOVW__) movw \r_dest, \r_src #else mov \r_dest, \r_src mov \r_dest+1, \r_src+1 #endif .endm ;; End preamble #define pNum 26 #define pBuf 30 #define nBytes 20 #define Radix 18 #define Num 19 #define Count 21 #define Quot 22 #define Rem 23 ;; extern void mem_tod (char *pBuf, void *pNum, uint8_t nBytes); .section .text.mem_tod,"ax",@progbits DEFUN mem_tod wmov pBuf, 24 _mem_tod_aux: wmov pNum, 22 ldi Radix, -100 .LnextDigit: add pNum, nBytes adc pNum+1, __zero_reg__ mov Count, nBytes ;; nBytes < 0 <==> nBytes is unknown ldi nBytes, -1 clr Rem .LnextByte: ld Num, -X ldi Quot, 1 .LnextBit: ;; Bit-wise construct quotient into Quot. ;; Bit-wise reconstruct Num into Rem. lsl Num rol Rem ;; Reducing Rem mod Radix; C=1 <==> reduction applied add Rem, Radix brcs 1f sub Rem, Radix 1: rol Quot brcc .LnextBit st X, Quot breq 2f sbrc nBytes, 7 mov nBytes, Count 2: dec Count brne .LnextByte ;; Now break Rem apart into two base-10 digits ;; Use Num, because we know it's zero 3: subi Num, -3 subi Rem, 30 brcc 3b 4: dec Num subi Rem, -10 brcs 4b subi Rem, -'0' st Z+, Rem subi Num, -'0' st Z+, Num sbrs nBytes, 7 rjmp .LnextDigit ;; Chop off redundant trailing zero cpi Num, '0' brne 5f st -Z, __zero_reg__ 5: st Z, __zero_reg__ ;; pBuf survived in R25:R24 #if 0 # XJMP strrev wmov pNum, 24 7: ld Num, X ld Count, -Z st X+, Count st Z, Num /* Loop while X < Z */ cp XL, ZL cpc XH, ZH brlo 7b #endif ret ENDF mem_tod #define Minus1 Num ;; extern void mem_toa_signed (char *pBuf, void *pNum, uint8_t nBytes, uint8_t Radix); .section .text.mem_toa_signed,"ax",@progbits DEFUN mem_tod_signed wmov pBuf, 24 wmov pNum, 22 add pNum, nBytes adc pNum+1, __zero_reg__ ld __tmp_reg__, -X cp __tmp_reg__, __zero_reg__ brpl 9f ;; Negate pNum[] according to -N = ~N + 1 = ~N - (-1). ;; Carry is clear now because ADC above didn't overflow. wmov pNum, 22 mov Count, nBytes ldi Minus1, -1 1: ld __tmp_reg__, X ;; Must use EOR for complement because COM clobbers carry. eor __tmp_reg__, Minus1 sbc __tmp_reg__, Minus1 st X+, __tmp_reg__ dec Count brne 1b ldi Num, '-' st Z+, Num 9: XJMP mem_tod_aux ENDF mem_tod_signed #undef Minus1 #undef pNum #undef pBuf #undef nBytes #undef Radix #undef Rem #undef Num #undef Count #undef nBits _______________________________________________ AVR-libc-dev mailing list AVR-libc-dev@nongnu.org https://lists.nongnu.org/mailman/listinfo/avr-libc-dev