1/* $OpenBSD: copy_subr.S,v 1.1 2006/11/17 22:32:38 miod Exp $ */ 2/* 3 * Mach Operating System 4 * Copyright (c) 1993-1992 Carnegie Mellon University 5 * Copyright (c) 1991 OMRON Corporation 6 * Copyright (c) 1996 Nivas Madhur 7 * Copyright (c) 1998 Steve Murphree, Jr. 8 * All Rights Reserved. 9 * 10 * Permission to use, copy, modify and distribute this software and its 11 * documentation is hereby granted, provided that both the copyright 12 * notice and this permission notice appear in all copies of the 13 * software, derivative works or modified versions, and any portions 14 * thereof, and that both notices appear in supporting documentation. 15 * 16 * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS" 17 * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND 18 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 19 * 20 * Carnegie Mellon requests users of this software to return to 21 * 22 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 23 * School of Computer Science 24 * Carnegie Mellon University 25 * Pittsburgh PA 15213-3890 26 * 27 * any improvements or extensions that they make and grant Carnegie the 28 * rights to redistribute these changes. 29 */ 30 31#include <machine/asm.h> 32 33/* 34 * copy count bytes of data from source to destination 35 * Don Harper (don@omron.co.jp), Omron Corporation. 36 */ 37 38#if defined(MEMCPY) || defined(MEMMOVE) 39#define SRC r3 40#define DST r2 41#define SAVE r5 42#else 43#define SRC r2 44#define DST r3 45#endif 46#define LEN r4 47 48#ifdef MEMCPY 49ENTRY(memcpy) 50#endif 51#ifdef MEMMOVE 52ENTRY(memmove) 53#endif 54#ifdef BCOPY 55ENTRY(bcopy) 56#endif 57#ifdef OVBCOPY 58ENTRY(ovbcopy) 59#endif 60 61#if defined(MEMCPY) || defined(MEMMOVE) 62 or SAVE, DST, r0 63#endif 64 65 bcnd eq0,LEN,_ASM_LABEL(bcopy_out) /* nothing to do if == 0 */ 66 67/* 68 * check position of source and destination data 69 */ 70 cmp r9,SRC,DST /* compare source address to destination */ 71 bb1 eq,r9,_ASM_LABEL(bcopy_out) /* nothing to do if equal */ 72#if defined(MEMMOVE) || defined(OVBCOPY) 73 bb1 lo,r9,_ASM_LABEL(bcopy_reverse) /* reverse copy if src < dest */ 74#endif 75 76/* 77 * source address is greater than destination address, or we do 78 * not have to care about overlapping areas: copy forward 79 */ 80 cmp r9,LEN,16 /* see if we have at least 16 bytes */ 81 bb1 lt,r9,_ASM_LABEL(f_byte_copy) /* copy bytes for small data length */ 82/* 83 * determine copy strategy based on alignment of source and destination 84 */ 85 mask r6,SRC,3 /* get 2 low order bits of source address */ 86 mask r7,DST,3 /* get 2 low order bits of destintation addr */ 87 mak r6,r6,0<4> /* convert source bits to table offset */ 88 mak r7,r7,0<2> /* convert destination bits to table offset */ 89 or.u r12,r0,hi16(_ASM_LABEL(f_strat)) 90 or r12,r12,lo16(_ASM_LABEL(f_strat)) 91 addu r6,r6,r7 /* compute final table offset for strategy */ 92 ld r12,r12,r6 /* load the strategy routine */ 93 jmp r12 /* branch to strategy routine */ 94 95/* 96 * Copy three bytes from src to destination then copy words 97 */ 98ASLOCAL(f_3byte_word_copy) 99 ld.bu r6,SRC,0 /* load byte from source */ 100 ld.bu r7,SRC,1 /* load byte from source */ 101 ld.bu r8,SRC,2 /* load byte from source */ 102 st.b r6,DST,0 /* store byte to destination */ 103 st.b r7,DST,1 /* store byte to destination */ 104 st.b r8,DST,2 /* store byte to destination */ 105 addu SRC,SRC,3 /* increment source pointer */ 106 addu DST,DST,3 /* increment destination pointer */ 107 br.n _ASM_LABEL(f_word_copy) /* copy full words */ 108 subu LEN,LEN,3 /* decrement length */ 109 110/* 111 * Copy 1 halfword from src to destination then copy words 112 */ 113ASLOCAL(f_1half_word_copy) 114 ld.hu r6,SRC,0 /* load half-word from source */ 115 st.h r6,DST,0 /* store half-word to destination */ 116 addu SRC,SRC,2 /* increment source pointer */ 117 addu DST,DST,2 /* increment destination pointer */ 118 br.n _ASM_LABEL(f_word_copy) /* copy full words */ 119 subu LEN,LEN,2 /* decrement remaining length */ 120 121/* 122 * Copy 1 byte from src to destination then copy words 123 */ 124ASLOCAL(f_1byte_word_copy) 125 ld.bu r6,SRC,0 /* load 1 byte from source */ 126 st.b r6,DST,0 /* store 1 byte to destination */ 127 addu SRC,SRC,1 /* increment source pointer */ 128 addu DST,DST,1 /* increment destination pointer */ 129 subu LEN,LEN,1 /* decrement remaining length */ 130 /* FALLTHROUGH */ 131/* 132 * Copy as many full words as possible, 4 words per loop 133 */ 134ASLOCAL(f_word_copy) 135 cmp r10,LEN,16 /* see if we have 16 bytes remaining */ 136 bb1 lo,r10,_ASM_LABEL(f_byte_copy) /* not enough left, copy bytes */ 137 ld r6,SRC,0 /* load first word */ 138 ld r7,SRC,4 /* load second word */ 139 ld r8,SRC,8 /* load third word */ 140 ld r9,SRC,12 /* load fourth word */ 141 st r6,DST,0 /* store first word */ 142 st r7,DST,4 /* store second word */ 143 st r8,DST,8 /* store third word */ 144 st r9,DST,12 /* store fourth word */ 145 addu SRC,SRC,16 /* increment source pointer */ 146 addu DST,DST,16 /* increment destination pointer */ 147 br.n _ASM_LABEL(f_word_copy) /* branch to copy another block */ 148 subu LEN,LEN,16 /* decrement remaining length */ 149 150ASLOCAL(f_1byte_half_copy) 151 ld.bu r6,SRC,0 /* load 1 byte from source */ 152 st.b r6,DST,0 /* store 1 byte to destination */ 153 addu SRC,SRC,1 /* increment source pointer */ 154 addu DST,DST,1 /* increment destination pointer */ 155 subu LEN,LEN,1 /* decrement remaining length */ 156 /* FALLTHROUGH */ 157 158ASLOCAL(f_half_copy) 159 cmp r10,LEN,16 /* see if we have 16 bytes remaining */ 160 bb1 lo,r10,_ASM_LABEL(f_byte_copy) /* not enough left, copy bytes */ 161 ld.hu r6,SRC,0 /* load first half-word */ 162 ld.hu r7,SRC,2 /* load second half-word */ 163 ld.hu r8,SRC,4 /* load third half-word */ 164 ld.hu r9,SRC,6 /* load fourth half-word */ 165 ld.hu r10,SRC,8 /* load fifth half-word */ 166 ld.hu r11,SRC,10 /* load sixth half-word */ 167 ld.hu r12,SRC,12 /* load seventh half-word */ 168 ld.hu r13,SRC,14 /* load eighth half-word */ 169 st.h r6,DST,0 /* store first half-word */ 170 st.h r7,DST,2 /* store second half-word */ 171 st.h r8,DST,4 /* store third half-word */ 172 st.h r9,DST,6 /* store fourth half-word */ 173 st.h r10,DST,8 /* store fifth half-word */ 174 st.h r11,DST,10 /* store sixth half-word */ 175 st.h r12,DST,12 /* store seventh half-word */ 176 st.h r13,DST,14 /* store eighth half-word */ 177 addu SRC,SRC,16 /* increment source pointer */ 178 addu DST,DST,16 /* increment destination pointer */ 179 br.n _ASM_LABEL(f_half_copy) /* branch to copy another block */ 180 subu LEN,LEN,16 /* decrement remaining length */ 181 182ASLOCAL(f_byte_copy) 183 bcnd eq0,LEN,_ASM_LABEL(bcopy_out) /* branch if nothing left to copy */ 184 ld.bu r6,SRC,0 /* load byte from source */ 185 st.b r6,DST,0 /* store byte in destination */ 186 addu SRC,SRC,1 /* increment source pointer */ 187 addu DST,DST,1 /* increment destination pointer */ 188 br.n _ASM_LABEL(f_byte_copy) /* branch for next byte */ 189 subu LEN,LEN,1 /* decrement remaining length */ 190 191#if defined(MEMMOVE) || defined(OVBCOPY) 192/* 193 * source address is less than destination address, copy in reverse 194 */ 195ASLOCAL(bcopy_reverse) 196/* 197 * start copy pointers at end of data 198 */ 199 addu SRC,SRC,LEN /* start source at end of data */ 200 addu DST,DST,LEN /* start destination at end of data */ 201/* 202 * check for short data 203 */ 204 cmp r9,LEN,16 /* see if we have at least 16 bytes */ 205 bb1 lt,r9,_ASM_LABEL(r_byte_copy) /* copy bytes for small data length */ 206/* 207 * determine copy strategy based on alignment of source and destination 208 */ 209 mask r6,SRC,3 /* get 2 low order bits of source address */ 210 mask r7,DST,3 /* get 2 low order bits of destintation addr */ 211 mak r6,r6,0<4> /* convert source bits to table offset */ 212 mak r7,r7,0<2> /* convert destination bits to table offset */ 213 or.u r12,r0,hi16(_ASM_LABEL(r_strat)) 214 or r12,r12,lo16(_ASM_LABEL(r_strat)) 215 addu r6,r6,r7 /* compute final table offset for strategy */ 216 ld r12,r12,r6 /* load the strategy routine */ 217 jmp r12 /* branch to strategy routine */ 218 219/* 220 * Copy three bytes from src to destination then copy words 221 */ 222ASLOCAL(r_3byte_word_copy) 223 subu SRC,SRC,3 /* decrement source pointer */ 224 subu DST,DST,3 /* decrement destination pointer */ 225 ld.bu r6,SRC,0 /* load byte from source */ 226 ld.bu r7,SRC,1 /* load byte from source */ 227 ld.bu r8,SRC,2 /* load byte from source */ 228 st.b r6,DST,0 /* store byte to destination */ 229 st.b r7,DST,1 /* store byte to destination */ 230 st.b r8,DST,2 /* store byte to destination */ 231 br.n _ASM_LABEL(r_word_copy) /* copy full words */ 232 subu LEN,LEN,3 /* decrement length */ 233 234/* 235 * Copy 1 halfword from src to destination then copy words 236 */ 237ASLOCAL(r_1half_word_copy) 238 subu SRC,SRC,2 /* decrement source pointer */ 239 subu DST,DST,2 /* decrement destination pointer */ 240 ld.hu r6,SRC,0 /* load half-word from source */ 241 st.h r6,DST,0 /* store half-word to destination */ 242 br.n _ASM_LABEL(r_word_copy) /* copy full words */ 243 subu LEN,LEN,2 /* decrement remaining length */ 244 245/* 246 * Copy 1 byte from src to destination then copy words 247 */ 248ASLOCAL(r_1byte_word_copy) 249 subu SRC,SRC,1 /* decrement source pointer */ 250 subu DST,DST,1 /* decrement destination pointer */ 251 ld.bu r6,SRC,0 /* load 1 byte from source */ 252 st.b r6,DST,0 /* store 1 byte to destination */ 253 subu LEN,LEN,1 /* decrement remaining length */ 254 /* FALLTHROUGH */ 255/* 256 * Copy as many full words as possible, 4 words per loop 257 */ 258ASLOCAL(r_word_copy) 259 cmp r10,LEN,16 /* see if we have 16 bytes remaining */ 260 bb1 lo,r10,_ASM_LABEL(r_byte_copy) /* not enough left, copy bytes */ 261 subu SRC,SRC,16 /* decrement source pointer */ 262 subu DST,DST,16 /* decrement destination pointer */ 263 ld r6,SRC,0 /* load first word */ 264 ld r7,SRC,4 /* load second word */ 265 ld r8,SRC,8 /* load third word */ 266 ld r9,SRC,12 /* load fourth word */ 267 st r6,DST,0 /* store first word */ 268 st r7,DST,4 /* store second word */ 269 st r8,DST,8 /* store third word */ 270 st r9,DST,12 /* store fourth word */ 271 br.n _ASM_LABEL(r_word_copy) /* branch to copy another block */ 272 subu LEN,LEN,16 /* decrement remaining length */ 273 274ASLOCAL(r_1byte_half_copy) 275 subu SRC,SRC,1 /* decrement source pointer */ 276 subu DST,DST,1 /* decrement destination pointer */ 277 ld.bu r6,SRC,0 /* load 1 byte from source */ 278 st.b r6,DST,0 /* store 1 byte to destination */ 279 subu LEN,LEN,1 /* decrement remaining length */ 280 /* FALLTHROUGH */ 281 282ASLOCAL(r_half_copy) 283 cmp r10,LEN,16 /* see if we have 16 bytes remaining */ 284 bb1 lo,r10,_ASM_LABEL(r_byte_copy) /* not enough left, copy bytes */ 285 subu SRC,SRC,16 /* decrement source pointer */ 286 subu DST,DST,16 /* decrement destination pointer */ 287 ld.hu r6,SRC,0 /* load first half-word */ 288 ld.hu r7,SRC,2 /* load second half-word */ 289 ld.hu r8,SRC,4 /* load third half-word */ 290 ld.hu r9,SRC,6 /* load fourth half-word */ 291 ld.hu r10,SRC,8 /* load fifth half-word */ 292 ld.hu r11,SRC,10 /* load sixth half-word */ 293 ld.hu r12,SRC,12 /* load seventh half-word */ 294 ld.hu r13,SRC,14 /* load eighth half-word */ 295 st.h r6,DST,0 /* store first half-word */ 296 st.h r7,DST,2 /* store second half-word */ 297 st.h r8,DST,4 /* store third half-word */ 298 st.h r9,DST,6 /* store fourth half-word */ 299 st.h r10,DST,8 /* store fifth half-word */ 300 st.h r11,DST,10 /* store sixth half-word */ 301 st.h r12,DST,12 /* store seventh half-word */ 302 st.h r13,DST,14 /* store eighth half-word */ 303 br.n _ASM_LABEL(r_half_copy) /* branch to copy another block */ 304 subu LEN,LEN,16 /* decrement remaining length */ 305 306ASLOCAL(r_byte_copy) 307 bcnd eq0,LEN,_ASM_LABEL(bcopy_out) /* branch if nothing left to copy */ 308 subu SRC,SRC,1 /* decrement source pointer */ 309 subu DST,DST,1 /* decrement destination pointer */ 310 ld.bu r6,SRC,0 /* load byte from source */ 311 st.b r6,DST,0 /* store byte in destination */ 312 br.n _ASM_LABEL(r_byte_copy) /* branch for next byte */ 313 subu LEN,LEN,1 /* decrement remaining length */ 314#endif /* MEMMOVE || OVBCOPY */ 315 316ASLOCAL(bcopy_out) 317#if defined(MEMCPY) || defined(MEMMOVE) 318 jmp.n r1 /* all done, return to caller */ 319 or r2, SAVE, r0 320#else 321 jmp r1 /* all done, return to caller */ 322#endif 323 324 data 325 align 4 326ASLOCAL(f_strat) 327 word _ASM_LABEL(f_word_copy) 328 word _ASM_LABEL(f_byte_copy) 329 word _ASM_LABEL(f_half_copy) 330 word _ASM_LABEL(f_byte_copy) 331 word _ASM_LABEL(f_byte_copy) 332 word _ASM_LABEL(f_3byte_word_copy) 333 word _ASM_LABEL(f_byte_copy) 334 word _ASM_LABEL(f_1byte_half_copy) 335 word _ASM_LABEL(f_half_copy) 336 word _ASM_LABEL(f_byte_copy) 337 word _ASM_LABEL(f_1half_word_copy) 338 word _ASM_LABEL(f_byte_copy) 339 word _ASM_LABEL(f_byte_copy) 340 word _ASM_LABEL(f_1byte_half_copy) 341 word _ASM_LABEL(f_byte_copy) 342 word _ASM_LABEL(f_1byte_word_copy) 343 344#if defined(MEMMOVE) || defined(OVBCOPY) 345ASLOCAL(r_strat) 346 word _ASM_LABEL(r_word_copy) 347 word _ASM_LABEL(r_byte_copy) 348 word _ASM_LABEL(r_half_copy) 349 word _ASM_LABEL(r_byte_copy) 350 word _ASM_LABEL(r_byte_copy) 351 word _ASM_LABEL(r_1byte_word_copy) 352 word _ASM_LABEL(r_byte_copy) 353 word _ASM_LABEL(r_1byte_half_copy) 354 word _ASM_LABEL(r_half_copy) 355 word _ASM_LABEL(r_byte_copy) 356 word _ASM_LABEL(r_1half_word_copy) 357 word _ASM_LABEL(r_byte_copy) 358 word _ASM_LABEL(r_byte_copy) 359 word _ASM_LABEL(r_1byte_half_copy) 360 word _ASM_LABEL(r_byte_copy) 361 word _ASM_LABEL(r_3byte_word_copy) 362#endif 363