avr-libc-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[avr-libc-dev] mem_tod.S


From: George Spelvin
Subject: [avr-libc-dev] mem_tod.S
Date: 20 Dec 2016 02:45:25 -0500

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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]