summaryrefslogtreecommitdiff
path: root/sys/lib
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2006-11-17 22:32:39 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2006-11-17 22:32:39 +0000
commit37e264971d57609cd9cf1bb417df64acc5371340 (patch)
tree2527c5bcdd5b8f5993b0cd3c710f5c03445b0e8d /sys/lib
parent3fea4cab24ade8220623a26c4e0e4f3458abf436 (diff)
Move m88k memory copy and fill functions to libkern. The copy functions will
no longer share the same code, but will be instead be duplicated from the same source, so that bcopy() and memcpy() do not need to check for overlap, and memcpy() and memmove() are shorter.
Diffstat (limited to 'sys/lib')
-rw-r--r--sys/lib/libkern/arch/m88k/Makefile.inc4
-rw-r--r--sys/lib/libkern/arch/m88k/bcopy.S4
-rw-r--r--sys/lib/libkern/arch/m88k/bzero.S195
-rw-r--r--sys/lib/libkern/arch/m88k/copy_subr.S362
-rw-r--r--sys/lib/libkern/arch/m88k/memcpy.S4
-rw-r--r--sys/lib/libkern/arch/m88k/memmove.S4
-rw-r--r--sys/lib/libkern/arch/m88k/ovbcopy.S4
7 files changed, 576 insertions, 1 deletions
diff --git a/sys/lib/libkern/arch/m88k/Makefile.inc b/sys/lib/libkern/arch/m88k/Makefile.inc
index d34437d10d7..74bbefb2a4a 100644
--- a/sys/lib/libkern/arch/m88k/Makefile.inc
+++ b/sys/lib/libkern/arch/m88k/Makefile.inc
@@ -1,6 +1,8 @@
-# $OpenBSD: Makefile.inc,v 1.8 2004/04/01 20:39:59 miod Exp $
+# $OpenBSD: Makefile.inc,v 1.9 2006/11/17 22:32:38 miod Exp $
SRCS+= __main.c imax.c imin.c lmax.c lmin.c max.c min.c ulmax.c ulmin.c \
memchr.c memcmp.c memset.c bcmp.c random.c \
strcmp.c strlcat.c strlcpy.c strlen.c strncmp.c \
strncpy.c scanc.c skpc.c strncasecmp.c ffs.c
+
+SRCS+= bcopy.S bzero.S memcpy.S memmove.S ovbcopy.S
diff --git a/sys/lib/libkern/arch/m88k/bcopy.S b/sys/lib/libkern/arch/m88k/bcopy.S
new file mode 100644
index 00000000000..7998a00c64a
--- /dev/null
+++ b/sys/lib/libkern/arch/m88k/bcopy.S
@@ -0,0 +1,4 @@
+/* $OpenBSD: bcopy.S,v 1.1 2006/11/17 22:32:38 miod Exp $ */
+
+#define BCOPY
+#include "copy_subr.S"
diff --git a/sys/lib/libkern/arch/m88k/bzero.S b/sys/lib/libkern/arch/m88k/bzero.S
new file mode 100644
index 00000000000..071b3304998
--- /dev/null
+++ b/sys/lib/libkern/arch/m88k/bzero.S
@@ -0,0 +1,195 @@
+/* $OpenBSD: bzero.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 <machine/asm.h>
+
+/*######################################################################*/
+
+/*
+ * April 1990, Omron Corporation
+ * jfriedl@nff.ncl.omron.co.jp
+ *
+ * void bzero(destination, length)
+ *
+ * Clear (set to zero) LENGTH bytes of memory starting at DESTINATION.
+ * Note that there is no return value.
+ *
+ * This is fast. Really fast. Especially for long lengths.
+ */
+#define R_dest r2
+#define R_len r3
+
+#define R_bytes r4
+#define R_mark_address r5
+#define R_addr r6 /* R_addr && R_temp SHARE */
+#define R_temp r6 /* R_addr && R_temp SHARE */
+
+ENTRY(bzero)
+ /*
+ * If the destination is not word aligned, we'll word align
+ * it first to make things easier.
+ *
+ * We'll check to see first if bit #0 is set and then bit #1
+ * (of the destination address). If either are set, it's
+ * not word aligned.
+ */
+ bb1 0, R_dest, _ASM_LABEL(not_initially_word_aligned)
+ bb1 1, R_dest, _ASM_LABEL(not_initially_word_aligned)
+
+ASLOCAL(now_word_aligned)
+ /*
+ * before we get into the main loop, grab the
+ * address of the label "mark" below.
+ */
+ or.u R_mark_address, r0, hi16(_ASM_LABEL(mark))
+ or R_mark_address, R_mark_address, lo16(_ASM_LABEL(mark))
+
+ASLOCAL(top_of_main_loop)
+#define MAX_AT_ONE_TIME 128
+ /*
+ * Now we find out how many words we can zero-fill in a row.
+ * We do this by doing something like:
+ *
+ * bytes &= 0xfffffffc;
+ * if (bytes > MAX_AT_ONE_TIME)
+ * bytes = MAX_AT_ONE_TIME;
+ */
+
+ /*
+ * Clear lower two bits of length to give us the number of bytes
+ * ALIGNED TO THE WORD LENGTH remaining to move.
+ */
+ clr R_bytes, R_len, 2<0>
+
+ /* if we're done clearing WORDS, jump out */
+ bcnd eq0, R_bytes, _ASM_LABEL(done_doing_words)
+
+ /* if the number of bytes > MAX_AT_ONE_TIME, do only the max */
+ cmp R_temp, R_bytes, MAX_AT_ONE_TIME
+ bb1 lt, R_temp, 1f
+
+ /*
+ * Since we're doing the max, we know exactly where we're
+ * jumping (the first one in the list!), so we can jump
+ * right there. However, we've still got to adjust
+ * the length, so we'll jump to where we ajust the length
+ * which just happens to fall through to the first store zero
+ * in the list.
+ *
+ * Note, however, that we're jumping to an instruction that
+ * would be in the delay slot for the jump in front of it,
+ * so if you change things here, WATCH OUT.
+ */
+ br.n do_max
+ or R_bytes, r0, MAX_AT_ONE_TIME
+
+1:
+ /*
+ * Now we have the number of bytes to zero during this iteration,
+ * (which, as it happens, is the last iteration if we're here).
+ * We'll calculate the proper place to jump and then jump there,
+ * after adjusting the length. NOTE that there is a label between
+ * the "jmp.n" and the "subu" below... the "subu" is NOT always
+ * executed in the delay slot of the "jmp.n".
+ */
+ subu R_addr, R_mark_address, R_bytes
+
+ /* and go there (after adjusting the length via ".n") */
+ jmp.n R_addr
+ASLOCAL(do_max)
+ subu R_len, R_len, R_bytes /* NOTE: this is in the delay slot! */
+
+ st r0, R_dest, 0x7c /* 128 */
+ st r0, R_dest, 0x78 /* 124 */
+ st r0, R_dest, 0x74 /* 120 */
+ st r0, R_dest, 0x70 /* 116 */
+ st r0, R_dest, 0x6c /* 112 */
+ st r0, R_dest, 0x68 /* 108 */
+ st r0, R_dest, 0x64 /* 104 */
+ st r0, R_dest, 0x60 /* 100 */
+ st r0, R_dest, 0x5c /* 96 */
+ st r0, R_dest, 0x58 /* 92 */
+ st r0, R_dest, 0x54 /* 88 */
+ st r0, R_dest, 0x50 /* 84 */
+ st r0, R_dest, 0x4c /* 80 */
+ st r0, R_dest, 0x48 /* 76 */
+ st r0, R_dest, 0x44 /* 72 */
+ st r0, R_dest, 0x40 /* 68 */
+ st r0, R_dest, 0x3c /* 64 */
+ st r0, R_dest, 0x38 /* 60 */
+ st r0, R_dest, 0x34 /* 56 */
+ st r0, R_dest, 0x30 /* 52 */
+ st r0, R_dest, 0x2c /* 44 */
+ st r0, R_dest, 0x28 /* 40 */
+ st r0, R_dest, 0x24 /* 36 */
+ st r0, R_dest, 0x20 /* 32 */
+ st r0, R_dest, 0x1c /* 28 */
+ st r0, R_dest, 0x18 /* 24 */
+ st r0, R_dest, 0x14 /* 20 */
+ st r0, R_dest, 0x10 /* 16 */
+ st r0, R_dest, 0x0c /* 12 */
+ st r0, R_dest, 0x08 /* 8 */
+ st r0, R_dest, 0x04 /* 4 */
+ st r0, R_dest, 0x00 /* 0 */
+
+ASLOCAL(mark)
+ br.n _ASM_LABEL(top_of_main_loop)
+ addu R_dest, R_dest, R_bytes /* bump up the dest address */
+
+ASLOCAL(done_doing_words)
+ bcnd ne0, R_len, 1f
+ jmp r1
+
+1:
+ subu R_len, R_len, 1
+ bcnd.n ne0, R_len, 1b
+ st.b r0, R_dest, R_len
+1:
+ jmp r1
+
+ASLOCAL(not_initially_word_aligned)
+ /*
+ * Bzero to word-align the address (at least if the length allows it).
+ */
+ bcnd eq0, R_len, 1b
+ st.b r0, R_dest, 0
+ addu R_dest, R_dest, 1
+ mask R_temp, R_dest, 0x3
+ bcnd.n eq0, R_temp, _ASM_LABEL(now_word_aligned)
+ subu R_len, R_len, 1
+ br _ASM_LABEL(not_initially_word_aligned)
+
+#undef R_dest
+#undef R_len
+#undef R_bytes
+#undef R_mark_address
+#undef R_addr
+#undef R_temp
+#undef MAX_AT_ONE_TIME
diff --git a/sys/lib/libkern/arch/m88k/copy_subr.S b/sys/lib/libkern/arch/m88k/copy_subr.S
new file mode 100644
index 00000000000..a8aef9c6b44
--- /dev/null
+++ b/sys/lib/libkern/arch/m88k/copy_subr.S
@@ -0,0 +1,362 @@
+/* $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 <machine/asm.h>
+
+/*
+ * 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
diff --git a/sys/lib/libkern/arch/m88k/memcpy.S b/sys/lib/libkern/arch/m88k/memcpy.S
new file mode 100644
index 00000000000..47666e5eab1
--- /dev/null
+++ b/sys/lib/libkern/arch/m88k/memcpy.S
@@ -0,0 +1,4 @@
+/* $OpenBSD: memcpy.S,v 1.1 2006/11/17 22:32:38 miod Exp $ */
+
+#define MEMCPY
+#include "copy_subr.S"
diff --git a/sys/lib/libkern/arch/m88k/memmove.S b/sys/lib/libkern/arch/m88k/memmove.S
new file mode 100644
index 00000000000..0fefddee50d
--- /dev/null
+++ b/sys/lib/libkern/arch/m88k/memmove.S
@@ -0,0 +1,4 @@
+/* $OpenBSD: memmove.S,v 1.1 2006/11/17 22:32:38 miod Exp $ */
+
+#define MEMMOVE
+#include "copy_subr.S"
diff --git a/sys/lib/libkern/arch/m88k/ovbcopy.S b/sys/lib/libkern/arch/m88k/ovbcopy.S
new file mode 100644
index 00000000000..7448aa1ab30
--- /dev/null
+++ b/sys/lib/libkern/arch/m88k/ovbcopy.S
@@ -0,0 +1,4 @@
+/* $OpenBSD: ovbcopy.S,v 1.1 2006/11/17 22:32:38 miod Exp $ */
+
+#define OVBCOPY
+#include "copy_subr.S"