[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
- [avr-libc-dev] Printing octal (brain dump), George Spelvin, 2016/12/14
- [avr-libc-dev] Working octal code (FYI), George Spelvin, 2016/12/16
- Re: [avr-libc-dev] Printing octal (brain dump), George Spelvin, 2016/12/19
- Re: [avr-libc-dev] Printing octal (brain dump), Georg-Johann Lay, 2016/12/19
- Re: [avr-libc-dev] Printing octal (brain dump), Georg-Johann Lay, 2016/12/21
- Re: [avr-libc-dev] Printing octal (brain dump), George Spelvin, 2016/12/21
- [avr-libc-dev] Even faster decimal code, George Spelvin, 2016/12/23
- Re: [avr-libc-dev] Even faster decimal code, Georg-Johann Lay, 2016/12/24
- Re: [avr-libc-dev] Even faster decimal code, George Spelvin, 2016/12/24
- Re: [avr-libc-dev] Even faster decimal code, Martin McKee, 2016/12/28
- Re: [avr-libc-dev] Even faster decimal code, George Spelvin, 2016/12/28
- Re: [avr-libc-dev] Even faster decimal code, Martin McKee, 2016/12/29
- Re: [avr-libc-dev] Even faster decimal code, George Spelvin, 2016/12/29
- Re: [avr-libc-dev] Printing octal (brain dump), George Spelvin, 2016/12/19