/* $OpenBSD: copy_subr.S,v 1.1 2006/11/17 22:32:38 miod Exp $ */ /* * Mach Operating System * Copyright (c) 1993-1992 Carnegie Mellon University * Copyright (c) 1991 OMRON Corporation * Copyright (c) 1996 Nivas Madhur * Copyright (c) 1998 Steve Murphree, Jr. * All Rights Reserved. * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */ #include /* * copy count bytes of data from source to destination * Don Harper (don@omron.co.jp), Omron Corporation. */ #if defined(MEMCPY) || defined(MEMMOVE) #define SRC r3 #define DST r2 #define SAVE r5 #else #define SRC r2 #define DST r3 #endif #define LEN r4 #ifdef MEMCPY ENTRY(memcpy) #endif #ifdef MEMMOVE ENTRY(memmove) #endif #ifdef BCOPY ENTRY(bcopy) #endif #ifdef OVBCOPY ENTRY(ovbcopy) #endif #if defined(MEMCPY) || defined(MEMMOVE) or SAVE, DST, r0 #endif bcnd eq0,LEN,_ASM_LABEL(bcopy_out) /* nothing to do if == 0 */ /* * check position of source and destination data */ cmp r9,SRC,DST /* compare source address to destination */ bb1 eq,r9,_ASM_LABEL(bcopy_out) /* nothing to do if equal */ #if defined(MEMMOVE) || defined(OVBCOPY) bb1 lo,r9,_ASM_LABEL(bcopy_reverse) /* reverse copy if src < dest */ #endif /* * source address is greater than destination address, or we do * not have to care about overlapping areas: copy forward */ cmp r9,LEN,16 /* see if we have at least 16 bytes */ bb1 lt,r9,_ASM_LABEL(f_byte_copy) /* copy bytes for small data length */ /* * determine copy strategy based on alignment of source and destination */ mask r6,SRC,3 /* get 2 low order bits of source address */ mask r7,DST,3 /* get 2 low order bits of destintation addr */ mak r6,r6,0<4> /* convert source bits to table offset */ mak r7,r7,0<2> /* convert destination bits to table offset */ or.u r12,r0,hi16(_ASM_LABEL(f_strat)) or r12,r12,lo16(_ASM_LABEL(f_strat)) addu r6,r6,r7 /* compute final table offset for strategy */ ld r12,r12,r6 /* load the strategy routine */ jmp r12 /* branch to strategy routine */ /* * Copy three bytes from src to destination then copy words */ ASLOCAL(f_3byte_word_copy) ld.bu r6,SRC,0 /* load byte from source */ ld.bu r7,SRC,1 /* load byte from source */ ld.bu r8,SRC,2 /* load byte from source */ st.b r6,DST,0 /* store byte to destination */ st.b r7,DST,1 /* store byte to destination */ st.b r8,DST,2 /* store byte to destination */ addu SRC,SRC,3 /* increment source pointer */ addu DST,DST,3 /* increment destination pointer */ br.n _ASM_LABEL(f_word_copy) /* copy full words */ subu LEN,LEN,3 /* decrement length */ /* * Copy 1 halfword from src to destination then copy words */ ASLOCAL(f_1half_word_copy) ld.hu r6,SRC,0 /* load half-word from source */ st.h r6,DST,0 /* store half-word to destination */ addu SRC,SRC,2 /* increment source pointer */ addu DST,DST,2 /* increment destination pointer */ br.n _ASM_LABEL(f_word_copy) /* copy full words */ subu LEN,LEN,2 /* decrement remaining length */ /* * Copy 1 byte from src to destination then copy words */ ASLOCAL(f_1byte_word_copy) ld.bu r6,SRC,0 /* load 1 byte from source */ st.b r6,DST,0 /* store 1 byte to destination */ addu SRC,SRC,1 /* increment source pointer */ addu DST,DST,1 /* increment destination pointer */ subu LEN,LEN,1 /* decrement remaining length */ /* FALLTHROUGH */ /* * Copy as many full words as possible, 4 words per loop */ ASLOCAL(f_word_copy) cmp r10,LEN,16 /* see if we have 16 bytes remaining */ bb1 lo,r10,_ASM_LABEL(f_byte_copy) /* not enough left, copy bytes */ ld r6,SRC,0 /* load first word */ ld r7,SRC,4 /* load second word */ ld r8,SRC,8 /* load third word */ ld r9,SRC,12 /* load fourth word */ st r6,DST,0 /* store first word */ st r7,DST,4 /* store second word */ st r8,DST,8 /* store third word */ st r9,DST,12 /* store fourth word */ addu SRC,SRC,16 /* increment source pointer */ addu DST,DST,16 /* increment destination pointer */ br.n _ASM_LABEL(f_word_copy) /* branch to copy another block */ subu LEN,LEN,16 /* decrement remaining length */ ASLOCAL(f_1byte_half_copy) ld.bu r6,SRC,0 /* load 1 byte from source */ st.b r6,DST,0 /* store 1 byte to destination */ addu SRC,SRC,1 /* increment source pointer */ addu DST,DST,1 /* increment destination pointer */ subu LEN,LEN,1 /* decrement remaining length */ /* FALLTHROUGH */ ASLOCAL(f_half_copy) cmp r10,LEN,16 /* see if we have 16 bytes remaining */ bb1 lo,r10,_ASM_LABEL(f_byte_copy) /* not enough left, copy bytes */ ld.hu r6,SRC,0 /* load first half-word */ ld.hu r7,SRC,2 /* load second half-word */ ld.hu r8,SRC,4 /* load third half-word */ ld.hu r9,SRC,6 /* load fourth half-word */ ld.hu r10,SRC,8 /* load fifth half-word */ ld.hu r11,SRC,10 /* load sixth half-word */ ld.hu r12,SRC,12 /* load seventh half-word */ ld.hu r13,SRC,14 /* load eighth half-word */ st.h r6,DST,0 /* store first half-word */ st.h r7,DST,2 /* store second half-word */ st.h r8,DST,4 /* store third half-word */ st.h r9,DST,6 /* store fourth half-word */ st.h r10,DST,8 /* store fifth half-word */ st.h r11,DST,10 /* store sixth half-word */ st.h r12,DST,12 /* store seventh half-word */ st.h r13,DST,14 /* store eighth half-word */ addu SRC,SRC,16 /* increment source pointer */ addu DST,DST,16 /* increment destination pointer */ br.n _ASM_LABEL(f_half_copy) /* branch to copy another block */ subu LEN,LEN,16 /* decrement remaining length */ ASLOCAL(f_byte_copy) bcnd eq0,LEN,_ASM_LABEL(bcopy_out) /* branch if nothing left to copy */ ld.bu r6,SRC,0 /* load byte from source */ st.b r6,DST,0 /* store byte in destination */ addu SRC,SRC,1 /* increment source pointer */ addu DST,DST,1 /* increment destination pointer */ br.n _ASM_LABEL(f_byte_copy) /* branch for next byte */ subu LEN,LEN,1 /* decrement remaining length */ #if defined(MEMMOVE) || defined(OVBCOPY) /* * source address is less than destination address, copy in reverse */ ASLOCAL(bcopy_reverse) /* * start copy pointers at end of data */ addu SRC,SRC,LEN /* start source at end of data */ addu DST,DST,LEN /* start destination at end of data */ /* * check for short data */ cmp r9,LEN,16 /* see if we have at least 16 bytes */ bb1 lt,r9,_ASM_LABEL(r_byte_copy) /* copy bytes for small data length */ /* * determine copy strategy based on alignment of source and destination */ mask r6,SRC,3 /* get 2 low order bits of source address */ mask r7,DST,3 /* get 2 low order bits of destintation addr */ mak r6,r6,0<4> /* convert source bits to table offset */ mak r7,r7,0<2> /* convert destination bits to table offset */ or.u r12,r0,hi16(_ASM_LABEL(r_strat)) or r12,r12,lo16(_ASM_LABEL(r_strat)) addu r6,r6,r7 /* compute final table offset for strategy */ ld r12,r12,r6 /* load the strategy routine */ jmp r12 /* branch to strategy routine */ /* * Copy three bytes from src to destination then copy words */ ASLOCAL(r_3byte_word_copy) subu SRC,SRC,3 /* decrement source pointer */ subu DST,DST,3 /* decrement destination pointer */ ld.bu r6,SRC,0 /* load byte from source */ ld.bu r7,SRC,1 /* load byte from source */ ld.bu r8,SRC,2 /* load byte from source */ st.b r6,DST,0 /* store byte to destination */ st.b r7,DST,1 /* store byte to destination */ st.b r8,DST,2 /* store byte to destination */ br.n _ASM_LABEL(r_word_copy) /* copy full words */ subu LEN,LEN,3 /* decrement length */ /* * Copy 1 halfword from src to destination then copy words */ ASLOCAL(r_1half_word_copy) subu SRC,SRC,2 /* decrement source pointer */ subu DST,DST,2 /* decrement destination pointer */ ld.hu r6,SRC,0 /* load half-word from source */ st.h r6,DST,0 /* store half-word to destination */ br.n _ASM_LABEL(r_word_copy) /* copy full words */ subu LEN,LEN,2 /* decrement remaining length */ /* * Copy 1 byte from src to destination then copy words */ ASLOCAL(r_1byte_word_copy) subu SRC,SRC,1 /* decrement source pointer */ subu DST,DST,1 /* decrement destination pointer */ ld.bu r6,SRC,0 /* load 1 byte from source */ st.b r6,DST,0 /* store 1 byte to destination */ subu LEN,LEN,1 /* decrement remaining length */ /* FALLTHROUGH */ /* * Copy as many full words as possible, 4 words per loop */ ASLOCAL(r_word_copy) cmp r10,LEN,16 /* see if we have 16 bytes remaining */ bb1 lo,r10,_ASM_LABEL(r_byte_copy) /* not enough left, copy bytes */ subu SRC,SRC,16 /* decrement source pointer */ subu DST,DST,16 /* decrement destination pointer */ ld r6,SRC,0 /* load first word */ ld r7,SRC,4 /* load second word */ ld r8,SRC,8 /* load third word */ ld r9,SRC,12 /* load fourth word */ st r6,DST,0 /* store first word */ st r7,DST,4 /* store second word */ st r8,DST,8 /* store third word */ st r9,DST,12 /* store fourth word */ br.n _ASM_LABEL(r_word_copy) /* branch to copy another block */ subu LEN,LEN,16 /* decrement remaining length */ ASLOCAL(r_1byte_half_copy) subu SRC,SRC,1 /* decrement source pointer */ subu DST,DST,1 /* decrement destination pointer */ ld.bu r6,SRC,0 /* load 1 byte from source */ st.b r6,DST,0 /* store 1 byte to destination */ subu LEN,LEN,1 /* decrement remaining length */ /* FALLTHROUGH */ ASLOCAL(r_half_copy) cmp r10,LEN,16 /* see if we have 16 bytes remaining */ bb1 lo,r10,_ASM_LABEL(r_byte_copy) /* not enough left, copy bytes */ subu SRC,SRC,16 /* decrement source pointer */ subu DST,DST,16 /* decrement destination pointer */ ld.hu r6,SRC,0 /* load first half-word */ ld.hu r7,SRC,2 /* load second half-word */ ld.hu r8,SRC,4 /* load third half-word */ ld.hu r9,SRC,6 /* load fourth half-word */ ld.hu r10,SRC,8 /* load fifth half-word */ ld.hu r11,SRC,10 /* load sixth half-word */ ld.hu r12,SRC,12 /* load seventh half-word */ ld.hu r13,SRC,14 /* load eighth half-word */ st.h r6,DST,0 /* store first half-word */ st.h r7,DST,2 /* store second half-word */ st.h r8,DST,4 /* store third half-word */ st.h r9,DST,6 /* store fourth half-word */ st.h r10,DST,8 /* store fifth half-word */ st.h r11,DST,10 /* store sixth half-word */ st.h r12,DST,12 /* store seventh half-word */ st.h r13,DST,14 /* store eighth half-word */ br.n _ASM_LABEL(r_half_copy) /* branch to copy another block */ subu LEN,LEN,16 /* decrement remaining length */ ASLOCAL(r_byte_copy) bcnd eq0,LEN,_ASM_LABEL(bcopy_out) /* branch if nothing left to copy */ subu SRC,SRC,1 /* decrement source pointer */ subu DST,DST,1 /* decrement destination pointer */ ld.bu r6,SRC,0 /* load byte from source */ st.b r6,DST,0 /* store byte in destination */ br.n _ASM_LABEL(r_byte_copy) /* branch for next byte */ subu LEN,LEN,1 /* decrement remaining length */ #endif /* MEMMOVE || OVBCOPY */ ASLOCAL(bcopy_out) #if defined(MEMCPY) || defined(MEMMOVE) jmp.n r1 /* all done, return to caller */ or r2, SAVE, r0 #else jmp r1 /* all done, return to caller */ #endif data align 4 ASLOCAL(f_strat) word _ASM_LABEL(f_word_copy) word _ASM_LABEL(f_byte_copy) word _ASM_LABEL(f_half_copy) word _ASM_LABEL(f_byte_copy) word _ASM_LABEL(f_byte_copy) word _ASM_LABEL(f_3byte_word_copy) word _ASM_LABEL(f_byte_copy) word _ASM_LABEL(f_1byte_half_copy) word _ASM_LABEL(f_half_copy) word _ASM_LABEL(f_byte_copy) word _ASM_LABEL(f_1half_word_copy) word _ASM_LABEL(f_byte_copy) word _ASM_LABEL(f_byte_copy) word _ASM_LABEL(f_1byte_half_copy) word _ASM_LABEL(f_byte_copy) word _ASM_LABEL(f_1byte_word_copy) #if defined(MEMMOVE) || defined(OVBCOPY) ASLOCAL(r_strat) word _ASM_LABEL(r_word_copy) word _ASM_LABEL(r_byte_copy) word _ASM_LABEL(r_half_copy) word _ASM_LABEL(r_byte_copy) word _ASM_LABEL(r_byte_copy) word _ASM_LABEL(r_1byte_word_copy) word _ASM_LABEL(r_byte_copy) word _ASM_LABEL(r_1byte_half_copy) word _ASM_LABEL(r_half_copy) word _ASM_LABEL(r_byte_copy) word _ASM_LABEL(r_1half_word_copy) word _ASM_LABEL(r_byte_copy) word _ASM_LABEL(r_byte_copy) word _ASM_LABEL(r_1byte_half_copy) word _ASM_LABEL(r_byte_copy) word _ASM_LABEL(r_3byte_word_copy) #endif