1/* $NetBSD: memmove.S,v 1.3 2011/01/15 07:31:12 matt Exp $ */
2
3/* stropt/memmove.S, pl_string_common, pl_linux 10/11/04 11:45:37
4 * ==========================================================================
5 * Optimized memmove implementation for IBM PowerPC 405/440.
6 *
7 *        Copyright (c) 2003, IBM Corporation
8 *        All rights reserved.
9 *
10 *        Redistribution and use in source and binary forms, with or
11 *        without modification, are permitted provided that the following
12 *        conditions are met:
13 *
14 *        * Redistributions of source code must retain the above
15 *        copyright notice, this list of conditions and the following
16 *        disclaimer.
17 *        * Redistributions in binary form must reproduce the above
18 *        copyright notice, this list of conditions and the following
19 *        disclaimer in the documentation and/or other materials
20 *        provided with the distribution.
21 *        * Neither the name of IBM nor the names of its contributors
22 *        may be used to endorse or promote products derived from this
23 *        software without specific prior written permission.
24 *
25 *        THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
26 *        CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
27 *        INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
28 *        MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29 *        DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
30 *        BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
31 *        OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 *        PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 *        PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
34 *        OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 *        (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
36 *        USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 *
38 * ==========================================================================
39 *
40 * Function: Move memory area (handles overlapping regions)
41 *
42 *                  void *memmove(void * dest, const void * src, int n)
43 *
44 * Input: r3 - destination address
45 *         r4 - source address
46 *         r5 - byte count
47 * Output: r3 - destination address
48 *
49 * ==========================================================================
50 */
51
52#include <machine/asm.h>
53
54        .text
55        .align 4
56#ifdef _BCOPY
57/* bcopy = memcpy/memmove with arguments reversed. */
58/* LINTSTUB: Func: void bcopy(void *, void *, size_t) */
59ENTRY(bcopy)
60          mr        %r6, %r3            /* swap src/dst */
61          mr        %r3, %r4
62          mr        %r4, %r6
63#else
64/* LINTSTUB: Func: void *memmove(void *, const void *, size_t) */
65ENTRY(memmove)
66#endif
67
68          mr        %r8, %r3            /* Save dst (return value)    */
69
70          cmpw      %r4, %r8            /* Branch to reverse if       */
71          blt       reverse                       /* src < dest. Don't want to  */
72                                                  /* overwrite end of src with  */
73                                                  /* start of dest              */
74
75          addi      %r4, %r4, -4                  /* Back up src and dst pointers */
76          addi      %r8, %r8, -4                  /* due to auto-update of 'load' */
77
78          srwi.     %r9,%r5,2                     /* How many words in total cnt          */
79          beq-      last1                         /* Handle byte by byte if < 4 */
80                                                  /* bytes total                          */
81          mtctr     %r9                           /* Count of words for loop              */
82          lwzu      %r7, 4(%r4)                   /* Preload first word                   */
83
84          b         g1
85
86g0:                                               /* Main loop                            */
87
88          lwzu      %r7, 4(%r4)                   /* Load a new word            */
89          stwu      %r6, 4(%r8)                   /* Store previous word                  */
90
91g1:
92
93          bdz-      last                          /* Dec cnt, and branch if just          */
94                                                  /* one word to store                    */
95          lwzu      %r6, 4(%r4)                   /* Load another word                    */
96          stwu      %r7, 4(%r8)                   /* Store previous word                  */
97          bdnz+     g0                            /* Dec cnt, and loop again if */
98                                                  /* more words                           */
99          mr        %r7, %r6                      /* If word count -> 0, then...          */
100
101last:
102
103          stwu      %r7, 4(%r8)                   /* ... store last word                  */
104
105last1:                                            /* Byte-by-byte copy                    */
106
107          clrlwi.   %r5,%r5,30                    /* If count -> 0, then ...    */
108          beqlr                                   /* we're done                           */
109
110          mtctr     %r5                           /* else load count for loop   */
111
112          lbzu      %r6, 4(%r4)                   /* 1st byte: update addr by 4 */
113          stbu      %r6, 4(%r8)                   /* since we pre-adjusted by 4 */
114          bdzlr-                                  /* in anticipation of main loop */
115
116last2:
117
118          lbzu      %r6, 1(%r4)                   /* But handle the rest by               */
119          stbu      %r6, 1(%r8)                   /* updating addr by 1                   */
120          bdnz+     last2
121
122          blr
123
124          /* We're here since src < dest. Don't want to overwrite end of        */
125          /* src with start of dest                                                       */
126
127reverse:
128
129          add       %r4, %r4, %r5                 /* Work from end to beginning */
130          add       %r8, %r8, %r5                 /* so add count to string ptrs          */
131          srwi.     %r9,%r5,2                     /* Words in total count                 */
132          beq-      rlast1                        /* Handle byte by byte if < 4 */
133                                                  /* bytes total                          */
134
135          mtctr     %r9                           /* Count of words for loop    */
136
137          lwzu      %r7, -4(%r4)                  /* Preload first word                   */
138          b         rg1
139
140rg0:                                              /* Main loop                            */
141
142          lwzu      %r7, -4(%r4)                  /* Load a new word            */
143          stwu      %r6, -4(%r8)                  /* Store previous word                  */
144
145rg1:
146
147          bdz-      rlast                         /* Dec cnt, and branch if just          */
148                                                  /* one word to store                    */
149
150          lwzu      %r6, -4(%r4)                  /* Load another word                    */
151          stwu      %r7, -4(%r8)                  /* Store previous word                  */
152
153          bdnz+     rg0                           /* Dec cnt, and loop again if */
154                                                  /* more words                           */
155
156          mr        %r7, %r6                      /* If word count -> 0, then...          */
157
158rlast:
159
160          stwu      %r7, -4(%r8)                  /* ... store last word                  */
161
162rlast1:                                           /* Byte-by-byte copy                    */
163
164          clrlwi.   %r5,%r5,30                    /* If count -> 0, then...     */
165          beqlr                                   /* ... we're done             */
166
167          mtctr     %r5                           /* else load count for loop   */
168
169rlast2:
170
171          lbzu      %r6, -1(%r4)                  /* Handle the rest, byte by   */
172          stbu      %r6, -1(%r8)                  /* byte                                 */
173
174          bdnz+     rlast2                        /* Dec ctr, and branch if more          */
175                                                  /* bytes left                           */
176          blr
177
178#ifdef _BCOPY
179END(bcopy)
180#else
181END(memmove)
182#endif
183