| 32 |
|
|
| 33 |
*/ |
*/ |
| 34 |
|
|
| 35 |
|
/* $Id$ */ |
| 36 |
|
|
| 37 |
/** \ingroup avr_pgmspace |
/** \ingroup avr_pgmspace |
| 38 |
\fn size_t strlcat_P (char *dst, PGM_P, size_t siz) |
\fn size_t strlcat_P (char *dst, PGM_P, size_t siz) |
| 50 |
|
|
| 51 |
#if !defined(DOXYGEN) |
#if !defined(DOXYGEN) |
| 52 |
|
|
|
#include "gasava.inc" |
|
| 53 |
#include "macros.inc" |
#include "macros.inc" |
| 54 |
|
|
| 55 |
#define dst_hi r25 |
#define dst_hi r25 |
| 69 |
|
|
| 70 |
.text |
.text |
| 71 |
.global _U(strlcat_P) |
.global _U(strlcat_P) |
| 72 |
.type _U(strlcat_P),@function |
.type _U(strlcat_P),@function |
| 73 |
|
|
| 74 |
_U(strlcat_P): |
_U(strlcat_P): |
| 75 |
LOAD_X (dst_lo, dst_hi) ; X = dst |
X_movw XL, dst_lo ; X = dst |
| 76 |
LOAD_Z (src_lo, src_hi) ; Z = src |
X_movw ZL, src_lo ; Z = src |
| 77 |
|
|
| 78 |
.strlcat_P_dlen: ; Find end of dst string |
.L_strlcat_P_dlen: ; Find end of dst string |
| 79 |
ld __tmp_reg__, X+ ; get next char from dst |
ld __tmp_reg__, X+ ; get next char from dst |
| 80 |
cp siz_lo, __zero_reg__ ; and calc dlen = len of dst |
cp siz_lo, __zero_reg__ ; and calc dlen = len of dst |
| 81 |
cpc siz_hi, __zero_reg__ ; size == 0 ? |
cpc siz_hi, __zero_reg__ ; size == 0 ? |
| 84 |
breq 1f ; --> done |
breq 1f ; --> done |
| 85 |
subi siz_lo, lo8(-(-1)) |
subi siz_lo, lo8(-(-1)) |
| 86 |
sbci siz_hi, hi8(-(-1)) ; siz-- |
sbci siz_hi, hi8(-(-1)) ; siz-- |
| 87 |
rjmp .strlcat_P_dlen ; --> next char |
rjmp .L_strlcat_P_dlen ; --> next char |
| 88 |
1: sbiw X_lo, 1 ; undo post increment |
1: sbiw X_lo, 1 ; undo post increment |
| 89 |
#if __AVR_ENHANCED__ |
X_movw dlen_lo, X_lo |
|
movw dlen_lo, X_lo |
|
|
#else |
|
|
mov dlen_lo, X_lo |
|
|
mov dlen_hi, X_hi |
|
|
#endif |
|
| 90 |
sub dlen_lo, dst_lo |
sub dlen_lo, dst_lo |
| 91 |
sbc dlen_hi, dst_hi ; dlen = X - dst |
sbc dlen_hi, dst_hi ; dlen = X - dst |
| 92 |
cp siz_lo, __zero_reg__ |
cp siz_lo, __zero_reg__ |
| 93 |
cpc siz_hi, __zero_reg__ ; size == 0 ? |
cpc siz_hi, __zero_reg__ ; size == 0 ? |
| 94 |
breq .strlcat_P_slen ; --> done |
breq .L_strlcat_P_slen ; --> done |
| 95 |
subi siz_lo, lo8(-(-1)) |
subi siz_lo, lo8(-(-1)) |
| 96 |
sbci siz_hi, hi8(-(-1)) ; siz-- |
sbci siz_hi, hi8(-(-1)) ; siz-- |
| 97 |
|
|
| 98 |
.strlcat_P_concat: ; Concatenate |
.L_strlcat_P_concat: ; Concatenate |
| 99 |
LPM_R0_ZP ; get next char from src |
LPM_R0_ZP ; get next char from src |
| 100 |
cp siz_lo, __zero_reg__ |
cp siz_lo, __zero_reg__ |
| 101 |
cpc siz_hi, __zero_reg__ ; size == 0 ? |
cpc siz_hi, __zero_reg__ ; size == 0 ? |
| 105 |
st X+, __tmp_reg__ ; store in dest |
st X+, __tmp_reg__ ; store in dest |
| 106 |
subi siz_lo, lo8(-(-1)) |
subi siz_lo, lo8(-(-1)) |
| 107 |
sbci siz_hi, hi8(-(-1)) ; siz-- |
sbci siz_hi, hi8(-(-1)) ; siz-- |
| 108 |
rjmp .strlcat_P_concat ; --> next char |
rjmp .L_strlcat_P_concat ; --> next char |
| 109 |
1: st X, __zero_reg__ ; *X = '\0' |
1: st X, __zero_reg__ ; *X = '\0' |
| 110 |
sbiw Z_lo, 1 ; undo post increment |
sbiw Z_lo, 1 ; undo post increment |
| 111 |
|
|
| 112 |
.strlcat_P_slen: |
.L_strlcat_P_slen: |
| 113 |
LPM_R0_ZP ; get next char from src |
LPM_R0_ZP ; get next char from src |
| 114 |
tst __tmp_reg__ ; end of src ? |
tst __tmp_reg__ ; end of src ? |
| 115 |
brne .strlcat_P_slen ; --> next char |
brne .L_strlcat_P_slen ; --> next char |
| 116 |
sbiw Z_lo, 1 ; undo post increment |
sbiw Z_lo, 1 ; undo post increment |
| 117 |
#if __AVR_ENHANCED__ |
X_movw rWord_lo, dlen_lo |
|
movw rWord_lo, dlen_lo |
|
|
#else |
|
|
mov rWord_lo, dlen_lo |
|
|
mov rWord_hi, dlen_hi |
|
|
#endif |
|
| 118 |
add rWord_lo, Z_lo |
add rWord_lo, Z_lo |
| 119 |
adc rWord_hi, Z_hi |
adc rWord_hi, Z_hi |
| 120 |
sub rWord_lo, src_lo |
sub rWord_lo, src_lo |
| 121 |
sbc rWord_hi, src_hi ; return(dlen + (Z - src)) |
sbc rWord_hi, src_hi ; return(dlen + (Z - src)) |
| 122 |
ret |
ret |
| 123 |
|
|
| 124 |
.strlcat_P_end: |
.L_strlcat_P_end: |
| 125 |
.size _U(strlcat_P), .strlcat_P_end - _U(strlcat) |
.size _U(strlcat_P), .L_strlcat_P_end - _U(strlcat) |
| 126 |
|
|
| 127 |
#endif /* not DOXYGEN */ |
#endif /* not DOXYGEN */ |