~ubuntu-branches/ubuntu/lucid/avr-libc/lucid

« back to all changes in this revision

Viewing changes to libc/pmstring/strlcat_P.S

  • Committer: Bazaar Package Importer
  • Author(s): Hakan Ardo
  • Date: 2005-03-19 11:16:14 UTC
  • mfrom: (1.1.1 upstream) (2.1.2 hoary)
  • Revision ID: james.westby@ubuntu.com-20050319111614-4g01s2ftv5x5nxf3
Tags: 1:1.2.3-3
* Added build depends on netpbm
* Added build depends on tetex-extra

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   AVR LIBC
 
3
   strlcat()
 
4
 
 
5
   Copyright (c) 2003, Eric B. Weddington, R. Patommel
 
6
   All rights reserved.
 
7
 
 
8
   Redistribution and use in source and binary forms, with or without
 
9
   modification, are permitted provided that the following conditions are met:
 
10
 
 
11
   * Redistributions of source code must retain the above copyright
 
12
     notice, this list of conditions and the following disclaimer.
 
13
   * Redistributions in binary form must reproduce the above copyright
 
14
     notice, this list of conditions and the following disclaimer in
 
15
     the documentation and/or other materials provided with the
 
16
     distribution.
 
17
   * Neither the name of the copyright holders nor the names of
 
18
     contributors may be used to endorse or promote products derived
 
19
     from this software without specific prior written permission.
 
20
 
 
21
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 
22
  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
23
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
24
  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 
25
  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 
26
  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 
27
  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 
28
  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 
29
  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
30
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 
31
  POSSIBILITY OF SUCH DAMAGE.
 
32
 
 
33
*/
 
34
 
 
35
 
 
36
/** \ingroup avr_pgmspace
 
37
    \fn size_t strlcat_P (char *dst, PGM_P, size_t siz)
 
38
    \brief Concatenate two strings.
 
39
 
 
40
    The strlcat_P() function is similar to strlcat(), except that the \e src
 
41
    string must be located in program space (flash).
 
42
 
 
43
    Appends src to string dst of size siz (unlike strncat(), siz is the
 
44
    full size of dst, not space left).  At most siz-1 characters
 
45
    will be copied.  Always NULL terminates (unless siz <= strlen(dst)).
 
46
 
 
47
    \returns The strlcat_P() function returns strlen(src) + MIN(siz,
 
48
    strlen(initial dst)).  If retval >= siz, truncation occurred.  */
 
49
 
 
50
#if !defined(DOXYGEN)
 
51
 
 
52
#include "gasava.inc"
 
53
#include "macros.inc"
 
54
 
 
55
#define dst_hi          r25
 
56
#define dst_lo          r24
 
57
#define src_hi          r23
 
58
#define src_lo          r22
 
59
#define siz_hi          r21
 
60
#define siz_lo          r20
 
61
#define dlen_hi         r19
 
62
#define dlen_lo         r18
 
63
#define rWord_hi        r25
 
64
#define rWord_lo        r24
 
65
#define Z_hi            r31
 
66
#define Z_lo            r30
 
67
#define X_hi            r27
 
68
#define X_lo            r26
 
69
 
 
70
        .text
 
71
        .global _U(strlcat_P)
 
72
        .type    _U(strlcat_P),@function
 
73
 
 
74
_U(strlcat_P):
 
75
        LOAD_X  (dst_lo, dst_hi)        ; X = dst
 
76
        LOAD_Z  (src_lo, src_hi)        ; Z = src
 
77
 
 
78
.strlcat_P_dlen:                        ; Find end of dst string
 
79
        ld      __tmp_reg__, X+         ; get next char from dst
 
80
        cp      siz_lo, __zero_reg__    ;  and calc dlen = len of dst
 
81
        cpc     siz_hi, __zero_reg__    ; size == 0 ?
 
82
        breq     1f                     ; --> done
 
83
        tst     __tmp_reg__             ; end of dst ?
 
84
        breq     1f                     ; --> done
 
85
        subi    siz_lo, lo8(-(-1))
 
86
        sbci    siz_hi, hi8(-(-1))      ; siz--
 
87
        rjmp    .strlcat_P_dlen         ; --> next char
 
88
1:      sbiw    X_lo, 1                 ; undo post increment
 
89
#if __AVR_ENHANCED__
 
90
        movw    dlen_lo, X_lo
 
91
#else
 
92
        mov     dlen_lo, X_lo
 
93
        mov     dlen_hi, X_hi
 
94
#endif
 
95
        sub     dlen_lo, dst_lo
 
96
        sbc     dlen_hi, dst_hi         ; dlen = X - dst
 
97
        cp      siz_lo, __zero_reg__
 
98
        cpc     siz_hi, __zero_reg__    ; size == 0 ?
 
99
        breq    .strlcat_P_slen         ; --> done
 
100
        subi    siz_lo, lo8(-(-1))
 
101
        sbci    siz_hi, hi8(-(-1))      ; siz--
 
102
 
 
103
.strlcat_P_concat:                      ; Concatenate
 
104
        LPM_R0_ZP                       ; get next char from src
 
105
        cp      siz_lo, __zero_reg__
 
106
        cpc     siz_hi, __zero_reg__    ; size == 0 ?
 
107
        breq    1f                      ; --> done
 
108
        tst     __tmp_reg__             ; end of src ?
 
109
        breq    1f                      ; --> done
 
110
        st      X+, __tmp_reg__         ; store in dest
 
111
        subi    siz_lo, lo8(-(-1))
 
112
        sbci    siz_hi, hi8(-(-1))      ; siz--
 
113
        rjmp    .strlcat_P_concat               ; --> next char
 
114
1:      st      X, __zero_reg__         ; *X = '\0'
 
115
        sbiw    Z_lo, 1                 ; undo post increment
 
116
 
 
117
.strlcat_P_slen:
 
118
        LPM_R0_ZP                       ; get next char from src
 
119
        tst     __tmp_reg__             ; end of src ?
 
120
        brne    .strlcat_P_slen         ; --> next char
 
121
        sbiw    Z_lo, 1                 ; undo post increment
 
122
#if __AVR_ENHANCED__
 
123
        movw    rWord_lo, dlen_lo
 
124
#else
 
125
        mov     rWord_lo, dlen_lo
 
126
        mov     rWord_hi, dlen_hi
 
127
#endif
 
128
        add     rWord_lo, Z_lo
 
129
        adc     rWord_hi, Z_hi
 
130
        sub     rWord_lo, src_lo
 
131
        sbc     rWord_hi, src_hi        ; return(dlen + (Z - src))
 
132
        ret
 
133
 
 
134
.strlcat_P_end:
 
135
.size   _U(strlcat_P), .strlcat_P_end - _U(strlcat)
 
136
 
 
137
#endif /* not DOXYGEN */