summaryrefslogtreecommitdiff
path: root/usr/src/lib/libc/sparc/gen
diff options
context:
space:
mode:
authorstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
committerstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
commit7c478bd95313f5f23a4c958a745db2134aa03244 (patch)
treec871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/libc/sparc/gen
downloadillumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/libc/sparc/gen')
-rw-r--r--usr/src/lib/libc/sparc/gen/_getsp.s47
-rw-r--r--usr/src/lib/libc/sparc/gen/_stack_grow.s112
-rw-r--r--usr/src/lib/libc/sparc/gen/_xregs_clrptr.c44
-rw-r--r--usr/src/lib/libc/sparc/gen/abs.s45
-rw-r--r--usr/src/lib/libc/sparc/gen/alloca.s58
-rw-r--r--usr/src/lib/libc/sparc/gen/cuexit.s47
-rw-r--r--usr/src/lib/libc/sparc/gen/ecvt.c109
-rw-r--r--usr/src/lib/libc/sparc/gen/getctxt.c65
-rw-r--r--usr/src/lib/libc/sparc/gen/ladd.s71
-rw-r--r--usr/src/lib/libc/sparc/gen/lexp10.c52
-rw-r--r--usr/src/lib/libc/sparc/gen/llog10.c53
-rw-r--r--usr/src/lib/libc/sparc/gen/lmul.c57
-rw-r--r--usr/src/lib/libc/sparc/gen/lock.s52
-rw-r--r--usr/src/lib/libc/sparc/gen/lshiftl.s102
-rw-r--r--usr/src/lib/libc/sparc/gen/lsign.s53
-rw-r--r--usr/src/lib/libc/sparc/gen/lsub.s70
-rw-r--r--usr/src/lib/libc/sparc/gen/makectxt.c168
-rw-r--r--usr/src/lib/libc/sparc/gen/memchr.s177
-rw-r--r--usr/src/lib/libc/sparc/gen/memcmp.s237
-rw-r--r--usr/src/lib/libc/sparc/gen/memcpy.s189
-rw-r--r--usr/src/lib/libc/sparc/gen/memmove.s193
-rw-r--r--usr/src/lib/libc/sparc/gen/memset.s96
-rw-r--r--usr/src/lib/libc/sparc/gen/setjmp.s121
-rw-r--r--usr/src/lib/libc/sparc/gen/siginfolst.c187
-rw-r--r--usr/src/lib/libc/sparc/gen/siglongjmp.c100
-rw-r--r--usr/src/lib/libc/sparc/gen/sparc_data.s33
-rw-r--r--usr/src/lib/libc/sparc/gen/strcasecmp.s353
-rw-r--r--usr/src/lib/libc/sparc/gen/strchr.s219
-rw-r--r--usr/src/lib/libc/sparc/gen/strcmp.s247
-rw-r--r--usr/src/lib/libc/sparc/gen/strcpy.s172
-rw-r--r--usr/src/lib/libc/sparc/gen/strlcpy.s236
-rw-r--r--usr/src/lib/libc/sparc/gen/strlen.s141
-rw-r--r--usr/src/lib/libc/sparc/gen/strncmp.s315
-rw-r--r--usr/src/lib/libc/sparc/gen/strncpy.s290
-rw-r--r--usr/src/lib/libc/sparc/gen/swapctxt.c63
-rw-r--r--usr/src/lib/libc/sparc/gen/sync_instruction_memory.s79
36 files changed, 4653 insertions, 0 deletions
diff --git a/usr/src/lib/libc/sparc/gen/_getsp.s b/usr/src/lib/libc/sparc/gen/_getsp.s
new file mode 100644
index 0000000000..fc5515217d
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/_getsp.s
@@ -0,0 +1,47 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 1989-2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+.ident "%Z%%M% %I% %E% SMI"
+
+ .file "_getsp.s"
+
+#include <sys/asm_linkage.h>
+
+/*
+ * Return the stack pointer
+ */
+ ENTRY(_getsp)
+ retl
+ mov %sp, %o0
+ SET_SIZE(_getsp)
+
+/*
+ * Return the frame pointer
+ */
+ ENTRY(_getfp)
+ retl
+ mov %fp, %o0
+ SET_SIZE(_getfp)
diff --git a/usr/src/lib/libc/sparc/gen/_stack_grow.s b/usr/src/lib/libc/sparc/gen/_stack_grow.s
new file mode 100644
index 0000000000..293769fd68
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/_stack_grow.s
@@ -0,0 +1,112 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+ .file "%M%"
+
+#include <sys/asm_linkage.h>
+#include "SYS.h"
+#include <../assym.h>
+
+/*
+ * void *
+ * _stack_grow(void *addr)
+ * {
+ * uintptr_t base = (uintptr_t)curthread->ul_ustack.ss_sp;
+ * size_t size = curthread->ul_ustack.ss_size;
+ *
+ * if (size > (uintptr_t)addr - (base - STACK_BIAS))
+ * return (addr);
+ *
+ * if (size == 0)
+ * return (addr);
+ *
+ * if (size > %sp - (base - STACK_BIAS))
+ * %sp = base - STACK_BIAS - STACK_ALIGN;
+ *
+ * *((char *)(base - 1));
+ *
+ * _lwp_kill(_lwp_self(), SIGSEGV);
+ * }
+ */
+
+#if defined(__sparcv9)
+#define PN ,pn %xcc,
+#else
+#define PN
+#endif
+
+ /*
+ * o0: address to which the stack will be grown (biased)
+ */
+ ENTRY(_stack_grow)
+ ldn [%g7 + UL_USTACK + SS_SP], %o1
+ ldn [%g7 + UL_USTACK + SS_SIZE], %o2
+ sub %o1, STACK_BIAS, %o3
+
+ sub %o0, %o3, %o4
+ cmp %o2, %o4
+ bleu PN 1f
+ tst %o2
+
+ retl
+ nop
+1:
+ /*
+ * If the stack size is 0, stack checking is disabled.
+ */
+ bnz PN 2f
+ nop
+ retl
+ nop
+2:
+ /*
+ * Move the stack pointer outside the stack bounds if it isn't already.
+ */
+ sub %sp, %o3, %o4
+ cmp %o2, %o4
+ bleu PN 3f
+ nop
+ sub %o3, STACK_ALIGN, %sp
+3:
+ /*
+ * Dereference an address in the guard page.
+ */
+ ldub [%o1 - 1], %g0
+
+ /*
+ * If the above load doesn't raise a SIGSEGV then do it ourselves.
+ */
+ SYSTRAP_RVAL1(lwp_self)
+ mov SIGSEGV, %o1
+ SYSTRAP_RVAL1(lwp_kill)
+
+ /*
+ * We should never get here; explode if we do.
+ */
+ illtrap
+ SET_SIZE(_stack_grow)
diff --git a/usr/src/lib/libc/sparc/gen/_xregs_clrptr.c b/usr/src/lib/libc/sparc/gen/_xregs_clrptr.c
new file mode 100644
index 0000000000..9be916fec2
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/_xregs_clrptr.c
@@ -0,0 +1,44 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "synonyms.h"
+#include <ucontext.h>
+#include <sys/types.h>
+#include "libc.h"
+
+/*
+ * clear the struct ucontext extra register state pointer
+ */
+void
+_xregs_clrptr(ucontext_t *uc)
+{
+#ifndef __LP64
+ uc->uc_mcontext.xrs.xrs_id = 0;
+ uc->uc_mcontext.xrs.xrs_ptr = NULL;
+#endif
+}
diff --git a/usr/src/lib/libc/sparc/gen/abs.s b/usr/src/lib/libc/sparc/gen/abs.s
new file mode 100644
index 0000000000..6a555d8dca
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/abs.s
@@ -0,0 +1,45 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1987 Sun Microsystems, Inc.
+ */
+
+.ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.5 */
+
+ .file "abs.s"
+
+#include <sys/asm_linkage.h>
+
+/*
+ * int abs(register int arg);
+ * long labs(register long int arg);
+ */
+ ENTRY2(abs,labs)
+ tst %o0
+ bl,a 1f
+ neg %o0
+1:
+ retl
+ nop
+
+ SET_SIZE(abs)
+ SET_SIZE(labs)
diff --git a/usr/src/lib/libc/sparc/gen/alloca.s b/usr/src/lib/libc/sparc/gen/alloca.s
new file mode 100644
index 0000000000..2c5bba3af4
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/alloca.s
@@ -0,0 +1,58 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1987 Sun Microsystems, Inc.
+ */
+
+#ident "%Z%%M% %I% %E% SMI"
+
+ .file "alloca.s"
+
+#include <sys/asm_linkage.h>
+
+ !
+ ! o0: # bytes of space to allocate, already rounded to 0 mod 8
+ ! o1: %sp-relative offset of tmp area
+ ! o2: %sp-relative offset of end of tmp area
+ !
+ ! we want to bump %sp by the requested size
+ ! then copy the tmp area to its new home
+ ! this is necessasy as we could theoretically
+ ! be in the middle of a compilicated expression.
+ !
+ ENTRY(__builtin_alloca)
+ mov %sp, %o3 ! save current sp
+ sub %sp, %o0, %sp ! bump to new value
+ ! copy loop: should do nothing gracefully
+ b 2f
+ subcc %o2, %o1, %o5 ! number of bytes to move
+1:
+ ld [%o3 + %o1], %o4 ! load from old temp area
+ st %o4, [%sp + %o1] ! store to new temp area
+ add %o1, 4, %o1
+2: bg 1b
+ subcc %o5, 4, %o5
+ ! now return new %sp + end-of-temp
+ retl
+ add %sp, %o2, %o0
+
+ SET_SIZE(__builtin_alloca)
diff --git a/usr/src/lib/libc/sparc/gen/cuexit.s b/usr/src/lib/libc/sparc/gen/cuexit.s
new file mode 100644
index 0000000000..e6e7fbe00f
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/cuexit.s
@@ -0,0 +1,47 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+.ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.7 */
+
+/* C library -- exit */
+/* void exit (int status); */
+
+ .file "cuexit.s"
+
+#include "SYS.h"
+
+ ENTRY(exit)
+ save %sp, -SA(MINFRAME), %sp
+ call _exithandle
+ nop
+ restore
+ SYSTRAP_RVAL1(exit)
+
+ SET_SIZE(exit)
diff --git a/usr/src/lib/libc/sparc/gen/ecvt.c b/usr/src/lib/libc/sparc/gen/ecvt.c
new file mode 100644
index 0000000000..18807b1eca
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/ecvt.c
@@ -0,0 +1,109 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+
+/*
+ * ecvt converts to decimal
+ * the number of digits is specified by ndigit
+ * decpt is set to the position of the decimal point
+ * sign is set to 0 for positive, 1 for negative
+ *
+ */
+#pragma weak ecvt = _ecvt
+#pragma weak fcvt = _fcvt
+#pragma weak qecvt = _qecvt
+#pragma weak qfcvt = _qfcvt
+#pragma weak qgcvt = _qgcvt
+
+#include "synonyms.h"
+#include <sys/types.h>
+#include <stdlib.h>
+#include <floatingpoint.h>
+#include "tsd.h"
+
+char *
+ecvt(double number, int ndigits, int *decpt, int *sign)
+{
+ char *buf = tsdalloc(_T_ECVT, DECIMAL_STRING_LENGTH, NULL);
+
+ return (econvert(number, ndigits, decpt, sign, buf));
+}
+
+char *
+fcvt(double number, int ndigits, int *decpt, int *sign)
+{
+ char *buf = tsdalloc(_T_ECVT, DECIMAL_STRING_LENGTH, NULL);
+ char *ptr, *val;
+ char ch;
+ int deci_val;
+
+ ptr = fconvert(number, ndigits, decpt, sign, buf);
+
+ val = ptr;
+ deci_val = *decpt;
+
+ while ((ch = *ptr) != 0) {
+ if (ch != '0') { /* You execute this if there are no */
+ /* leading zero's remaining. */
+ *decpt = deci_val; /* If there are leading zero's */
+ return (ptr); /* gets updated. */
+ }
+ ptr++;
+ deci_val--;
+ }
+ return (val);
+}
+
+char *
+qecvt(
+ long double number,
+ int ndigits,
+ int *decpt,
+ int *sign)
+{
+ char *buf = tsdalloc(_T_ECVT, DECIMAL_STRING_LENGTH, NULL);
+
+ return (qeconvert(&number, ndigits, decpt, sign, buf));
+}
+
+char *
+qfcvt(long double number, int ndigits, int *decpt, int *sign)
+{
+ char *buf = tsdalloc(_T_ECVT, DECIMAL_STRING_LENGTH, NULL);
+
+ return (qfconvert(&number, ndigits, decpt, sign, buf));
+}
+
+char *
+qgcvt(long double number, int ndigits, char *buffer)
+{
+ return (qgconvert(&number, ndigits, 0, buffer));
+}
diff --git a/usr/src/lib/libc/sparc/gen/getctxt.c b/usr/src/lib/libc/sparc/gen/getctxt.c
new file mode 100644
index 0000000000..d751462234
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/getctxt.c
@@ -0,0 +1,65 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+
+/*
+ * Copyright 1996-2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#pragma weak _private_getcontext = _getcontext
+#pragma weak getcontext = _getcontext
+
+#include "synonyms.h"
+#include <ucontext.h>
+#include <sys/types.h>
+#include "libc.h"
+
+int
+getcontext(ucontext_t *ucp)
+{
+ greg_t *reg;
+
+ ucp->uc_flags = UC_ALL;
+ if (__getcontext_syscall(ucp))
+ return (-1);
+
+ /*
+ * Note that %o1 and %g1 are modified by the system call
+ * routine. ABI calling conventions specify that the caller
+ * cannot depend upon %o0 through %o5 nor %g1, so no effort is
+ * made to maintain these registers. %o0 is forced to reflect
+ * an affirmative return code.
+ */
+ reg = ucp->uc_mcontext.gregs;
+ reg[REG_SP] = getfp();
+ reg[REG_O7] = caller();
+ reg[REG_PC] = reg[REG_O7] + 8;
+ reg[REG_nPC] = reg[REG_PC] + 4;
+ reg[REG_O0] = 0;
+
+ return (0);
+}
diff --git a/usr/src/lib/libc/sparc/gen/ladd.s b/usr/src/lib/libc/sparc/gen/ladd.s
new file mode 100644
index 0000000000..a5ddacc329
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/ladd.s
@@ -0,0 +1,71 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+
+/* Copyright (c) 1989 by Sun Microsystems, Inc. */
+
+.ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.1 */
+
+/*
+ * Double long add routine. Ported from pdp 11/70 version
+ * with considerable effort. All supplied comments were ported.
+ *
+ * Ported from m32 version to sparc. No comments about difficulty.
+ *
+ * dl_t
+ * ladd (lop, rop)
+ * dl_t lop;
+ * dl_t rop;
+ */
+
+ .file "ladd.s"
+
+#include <sys/asm_linkage.h>
+
+ ANSI_PRAGMA_WEAK(ladd,function)
+
+#include "synonyms.h"
+
+ ENTRY(ladd)
+
+ ld [%o7+8],%o4 ! Instruction at ret-addr should be a
+ cmp %o4,8 ! 'unimp 8' indicating a valid call.
+ be 1f ! if OK, go forward.
+ nop ! delay instruction.
+ jmp %o7+8 ! return
+ nop ! delay instruction.
+
+1:
+ ld [%o0+0],%o2 ! fetch lop.dl_hop
+ ld [%o0+4],%o3 ! fetch lop.dl_lop
+ ld [%o1+0],%o4 ! fetch rop.dl_hop
+ ld [%o1+4],%o5 ! fetch rop.dl_lop
+ addcc %o3,%o5,%o3 ! lop.dl_lop + rop.dl_lop (set carry)
+ addxcc %o2,%o4,%o2 ! lop.dl_hop + rop.dl_hop + <carry>
+ ld [%sp+(16*4)],%o0 ! address to store result into
+ st %o2,[%o0+0] ! store result, dl_hop
+ jmp %o7+12 ! return
+ st %o3,[%o0+4] ! store result, dl_lop
+
+ SET_SIZE(ladd)
diff --git a/usr/src/lib/libc/sparc/gen/lexp10.c b/usr/src/lib/libc/sparc/gen/lexp10.c
new file mode 100644
index 0000000000..28152a5b8f
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/lexp10.c
@@ -0,0 +1,52 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+
+#pragma weak lexp10 = _lexp10
+
+#include "synonyms.h"
+#include <sys/types.h>
+#include <sys/dl.h>
+
+dl_t
+lexp10(dl_t exp)
+{
+ dl_t result;
+
+ result = lone;
+
+ while (exp.dl_hop != 0 || exp.dl_lop != 0) {
+ result = lmul(result, lten);
+ exp = lsub(exp, lone);
+ }
+
+ return (result);
+}
diff --git a/usr/src/lib/libc/sparc/gen/llog10.c b/usr/src/lib/libc/sparc/gen/llog10.c
new file mode 100644
index 0000000000..14f690c61b
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/llog10.c
@@ -0,0 +1,53 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+
+#pragma weak llog10 = _llog10
+
+#include "synonyms.h"
+#include <sys/types.h>
+#include <sys/dl.h>
+
+dl_t
+llog10(dl_t val)
+{
+ dl_t result;
+
+ result = lzero;
+ val = ldivide(val, lten);
+
+ while (val.dl_hop != 0 || val.dl_lop != 0) {
+ val = ldivide(val, lten);
+ result = ladd(result, lone);
+ }
+
+ return (result);
+}
diff --git a/usr/src/lib/libc/sparc/gen/lmul.c b/usr/src/lib/libc/sparc/gen/lmul.c
new file mode 100644
index 0000000000..7f6aa0f079
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/lmul.c
@@ -0,0 +1,57 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+
+#pragma weak lmul = _lmul
+
+#include "synonyms.h"
+#include "sys/types.h"
+#include "sys/dl.h"
+
+dl_t
+lmul(dl_t lop, dl_t rop)
+{
+ dl_t ans;
+ dl_t tmp;
+ int jj;
+
+ ans = lzero;
+
+ for (jj = 0; jj <= 63; jj++) {
+ if ((lshiftl(rop, -jj).dl_lop & 1) == 0)
+ continue;
+ tmp = lshiftl(lop, jj);
+ tmp.dl_hop &= 0x7fffffff;
+ ans = ladd(ans, tmp);
+ };
+
+ return (ans);
+}
diff --git a/usr/src/lib/libc/sparc/gen/lock.s b/usr/src/lib/libc/sparc/gen/lock.s
new file mode 100644
index 0000000000..a96043767d
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/lock.s
@@ -0,0 +1,52 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+ .file "%M%"
+
+#include <sys/asm_linkage.h>
+
+/*
+ * lock_try(lp)
+ * - returns non-zero on success.
+ */
+ ENTRY(_lock_try)
+ ldstub [%o0], %o1 ! try to set lock, get value in %o1
+ membar #LoadLoad
+ retl
+ xor %o1, 0xff, %o0 ! delay - return non-zero if success
+ SET_SIZE(_lock_try)
+
+/*
+ * lock_clear(lp)
+ * - clear lock.
+ */
+ ENTRY(_lock_clear)
+ membar #LoadStore|#StoreStore
+ retl
+ clrb [%o0]
+ SET_SIZE(_lock_clear)
diff --git a/usr/src/lib/libc/sparc/gen/lshiftl.s b/usr/src/lib/libc/sparc/gen/lshiftl.s
new file mode 100644
index 0000000000..820c91f8ea
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/lshiftl.s
@@ -0,0 +1,102 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+
+/* Copyright (c) 1989 by Sun Microsystems, Inc. */
+
+.ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.1 */
+
+/*
+ * Shift a double long value. Ported from m32 version to sparc.
+ *
+ * dl_t
+ * lshiftl (op, cnt)
+ * dl_t op;
+ * int cnt;
+ */
+
+ .file "lshiftl.s"
+
+#include <sys/asm_linkage.h>
+
+ ANSI_PRAGMA_WEAK(lshiftl,function)
+
+#include "synonyms.h"
+
+
+ ENTRY(lshiftl)
+
+ ld [%o7+8],%o4 ! Instruction at ret-addr should be a
+ cmp %o4,8 ! 'unimp 8' indicating a valid call.
+ be 1f ! if OK, go forward.
+ nop ! delay instruction.
+ jmp %o7+8 ! return
+ nop ! delay instruction.
+
+1:
+ ld [%o0+0],%o2 ! fetch op.dl_hop
+ ld [%o0+4],%o3 ! fetch op.dl_lop
+ subcc %g0,%o1,%o4 ! test cnt < 0 and save reciprocol
+ bz .done
+ ld [%sp+(16*4)],%o0 ! address to store result into
+ bg .right !
+ nop
+ ! Positive (or null) shift (left)
+ and %o1,0x3f,%o1 ! Reduce range to 0..63
+ subcc %o1,32,%o5 ! cnt - 32 (also test cnt >= 32)
+ bneg,a .leftsmall !
+ add %o4,32,%o4 ! 32 - cnt (actually ((-cnt) + 32)
+ sll %o3,%o5,%o2 ! R.h = R.l << (cnt - 32)
+ ba .done !
+ or %g0,%g0,%o3 ! R.l = 0
+
+.leftsmall:
+ srl %o3,%o4,%o5 ! temp = R.l >> (31 - cnt)
+ sll %o3,%o1,%o3 ! R.l = R.l << cnt
+ sll %o2,%o1,%o2 ! R.h = R.h << cnt
+ ba .done !
+ or %o2,%o5,%o2 ! R.h = R.h | temp
+
+.right: ! Negative shift (right)
+ and %o4,0x3f,%o4 ! Reduce range to 0..63
+ subcc %o4,32,%o5 ! cnt - 32 (also test cnt >= 32)
+ bneg,a .rightsmall !
+ add %o1,32,%o1 ! 32 - cnt (actually ((-cnt) + 32)
+ srl %o2,%o5,%o3 ! R.l = R.h >> (cnt - 32)
+ ba .done !
+ or %g0,%g0,%o2 ! R.h = 0
+
+.rightsmall:
+ sll %o2,%o1,%o5 ! temp = R.h << (31 - cnt)
+ srl %o3,%o4,%o3 ! R.l = R.l >> cnt
+ srl %o2,%o4,%o2 ! R.h = R.h >> cnt
+ ba .done !
+ or %o3,%o5,%o3 ! R.l = R.l | temp
+
+.done:
+ st %o2,[%o0+0] ! store result, dl_hop
+ jmp %o7+12 ! return
+ st %o3,[%o0+4] ! store result, dl_lop
+
+ SET_SIZE(lshiftl)
diff --git a/usr/src/lib/libc/sparc/gen/lsign.s b/usr/src/lib/libc/sparc/gen/lsign.s
new file mode 100644
index 0000000000..1269fbe551
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/lsign.s
@@ -0,0 +1,53 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+
+/* Copyright (c) 1989 by Sun Microsystems, Inc. */
+
+.ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.1 */
+
+/*
+ * Determine the sign of a double-long number.
+ * Ported from m32 version to sparc.
+ *
+ * int
+ * lsign (op)
+ * dl_t op;
+ */
+
+ .file "lsign.s"
+
+#include <sys/asm_linkage.h>
+
+ ANSI_PRAGMA_WEAK(lsign,function)
+
+#include "synonyms.h"
+
+ ENTRY(lsign)
+
+ ld [%o0],%o0 ! fetch op (high word only)
+ jmp %o7+8 ! return
+ srl %o0,31,%o0 ! shift letf logical to isolate sign
+
+ SET_SIZE(lsign)
diff --git a/usr/src/lib/libc/sparc/gen/lsub.s b/usr/src/lib/libc/sparc/gen/lsub.s
new file mode 100644
index 0000000000..e6457b9abe
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/lsub.s
@@ -0,0 +1,70 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+
+/* Copyright (c) 1989 by Sun Microsystems, Inc. */
+
+.ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.1 */
+
+/*
+ * Double long subtraction routine. Ported from pdp 11/70 version
+ * with considerable effort. All supplied comments were ported.
+ * Ported from m32 version to sparc. No comments about difficulty.
+ *
+ * dl_t
+ * lsub (lop, rop)
+ * dl_t lop;
+ * dl_t rop;
+ */
+
+ .file "lsub.s"
+
+#include <sys/asm_linkage.h>
+
+ ANSI_PRAGMA_WEAK(lsub,function)
+
+#include "synonyms.h"
+
+ ENTRY(lsub)
+
+ ld [%o7+8],%o4 ! Instruction at ret-addr should be a
+ cmp %o4,8 ! 'unimp 8' indicating a valid call.
+ be 1f ! if OK, go forward.
+ nop ! delay instruction.
+ jmp %o7+8 ! return
+ nop ! delay instruction.
+
+1:
+ ld [%o0+0],%o2 ! fetch lop.dl_hop
+ ld [%o0+4],%o3 ! fetch lop.dl_lop
+ ld [%o1+0],%o4 ! fetch rop.dl_hop
+ ld [%o1+4],%o5 ! fetch rop.dl_lop
+ subcc %o3,%o5,%o3 ! lop.dl_lop - rop.dl_lop (set carry)
+ subxcc %o2,%o4,%o2 ! lop.dl_hop - rop.dl_hop - <carry>
+ ld [%sp+(16*4)],%o0 ! address to store result into
+ st %o2,[%o0] ! store result.dl_hop
+ jmp %o7+12 ! return
+ st %o3,[%o0+4] ! store result.dl_lop
+
+ SET_SIZE(lsub)
diff --git a/usr/src/lib/libc/sparc/gen/makectxt.c b/usr/src/lib/libc/sparc/gen/makectxt.c
new file mode 100644
index 0000000000..9dc4c64697
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/makectxt.c
@@ -0,0 +1,168 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+
+#pragma weak makecontext = _makecontext
+#pragma weak __makecontext_v2 = ___makecontext_v2
+
+#include "synonyms.h"
+#include <stdarg.h>
+#include <strings.h>
+#include <sys/ucontext.h>
+#include <sys/stack.h>
+#include <sys/frame.h>
+
+/*
+ * The ucontext_t that the user passes in must have been primed with a
+ * call to getcontext(2), have the uc_stack member set to reflect the
+ * stack which this context will use, and have the uc_link member set
+ * to the context which should be resumed when this context returns.
+ * When makecontext() returns, the ucontext_t will be set to run the
+ * given function with the given parameters on the stack specified by
+ * uc_stack, and which will return to the ucontext_t specified by uc_link.
+ */
+
+static void resumecontext(void);
+
+void
+_makecontext(ucontext_t *ucp, void (*func)(), int argc, ...)
+{
+ greg_t *reg;
+ long *tsp;
+ char *sp;
+ int argno;
+ va_list ap;
+ size_t size;
+
+ reg = ucp->uc_mcontext.gregs;
+ reg[REG_PC] = (greg_t)func;
+ reg[REG_nPC] = reg[REG_PC] + 0x4;
+
+ /*
+ * Reserve enough space for a frame and the arguments beyond the
+ * sixth; round to stack alignment.
+ */
+ size = sizeof (struct frame);
+ size += (argc > 6 ? argc - 6 : 0) * sizeof (long);
+
+ /*
+ * The legacy implemenation of makecontext() on sparc has been to
+ * interpret the uc_stack.ss_sp member incorrectly as the top of the
+ * stack rather than the base. We preserve this behavior here, but
+ * provide the correct semantics in __makecontext_v2().
+ */
+ sp = (char *)(((uintptr_t)ucp->uc_stack.ss_sp - size) &
+ ~(STACK_ALIGN - 1));
+
+ /*
+ * Copy all args to the stack, and put the first 6 args into the
+ * ucontext_t. Zero the other fields of the frame.
+ */
+ /* LINTED pointer cast may result in improper alignment */
+ tsp = &((struct frame *)sp)->fr_argd[0];
+ bzero(sp, sizeof (struct frame));
+
+ va_start(ap, argc);
+
+ for (argno = 0; argno < argc; argno++) {
+ if (argno < 6)
+ *tsp++ = reg[REG_O0 + argno] = va_arg(ap, long);
+ else
+ *tsp++ = va_arg(ap, long);
+ }
+
+ va_end(ap);
+
+ reg[REG_SP] = (greg_t)sp - STACK_BIAS; /* sp (when done) */
+ reg[REG_O7] = (greg_t)resumecontext - 8; /* return pc */
+}
+
+void
+__makecontext_v2(ucontext_t *ucp, void (*func)(), int argc, ...)
+{
+ greg_t *reg;
+ long *tsp;
+ char *sp;
+ int argno;
+ va_list ap;
+ size_t size;
+
+ reg = ucp->uc_mcontext.gregs;
+ reg[REG_PC] = (greg_t)func;
+ reg[REG_nPC] = reg[REG_PC] + 0x4;
+
+ /*
+ * Reserve enough space for a frame and the arguments beyond the
+ * sixth; round to stack alignment.
+ */
+ size = sizeof (struct frame);
+ size += (argc > 6 ? argc - 6 : 0) * sizeof (long);
+
+ sp = (char *)(((uintptr_t)ucp->uc_stack.ss_sp +
+ ucp->uc_stack.ss_size - size) & ~(STACK_ALIGN - 1));
+
+ /*
+ * Copy all args to the stack, and put the first 6 args into the
+ * ucontext_t. Zero the other fields of the frame.
+ */
+ /* LINTED pointer cast may result in improper alignment */
+ tsp = &((struct frame *)sp)->fr_argd[0];
+ bzero(sp, sizeof (struct frame));
+
+ va_start(ap, argc);
+
+ for (argno = 0; argno < argc; argno++) {
+ if (argno < 6)
+ *tsp++ = reg[REG_O0 + argno] = va_arg(ap, long);
+ else
+ *tsp++ = va_arg(ap, long);
+ }
+
+ va_end(ap);
+
+ reg[REG_SP] = (greg_t)sp - STACK_BIAS; /* sp (when done) */
+ reg[REG_O7] = (greg_t)resumecontext - 8; /* return pc */
+}
+
+static void
+resumecontext(void)
+{
+ /*
+ * We can't include ucontext.h (where these functions are defined)
+ * because it remaps the symbol makecontext.
+ */
+ extern int getcontext(ucontext_t *);
+ extern int setcontext(const ucontext_t *);
+ ucontext_t uc;
+
+ (void) getcontext(&uc);
+ (void) setcontext(uc.uc_link);
+}
diff --git a/usr/src/lib/libc/sparc/gen/memchr.s b/usr/src/lib/libc/sparc/gen/memchr.s
new file mode 100644
index 0000000000..0f38ad2c77
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/memchr.s
@@ -0,0 +1,177 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+.ident "%Z%%M% %I% %E% SMI"
+
+ .file "%M%"
+/*
+ * Return the ptr in sptr at which the character c1 appears;
+ * or NULL if not found in n chars; don't stop at \0.
+ * void *
+ * memchr(const void *sptr, int c1, size_t n)
+ * {
+ * if (n != 0) {
+ * unsigned char c = (unsigned char)c1;
+ * const unsigned char *sp = sptr;
+ *
+ * do {
+ * if (*sp++ == c)
+ * return ((void *)--sp);
+ * } while (--n != 0);
+ * }
+ * return (NULL);
+ * }
+ */
+
+#include <sys/asm_linkage.h>
+#include "synonyms.h"
+
+ ! The first part of this algorithm focuses on determining
+ ! whether or not the desired character is in the first few bytes
+ ! of memory, aligning the memory for word-wise copies, and
+ ! initializing registers to detect zero bytes
+
+ ENTRY(memchr)
+
+ .align 32
+
+ tst %o2 ! n == 0 ?
+ bz .notfound ! yup, c not found, return null ptr
+ andcc %o0, 3, %o4 ! s word aligned ?
+ add %o0, %o2, %o0 ! s + n
+ sub %g0, %o2, %o2 ! n = -n
+ bz .prepword ! yup, prepare for word-wise search
+ and %o1, 0xff, %o1 ! search only for this one byte
+
+ ldub [%o0 + %o2], %o3 ! s[0]
+ cmp %o3, %o1 ! s[0] == c ?
+ be .done ! yup, done
+ nop !
+ addcc %o2, 1, %o2 ! n++, s++
+ bz .notfound ! c not found in first n bytes
+ cmp %o4, 3 ! only one byte needed to align?
+ bz .prepword2 ! yup, prepare for word-wise search
+ sll %o1, 8, %g1 ! start spreading c across word
+ ldub [%o0 + %o2], %o3 ! s[1]
+ cmp %o3, %o1 ! s[1] == c ?
+ be .done ! yup, done
+ nop !
+ addcc %o2, 1, %o2 ! n++, s++
+ bz .notfound ! c not found in first n bytes
+ cmp %o4, 2 ! only two bytes needed to align?
+ bz .prepword3 ! yup, prepare for word-wise search
+ sethi %hi(0x01010101), %o4 ! start loading Alan Mycroft's magic1
+ ldub [%o0 + %o2], %o3 ! s[1]
+ cmp %o3, %o1 ! s[1] == c ?
+ be .done ! yup, done
+ nop
+ addcc %o2, 1, %o2 ! n++, s++
+ bz .notfound ! c not found in first n bytes
+ nop
+
+.prepword:
+ sll %o1, 8, %g1 ! spread c -------------+
+.prepword2: ! !
+ sethi %hi(0x01010101), %o4 ! Alan Mycroft's magic1 !
+.prepword3: ! !
+ or %o1, %g1, %o1 ! across all <---------+
+ or %o4, %lo(0x01010101),%o4! finish loading magic1 !
+ sll %o1, 16, %g1 ! four bytes <--------+
+ sll %o4, 7, %o5 ! Alan Mycroft's magic2 !
+ or %o1, %g1, %o1 ! of a word <--------+
+
+.searchchar:
+ lduw [%o0 + %o2], %o3 ! src word
+.searchchar2:
+ addcc %o2, 4, %o2 ! s+=4, n+=4
+ bcs .lastword ! if counter wraps, last word
+ xor %o3, %o1, %g1 ! tword = word ^ c
+ andn %o5, %g1, %o3 ! ~tword & 0x80808080
+ sub %g1, %o4, %g1 ! (tword - 0x01010101)
+ andcc %o3, %g1, %g0 ! ((tword - 0x01010101) & ~tword & 0x80808080)
+ bz,a .searchchar2 ! c not found if magic expression == 0
+ lduw [%o0 + %o2], %o3 ! src word
+
+ ! here we know "word" contains the searched character, and no byte in
+ ! "word" exceeds n. If we had exceeded n, we would have gone to label
+ ! .lastword. "tword" has null bytes where "word" had c. After
+ ! restoring "tword" from "(tword - 0x01010101)" in %g1, examine "tword"
+
+.foundchar:
+ add %g1, %o4, %g1 ! restore tword
+ set 0xff000000, %o4 ! mask for 1st byte
+ andcc %g1, %o4, %g0 ! first byte zero (= found c) ?
+ bz,a .done ! yup, done
+ sub %o2, 4, %o2 ! n -= 4 (undo counter bumping)
+ set 0x00ff0000, %o5 ! mask for 2nd byte
+ andcc %g1, %o5, %g0 ! second byte zero (= found c) ?
+ bz,a .done ! yup, done
+ sub %o2, 3, %o2 ! n -= 3 (undo counter bumping)
+ srl %o4, 16, %o4 ! 0x0000ff00 = mask for 3rd byte
+ andcc %g1, %o4, %g0 ! third byte zero (= found c) ?
+ bz,a .done ! nope, must be fourth byte
+ sub %o2, 2, %o2 ! n -= 2 (undo counter bumping)
+ sub %o2, 1, %o2 ! n -= 1, if fourth byte
+ retl ! done with leaf function
+ add %o0, %o2, %o0 ! return pointer to c in s
+.done:
+ retl ! done with leaf function
+ add %o0, %o2, %o0 ! return pointer to c in s
+ nop
+ nop
+
+ ! Here we know that "word" is the last word in the search, and that
+ ! some bytes possibly exceed n. However, "word" might also contain c.
+ ! "tword" (in %g1) has null bytes where "word" had c. Examine "tword"
+ ! while keeping track of number of remaining bytes
+
+.lastword:
+ set 0xff000000, %o4 ! mask for 1st byte
+ sub %o2, 4, %o2 ! n -= 4 (undo counter bumping)
+ andcc %g1, %o4, %g0 ! first byte zero (= found c) ?
+ bz .done ! yup, done
+ set 0x00ff0000, %o5 ! mask for 2nd byte
+ addcc %o2, 1, %o2 ! n += 1
+ bz .notfound ! c not found in first n bytes
+ andcc %g1, %o5, %g0 ! second byte zero (= found c) ?
+ bz .done ! yup, done
+ srl %o4, 16, %o4 ! 0x0000ff00 = mask for 3rd byte
+ addcc %o2, 1, %o2 ! n += 1
+ bz .notfound ! c not found in first n bytes
+ andcc %g1, %o4, %g0 ! third byte zero (= found c) ?
+ bz .done ! yup, done
+ nop !
+ addcc %o2, 1, %o2 ! n += 1
+ bz .notfound ! c not found in first n bytes
+ andcc %g1, 0xff, %g0 ! fourth byte zero (= found c) ?
+ bz .done ! yup, done
+ nop
+
+.notfound:
+ retl ! done with leaf function
+ mov %g0, %o0 ! return null pointer
+
+ SET_SIZE(memchr)
diff --git a/usr/src/lib/libc/sparc/gen/memcmp.s b/usr/src/lib/libc/sparc/gen/memcmp.s
new file mode 100644
index 0000000000..1ba5cc454b
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/memcmp.s
@@ -0,0 +1,237 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1989-1995,1998 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+.ident "%Z%%M% %I% %E% SMI" /* SunOS 4.1 1.2 */
+
+ .file "%M%"
+
+/*
+ * memcmp(s1, s2, len)
+ *
+ * Compare n bytes: s1>s2: >0 s1==s2: 0 s1<s2: <0
+ *
+ * Fast assembler language version of the following C-program for memcmp
+ * which represents the `standard' for the C-library.
+ *
+ * int
+ * memcmp(const void *s1, const void *s2, size_t n)
+ * {
+ * if (s1 != s2 && n != 0) {
+ * const char *ps1 = s1;
+ * const char *ps2 = s2;
+ * do {
+ * if (*ps1++ != *ps2++)
+ * return (ps1[-1] - ps2[-1]);
+ * } while (--n != 0);
+ * }
+ * return (NULL);
+ * }
+ */
+
+#include <sys/asm_linkage.h>
+
+ ANSI_PRAGMA_WEAK(memcmp,function)
+
+#include "synonyms.h"
+
+ ENTRY(memcmp)
+ st %g2, [%sp + 68] ! g2 must be restored before retl
+ cmp %o0, %o1 ! s1 == s2?
+ be .cmpeq
+ cmp %o2, 17
+ bleu,a .cmpbyt ! for small counts go do bytes
+ sub %o1, %o0, %o1
+
+ andcc %o0, 3, %o3 ! is s1 aligned?
+ bz,a .iss2 ! if so go check s2
+ andcc %o1, 3, %o4 ! is s2 aligned?
+ cmp %o3, 2
+ be .algn2
+ cmp %o3, 3
+
+.algn1: ldub [%o0], %o4 ! cmp one byte
+ inc %o0
+ ldub [%o1], %o5
+ inc %o1
+ dec %o2
+ be .algn3
+ cmp %o4, %o5
+ be .algn2
+ nop
+ b,a .noteq
+
+.algn2: lduh [%o0], %o4
+ inc 2, %o0
+ ldub [%o1], %o5
+ inc 1, %o1
+ srl %o4, 8, %o3
+ cmp %o3, %o5
+ be,a 1f
+ ldub [%o1], %o5 ! delay slot, get next byte from s2
+ b .noteq
+ mov %o3, %o4 ! delay slot, move *s1 to %o4
+1: inc %o1
+ dec 2, %o2
+ and %o4, 0xff, %o4
+ cmp %o4, %o5
+.algn3: be,a .iss2
+ andcc %o1, 3, %o4 ! delay slot, is s2 aligned?
+ b,a .noteq
+
+.cmpbyt:b .bytcmp
+ deccc %o2
+1: ldub [%o0 + %o1], %o5 ! byte compare loop
+ inc %o0
+ cmp %o4, %o5
+ be,a .bytcmp
+ deccc %o2 ! delay slot, compare count (len)
+ b,a .noteq
+.bytcmp:bgeu,a 1b
+ ldub [%o0], %o4
+.cmpeq: ld [%sp + 68], %g2
+ retl ! strings compare equal
+ clr %o0
+
+.noteq_word: ! words aren't equal. find unequal byte
+ srl %o4, 24, %o1 ! first byte
+ srl %o5, 24, %o2
+ cmp %o1, %o2
+ bne 1f
+ sll %o4, 8, %o4
+ sll %o5, 8, %o5
+ srl %o4, 24, %o1
+ srl %o5, 24, %o2
+ cmp %o1, %o2
+ bne 1f
+ sll %o4, 8, %o4
+ sll %o5, 8, %o5
+ srl %o4, 24, %o1
+ srl %o5, 24, %o2
+ cmp %o1, %o2
+ bne 1f
+ sll %o4, 8, %o4
+ sll %o5, 8, %o5
+ srl %o4, 24, %o1
+ srl %o5, 24, %o2
+1:
+ ld [%sp + 68], %g2
+ retl
+ sub %o1, %o2, %o0 ! delay slot
+
+.noteq:
+ ld [%sp + 68], %g2
+ retl ! strings aren't equal
+ sub %o4, %o5, %o0 ! delay slot, return(*s1 - *s2)
+
+.iss2: andn %o2, 3, %o3 ! count of aligned bytes
+ and %o2, 3, %o2 ! remaining bytes
+ bz .w4cmp ! if s2 word aligned, compare words
+ cmp %o4, 2
+ be .w2cmp ! s2 half aligned
+ cmp %o4, 1
+
+.w3cmp:
+ dec 4, %o3 ! avoid reading beyond the last byte
+ inc 4, %o2
+ ldub [%o1], %g1 ! read a byte to align for word reads
+ inc 1, %o1
+ be .w1cmp ! aligned to 1 or 3 bytes
+ sll %g1, 24, %o5
+
+ sub %o1, %o0, %o1
+2: ld [%o0 + %o1], %g1
+ ld [%o0], %o4
+ inc 4, %o0
+ srl %g1, 8, %g2 ! merge with the other half
+ or %g2, %o5, %o5
+ cmp %o4, %o5
+ bne .noteq_word
+ deccc 4, %o3
+ bnz 2b
+ sll %g1, 24, %o5
+ sub %o1, 1, %o1 ! used 3 bytes of the last word read
+ b .bytcmp
+ deccc %o2
+
+.w1cmp:
+ dec 4, %o3 ! avoid reading beyond the last byte
+ inc 4, %o2
+ lduh [%o1], %g1 ! read 3 bytes to word align
+ inc 2, %o1
+ sll %g1, 8, %g2
+ or %o5, %g2, %o5
+
+ sub %o1, %o0, %o1
+3: ld [%o0 + %o1], %g1
+ ld [%o0], %o4
+ inc 4, %o0
+ srl %g1, 24, %g2 ! merge with the other half
+ or %g2, %o5, %o5
+ cmp %o4, %o5
+ bne .noteq_word
+ deccc 4, %o3
+ bnz 3b
+ sll %g1, 8, %o5
+ sub %o1, 3, %o1 ! used 1 byte of the last word read
+ b .bytcmp
+ deccc %o2
+
+.w2cmp:
+ dec 4, %o3 ! avoid reading beyond the last byte
+ inc 4, %o2
+ lduh [%o1], %g1 ! read a halfword to align s2
+ inc 2, %o1
+ sll %g1, 16, %o5
+
+ sub %o1, %o0, %o1
+4: ld [%o0 + %o1], %g1 ! read a word from s2
+ ld [%o0], %o4 ! read a word from s1
+ inc 4, %o0
+ srl %g1, 16, %g2 ! merge with the other half
+ or %g2, %o5, %o5
+ cmp %o4, %o5
+ bne .noteq_word
+ deccc 4, %o3
+ bnz 4b
+ sll %g1, 16, %o5
+ sub %o1, 2, %o1 ! only used half of the last read word
+ b .bytcmp
+ deccc %o2
+
+.w4cmp:
+ sub %o1, %o0, %o1
+ ld [%o0 + %o1], %o5
+5: ld [%o0], %o4
+ inc 4, %o0
+ cmp %o4, %o5
+ bne .noteq_word
+ deccc 4, %o3
+ bnz,a 5b
+ ld [%o0 + %o1], %o5
+ b .bytcmp ! compare remaining bytes, if any
+ deccc %o2
+
+ SET_SIZE(memcmp)
diff --git a/usr/src/lib/libc/sparc/gen/memcpy.s b/usr/src/lib/libc/sparc/gen/memcpy.s
new file mode 100644
index 0000000000..bfa751fd6e
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/memcpy.s
@@ -0,0 +1,189 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 1987-2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+ .ident "%Z%%M% %I% %E% SMI"
+
+ .file "%M%"
+
+/*
+ * memcpy(s1, s2, len)
+ *
+ * Copy s2 to s1, always copy n bytes.
+ * Note: this does not work for overlapped copies, bcopy() does
+ *
+ * Fast assembler language version of the following C-program for memcpy
+ * which represents the `standard' for the C-library.
+ *
+ * void *
+ * memcpy(void *s, const void *s0, size_t n)
+ * {
+ * if (n != 0) {
+ * char *s1 = s;
+ * const char *s2 = s0;
+ * do {
+ * *s1++ = *s2++;
+ * } while (--n != 0);
+ * }
+ * return (s);
+ * }
+ */
+
+#include <sys/asm_linkage.h>
+
+ ANSI_PRAGMA_WEAK(memcpy,function)
+
+#include "synonyms.h"
+
+ .weak _private_memcpy
+ .type _private_memcpy, #function
+ _private_memcpy = memcpy
+
+ ENTRY(memcpy)
+ st %o0, [%sp + 68] ! save des address for return val
+ cmp %o2, 17 ! for small counts copy bytes
+ bleu .dbytecp
+ andcc %o1, 3, %o5 ! is src word aligned
+ bz .aldst
+ cmp %o5, 2 ! is src half-word aligned
+ be .s2algn
+ cmp %o5, 3 ! src is byte aligned
+.s1algn:ldub [%o1], %o3 ! move 1 or 3 bytes to align it
+ inc 1, %o1
+ stb %o3, [%o0] ! move a byte to align src
+ inc 1, %o0
+ bne .s2algn
+ dec %o2
+ b .ald ! now go align dest
+ andcc %o0, 3, %o5
+
+.s2algn:lduh [%o1], %o3 ! know src is 2 byte alinged
+ inc 2, %o1
+ srl %o3, 8, %o4
+ stb %o4, [%o0] ! have to do bytes,
+ stb %o3, [%o0 + 1] ! don't know dst alingment
+ inc 2, %o0
+ dec 2, %o2
+
+.aldst: andcc %o0, 3, %o5 ! align the destination address
+.ald: bz .w4cp
+ cmp %o5, 2
+ bz .w2cp
+ cmp %o5, 3
+.w3cp: ld [%o1], %o4
+ inc 4, %o1
+ srl %o4, 24, %o5
+ stb %o5, [%o0]
+ bne .w1cp
+ inc %o0
+ dec 1, %o2
+ andn %o2, 3, %o3 ! o3 is aligned word count
+ dec 4, %o3 ! avoid reading beyond tail of src
+ sub %o1, %o0, %o1 ! o1 gets the difference
+
+1: sll %o4, 8, %g1 ! save residual bytes
+ ld [%o1+%o0], %o4
+ deccc 4, %o3
+ srl %o4, 24, %o5 ! merge with residual
+ or %o5, %g1, %g1
+ st %g1, [%o0]
+ bnz 1b
+ inc 4, %o0
+ sub %o1, 3, %o1 ! used one byte of last word read
+ and %o2, 3, %o2
+ b 7f
+ inc 4, %o2
+
+.w1cp: srl %o4, 8, %o5
+ sth %o5, [%o0]
+ inc 2, %o0
+ dec 3, %o2
+ andn %o2, 3, %o3 ! o3 is aligned word count
+ dec 4, %o3 ! avoid reading beyond tail of src
+ sub %o1, %o0, %o1 ! o1 gets the difference
+
+2: sll %o4, 24, %g1 ! save residual bytes
+ ld [%o1+%o0], %o4
+ deccc 4, %o3
+ srl %o4, 8, %o5 ! merge with residual
+ or %o5, %g1, %g1
+ st %g1, [%o0]
+ bnz 2b
+ inc 4, %o0
+ sub %o1, 1, %o1 ! used three bytes of last word read
+ and %o2, 3, %o2
+ b 7f
+ inc 4, %o2
+
+.w2cp: ld [%o1], %o4
+ inc 4, %o1
+ srl %o4, 16, %o5
+ sth %o5, [%o0]
+ inc 2, %o0
+ dec 2, %o2
+ andn %o2, 3, %o3 ! o3 is aligned word count
+ dec 4, %o3 ! avoid reading beyond tail of src
+ sub %o1, %o0, %o1 ! o1 gets the difference
+
+3: sll %o4, 16, %g1 ! save residual bytes
+ ld [%o1+%o0], %o4
+ deccc 4, %o3
+ srl %o4, 16, %o5 ! merge with residual
+ or %o5, %g1, %g1
+ st %g1, [%o0]
+ bnz 3b
+ inc 4, %o0
+ sub %o1, 2, %o1 ! used two bytes of last word read
+ and %o2, 3, %o2
+ b 7f
+ inc 4, %o2
+
+.w4cp: andn %o2, 3, %o3 ! o3 is aligned word count
+ sub %o1, %o0, %o1 ! o1 gets the difference
+
+1: ld [%o1+%o0], %o4 ! read from address
+ deccc 4, %o3 ! decrement count
+ st %o4, [%o0] ! write at destination address
+ bgu 1b
+ inc 4, %o0 ! increment to address
+ b 7f
+ and %o2, 3, %o2 ! number of leftover bytes, if any
+
+ !
+ ! differenced byte copy, works with any alignment
+ !
+.dbytecp:
+ b 7f
+ sub %o1, %o0, %o1 ! o1 gets the difference
+
+4: stb %o4, [%o0] ! write to address
+ inc %o0 ! inc to address
+7: deccc %o2 ! decrement count
+ bgeu,a 4b ! loop till done
+ ldub [%o1+%o0], %o4 ! read from address
+ retl
+ ld [%sp + 68], %o0 ! return s1, destination address
+
+ SET_SIZE(memcpy)
diff --git a/usr/src/lib/libc/sparc/gen/memmove.s b/usr/src/lib/libc/sparc/gen/memmove.s
new file mode 100644
index 0000000000..e57650f6ab
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/memmove.s
@@ -0,0 +1,193 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1987-1995, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+.ident "%Z%%M% %I% %E% SMI"
+
+ .file "%M%"
+
+#include <sys/asm_linkage.h>
+
+ ANSI_PRAGMA_WEAK(memmove,function)
+
+#include "synonyms.h"
+
+/*
+ * memmove(s1, s2, len)
+ * Copy s2 to s1, always copy n bytes.
+ * For overlapped copies it does the right thing.
+ */
+ ENTRY(memmove)
+ save %sp, -SA(MINFRAME), %sp ! not a leaf routine any more
+ mov %i0, %l6 ! Save pointer to destination
+ cmp %i1, %i0 ! if from address is >= to use forward copy
+ bgeu,a 2f ! else use backward if ...
+ cmp %i2, 17 ! delay slot, for small counts copy bytes
+
+ sub %i0, %i1, %i4 ! get difference of two addresses
+ cmp %i2, %i4 ! compare size and difference of addresses
+ bgu ovbc ! if size is bigger, have do overlapped copy
+ cmp %i2, 17 ! delay slot, for small counts copy bytes
+ !
+ ! normal, copy forwards
+ !
+2: ble dbytecp
+ andcc %i1, 3, %i5 ! is src word aligned
+ bz aldst
+ cmp %i5, 2 ! is src half-word aligned
+ be s2algn
+ cmp %i5, 3 ! src is byte aligned
+s1algn: ldub [%i1], %i3 ! move 1 or 3 bytes to align it
+ inc 1, %i1
+ stb %i3, [%i0] ! move a byte to align src
+ inc 1, %i0
+ bne s2algn
+ dec %i2
+ b ald ! now go align dest
+ andcc %i0, 3, %i5
+
+s2algn: lduh [%i1], %i3 ! know src is 2 byte alinged
+ inc 2, %i1
+ srl %i3, 8, %i4
+ stb %i4, [%i0] ! have to do bytes,
+ stb %i3, [%i0 + 1] ! don't know dst alingment
+ inc 2, %i0
+ dec 2, %i2
+
+aldst: andcc %i0, 3, %i5 ! align the destination address
+ald: bz w4cp
+ cmp %i5, 2
+ bz w2cp
+ cmp %i5, 3
+w3cp: ld [%i1], %i4
+ inc 4, %i1
+ srl %i4, 24, %i5
+ stb %i5, [%i0]
+ bne w1cp
+ inc %i0
+ dec 1, %i2
+ andn %i2, 3, %i3 ! i3 is aligned word count
+ dec 4, %i3 ! avoid reading beyond tail of src
+ sub %i1, %i0, %i1 ! i1 gets the difference
+
+1: sll %i4, 8, %g1 ! save residual bytes
+ ld [%i1+%i0], %i4
+ deccc 4, %i3
+ srl %i4, 24, %i5 ! merge with residual
+ or %i5, %g1, %g1
+ st %g1, [%i0]
+ bnz 1b
+ inc 4, %i0
+ sub %i1, 3, %i1 ! used one byte of last word read
+ and %i2, 3, %i2
+ b 7f
+ inc 4, %i2
+
+w1cp: srl %i4, 8, %i5
+ sth %i5, [%i0]
+ inc 2, %i0
+ dec 3, %i2
+ andn %i2, 3, %i3
+ dec 4, %i3 ! avoid reading beyond tail of src
+ sub %i1, %i0, %i1 ! i1 gets the difference
+
+2: sll %i4, 24, %g1 ! save residual bytes
+ ld [%i1+%i0], %i4
+ deccc 4, %i3
+ srl %i4, 8, %i5 ! merge with residual
+ or %i5, %g1, %g1
+ st %g1, [%i0]
+ bnz 2b
+ inc 4, %i0
+ sub %i1, 1, %i1 ! used three bytes of last word read
+ and %i2, 3, %i2
+ b 7f
+ inc 4, %i2
+
+w2cp: ld [%i1], %i4
+ inc 4, %i1
+ srl %i4, 16, %i5
+ sth %i5, [%i0]
+ inc 2, %i0
+ dec 2, %i2
+ andn %i2, 3, %i3 ! i3 is aligned word count
+ dec 4, %i3 ! avoid reading beyond tail of src
+ sub %i1, %i0, %i1 ! i1 gets the difference
+
+3: sll %i4, 16, %g1 ! save residual bytes
+ ld [%i1+%i0], %i4
+ deccc 4, %i3
+ srl %i4, 16, %i5 ! merge with residual
+ or %i5, %g1, %g1
+ st %g1, [%i0]
+ bnz 3b
+ inc 4, %i0
+ sub %i1, 2, %i1 ! used two bytes of last word read
+ and %i2, 3, %i2
+ b 7f
+ inc 4, %i2
+
+w4cp: andn %i2, 3, %i3 ! i3 is aligned word count
+ sub %i1, %i0, %i1 ! i1 gets the difference
+
+1: ld [%i1+%i0], %i4 ! read from address
+ deccc 4, %i3 ! decrement count
+ st %i4, [%i0] ! write at destination address
+ bg 1b
+ inc 4, %i0 ! increment to address
+ b 7f
+ and %i2, 3, %i2 ! number of leftover bytes, if any
+
+ !
+ ! differenced byte copy, works with any alignment
+ !
+dbytecp:
+ b 7f
+ sub %i1, %i0, %i1 ! i1 gets the difference
+
+4: stb %i4, [%i0] ! write to address
+ inc %i0 ! inc to address
+7: deccc %i2 ! decrement count
+ bge,a 4b ! loop till done
+ ldub [%i1+%i0], %i4 ! read from address
+ ret
+ restore %l6, %g0, %o0 ! return pointer to destination
+
+ !
+ ! an overlapped copy that must be done "backwards"
+ !
+ovbc: add %i1, %i2, %i1 ! get to end of source space
+ add %i0, %i2, %i0 ! get to end of destination space
+ sub %i1, %i0, %i1 ! i1 gets the difference
+
+5: dec %i0 ! decrement to address
+ ldub [%i1+%i0], %i3 ! read a byte
+ deccc %i2 ! decrement count
+ bg 5b ! loop until done
+ stb %i3, [%i0] ! write byte
+ ret
+ restore %l6, %g0, %o0 ! return pointer to destination
+
+ SET_SIZE(memmove)
diff --git a/usr/src/lib/libc/sparc/gen/memset.s b/usr/src/lib/libc/sparc/gen/memset.s
new file mode 100644
index 0000000000..a1f9c223c1
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/memset.s
@@ -0,0 +1,96 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 1987-2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+ .ident "%Z%%M% %I% %E% SMI"
+
+ .file "%M%"
+
+/*
+ * char *memset(sp, c, n)
+ *
+ * Set an array of n chars starting at sp to the character c.
+ * Return sp.
+ *
+ * Fast assembler language version of the following C-program for memset
+ * which represents the `standard' for the C-library.
+ *
+ * void *
+ * memset(void *sp1, int c, size_t n)
+ * {
+ * if (n != 0) {
+ * char *sp = sp1;
+ * do {
+ * *sp++ = (char)c;
+ * } while (--n != 0);
+ * }
+ * return (sp1);
+ * }
+ */
+
+#include <sys/asm_linkage.h>
+
+ ANSI_PRAGMA_WEAK(memset,function)
+
+#include "synonyms.h"
+
+ .weak _private_memset
+ .type _private_memset, #function
+ _private_memset = memset
+
+ ENTRY(memset)
+ mov %o0, %o5 ! copy sp before using it
+ cmp %o2, 7 ! if small counts, just write bytes
+ blu .wrchar
+ .empty ! following lable is ok in delay slot
+
+.walign:btst 3, %o5 ! if bigger, align to 4 bytes
+ bz .wrword
+ andn %o2, 3, %o3 ! create word sized count in %o3
+ dec %o2 ! decrement count
+ stb %o1, [%o5] ! clear a byte
+ b .walign
+ inc %o5 ! next byte
+
+.wrword:and %o1, 0xff, %o1 ! generate a word filled with c
+ sll %o1, 8, %o4
+ or %o1, %o4, %o1
+ sll %o1, 16, %o4
+ or %o1, %o4, %o1
+1: st %o1, [%o5] ! word writing loop
+ subcc %o3, 4, %o3
+ bnz 1b
+ inc 4, %o5
+
+ and %o2, 3, %o2 ! leftover count, if any
+.wrchar:deccc %o2 ! byte clearing loop
+ inc %o5
+ bgeu,a .wrchar
+ stb %o1, [%o5 + -1] ! we've already incremented the address
+
+ retl
+ nop
+
+ SET_SIZE(memset)
diff --git a/usr/src/lib/libc/sparc/gen/setjmp.s b/usr/src/lib/libc/sparc/gen/setjmp.s
new file mode 100644
index 0000000000..264e9be602
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/setjmp.s
@@ -0,0 +1,121 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+
+/*
+ * Copyright 1987-2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+.ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.4 */
+
+ .file "setjmp.s"
+
+#include <sys/asm_linkage.h>
+
+ ANSI_PRAGMA_WEAK(setjmp,function)
+ ANSI_PRAGMA_WEAK(longjmp,function)
+
+#include "synonyms.h"
+
+#include <sys/trap.h>
+
+JB_FLAGS = (0*4) ! offsets in jmpbuf (see siglonglmp.c)
+JB_SP = (1*4) ! words 5 through 11 are unused!
+JB_PC = (2*4)
+JB_FP = (3*4)
+JB_I7 = (4*4)
+
+/*
+ * setjmp(buf_ptr)
+ * buf_ptr points to a twelve word array (jmp_buf)
+ */
+ ENTRY(setjmp)
+ clr [%o0 + JB_FLAGS] ! clear flags (used by sigsetjmp)
+ st %sp, [%o0 + JB_SP] ! save caller's sp
+ add %o7, 8, %o1 ! comupte return pc
+ st %o1, [%o0 + JB_PC] ! save pc
+ st %fp, [%o0 + JB_FP] ! save fp
+ st %i7, [%o0 + JB_I7] ! save %i7
+ retl
+ clr %o0 ! return (0)
+
+ SET_SIZE(setjmp)
+
+/*
+ * longjmp(buf_ptr, val)
+ * buf_ptr points to a jmpbuf which has been initialized by setjmp.
+ * val is the value we wish to return to setjmp's caller
+ *
+ * We flush the register file to the stack by doing a kernel call.
+ * This is necessary to ensure that the registers we want to
+ * pick up are stored on the stack, and that subsequent restores
+ * will function correctly.
+ *
+ * sp, fp, and %i7, the caller's return address, are all restored
+ * to the values they had at the time of the call to setjmp(). All
+ * other locals, ins and outs are set to potentially random values
+ * (as per the man page). This is sufficient to permit the correct
+ * operation of normal code.
+ *
+ * Actually, the above description is not quite correct. If the routine
+ * that called setjmp() has not altered the sp value of their frame we
+ * will restore the remaining locals and ins to the values these
+ * registers had in the this frame at the time of the call to longjmp()
+ * (not setjmp()!). This is intended to help compilers, typically not
+ * C compilers, that have some registers assigned to fixed purposes,
+ * and that only alter the values of these registers on function entry
+ * and exit.
+ *
+ * Since a C routine could call setjmp() followed by alloca() and thus
+ * alter the sp this feature will typically not be helpful for a C
+ * compiler.
+ *
+ * Note also that because the caller of a routine compiled "flat" (without
+ * register windows) assumes that their ins and locals are preserved,
+ * routines that call setjmp() must not be flat.
+ */
+ ENTRY(longjmp)
+ ta ST_FLUSH_WINDOWS ! flush all reg windows to the stack.
+ ld [%o0 + JB_SP], %o2 ! sp in %o2 until safe to puke there
+ ldd [%o2 + (0*8)], %l0 ! restore locals and ins if we can
+ ldd [%o2 + (1*8)], %l2
+ ldd [%o2 + (2*8)], %l4
+ ldd [%o2 + (3*8)], %l6
+ ldd [%o2 + (4*8)], %i0
+ ldd [%o2 + (5*8)], %i2
+ ldd [%o2 + (6*8)], %i4
+ ld [%o0 + JB_FP], %fp ! restore fp
+ mov %o2, %sp ! restore sp
+ ld [%o0 + JB_I7], %i7 ! restore %i7
+ ld [%o0 + JB_PC], %o3 ! get new return pc
+ tst %o1 ! is return value 0?
+ bnz 1f ! no - leave it alone
+ sub %o3, 8, %o7 ! normalize return (for adb) (dly slot)
+ mov 1, %o1 ! yes - set it to one
+1:
+ retl
+ mov %o1, %o0 ! return (val)
+
+ SET_SIZE(longjmp)
diff --git a/usr/src/lib/libc/sparc/gen/siginfolst.c b/usr/src/lib/libc/sparc/gen/siginfolst.c
new file mode 100644
index 0000000000..8939850c60
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/siginfolst.c
@@ -0,0 +1,187 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+
+#include "synonyms.h"
+#include <signal.h>
+#include <siginfo.h>
+
+#undef _sys_siginfolist
+#define OLDNSIG 34
+
+const char *_sys_traplist[NSIGTRAP] = {
+ "breakpoint trap",
+ "trace trap",
+ "read access trap",
+ "write access trap",
+ "execute access trap",
+ "dtrace trap"
+};
+
+const char *_sys_illlist[NSIGILL] = {
+ "illegal opcode",
+ "illegal operand",
+ "illegal addressing mode",
+ "illegal trap",
+ "privileged opcode",
+ "privileged register",
+ "co-processor",
+ "bad stack"
+};
+
+const char *_sys_fpelist[NSIGFPE] = {
+ "integer divide by zero",
+ "integer overflow",
+ "floating point divide by zero",
+ "floating point overflow",
+ "floating point underflow",
+ "floating point inexact result",
+ "invalid floating point operation",
+ "subscript out of range"
+};
+
+const char *_sys_segvlist[NSIGSEGV] = {
+ "address not mapped to object",
+ "invalid permissions"
+};
+
+const char *_sys_buslist[NSIGBUS] = {
+ "invalid address alignment",
+ "non-existent physical address",
+ "object specific"
+};
+
+const char *_sys_cldlist[NSIGCLD] = {
+ "child has exited",
+ "child was killed",
+ "child has coredumped",
+ "traced child has trapped",
+ "child has stopped",
+ "stopped child has continued"
+};
+
+const char *_sys_polllist[NSIGPOLL] = {
+ "input available",
+ "output possible",
+ "message available",
+ "I/O error",
+ "high priority input available",
+ "device disconnected"
+};
+
+struct siginfolist _sys_siginfolist[OLDNSIG-1] = {
+ 0, 0, /* SIGHUP */
+ 0, 0, /* SIGINT */
+ 0, 0, /* SIGQUIT */
+ NSIGILL, (char **)_sys_illlist, /* SIGILL */
+ NSIGTRAP, (char **)_sys_traplist, /* SIGTRAP */
+ 0, 0, /* SIGABRT */
+ 0, 0, /* SIGEMT */
+ NSIGFPE, (char **)_sys_fpelist, /* SIGFPE */
+ 0, 0, /* SIGKILL */
+ NSIGBUS, (char **)_sys_buslist, /* SIGBUS */
+ NSIGSEGV, (char **)_sys_segvlist, /* SIGSEGV */
+ 0, 0, /* SIGSYS */
+ 0, 0, /* SIGPIPE */
+ 0, 0, /* SIGALRM */
+ 0, 0, /* SIGTERM */
+ 0, 0, /* SIGUSR1 */
+ 0, 0, /* SIGUSR2 */
+ NSIGCLD, (char **)_sys_cldlist, /* SIGCLD */
+ 0, 0, /* SIGPWR */
+ 0, 0, /* SIGWINCH */
+ 0, 0, /* SIGURG */
+ NSIGPOLL, (char **)_sys_polllist, /* SIGPOLL */
+ 0, 0, /* SIGSTOP */
+ 0, 0, /* SIGTSTP */
+ 0, 0, /* SIGCONT */
+ 0, 0, /* SIGTTIN */
+ 0, 0, /* SIGTTOU */
+ 0, 0, /* SIGVTALRM */
+ 0, 0, /* SIGPROF */
+ 0, 0, /* SIGXCPU */
+ 0, 0, /* SIGXFSZ */
+ 0, 0, /* SIGWAITING */
+ 0, 0, /* SIGLWP */
+};
+
+static const struct siginfolist _sys_siginfolist_data[NSIG-1] = {
+ 0, 0, /* SIGHUP */
+ 0, 0, /* SIGINT */
+ 0, 0, /* SIGQUIT */
+ NSIGILL, (char **)_sys_illlist, /* SIGILL */
+ NSIGTRAP, (char **)_sys_traplist, /* SIGTRAP */
+ 0, 0, /* SIGABRT */
+ 0, 0, /* SIGEMT */
+ NSIGFPE, (char **)_sys_fpelist, /* SIGFPE */
+ 0, 0, /* SIGKILL */
+ NSIGBUS, (char **)_sys_buslist, /* SIGBUS */
+ NSIGSEGV, (char **)_sys_segvlist, /* SIGSEGV */
+ 0, 0, /* SIGSYS */
+ 0, 0, /* SIGPIPE */
+ 0, 0, /* SIGALRM */
+ 0, 0, /* SIGTERM */
+ 0, 0, /* SIGUSR1 */
+ 0, 0, /* SIGUSR2 */
+ NSIGCLD, (char **)_sys_cldlist, /* SIGCLD */
+ 0, 0, /* SIGPWR */
+ 0, 0, /* SIGWINCH */
+ 0, 0, /* SIGURG */
+ NSIGPOLL, (char **)_sys_polllist, /* SIGPOLL */
+ 0, 0, /* SIGSTOP */
+ 0, 0, /* SIGTSTP */
+ 0, 0, /* SIGCONT */
+ 0, 0, /* SIGTTIN */
+ 0, 0, /* SIGTTOU */
+ 0, 0, /* SIGVTALRM */
+ 0, 0, /* SIGPROF */
+ 0, 0, /* SIGXCPU */
+ 0, 0, /* SIGXFSZ */
+ 0, 0, /* SIGWAITING */
+ 0, 0, /* SIGLWP */
+ 0, 0, /* SIGFREEZE */
+ 0, 0, /* SIGTHAW */
+ 0, 0, /* SIGCANCEL */
+ 0, 0, /* SIGLOST */
+ 0, 0, /* SIGXRES */
+ 0, 0, /* SIGJVM1 */
+ 0, 0, /* SIGJVM2 */
+ 0, 0, /* SIGRTMIN */
+ 0, 0, /* SIGRTMIN+1 */
+ 0, 0, /* SIGRTMIN+2 */
+ 0, 0, /* SIGRTMIN+3 */
+ 0, 0, /* SIGRTMAX-3 */
+ 0, 0, /* SIGRTMAX-2 */
+ 0, 0, /* SIGRTMAX-1 */
+ 0, 0, /* SIGRTMAX */
+};
+
+const struct siginfolist *_sys_siginfolistp = _sys_siginfolist_data;
diff --git a/usr/src/lib/libc/sparc/gen/siglongjmp.c b/usr/src/lib/libc/sparc/gen/siglongjmp.c
new file mode 100644
index 0000000000..3b90f52164
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/siglongjmp.c
@@ -0,0 +1,100 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+
+#pragma weak siglongjmp = _siglongjmp
+
+#include "lint.h"
+#include <sys/types.h>
+#include <sys/stack.h>
+#include <sys/frame.h>
+#include <memory.h>
+#include <ucontext.h>
+#include <setjmp.h>
+#include "sigjmp_struct.h"
+#include "libc.h"
+
+void
+_siglongjmp(sigjmp_buf env, int val)
+{
+ extern void _fetch_globals(greg_t *);
+ ucontext_t uc;
+ greg_t *reg = uc.uc_mcontext.gregs;
+ volatile sigjmp_struct_t *bp = (sigjmp_struct_t *)env;
+ greg_t fp = bp->sjs_fp;
+ greg_t i7 = bp->sjs_i7;
+
+ /*
+ * Create a ucontext_t structure from scratch.
+ * We only need to fetch the globals.
+ * The outs are assumed to be trashed on return from sigsetjmp().
+ * The ins and locals are restored from the resumed register window.
+ * The floating point state is unmodified.
+ * Everything else is in the sigjmp_struct_t buffer.
+ */
+ (void) memset(&uc, 0, sizeof (uc));
+ uc.uc_flags = UC_STACK | UC_CPU;
+ _fetch_globals(&reg[REG_G1]);
+ uc.uc_stack = bp->sjs_stack;
+ uc.uc_link = bp->sjs_uclink;
+ reg[REG_PC] = bp->sjs_pc;
+ reg[REG_nPC] = reg[REG_PC] + 0x4;
+ reg[REG_SP] = bp->sjs_sp;
+
+ if (bp->sjs_flags & JB_SAVEMASK) {
+ uc.uc_flags |= UC_SIGMASK;
+ uc.uc_sigmask = bp->sjs_sigmask;
+ }
+
+ if (val)
+ reg[REG_O0] = (greg_t)val;
+ else
+ reg[REG_O0] = (greg_t)1;
+
+ /*
+ * Copy the fp and i7 values into the register window save area.
+ * These may have been clobbered between calls to sigsetjmp
+ * and siglongjmp. For example, the save area could have been
+ * relocated to lower addresses and the original save area
+ * given to an alloca() call. Notice that all reads from
+ * the sigjmp_struct_t buffer should take place before the
+ * following two writes. It is possible that user code may
+ * move/copy the sigjmpbuf around, and overlap the original
+ * register window save area.
+ */
+ if (bp->sjs_sp != 0 && (bp->sjs_flags & JB_FRAMEPTR)) {
+ struct frame *sp = (struct frame *)(bp->sjs_sp + STACK_BIAS);
+ sp->fr_savfp = (struct frame *)fp;
+ sp->fr_savpc = i7;
+ }
+
+ (void) setcontext(&uc);
+}
diff --git a/usr/src/lib/libc/sparc/gen/sparc_data.s b/usr/src/lib/libc/sparc/gen/sparc_data.s
new file mode 100644
index 0000000000..dbaece392c
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/sparc_data.s
@@ -0,0 +1,33 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+
+/* Copyright (c) 1989 by Sun Microsystems, Inc. */
+
+.ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.10 */
+
+ .file "sparc_data.s"
+
+ .global errno
+ .common errno,4,4
diff --git a/usr/src/lib/libc/sparc/gen/strcasecmp.s b/usr/src/lib/libc/sparc/gen/strcasecmp.s
new file mode 100644
index 0000000000..8efc518ab4
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/strcasecmp.s
@@ -0,0 +1,353 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+.ident "%Z%%M% %I% %E% SMI"
+
+ .file "%M%"
+/*
+ * The strcasecmp() function is a case insensitive versions of strcmp().
+ * It assumes the ASCII character set and ignores differences in case
+ * when comparing lower and upper case characters. In other words, it
+ * behaves as if both strings had been converted to lower case using
+ * tolower() in the "C" locale on each byte, and the results had then
+ * been compared using strcmp().
+ *
+ * The assembly code below is an optimized version of the following C
+ * reference:
+ *
+ * static const char charmap[] = {
+ * '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
+ * '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
+ * '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
+ * '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
+ * '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
+ * '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
+ * '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
+ * '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
+ * '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+ * '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+ * '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+ * '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
+ * '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+ * '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+ * '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+ * '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
+ * '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
+ * '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
+ * '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
+ * '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
+ * '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
+ * '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
+ * '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
+ * '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
+ * '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
+ * '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
+ * '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
+ * '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
+ * '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+ * '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+ * '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+ * '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
+ * };
+ *
+ * int
+ * strcasecmp(const char *s1, const char *s2)
+ * {
+ * const unsigned char *cm = (const unsigned char *)charmap;
+ * const unsigned char *us1 = (const unsigned char *)s1;
+ * const unsigned char *us2 = (const unsigned char *)s2;
+ *
+ * while (cm[*us1] == cm[*us2++])
+ * if (*us1++ == '\0')
+ * return (0);
+ * return (cm[*us1] - cm[*(us2 - 1)]);
+ * }
+ *
+ * The following algorithm, from a 1987 news posting by Alan Mycroft, is
+ * used for finding null bytes in a word:
+ *
+ * #define has_null(word) ((word - 0x01010101) & (~word & 0x80808080))
+ *
+ * The following algorithm is used for a wordwise tolower() operation:
+ *
+ * unsigned int
+ * parallel_tolower (unsigned int x)
+ * {
+ * unsigned int p;
+ * unsigned int q;
+ *
+ * unsigned int m1 = 0x80808080;
+ * unsigned int m2 = 0x3f3f3f3f;
+ * unsigned int m3 = 0x25252525;
+ *
+ * q = x & ~m1;// newb = byte & 0x7F
+ * p = q + m2; // newb > 0x5A --> MSB set
+ * q = q + m3; // newb < 0x41 --> MSB clear
+ * p = p & ~q; // newb > 0x40 && newb < 0x5B --> MSB set
+ * q = m1 & ~x;// byte < 0x80 --> 0x80
+ * q = p & q; // newb > 0x40 && newb < 0x5B && byte < 0x80 -> 0x80,else 0
+ * q = q >> 2; // newb > 0x40 && newb < 0x5B && byte < 0x80 -> 0x20,else 0
+ * return (x + q); // translate uppercase characters to lowercase
+ * }
+ *
+ * Both algorithms have been tested exhaustively for all possible 2^32 inputs.
+ */
+
+
+#include <sys/asm_linkage.h>
+#include "synonyms.h"
+
+ ! The first part of this algorithm walks through the beginning of
+ ! both strings a byte at a time until the source ptr is aligned to
+ ! a word boundary. During these steps, the bytes are translated to
+ ! lower-case if they are upper-case, and are checked against
+ ! the source string.
+
+ ENTRY(strcasecmp)
+
+ .align 32
+
+ save %sp, -SA(WINDOWSIZE), %sp
+ subcc %i0, %i1, %i2 ! s1 == s2 ?
+ bz .stringsequal ! yup, done, strings equal
+ andcc %i0, 3, %i3 ! s1 word-aligned ?
+ bz .s1aligned1 ! yup
+ sethi %hi(0x80808080), %i4 ! start loading Mycroft's magic1
+
+ ldub [%i1 + %i2], %i0 ! s1[0]
+ ldub [%i1], %g1 ! s2[0]
+ sub %i0, 'A', %l0 ! transform for faster uppercase check
+ sub %g1, 'A', %l1 ! transform for faster uppercase check
+ cmp %l0, ('Z' - 'A') ! s1[0] uppercase?
+ bleu,a .noxlate11 ! yes
+ add %i0, ('a' - 'A'), %i0 ! s1[0] = tolower(s1[0])
+.noxlate11:
+ cmp %l1, ('Z' - 'A') ! s2[0] uppercase?
+ bleu,a .noxlate12 ! yes
+ add %g1, ('a' - 'A'), %g1 ! s2[0] = tolower(s2[0])
+.noxlate12:
+ subcc %i0, %g1, %i0 ! tolower(s1[0]) != tolower(s2[0]) ?
+ bne .done ! yup, done
+ inc %i1 ! s1++, s2++
+ addcc %i0, %g1, %i0 ! s1[0] == 0 ?
+ bz .done ! yup, done, strings equal
+ cmp %i3, 3 ! s1 aligned now?
+ bz .s1aligned2 ! yup
+ sethi %hi(0x01010101), %i5 ! start loading Mycroft's magic2
+
+ ldub [%i1 + %i2], %i0 ! s1[1]
+ ldub [%i1], %g1 ! s2[1]
+ sub %i0, 'A', %l0 ! transform for faster uppercase check
+ sub %g1, 'A', %l1 ! transform for faster uppercase check
+ cmp %l0, ('Z' - 'A') ! s1[1] uppercase?
+ bleu,a .noxlate21 ! yes
+ add %i0, ('a' - 'A'), %i0 ! s1[1] = tolower(s1[1])
+.noxlate21:
+ cmp %l1, ('Z' - 'A') ! s2[1] uppercase?
+ bleu,a .noxlate22 ! yes
+ add %g1, ('a' - 'A'), %g1 ! s2[1] = tolower(s2[1])
+.noxlate22:
+ subcc %i0, %g1, %i0 ! tolower(s1[1]) != tolower(s2[1]) ?
+ bne .done ! yup, done
+ inc %i1 ! s1++, s2++
+ addcc %i0, %g1, %i0 ! s1[1] == 0 ?
+ bz .done ! yup, done, strings equal
+ cmp %i3, 2 ! s1 aligned now?
+ bz .s1aligned3 ! yup
+ or %i4, %lo(0x80808080),%i4! finish loading Mycroft's magic1
+
+ ldub [%i1 + %i2], %i0 ! s1[2]
+ ldub [%i1], %g1 ! s2[2]
+ sub %i0, 'A', %l0 ! transform for faster uppercase check
+ sub %g1, 'A', %l1 ! transform for faster uppercase check
+ cmp %l0, ('Z' - 'A') ! s1[2] uppercase?
+ bleu,a .noxlate31 ! yes
+ add %i0, ('a' - 'A'), %i0 ! s1[2] = tolower(s1[2])
+.noxlate31:
+ cmp %l1, ('Z' - 'A') ! s2[2] uppercase?
+ bleu,a .noxlate32 ! yes
+ add %g1, ('a' - 'A'), %g1 ! s2[2] = tolower(s2[2])
+.noxlate32:
+ subcc %i0, %g1, %i0 ! tolower(s1[2]) != tolower(s2[2]) ?
+ bne .done ! yup, done
+ inc %i1 ! s1++, s2++
+ addcc %i0, %g1, %i0 ! s1[2] == 0 ?
+ bz .done ! yup, done, strings equal
+ or %i5, %lo(0x01010101),%i5! finish loading Mycroft's magic2
+ ba .s1aligned4 ! s1 aligned now
+ andcc %i1, 3, %i3 ! s2 word-aligned ?
+
+ ! Here, we initialize our checks for a zero byte and decide
+ ! whether or not we can optimize further if we're fortunate
+ ! enough to have a word aligned desintation
+
+.s1aligned1:
+ sethi %hi(0x01010101), %i5 ! start loading Mycroft's magic2
+.s1aligned2:
+ or %i4, %lo(0x80808080),%i4! finish loading Mycroft's magic1
+.s1aligned3:
+ or %i5, %lo(0x01010101),%i5! finish loading Mycroft's magic2
+ andcc %i1, 3, %i3 ! s2 word aligned ?
+.s1aligned4:
+ sethi %hi(0x3f3f3f3f), %l2 ! load m2 for parallel tolower()
+ sethi %hi(0x25252525), %l3 ! load m3 for parallel tolower()
+ or %l2, %lo(0x3f3f3f3f),%l2! finish loading m2
+ bz .word4 ! yup, s2 word-aligned
+ or %l3, %lo(0x25252525),%l3! finish loading m3
+
+ add %i2, %i3, %i2 ! start adjusting offset s1-s2
+ sll %i3, 3, %l6 ! shift factor for left shifts
+ andn %i1, 3, %i1 ! round s1 pointer down to next word
+ sub %g0, %l6, %l7 ! shift factor for right shifts
+ orn %i3, %g0, %i3 ! generate all ones
+ lduw [%i1], %i0 ! new lower word from s2
+ srl %i3, %l6, %i3 ! mask for fixing up bytes
+ sll %i0, %l6, %g1 ! partial unaligned word from s2
+ orn %i0, %i3, %i0 ! force start bytes to non-zero
+ nop ! pad to align loop to 16-byte boundary
+ nop ! pad to align loop to 16-byte boundary
+
+ ! This is the comparision procedure used if the destination is not
+ ! word aligned, if it is, we use word4 & cmp4
+
+.cmp:
+ andn %i4, %i0, %l4 ! ~word & 0x80808080
+ sub %i0, %i5, %l5 ! word - 0x01010101
+ andcc %l5, %l4, %g0 ! (word - 0x01010101) & ~word & 0x80808080
+ bz,a .doload ! null byte in previous aligned s2 word
+ lduw [%i1 + 4], %i0 ! load next aligned word from s2
+.doload:
+ srl %i0, %l7, %i3 ! byte(s) from new aligned word from s2
+ or %g1, %i3, %g1 ! merge to get unaligned word from s2
+ lduw [%i1 + %i2], %i3 ! x1 = word from s1
+ andn %i3, %i4, %l0 ! q1 = x1 & ~m1
+ andn %g1, %i4, %l4 ! q2 = x2 & ~m1
+ add %l0, %l2, %l1 ! p1 = q1 + m2
+ add %l4, %l2, %l5 ! p2 = q2 + m2
+ add %l0, %l3, %l0 ! q1 = q1 + m3
+ add %l4, %l3, %l4 ! q2 = q2 + m3
+ andn %l1, %l0, %l1 ! p1 = p1 & ~q1
+ andn %l5, %l4, %l5 ! p2 = p2 & ~q2
+ andn %i4, %i3, %l0 ! q1 = m1 & ~x1
+ andn %i4, %g1, %l4 ! q2 = m1 & ~x2
+ and %l0, %l1, %l0 ! q1 = p1 & q1
+ and %l4, %l5, %l4 ! q2 = p2 & q2
+ srl %l0, 2, %l0 ! q1 = q1 >> 2
+ srl %l4, 2, %l4 ! q2 = q2 >> 2
+ add %l0, %i3, %i3 ! lowercase word from s1
+ add %l4, %g1, %g1 ! lowercase word from s2
+ cmp %i3, %g1 ! tolower(*s1) != tolower(*s2) ?
+ bne .wordsdiffer ! yup, now find byte that is different
+ add %i1, 4, %i1 ! s1+=4, s2+=4
+ andn %i4, %i3, %l4 ! ~word & 0x80808080
+ sub %i3, %i5, %l5 ! word - 0x01010101
+ andcc %l5, %l4, %g0 ! (word - 0x01010101) & ~word & 0x80808080
+ bz .cmp ! no null-byte in s1 yet
+ sll %i0, %l6, %g1 ! bytes from old aligned word from s2
+
+ ! words are equal but the end of s1 has been reached
+ ! this means the strings must be equal
+.stringsequal:
+ ret ! return
+ restore %g0, %g0, %o0 ! return 0, i.e. strings are equal
+ nop ! pad
+
+ ! we have a word aligned source and destination! This means
+ ! things get to go fast!
+
+.word4:
+ lduw [%i1 + %i2], %i3 ! x1 = word from s1
+
+.cmp4:
+ andn %i3, %i4, %l0 ! q1 = x1 & ~m1
+ lduw [%i1], %g1 ! x2 = word from s2
+ andn %g1, %i4, %l4 ! q2 = x2 & ~m1
+ add %l0, %l2, %l1 ! p1 = q1 + m2
+ add %l4, %l2, %l5 ! p2 = q2 + m2
+ add %l0, %l3, %l0 ! q1 = q1 + m3
+ add %l4, %l3, %l4 ! q2 = q2 + m3
+ andn %l1, %l0, %l1 ! p1 = p1 & ~q1
+ andn %l5, %l4, %l5 ! p2 = p2 & ~q2
+ andn %i4, %i3, %l0 ! q1 = m1 & ~x1
+ andn %i4, %g1, %l4 ! q2 = m1 & ~x2
+ and %l0, %l1, %l0 ! q1 = p1 & q1
+ and %l4, %l5, %l4 ! q2 = p2 & q2
+ srl %l0, 2, %l0 ! q1 = q1 >> 2
+ srl %l4, 2, %l4 ! q2 = q2 >> 2
+ add %l0, %i3, %i3 ! lowercase word from s1
+ add %l4, %g1, %g1 ! lowercase word from s2
+ cmp %i3, %g1 ! tolower(*s1) != tolower(*s2) ?
+ bne .wordsdiffer ! yup, now find mismatching character
+ add %i1, 4, %i1 ! s1+=4, s2+=4
+ andn %i4, %i3, %l4 ! ~word & 0x80808080
+ sub %i3, %i5, %l5 ! word - 0x01010101
+ andcc %l5, %l4, %g0 ! (word - 0x01010101) & ~word & 0x80808080
+ bz,a .cmp4 ! no null-byte in s1 yet
+ lduw [%i1 + %i2], %i3 ! load word from s1
+
+ ! words are equal but the end of s1 has been reached
+ ! this means the strings must be equal
+.stringsequal4:
+ ret ! return
+ restore %g0, %g0, %o0 ! return 0, i.e. strings are equal
+
+.wordsdiffer:
+ srl %g1, 24, %i2 ! first byte of mismatching word in s2
+ srl %i3, 24, %i1 ! first byte of mismatching word in s1
+ subcc %i1, %i2, %i0 ! *s1-*s2
+ bnz .done ! bytes differ, return difference
+ srl %g1, 16, %i2 ! second byte of mismatching word in s2
+ andcc %i1, 0xff, %i0 ! *s1 == 0 ?
+ bz .done ! yup, done, strings equal
+
+ ! we know byte 1 is equal, so can compare bytes 1,2 as a group
+
+ srl %i3, 16, %i1 ! second byte of mismatching word in s1
+ subcc %i1, %i2, %i0 ! *s1-*s2
+ bnz .done ! bytes differ, return difference
+ srl %g1, 8, %i2 ! third byte of mismatching word in s2
+ andcc %i1, 0xff, %i0 ! *s1 == 0 ?
+ bz .done ! yup, done, strings equal
+
+ ! we know bytes 1, 2 are equal, so can compare bytes 1,2,3 as a group
+
+ srl %i3, 8, %i1 ! third byte of mismatching word in s1
+ subcc %i1, %i2, %i0 ! *s1-*s2
+ bnz .done ! bytes differ, return difference
+ andcc %i1, 0xff, %g0 ! *s1 == 0 ?
+ bz .stringsequal ! yup, done, strings equal
+
+ ! we know bytes 1,2,3 are equal, so can compare bytes 1,2,3,4 as group
+
+ subcc %i3, %g1, %i0 ! *s1-*s2
+ bz,a .done ! bytes differ, return difference
+ andcc %i3, 0xff, %i0 ! *s1 == 0, strings equal
+
+.done:
+ ret ! return
+ restore %i0, %g0, %o0 ! return 0 or byte difference
+
+ SET_SIZE(strcasecmp)
diff --git a/usr/src/lib/libc/sparc/gen/strchr.s b/usr/src/lib/libc/sparc/gen/strchr.s
new file mode 100644
index 0000000000..6a7ee9008b
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/strchr.s
@@ -0,0 +1,219 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+.ident "%Z%%M% %I% %E% SMI"
+
+ .file "%M%"
+
+/*
+ * The strchr() function returns a pointer to the first occurrence of c
+ * (converted to a char) in string s, or a null pointer if c does not occur
+ * in the string.
+ */
+
+#include <sys/asm_linkage.h>
+#include "synonyms.h"
+
+ ! Here, we start by checking to see if we're searching the dest
+ ! string for a null byte. We have fast code for this, so it's
+ ! an important special case. Otherwise, if the string is not
+ ! word aligned, we check a for the search char a byte at a time
+ ! until we've reached a word boundary. Once this has happened
+ ! some zero-byte finding values are initialized and the string
+ ! is checked a word at a time
+
+ ENTRY(strchr)
+
+ .align 32
+
+ andcc %o1, 0xff, %o1 ! search only for this one byte
+ bz .searchnullbyte ! faster code for searching null
+ andcc %o0, 3, %o4 ! str word aligned ?
+ bz,a .prepword2 ! yup, prepare for word-wise search
+ sll %o1, 8, %g1 ! start spreading findchar across word
+
+ ldub [%o0], %o2 ! str[0]
+ cmp %o2, %o1 ! str[0] == findchar ?
+ be .done ! yup, done
+ tst %o2 ! str[0] == 0 ?
+ bz .notfound ! yup, return null pointer
+ cmp %o4, 3 ! only one byte needed to align?
+ bz .prepword ! yup, prepare for word-wise search
+ inc %o0 ! str++
+ ldub [%o0], %o2 ! str[1]
+ cmp %o2, %o1 ! str[1] == findchar ?
+ be .done ! yup, done
+ tst %o2 ! str[1] == 0 ?
+ bz .notfound ! yup, return null pointer
+ cmp %o4, 2 ! only two bytes needed to align?
+ bz .prepword ! yup, prepare for word-wise search
+ inc %o0 ! str++
+ ldub [%o0], %o2 ! str[2]
+ cmp %o2, %o1 ! str[2] == findchar ?
+ be .done ! yup, done
+ tst %o2 ! str[2] == 0 ?
+ bz .notfound ! yup, return null pointer
+ inc %o0 ! str++
+
+.prepword:
+ sll %o1, 8, %g1 ! spread findchar ------+
+.prepword2: !
+ sethi %hi(0x01010101), %o4 ! Alan Mycroft's magic1 !
+ or %o1, %g1, %o1 ! across all <---------+
+ sethi %hi(0x80808080), %o5 ! Alan Mycroft's magic2 !
+ sll %o1, 16, %g1 ! four bytes <--------+
+ or %o4, %lo(0x01010101), %o4 !
+ or %o1, %g1, %o1 ! of a word <--------+
+ or %o5, %lo(0x80808080), %o5
+
+.searchchar:
+ lduw [%o0], %o2 ! src word
+ andn %o5, %o2, %o3 ! ~word & 0x80808080
+ sub %o2, %o4, %g1 ! word = (word - 0x01010101)
+ andcc %o3, %g1, %g0 ! ((word - 0x01010101) & ~word & 0x80808080)
+ bnz .haszerobyte ! zero byte if magic expression != 0
+ xor %o2, %o1, %g1 ! tword = word ^ findchar
+ andn %o5, %g1, %o3 ! ~tword & 0x80808080
+ sub %g1, %o4, %o2 ! (tword - 0x01010101)
+ andcc %o3, %o2, %g0 ! ((tword - 0x01010101) & ~tword & 0x80808080)
+ bz,a .searchchar ! no findchar if magic expression == 0
+ add %o0, 4, %o0 ! str += 4
+
+ ! here we know "word" contains the searched character, but no null
+ ! byte. if there was a null byte, we would have gone to .haszerobyte
+ ! "tword" has null bytes where "word" had findchar. Examine "tword"
+
+.foundchar:
+ set 0xff000000, %o4 ! mask for 1st byte
+ andcc %g1, %o4, %g0 ! first byte zero (= found search char) ?
+ bz .done ! yup, done
+ set 0x00ff0000, %o5 ! mask for 2nd byte
+ inc %o0 ! str++
+ andcc %g1, %o5, %g0 ! second byte zero (= found search char) ?
+ bz .done ! yup, done
+ srl %o4, 16, %o4 ! 0x0000ff00 = mask for 3rd byte
+ inc %o0 ! str++
+ andcc %g1, %o4, %g0 ! third byte zero (= found search char) ?
+ bnz,a .done ! nope, increment in delay slot
+ inc %o0 ! str++
+
+.done:
+ retl ! done with leaf function
+ nop ! padding
+
+ ! Here we know that "word" contains a null byte indicating the
+ ! end of the string. However, "word" might also contain findchar
+ ! "tword" (in %g1) has null bytes where "word" had findchar. So
+ ! check both "tword" and "word"
+
+.haszerobyte:
+ set 0xff000000, %o4 ! mask for 1st byte
+ andcc %g1, %o4, %g0 ! first byte == findchar ?
+ bz .done ! yup, done
+ andcc %o2, %o4, %g0 ! first byte == 0 ?
+ bz .notfound ! yup, return null pointer
+ set 0x00ff0000, %o4 ! mask for 2nd byte
+ inc %o0 ! str++
+ andcc %g1, %o4, %g0 ! second byte == findchar ?
+ bz .done ! yup, done
+ andcc %o2, %o4, %g0 ! second byte == 0 ?
+ bz .notfound ! yup, return null pointer
+ srl %o4, 8, %o4 ! mask for 3rd byte = 0x0000ff00
+ inc %o0 ! str++
+ andcc %g1, %o4, %g0 ! third byte == findchar ?
+ bz .done ! yup, done
+ andcc %o2, %o4, %g0 ! third byte == 0 ?
+ bz .notfound ! yup, return null pointer
+ andcc %g1, 0xff, %g0 ! fourth byte == findchar ?
+ bz .done ! yup, done
+ inc %o0 ! str++
+
+.notfound:
+ retl ! done with leaf function
+ xor %o0, %o0, %o0 ! return null pointer
+
+ ! since findchar == 0, we only have to do one test per item
+ ! instead of two. This makes the search much faster.
+
+.searchnullbyte:
+ bz .straligned ! str is word aligned
+ nop ! padding
+
+ cmp %o4, 2 ! str halfword aligned ?
+ be .s2aligned ! yup
+ ldub [%o0], %o1 ! str[0]
+ tst %o1 ! byte zero?
+ bz .done2 ! yup, done
+ cmp %o4, 3 ! only one byte needed to align?
+ bz .straligned ! yup
+ inc %o0 ! str++
+
+ ! check to see if we're half word aligned, which it better than
+ ! not being aligned at all. Search the first half of the word
+ ! if we are, and then search by whole word.
+
+.s2aligned:
+ lduh [%o0], %o1 ! str[]
+ srl %o1, 8, %o4 ! %o4<7:0> = first byte
+ tst %o4 ! first byte zero ?
+ bz .done2 ! yup, done
+ andcc %o1, 0xff, %g0 ! second byte zero ?
+ bz,a .done2 ! yup, done
+ inc %o0 ! str++
+ add %o0, 2, %o0 ! str+=2
+
+.straligned:
+ sethi %hi(0x01010101), %o4 ! Alan Mycroft's magic1
+ sethi %hi(0x80808080), %o5 ! Alan Mycroft's magic2
+ or %o4, %lo(0x01010101), %o4
+ or %o5, %lo(0x80808080), %o5
+
+.searchword:
+ lduw [%o0], %o1 ! src word
+ andn %o5, %o1, %o3 ! ~word & 0x80808080
+ sub %o1, %o4, %g1 ! word = (word - 0x01010101)
+ andcc %o3, %g1, %g0 ! ((word - 0x01010101) & ~word & 0x80808080)
+ bz,a .searchword ! no zero byte if magic expression == 0
+ add %o0, 4, %o0 ! str += 4
+
+.zerobyte:
+ set 0xff000000, %o4 ! mask for 1st byte
+ andcc %o1, %o4, %g0 ! first byte zero?
+ bz .done2 ! yup, done
+ set 0x00ff0000, %o5 ! mask for 2nd byte
+ inc %o0 ! str++
+ andcc %o1, %o5, %g0 ! second byte zero?
+ bz .done2 ! yup, done
+ srl %o4, 16, %o4 ! 0x0000ff00 = mask for 3rd byte
+ inc %o0 ! str++
+ andcc %o1, %o4, %g0 ! third byte zero?
+ bnz,a .done2 ! nope, increment in delay slot
+ inc %o0 ! str++
+.done2:
+ retl ! return from leaf function
+ nop ! padding
+
+ SET_SIZE(strchr)
diff --git a/usr/src/lib/libc/sparc/gen/strcmp.s b/usr/src/lib/libc/sparc/gen/strcmp.s
new file mode 100644
index 0000000000..a1b7065a04
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/strcmp.s
@@ -0,0 +1,247 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+.ident "%Z%%M% %I% %E% SMI"
+
+ .file "%M%"
+
+/* strcmp(s1, s2)
+ *
+ * Compare strings: s1>s2: >0 s1==s2: 0 s1<s2: <0
+ *
+ * Fast assembler language version of the following C-program for strcmp
+ * which represents the `standard' for the C-library.
+ *
+ * int
+ * strcmp(s1, s2)
+ * register const char *s1;
+ * register const char *s2;
+ * {
+ *
+ * if(s1 == s2)
+ * return(0);
+ * while(*s1 == *s2++)
+ * if(*s1++ == '\0')
+ * return(0);
+ * return(*s1 - s2[-1]);
+ * }
+ */
+
+#include <sys/asm_linkage.h>
+#include "synonyms.h"
+
+ ! This strcmp implementation first determines whether s1 is aligned.
+ ! If it is not, it attempts to align it and then checks the
+ ! alignment of the destination string. If it is possible to
+ ! align s2, this also happens and then the compare begins. Otherwise,
+ ! a different compare for non-aligned strings is used.
+ ! In this case, we have multiple routines depending upon the
+ ! degree to which a string is mis-aligned.
+
+ ENTRY(strcmp)
+
+ .align 32
+
+ subcc %o0, %o1, %o2 ! s1 == s2 ?
+ bz .stringsequal1 ! yup, same string, done
+ sethi %hi(0x01010101), %o5 ! start loading Mycroft's magic2
+ andcc %o0, 3, %o3 ! s1 word-aligned ?
+ or %o5, %lo(0x01010101),%o5! finish loading Mycroft's magic2
+ bz .s1aligned ! yup
+ sll %o5, 7, %o4 ! load Mycroft's magic1
+ sub %o3, 4, %o3 ! number of bytes till aligned
+
+.aligns1:
+ ldub [%o1 + %o2], %o0 ! s1[]
+ ldub [%o1], %g1 ! s2[]
+ subcc %o0, %g1, %o0 ! s1[] != s2[] ?
+ bne .done ! yup, done
+ addcc %o0, %g1, %g0 ! s1[] == 0 ?
+ bz .done ! yup, done
+ inccc %o3 ! s1 aligned yet?
+ bnz .aligns1 ! nope, compare another pair of bytes
+ inc %o1 ! s1++, s2++
+
+.s1aligned:
+ andcc %o1, 3, %o3 ! s2 word aligned ?
+ bz .word4 ! yup
+ cmp %o3, 2 ! s2 half-word aligned ?
+ be .word2 ! yup
+ cmp %o3, 3 ! s2 offset to dword == 3 ?
+ be,a .word3 ! yup
+ ldub [%o1], %o0 ! new lower word in s2
+
+.word1:
+ lduw [%o1 - 1], %o0 ! new lower word in s2
+ sethi %hi(0xff000000), %o3 ! mask for forcing byte 1 non-zero
+ sll %o0, 8, %g1 ! partial unaligned word from s2
+ or %o0, %o3, %o0 ! force byte 1 non-zero
+
+.cmp1:
+ andn %o4, %o0, %o3 ! ~word & 0x80808080
+ sub %o0, %o5, %o0 ! word - 0x01010101
+ andcc %o0, %o3, %g0 ! (word - 0x01010101) & ~word & 0x80808080
+ bz,a .doload1 ! no null byte in previous word from s2
+ lduw [%o1 + 3], %o0 ! load next aligned word from s2
+.doload1:
+ srl %o0, 24, %o3 ! byte 1 of new aligned word from s2
+ or %g1, %o3, %g1 ! merge to get unaligned word from s2
+ lduw [%o1 + %o2], %o3 ! word from s1
+ cmp %o3, %g1 ! *s1 != *s2 ?
+ bne .wordsdiffer ! yup, find the byte that is different
+ add %o1, 4, %o1 ! s1+=4, s2+=4
+ andn %o4, %o3, %g1 ! ~word & 0x80808080
+ sub %o3, %o5, %o3 ! word - 0x01010101
+ andcc %o3, %g1, %g0 ! (word - 0x01010101) & ~word & 0x80808080
+ bz .cmp1 ! no null-byte in s1 yet
+ sll %o0, 8, %g1 ! partial unaligned word from s2
+
+ ! words are equal but the end of s1 has been reached
+ ! this means the strings must be equal
+.stringsequal1:
+ retl ! return from leaf function
+ mov %g0, %o0 ! return 0, i.e. strings are equal
+ nop ! pad for optimal alignment of .cmp2
+ nop ! pad for optimal alignment of .cmp2
+
+.word2:
+ lduh [%o1], %o0 ! new lower word in s2
+ sethi %hi(0xffff0000), %o3 ! mask for forcing bytes 1,2 non-zero
+ sll %o0, 16, %g1 ! partial unaligned word from s2
+ or %o0, %o3, %o0 ! force bytes 1,2 non-zero
+
+.cmp2:
+ andn %o4, %o0, %o3 ! ~word & 0x80808080
+ sub %o0, %o5, %o0 ! word - 0x01010101
+ andcc %o0, %o3, %g0 ! (word - 0x01010101) & ~word & 0x80808080
+ bz,a .doload2 ! no null byte in previous word from s2
+ lduw [%o1 + 2], %o0 ! load next aligned word from s2
+.doload2:
+ srl %o0, 16, %o3 ! bytes 1,2 of new aligned word from s2
+ or %g1, %o3, %g1 ! merge to get unaligned word from s2
+ lduw [%o1 + %o2], %o3 ! word from s1
+ cmp %o3, %g1 ! *s1 != *s2 ?
+ bne .wordsdiffer ! yup, find the byte that is different
+ add %o1, 4, %o1 ! s1+=4, s2+=4
+ andn %o4, %o3, %g1 ! ~word & 0x80808080
+ sub %o3, %o5, %o3 ! word - 0x01010101
+ andcc %o3, %g1, %g0 ! (word - 0x01010101) & ~word & 0x80808080
+ bz .cmp2 ! no null-byte in s1 yet
+ sll %o0, 16, %g1 ! partial unaligned word from s2
+
+ ! words are equal but the end of s1 has been reached
+ ! this means the strings must be equal
+.stringsequal2:
+ retl ! return from leaf function
+ mov %g0, %o0 ! return 0, i.e. strings are equal
+
+.word3:
+ sll %o0, 24, %g1 ! partial unaligned word from s2
+ nop ! pad for optimal alignment of .cmp3
+.cmp3:
+ andcc %o0, 0xff, %g0 ! did previous word contain null-byte ?
+ bnz,a .doload3 ! nope, load next word from s2
+ lduw [%o1 + 1], %o0 ! load next aligned word from s2
+.doload3:
+ srl %o0, 8, %o3 ! bytes 1,2,3 from new aligned s2 word
+ or %g1, %o3, %g1 ! merge to get unaligned word from s2
+ lduw [%o1 + %o2], %o3 ! word from s1
+ cmp %o3, %g1 ! *s1 != *s2 ?
+ bne .wordsdiffer ! yup, find the byte that is different
+ add %o1, 4, %o1 ! s1+=4, s2+=4
+ andn %o4, %o3, %g1 ! ~word & 0x80808080
+ sub %o3, %o5, %o3 ! word - 0x01010101
+ andcc %o3, %g1, %g0 ! (word - 0x01010101) & ~word & 0x80808080
+ bz .cmp3 ! no null-byte in s1 yet
+ sll %o0, 24, %g1 ! partial unaligned word from s2
+
+ ! words are equal but the end of s1 has been reached
+ ! this means the strings must be equal
+.stringsequal3:
+ retl ! return from leaf function
+ mov %g0, %o0 ! return 0, i.e. strings are equal
+
+.word4:
+ lduw [%o1 + %o2], %o3 ! load word from s1
+ nop ! pad for optimal alignment of .cmp4
+ nop ! pad for optimal alignment of .cmp4
+ nop ! pad for optimal alignment of .cmp4
+
+.cmp4:
+ lduw [%o1], %g1 ! load word from s2
+ cmp %o3, %g1 ! *scr1 == *src2 ?
+ bne .wordsdiffer ! nope, find mismatching character
+ add %o1, 4, %o1 ! src1 += 4, src2 += 4
+ andn %o4, %o3, %o0 ! ~word & 0x80808080
+ sub %o3, %o5, %o3 ! word - 0x01010101
+ andcc %o3, %o0, %g0 ! (word - 0x01010101) & ~word & 0x80808080
+ bz,a .cmp4 ! no null-byte in s1 yet
+ lduw [%o1 + %o2], %o3 ! load word from s1
+
+ ! words are equal but the end of s1 has been reached
+ ! this means the strings must be equal
+.stringsequal4:
+ retl ! return from leaf function
+ mov %g0, %o0 ! return 0, i.e. strings are equal
+
+.wordsdiffer:
+ srl %g1, 24, %o2 ! first byte of mismatching word in s2
+ srl %o3, 24, %o1 ! first byte of mismatching word in s1
+ subcc %o1, %o2, %o0 ! *s1-*s2
+ bnz .done ! bytes differ, return difference
+ srl %g1, 16, %o2 ! second byte of mismatching word in s2
+ andcc %o1, 0xff, %o0 ! *s1 == 0 ?
+ bz .done ! yup
+
+ ! we know byte 1 is equal, so can compare bytes 1,2 as a group
+
+ srl %o3, 16, %o1 ! second byte of mismatching word in s1
+ subcc %o1, %o2, %o0 ! *s1-*s2
+ bnz .done ! bytes differ, return difference
+ srl %g1, 8, %o2 ! third byte of mismatching word in s2
+ andcc %o1, 0xff, %o0 ! *s1 == 0 ?
+ bz .done ! yup
+
+ ! we know bytes 1, 2 are equal, so can compare bytes 1,2,3 as a group
+
+ srl %o3, 8, %o1 ! third byte of mismatching word in s1
+ subcc %o1, %o2, %o0 ! *s1-*s2
+ bnz .done ! bytes differ, return difference
+ andcc %o1, 0xff, %g0 ! *s1 == 0 ?
+ bz .stringsequal1 ! yup
+
+ ! we know bytes 1,2,3 are equal, so can compare bytes 1,2,3,4 as group
+
+ subcc %o3, %g1, %o0 ! *s1-*s2
+ bz,a .done ! bytes differ, return difference
+ andcc %o3, 0xff, %o0 ! *s1 == 0 ?
+
+.done:
+ retl ! return from leaf routine
+ nop ! padding
+
+
+ SET_SIZE(strcmp)
diff --git a/usr/src/lib/libc/sparc/gen/strcpy.s b/usr/src/lib/libc/sparc/gen/strcpy.s
new file mode 100644
index 0000000000..63de6cfe8c
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/strcpy.s
@@ -0,0 +1,172 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+.ident "%Z%%M% %I% %E% SMI"
+
+ .file "%M%"
+
+/*
+ * strcpy(s1, s2)
+ *
+ * Copy string s2 to s1. s1 must be large enough. Return s1.
+ *
+ * Fast assembler language version of the following C-program strcpy
+ * which represents the `standard' for the C-library.
+ *
+ * char *
+ * strcpy(s1, s2)
+ * register char *s1;
+ * register const char *s2;
+ * {
+ * char *os1 = s1;
+ *
+ * while(*s1++ = *s2++)
+ * ;
+ * return(os1);
+ * }
+ *
+ */
+
+#include <sys/asm_linkage.h>
+#include "synonyms.h"
+
+ ! This is a 32-bit implementation of strcpy. It works by
+ ! first checking the alignment of its source pointer. And,
+ ! if it is not aligned, attempts to copy bytes until it is.
+ ! once this has occurred, the copy takes place, while checking
+ ! for zero bytes, based upon destination alignment.
+ ! Methods exist to handle per-byte, half-word, and word sized
+ ! copies.
+
+ ENTRY(strcpy)
+
+ .align 32
+
+ sub %o1, %o0, %o3 ! src - dst
+ andcc %o1, 3, %o4 ! src word aligned ?
+ bz .srcaligned ! yup
+ mov %o0, %o2 ! save dst
+
+ cmp %o4, 2 ! src halfword aligned
+ be .s2aligned ! yup
+ ldub [%o2 + %o3], %o1 ! src[0]
+ tst %o1 ! byte zero?
+ stb %o1, [%o2] ! store first byte
+ bz .done ! yup, done
+ cmp %o4, 3 ! only one byte needed to align?
+ bz .srcaligned ! yup
+ inc %o2 ! src++, dst++
+
+.s2aligned:
+ lduh [%o2 + %o3], %o1 ! src[]
+ srl %o1, 8, %o4 ! %o4<7:0> = first byte
+ tst %o4 ! first byte zero ?
+ bz .done ! yup, done
+ stb %o4, [%o2] ! store first byte
+ andcc %o1, 0xff, %g0 ! second byte zero ?
+ bz .done ! yup, done
+ stb %o1, [%o2 + 1] ! store second byte
+ add %o2, 2, %o2 ! src += 2, dst += 2
+
+.srcaligned:
+ sethi %hi(0x01010101), %o4 ! Alan Mycroft's magic1
+ sethi %hi(0x80808080), %o5 ! Alan Mycroft's magic2
+ or %o4, %lo(0x01010101), %o4
+ andcc %o2, 3, %o1 ! destination word aligned?
+ bnz .dstnotaligned ! nope
+ or %o5, %lo(0x80808080), %o5
+
+.copyword:
+ lduw [%o2 + %o3], %o1 ! src word
+ add %o2, 4, %o2 ! src += 4, dst += 4
+ andn %o5, %o1, %g1 ! ~word & 0x80808080
+ sub %o1, %o4, %o1 ! word - 0x01010101
+ andcc %o1, %g1, %g0 ! ((word - 0x01010101) & ~word & 0x80808080)
+ add %o1, %o4, %o1 ! restore word
+ bz,a .copyword ! no zero byte if magic expression == 0
+ st %o1, [%o2 - 4] ! store word to dst (address pre-incremented)
+
+.zerobyte:
+ set 0xff000000, %o4 ! mask for 1st byte
+ srl %o1, 24, %o3 ! %o3<7:0> = first byte
+ andcc %o1, %o4, %g0 ! first byte zero?
+ bz .done ! yup, done
+ stb %o3, [%o2 - 4] ! store first byte
+ set 0x00ff0000, %o5 ! mask for 2nd byte
+ srl %o1, 16, %o3 ! %o3<7:0> = second byte
+ andcc %o1, %o5, %g0 ! second byte zero?
+ bz .done ! yup, done
+ stb %o3, [%o2 - 3] ! store second byte
+ srl %o4, 16, %o4 ! 0x0000ff00 = mask for 3rd byte
+ andcc %o1, %o4, %g0 ! third byte zero?
+ srl %o1, 8, %o3 ! %o3<7:0> = third byte
+ bz .done ! yup, done
+ stb %o3, [%o2 - 2] ! store third byte
+ stb %o1, [%o2 - 1] ! store fourth byte
+
+.done:
+ retl ! done with leaf function
+ .empty
+
+.dstnotaligned:
+ cmp %o1, 2 ! dst half word aligned?
+ be,a .storehalfword2 ! yup, store half word at a time
+ lduw [%o2 + %o3], %o1 ! src word
+
+.storebyte:
+ lduw [%o2 + %o3], %o1 ! src word
+ add %o2, 4, %o2 ! src += 4, dst += 4
+ sub %o1, %o4, %g1 ! x - 0x01010101
+ andn %g1, %o1, %g1 ! (x - 0x01010101) & ~x
+ andcc %g1, %o5, %g0 ! ((x - 0x01010101) & ~x & 0x80808080)
+ bnz .zerobyte ! word has zero byte, handle end cases
+ srl %o1, 24, %g1 ! %g1<7:0> = first byte
+ stb %g1, [%o2 - 4] ! store first byte; half-word aligned now
+ srl %o1, 8, %g1 ! %g1<15:0> = byte 2, 3
+ sth %g1, [%o2 - 3] ! store bytes 2, 3
+ ba .storebyte ! next word
+ stb %o1, [%o2 - 1] ! store fourth byte
+
+.storehalfword:
+ lduw [%o2 + %o3], %o1 ! src word
+.storehalfword2:
+ add %o2, 4, %o2 ! src += 4, dst += 4
+ sub %o1, %o4, %g1 ! x - 0x01010101
+ andn %g1, %o1, %g1 ! (x - 0x01010101) & ~x
+ andcc %g1, %o5, %g0 ! ((x - 0x01010101) & ~x & 0x80808080)
+ bnz .zerobyte ! word has zero byte, handle end cases
+ srl %o1, 16, %g1 ! get first and second byte
+ sth %g1, [%o2 - 4] ! store first and second byte
+ ba .storehalfword ! next word
+ sth %o1, [%o2 - 2] ! store third and fourth byte
+
+ ! DO NOT remove these NOPs. It will slow down the halfword loop by 15%
+
+ nop ! padding
+ nop ! padding
+
+ SET_SIZE(strcpy)
+
diff --git a/usr/src/lib/libc/sparc/gen/strlcpy.s b/usr/src/lib/libc/sparc/gen/strlcpy.s
new file mode 100644
index 0000000000..0dd5366dd3
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/strlcpy.s
@@ -0,0 +1,236 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+.ident "%Z%%M% %I% %E% SMI"
+
+ .file "%M%"
+/*
+ * The strlcpy() function copies at most dstsize-1 characters
+ * (dstsize being the size of the string buffer dst) from src
+ * to dst, truncating src if necessary. The result is always
+ * null-terminated. The function returns strlen(src). Buffer
+ * overflow can be checked as follows:
+ *
+ * if (strlcpy(dst, src, dstsize) >= dstsize)
+ * return -1;
+ */
+
+#include <sys/asm_linkage.h>
+#include "synonyms.h"
+
+ ! strlcpy implementation is similar to that of strcpy, except
+ ! in this case, the maximum size of the detination must be
+ ! tracked since it bounds our maximum copy size. However,
+ ! we must still continue to check for zero since the routine
+ ! is expected to null-terminate any string that is within
+ ! the dest size bound.
+ !
+ ! this method starts by checking for and arranging source alignment.
+ ! Once this has occurred, we copy based upon destination alignment.
+ ! This is either by word, halfword, or byte. As this occurs, we
+ ! check for a zero-byte. If one is found, we branch to a method
+ ! which checks for the exact location of a zero-byte within a
+ ! larger word/half-word quantity.
+
+ ENTRY(strlcpy)
+
+ .align 32
+ save %sp, -SA(WINDOWSIZE), %sp
+ subcc %g0, %i2, %g4 ! n = -n or n == 0 ?
+ bz,pn %icc, .getstrlen ! if 0 do nothing but strlen(src)
+ add %i1, %i2, %i3 ! i3 = src + n
+ andcc %i1, 3, %i4 ! word aligned?
+ bz,pn %icc, .wordaligned
+ add %i0, %i2, %i2 ! n = dst + n
+ sub %i4, 4, %i4 ! bytes until src aligned
+
+.alignsrc:
+ ldub [%i3 + %g4], %l1 ! l1 = src[]
+ andcc %l1, 0xff, %g0 ! null byte reached?
+ stub %l1, [%i2 + %g4] ! dst[] = src[]
+ bz,a %icc, .done
+ add %i2, %g4, %i2 ! get single dest ptr for strlen
+ addcc %g4, 1, %g4 ! src++ dest++ n--
+ bz,pn %icc, .forcenullunalign ! n == 0, append null byte
+ addcc %i4, 1, %i4 ! incr, check align
+ bnz,a %icc, .alignsrc
+ nop
+
+.wordaligned:
+ sethi %hi(0x01010101), %i4
+ add %i2, %g4, %l0 ! l0 = dest
+ or %i4, %lo(0x01010101), %i4
+ sub %i2, 4, %i2 ! pre-incr for in cpy loop
+ andcc %l0, 3, %g1 ! word aligned?
+ bnz %icc, .dstnotaligned
+ sll %i4, 7, %i5 ! Mycroft part deux
+
+.storeword:
+ ld [%i3 + %g4], %l1 ! l1 = src[]
+ addcc %g4, 4, %g4 ! n += 4, src += 4, dst +=4
+ bcs,pn %icc, .lastword
+ andn %i5, %l1, %g1 ! ~word & 0x80808080
+ sub %l1, %i4, %l0 ! word - 0x01010101
+ andcc %l0, %g1, %g0 ! doit
+ bz,a,pt %icc, .storeword ! if expr == 0, no zero byte
+ st %l1, [%i2 + %g4] ! dst[] = src[]
+
+.zerobyte:
+ add %i2, %g4, %i2 ! ptr to dest
+ srl %l1, 24, %g1 ! 1st byte
+ andcc %g1, 0xff, %g0 ! test for end
+ bz,pn %icc, .done
+ stb %g1, [%i2] ! store byte
+ add %i2, 1, %i2 ! dst ++
+ srl %l1, 16, %g1 ! 2nd byte
+ andcc %g1, 0xff, %g0 ! zero byte ?
+ bz,pn %icc, .done
+ stb %g1, [%i2] ! store byte
+ add %i2, 1, %i2 ! dst ++
+ srl %l1, 8, %g1 ! 3rd byte
+ andcc %g1, 0xff, %g0 ! zero byte ?
+ bz,pn %icc, .done
+ stb %g1, [%i2] ! store byte
+ stb %l1, [%i2 + 1] ! store last byte
+ add %i2, 1, %i2 ! dst ++
+
+.done:
+ sub %i2, %i0, %i0 ! len = dst - orig dst
+ ret
+ restore %i0, %g0, %o0
+
+.lastword:
+ add %i2, %g4, %i2
+ sub %g4, 4, %g4 ! undo pre-incr
+ add %i3, %g4, %i3
+
+ srl %l1, 24, %g1 ! 1st byte
+ andcc %g1, 0xff, %g0 ! zero byte?
+ bz,pn %icc, .done
+ stb %g1, [%i2] ! store byte
+ inccc %g4 ! n--
+ bz .forcenull
+ srl %l1, 16, %g1 ! 2nd byte
+ add %i2, 1, %i2 ! dst++
+ andcc %g1, 0xff, %g0 ! zero?
+ bz,pn %icc, .done
+ stb %g1, [%i2] ! store
+ inccc %g4
+ bz .forcenull
+ srl %l1, 8, %g1 ! 3rd byte
+ add %i2, 1, %i2 ! dst++
+ andcc %g1, 0xff, %g0 ! zero?
+ bz,pn %icc, .done
+ stb %g1, [%i2] ! store
+ inccc %g4 ! n--
+ bz .forcenull
+ andcc %l1, 0xff, %g0 ! zero?
+ add %i2, 1, %i2 ! dst++
+ bz,pn %ncc, .done
+ stb %l1, [%i2]
+
+.forcenull:
+ stb %g0, [%i2]
+
+.searchword:
+ ld [%i3], %l1
+.searchword2:
+ andn %i5, %l1, %g1 ! word & 0x80808080
+ sub %l1, %i4, %l0 ! word - 0x01010101
+ andcc %l0, %g1, %g0 ! do it
+ bz,a,pt %icc, .searchword
+ add %i3, 4, %i3 ! src += 4
+
+ mov 0xff, %i5
+ sll %i5, 24, %i5 ! mask 1st byte = 0xff000000
+.searchbyte:
+ andcc %l1, %i5, %g0 ! cur byte 0?
+ srl %i5, 8, %i5 ! mask next byte
+ bnz,a %icc, .searchbyte ! cur !=0 continue
+ add %i3, 1, %i3
+
+.endfound:
+ sub %i3, %i1, %i0 ! len = src - orig src
+ ret
+ restore %i0, %g0, %o0
+ nop
+
+.dstnotaligned:
+ cmp %g1, 2 ! halfword aligned?
+ be .storehalfword2
+ .empty
+.storebyte:
+ ld [%i3 + %g4], %l1 ! load src word
+ addcc %g4, 4, %g4 ! src +=4 dst +=4
+ bcs,pn %icc, .lastword
+ andn %i5, %l1, %g1 ! ~x & 0x80808080
+ sub %l1, %i4, %l0 ! x - 0x01010101
+ andcc %l0, %g1, %g0 ! get your Mycroft on
+ bnz,pn %icc, .zerobyte ! non-zero, we have zero byte
+ add %i2, %g4, %l0 ! dst in ptr form
+ srl %l1, 24, %g1 ! get 1st byte, then be hw aligned
+ stb %g1, [%l0]
+ srl %l1, 8, %g1 ! 2nd & 3rd bytes
+ sth %g1, [%l0 + 1]
+ ba .storebyte
+ stb %l1, [%l0 + 3] ! store 4th byte
+
+.storehalfword:
+ ld [%i3 + %g4], %l1 ! src word
+.storehalfword2:
+ addcc %g4, 4, %g4 ! src += 4 dst += 4
+ bcs,pn %icc, .lastword
+ andn %i5, %l1, %g1 ! ~x & 0x80808080
+ sub %l1, %i4, %l0 ! x - 0x01010101
+ andcc %l0, %g1, %g0 ! Mycroft again...
+ bnz,pn %icc, .zerobyte ! non-zer, we have zero byte
+ add %i2, %g4, %l0 ! dst in ptr form
+ srl %l1, 16, %g1 ! first two bytes
+ sth %g1, [%l0]
+ ba .storehalfword
+ sth %l1, [%l0 + 2]
+
+.forcenullunalign:
+ add %i2, %g4, %i2 ! single dst ptr
+ stb %g0, [%i2 - 1] ! store terminating null byte
+
+.getstrlen:
+ sethi %hi(0x01010101), %i4 ! Mycroft...
+ or %i4, %lo(0x01010101), %i4
+ sll %i4, 7, %i5
+
+.getstrlenloop:
+ andcc %i3, 3, %g0 ! word aligned?
+ bz,a,pn %icc, .searchword2 ! search word at a time
+ ld [%i3], %l1 ! src word
+ ldub [%i3], %l1 ! src byte
+ andcc %l1, 0xff, %g0 ! end of src?
+ bnz,a %icc, .getstrlenloop
+ add %i3, 1, %i3 ! src ++
+ sub %i3, %i1, %i0 ! len = src - orig src
+ ret
+ restore %i0, %g0, %o0
+ SET_SIZE(strlcpy)
diff --git a/usr/src/lib/libc/sparc/gen/strlen.s b/usr/src/lib/libc/sparc/gen/strlen.s
new file mode 100644
index 0000000000..09da4ed196
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/strlen.s
@@ -0,0 +1,141 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+
+.ident "%Z%%M% %I% %E% SMI"
+
+ .file "%M%"
+
+/*
+ * strlen(s)
+ *
+ * Given string s, return length (not including the terminating null).
+ *
+ * Fast assembler language version of the following C-program strlen
+ * which represents the `standard' for the C-library.
+ *
+ * size_t
+ * strlen(s)
+ * register const char *s;
+ * {
+ * register const char *s0 = s + 1;
+ *
+ * while (*s++ != '\0')
+ * ;
+ * return (s - s0);
+ * }
+ */
+
+#include <sys/asm_linkage.h>
+#include "synonyms.h"
+
+ ! The object of strlen is to, as quickly as possible, find the
+ ! null byte. To this end, we attempt to get our string aligned
+ ! and then blast across it using Alan Mycroft's algorithm for
+ ! finding null bytes. If we are not aligned, the string is
+ ! checked a byte at a time until it is. Once this occurs,
+ ! we can proceed word-wise across it. Once a word with a
+ ! zero byte has been found, we then check the word a byte
+ ! at a time until we've located the zero byte, and return
+ ! the proper length.
+
+ .align 32
+ ENTRY(strlen)
+ andcc %o0, 3, %o4 ! is src word aligned
+ bz,pt %icc, .nowalgnd
+ mov %o0, %o2
+
+ cmp %o4, 2 ! is src half-word aligned
+ be,a,pn %icc, .s2algn
+ lduh [%o2], %o1
+
+ ldub [%o2], %o1
+ tst %o1 ! byte zero?
+ bz,pn %icc, .done
+ cmp %o4, 3 ! src is byte aligned
+
+ be,pn %icc, .nowalgnd
+ inc 1, %o2
+
+ lduh [%o2], %o1
+
+.s2algn:
+ srl %o1, 8, %o4
+ tst %o4
+ bz,pn %icc, .done
+ andcc %o1, 0xff, %g0
+
+ bz,pn %icc, .done
+ inc 1, %o2
+
+ inc 1, %o2
+
+.nowalgnd:
+ ld [%o2], %o1
+ sethi %hi(0x01010101), %o4
+ sethi %hi(0x80808080), %o5
+ or %o4, %lo(0x01010101), %o4
+ or %o5, %lo(0x80808080), %o5
+
+ andn %o5, %o1, %o3
+ sub %o1, %o4, %g1
+ andcc %o3, %g1, %g0
+ bnz,a,pn %icc, .nullfound
+ sethi %hi(0xff000000), %o4
+
+ ld [%o2+4], %o1
+ inc 4, %o2
+
+.loop: ! this should be aligned to 32
+ inc 4, %o2
+ andn %o5, %o1, %o3 ! %o5 = ~word & 0x80808080
+ sub %o1, %o4, %g1 ! %g1 = word - 0x01010101
+ andcc %o3, %g1, %g0
+ bz,a,pt %icc, .loop
+ ld [%o2], %o1
+
+ dec 4, %o2
+ sethi %hi(0xff000000), %o4
+.nullfound:
+ andcc %o1, %o4, %g0
+ bz,pn %icc, .done ! first byte zero
+ srl %o4, 8, %o4
+
+ andcc %o1, %o4, %g0
+ bz,pn %icc, .done ! second byte zero
+ inc 1, %o2
+
+ srl %o4, 8, %o4
+ andcc %o1, %o4, %g0
+ bz,pn %icc, .done ! thrid byte zero
+ inc 1, %o2
+
+ inc 1, %o2 ! fourth byte zero
+.done:
+ retl
+ sub %o2, %o0, %o0
+ SET_SIZE(strlen)
+
diff --git a/usr/src/lib/libc/sparc/gen/strncmp.s b/usr/src/lib/libc/sparc/gen/strncmp.s
new file mode 100644
index 0000000000..2d9c138ce0
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/strncmp.s
@@ -0,0 +1,315 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1989,1998 by Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * .seg "data"
+ * .asciz "@(#)strncmp.s 1.2 89/08/16"
+ */
+
+.ident "%Z%%M% %I% %E% SMI" /* SunOS 4.1 1.4 */
+
+ .file "strncmp.s"
+
+/*
+ * strncmp(s1, s2, n)
+ *
+ * Compare strings (at most n bytes): s1>s2: >0 s1==s2: 0 s1<s2: <0
+ *
+ * Fast assembler language version of the following C-program for strncmp
+ * which represents the `standard' for the C-library.
+ *
+ * int
+ * strncmp(const char *s1, const char *s2, size_t n)
+ * {
+ * n++;
+ * if (s1 == s2)
+ * return (0);
+ * while (--n != 0 && *s1 == *s2++)
+ * if (*s1++ == '\0')
+ * return (0);
+ * return ((n == 0) ? 0 : (*s1 - s2[-1]));
+ * }
+ */
+
+#include <sys/asm_linkage.h>
+#include "synonyms.h"
+
+ ENTRY(strncmp)
+ save %sp, -SA(WINDOWSIZE), %sp
+ cmp %i2, 8
+ blu,a .cmp_bytes ! for small counts go do bytes
+ sub %i0, %i1, %i0 ! delay slot, get diff from s1 - s2
+ andcc %i0, 3, %g0 ! is s1 aligned
+1: bz .iss2 ! if so go check s2
+ andcc %i1, 3, %i3 ! is s2 aligned
+
+ deccc %i2 ! --n >= 0 ?
+ bcs .doneq
+ nop ! delay slot
+
+ ldub [%i0], %i4 ! else cmp one byte
+ ldub [%i1], %i5
+ inc %i0
+ cmp %i4, %i5
+ bne .noteqb
+ inc %i1
+ tst %i4 ! terminating zero
+ bnz 1b
+ andcc %i0, 3, %g0
+ b,a .doneq
+
+.iss2:
+ set 0x7efefeff, %l6
+ set 0x81010100, %l7
+ sethi %hi(0xff000000), %l0 ! masks to test for terminating null
+ sethi %hi(0x00ff0000), %l1
+ srl %l1, 8, %l2 ! generate 0x0000ff00 mask
+
+ bz .w4cmp ! if s2 word aligned, compare words
+ cmp %i3, 2 ! check if s2 half aligned
+ be .w2cmp
+ cmp %i3, 1 ! check if aligned to 1 or 3 bytes
+.w3cmp: ldub [%i1], %i5
+ inc 1, %i1
+ be .w1cmp
+ sll %i5, 24, %i5
+ sub %i0, %i1, %i0
+2:
+ deccc 4, %i2 ! n >= 4 ?
+ bgeu,a 3f
+ ld [%i1], %i3 ! delay slot
+ dec %i1 ! reset s2
+ inc %i0 ! reset s1 diff
+ b .cmp_bytes ! do a byte at a time if n < 4
+ inc 4, %i2
+3:
+ ld [%i0 + %i1], %i4
+ inc 4, %i1
+ srl %i3, 8, %l4 ! merge with the other half
+ or %l4, %i5, %i5
+ cmp %i4, %i5
+ be 1f
+
+ add %i4, %l6, %l3
+ b,a .noteq
+1: xor %l3, %i4, %l3
+ and %l3, %l7, %l3
+ cmp %l3, %l7
+ be,a 2b
+ sll %i3, 24, %i5
+
+ !
+ ! For 7-bit characters, we know one of the bytes is zero, but for
+ ! 8-bit characters, the zero detection algorithm gives some false
+ ! triggers ... check every byte individually.
+ !
+ andcc %i4, %l0, %g0 ! check if first byte was zero
+ bnz 1f
+ andcc %i4, %l1, %g0 ! check if second byte was zero
+ b,a .doneq
+1: bnz 1f
+ andcc %i4, %l2, %g0 ! check if third byte was zero
+ b,a .doneq
+1: bnz 1f
+ andcc %i4, 0xff, %g0 ! check if last byte is zero
+ b,a .doneq
+1: bnz 2b
+ sll %i3, 24, %i5
+ b,a .doneq
+
+.w1cmp: clr %l4
+ lduh [%i1], %l4
+ inc 2, %i1
+ sll %l4, 8, %l4
+ or %i5, %l4, %i5
+
+ sub %i0, %i1, %i0
+3:
+ deccc 4, %i2 ! n >= 4 ?
+ bgeu,a 4f
+ ld [%i1], %i3 ! delay slot
+ dec 3, %i1 ! reset s2
+ inc 3, %i0 ! reset s1 diff
+ b .cmp_bytes ! do a byte at a time if n < 4
+ inc 4, %i2
+4:
+ ld [%i0 + %i1], %i4
+ inc 4, %i1
+ srl %i3, 24, %l4 ! merge with the other half
+ or %l4, %i5, %i5
+ cmp %i4, %i5
+ be 1f
+
+ add %i4, %l6, %l3
+ b,a .noteq
+1: xor %l3, %i4, %l3
+ and %l3, %l7, %l3
+ cmp %l3, %l7
+ be,a 3b
+ sll %i3, 8, %i5
+
+ andcc %i4, %l0, %g0 ! check if first byte was zero
+ bnz 1f
+ andcc %i4, %l1, %g0 ! check if second byte was zero
+ b,a .doneq
+1: bnz 1f
+ andcc %i4, %l2, %g0 ! check if third byte was zero
+ b,a .doneq
+1: bnz 1f
+ andcc %i4, 0xff, %g0 ! check if last byte is zero
+ b,a .doneq
+1: bnz 3b
+ sll %i3, 8, %i5
+ b,a .doneq
+
+.w2cmp:
+ lduh [%i1], %i5 ! read a halfword to align s2
+ inc 2, %i1
+ sll %i5, 16, %i5
+
+ sub %i0, %i1, %i0
+4:
+ deccc 4, %i2 ! n >= 4 ?
+ bgeu,a 5f
+ ld [%i1], %i3 ! delay slot
+ dec 2, %i1 ! reset s2
+ inc 2, %i0 ! reset s1 diff
+ b .cmp_bytes ! do a byte at a time if n < 4
+ inc 4, %i2 ! delay slot
+5:
+ ld [%i1 + %i0], %i4 ! read a word from s2
+ inc 4, %i1
+ srl %i3, 16, %l4 ! merge with the other half
+ or %l4, %i5, %i5
+ cmp %i4, %i5
+ be 1f
+
+ add %i4, %l6, %l3
+ b,a .noteq
+1: xor %l3, %i4, %l3 ! are any bytes 0?
+ and %l3, %l7, %l3
+ cmp %l3, %l7
+ be,a 4b
+ sll %i3, 16, %i5
+
+ andcc %i4, %l0, %g0 ! check if first byte was zero
+ bnz 1f
+ andcc %i4, %l1, %g0 ! check if second byte was zero
+ b,a .doneq
+1: bnz 1f
+ andcc %i4, %l2, %g0 ! check if third byte was zero
+ b,a .doneq
+1: bnz 1f
+ andcc %i4, 0xff, %g0 ! check if last byte is zero
+ b,a .doneq
+1: bnz 4b
+ sll %i3, 16, %i5
+ b,a .doneq
+
+.w4cmp: sub %i0, %i1, %i0
+ ld [%i1], %i5 ! read a word from s1
+5: cmp %i2,0
+ be,a .doneq
+ nop
+ ld [%i1], %i5 ! read a word from s1
+ deccc 4, %i2 ! n >= 4 ?
+ bcs,a .cmp_bytes ! do a byte at a time if n < 4
+ inc 4, %i2
+
+ ld [%i1 + %i0], %i4 ! read a word from s2
+ cmp %i4, %i5
+ inc 4, %i1
+ be 1f
+
+ add %i4, %l6, %l3
+ b,a .noteq
+1: xor %l3, %i4, %l3
+ and %l3, %l7, %l3
+ cmp %l3, %l7
+ be,a 5b
+ nop
+
+ andcc %i4, %l0, %g0 ! check if first byte was zero
+ bnz 1f
+ andcc %i4, %l1, %g0 ! check if second byte was zero
+ b,a .doneq
+1: bnz 1f
+ andcc %i4, %l2, %g0 ! check if third byte was zero
+ b,a .doneq
+1: bnz 1f
+ andcc %i4, 0xff, %g0 ! check if last byte is zero
+ b,a .doneq
+1: bnz,a 5b
+ ld [%i1], %i5
+.doneq: ret
+ restore %g0, %g0, %o0 ! equal return zero
+
+.noteq: srl %i4, 24, %l4
+ srl %i5, 24, %l5
+ subcc %l4, %l5, %i0
+ bne 6f
+ andcc %l4, 0xff, %g0
+ bz .doneq
+ sll %i4, 8, %l4
+ sll %i5, 8, %l5
+ srl %l4, 24, %l4
+ srl %l5, 24, %l5
+ subcc %l4, %l5, %i0
+ bne 6f
+ andcc %l4, 0xff, %g0
+ bz .doneq
+ sll %i4, 16, %l4
+ sll %i5, 16, %l5
+ srl %l4, 24, %l4
+ srl %l5, 24, %l5
+ subcc %l4, %l5, %i0
+ bne 6f
+ andcc %l4, 0xff, %g0
+ bz .doneq
+ nop
+.noteqb:
+ and %i4, 0xff, %l4
+ and %i5, 0xff, %l5
+ subcc %l4, %l5, %i0
+6: ret
+ restore %i0, %g0, %o0
+
+ ! Do a byte by byte comparison, disregarding alignments
+.cmp_bytes:
+ deccc %i2 ! --n >= 0 ?
+1:
+ bcs .doneq
+ nop ! delay slot
+ ldub [%i1 + %i0], %i4 ! read a word from s1
+ ldub [%i1], %i5 ! read a word from s2
+
+ inc %i1
+ cmp %i4, %i5
+ bne .noteqb
+ tst %i4 ! terminating zero
+ bnz 1b
+ deccc %i2 ! --n >= 0
+ b,a .doneq
+
+ SET_SIZE(strncmp)
diff --git a/usr/src/lib/libc/sparc/gen/strncpy.s b/usr/src/lib/libc/sparc/gen/strncpy.s
new file mode 100644
index 0000000000..11afb2ac4b
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/strncpy.s
@@ -0,0 +1,290 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+
+.ident "%Z%%M% %I% %E% SMI"
+
+ .file "%M%"
+
+/*
+ * strncpy(s1, s2)
+ *
+ * Copy string s2 to s1, truncating or null-padding to always copy n bytes
+ * return s1.
+ *
+ * Fast assembler language version of the following C-program for strncpy
+ * which represents the `standard' for the C-library.
+ *
+ * char *
+ * strncpy(char *s1, const char *s2, size_t n)
+ * {
+ * char *os1 = s1;
+ *
+ * n++;
+ * while ((--n != 0) && ((*s1++ = *s2++) != '\0'))
+ * ;
+ * if (n != 0)
+ * while (--n != 0)
+ * *s1++ = '\0';
+ * return (os1);
+ * }
+ */
+
+#include <sys/asm_linkage.h>
+#include "synonyms.h"
+
+ ! strncpy works similarly to strcpy, except that n bytes of s2
+ ! are copied to s1. If a null character is reached in s2 yet more
+ ! bytes remain to be copied, strncpy will copy null bytes into
+ ! the destination string.
+ !
+ ! This implementation works by first aligning the src ptr and
+ ! performing small copies until it is aligned. Then, the string
+ ! is copied based upon destination alignment. (byte, half-word,
+ ! word, etc.)
+
+ ENTRY(strncpy)
+
+ .align 32
+ subcc %g0, %o2, %o4 ! n = -n
+ bz .doneshort ! if n == 0, done
+ cmp %o2, 7 ! n < 7 ?
+ add %o1, %o2, %o3 ! src = src + n
+ blu .shortcpy ! n < 7, use byte-wise copy
+ add %o0, %o2, %o2 ! dst = dst + n
+ andcc %o1, 3, %o5 ! src word aligned ?
+ bz .wordaligned ! yup
+ save %sp, -0x40, %sp ! create new register window
+ sub %i5, 4, %i5 ! bytes until src aligned
+ nop ! align loop on 16-byte boundary
+ nop ! align loop on 16-byte boundary
+
+.alignsrc:
+ ldub [%i3 + %i4], %i1 ! src[]
+ stb %i1, [%i2 + %i4] ! dst[] = src[]
+ inccc %i4 ! src++, dst++, n--
+ bz .done ! n == 0, done
+ tst %i1 ! end of src reached (null byte) ?
+ bz,a .bytepad ! yes, at least one byte to pad here
+ add %i2, %i4, %l0 ! need single dest pointer for fill
+ inccc %i5 ! src aligned now?
+ bnz .alignsrc ! no, copy another byte
+ .empty
+
+.wordaligned:
+ add %i2, %i4, %l0 ! dst
+ sethi %hi(0x01010101), %l1 ! Alan Mycroft's magic1
+ sub %i2, 4, %i2 ! adjust for dest pre-incr in cpy loops
+ or %l1, %lo(0x01010101),%l1! finish loading magic1
+ andcc %l0, 3, %g1 ! destination word aligned ?
+ bnz .dstnotaligned ! nope
+ sll %l1, 7, %i5 ! create Alan Mycroft's magic2
+
+.storeword:
+ lduw [%i3 + %i4], %i1 ! src dword
+ addcc %i4, 4, %i4 ! n += 4, src += 4, dst += 4
+ bcs .lastword ! if counter wraps, last word
+ andn %i5, %i1, %g1 ! ~dword & 0x80808080
+ sub %i1, %l1, %l0 ! dword - 0x01010101
+ andcc %l0, %g1, %g0 ! ((dword - 0x01010101) & ~dword & 0x80808080)
+ bz,a .storeword ! no zero byte if magic expression == 0
+ stw %i1, [%i2 + %i4] ! store word to dst (address pre-incremented)
+
+ ! n has not expired, but src is at the end. we need to push out the
+ ! remaining src bytes and then start padding with null bytes
+
+.zerobyte:
+ add %i2, %i4, %l0 ! pointer to dest string
+ srl %i1, 24, %g1 ! first byte
+ stb %g1, [%l0] ! store it
+ sub %g1, 1, %g1 ! byte == 0 ? -1 : byte - 1
+ sra %g1, 31, %g1 ! byte == 0 ? -1 : 0
+ andn %i1, %g1, %i1 ! if byte == 0, start padding with null bytes
+ srl %i1, 16, %g1 ! second byte
+ stb %g1, [%l0 + 1] ! store it
+ and %g1, 0xff, %g1 ! isolate byte
+ sub %g1, 1, %g1 ! byte == 0 ? -1 : byte - 1
+ sra %g1, 31, %g1 ! byte == 0 ? -1 : 0
+ andn %i1, %g1, %i1 ! if byte == 0, start padding with null bytes
+ srl %i1, 8, %g1 ! third byte
+ stb %g1, [%l0 + 2] ! store it
+ and %g1, 0xff, %g1 ! isolate byte
+ sub %g1, 1, %g1 ! byte == 0 ? -1 : byte - 1
+ sra %g1, 31, %g1 ! byte == 0 ? -1 : 0
+ andn %i1, %g1, %i1 ! if byte == 0, start padding with null bytes
+ stb %i1, [%l0 + 3] ! store fourth byte
+ addcc %i4, 8, %g0 ! number of pad bytes < 8 ?
+ bcs .bytepad ! yes, do simple byte wise fill
+ add %l0, 4, %l0 ! dst += 4
+ andcc %l0, 3, %l1 ! dst offset relative to word boundary
+ bz .fillaligned ! dst already word aligned
+
+ ! here there is a least one more byte to zero out: otherwise we would
+ ! have exited through label .lastword
+
+ sub %l1, 4, %l1 ! bytes to align dst to word boundary
+.makealigned:
+ stb %g0, [%l0] ! dst[] = 0
+ addcc %i4, 1, %i4 ! n--
+ bz .done ! n == 0, we are done
+ addcc %l1, 1, %l1 ! any more byte needed to align
+ bnz .makealigned ! yup, pad another byte
+ add %l0, 1, %l0 ! dst++
+ nop ! pad to align copy loop below
+
+ ! here we know that there at least another 4 bytes to pad, since
+ ! we don't get here unless there were >= 8 bytes to pad to begin
+ ! with, and we have padded at most 3 bytes suring dst aligning
+
+.fillaligned:
+ add %i4, 3, %i2 ! round up to next word boundary
+ and %i2, -4, %l1 ! pointer to next word boundary
+ and %i2, 4, %i2 ! word count odd ? 4 : 0
+ stw %g0, [%l0] ! store first word
+ addcc %l1, %i2, %l1 ! dword count == 1 ?
+ add %i4, %i2, %i4 ! if word count odd, n -= 4
+ bz .bytepad ! if word count == 1, pad bytes left
+ add %l0, %i2, %l0 ! bump dst if word count odd
+
+.fillword:
+ addcc %l1, 8, %l1 ! count -= 8
+ stw %g0, [%l0] ! dst[n] = 0
+ stw %g0, [%l0 + 4] ! dst[n+4] = 0
+ add %l0, 8, %l0 ! dst += 8
+ bcc .fillword ! fill words until count == 0
+ addcc %i4, 8, %i4 ! n -= 8
+ bz .done ! if n == 0, we are done
+ .empty
+
+.bytepad:
+ and %i4, 1, %i2 ! byte count odd ? 1 : 0
+ stb %g0, [%l0] ! store first byte
+ addcc %i4, %i2, %i4 ! byte count == 1 ?
+ bz .done ! yup, we are done
+ add %l0, %i2, %l0 ! bump pointer if odd
+
+.fillbyte:
+ addcc %i4, 2, %i4 ! n -= 2
+ stb %g0, [%l0] ! dst[n] = 0
+ stb %g0, [%l0 + 1] ! dst[n+1] = 0
+ bnz .fillbyte ! fill until n == 0
+ add %l0, 2, %l0 ! dst += 2
+
+.done:
+ ret ! done
+ restore %i0, %g0, %o0 ! restore reg window, return dst
+
+ ! this is the last word. It may contain null bytes. store bytes
+ ! until n == 0. if null byte encountered, continue
+
+.lastword:
+ sub %i4, 4, %i4 ! undo counter pre-increment
+ add %i2, 4, %i2 ! adjust dst for counter un-bumping
+
+ srl %i1, 24, %g1 ! first byte
+ stb %g1, [%i2 + %i4] ! store it
+ inccc %i4 ! n--
+ bz .done ! if n == 0, we're done
+ sub %g1, 1, %g1 ! byte == 0 ? -1 : byte - 1
+ sra %g1, 31, %g1 ! byte == 0 ? -1 : 0
+ andn %i1, %g1, %i1 ! if byte == 0, start padding with null
+ srl %i1, 16, %g1 ! second byte
+ stb %g1, [%i2 + %i4] ! store it
+ inccc %i4 ! n--
+ bz .done ! if n == 0, we're done
+ and %g1, 0xff, %g1 ! isolate byte
+ sub %g1, 1, %g1 ! byte == 0 ? -1 : byte - 1
+ sra %g1, 31, %g1 ! byte == 0 ? -1 : 0
+ andn %i1, %g1, %i1 ! if byte == 0, start padding with null
+ srl %i1, 8, %g1 ! third byte
+ stb %g1, [%i2 + %i4] ! store it
+ inccc %i4 ! n--
+ bz .done ! if n == 0, we're done
+ and %g1, 0xff, %g1 ! isolate byte
+ sub %g1, 1, %g1 ! byte == 0 ? -1 : byte - 1
+ sra %g1, 31, %g1 ! byte == 0 ? -1 : 0
+ andn %i1, %g1, %i1 ! if byte == 0, start padding with null
+ ba .done ! here n must be zero, we are done
+ stb %i1, [%i2 + %i4] ! store fourth byte
+
+.dstnotaligned:
+ cmp %g1, 2 ! dst half word aligned?
+ be .storehalfword2 ! yup, store half word at a time
+ .empty
+.storebyte:
+ lduw [%i3 + %i4], %i1 ! x = src[]
+ addcc %i4, 4, %i4 ! src += 4, dst += 4, n -= 4
+ bcs .lastword ! if counter wraps, last word
+ andn %i5, %i1, %g1 ! ~x & 0x80808080
+ sub %i1, %l1, %l0 ! x - 0x01010101
+ andcc %l0, %g1, %g0 ! ((x - 0x01010101) & ~x & 0x80808080)
+ bnz .zerobyte ! end of src found, may need to pad
+ add %i2, %i4, %l0 ! dst (in pointer form)
+ srl %i1, 24, %g1 ! %g1<7:0> = 1st byte; half-word aligned now
+ stb %g1, [%l0] ! store first byte
+ srl %i1, 8, %g1 ! %g1<15:0> = bytes 2, 3
+ sth %g1, [%l0 + 1] ! store bytes 2, 3
+ ba .storebyte ! next word
+ stb %i1, [%l0 + 3] ! store fourth byte
+ nop
+ nop
+
+.storehalfword:
+ lduw [%i3 + %i4], %i1 ! x = src[]
+.storehalfword2:
+ addcc %i4, 4, %i4 ! src += 4, dst += 4, n -= 4
+ bcs .lastword ! if counter wraps, last word
+ andn %i5, %i1, %g1 ! ~x & 0x80808080
+ sub %i1, %l1, %l0 ! x - 0x01010101
+ andcc %l0, %g1, %g0 ! ((x -0x01010101) & ~x & 0x8080808080)
+ bnz .zerobyte ! x has zero byte, handle end cases
+ add %i2, %i4, %l0 ! dst (in pointer form)
+ srl %i1, 16, %g1 ! %g1<15:0> = bytes 1, 2
+ sth %g1, [%l0] ! store bytes 1, 2
+ ba .storehalfword ! next dword
+ sth %i1, [%l0 + 2] ! store bytes 3, 4
+
+.shortcpy:
+ ldub [%o3 + %o4], %o5 ! src[]
+ stb %o5, [%o2 + %o4] ! dst[] = src[]
+ inccc %o4 ! src++, dst++, n--
+ bz .doneshort ! if n == 0, done
+ tst %o5 ! src[] == 0 ?
+ bnz,a .shortcpy ! nope, next byte
+ nop ! empty delay slot
+
+.padbyte:
+ stb %g0, [%o2 + %o4] ! dst[] = 0
+.padbyte2:
+ addcc %o4, 1, %o4 ! dst++, n--
+ bnz,a .padbyte2 ! if n != 0, next byte
+ stb %g0, [%o2 + %o4] ! dst[] = 0
+ nop ! align label below to 16-byte boundary
+
+.doneshort:
+ retl ! return from leaf
+ nop ! empty delay slot
+ SET_SIZE(strncpy)
diff --git a/usr/src/lib/libc/sparc/gen/swapctxt.c b/usr/src/lib/libc/sparc/gen/swapctxt.c
new file mode 100644
index 0000000000..881ff7b638
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/swapctxt.c
@@ -0,0 +1,63 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+
+/*
+ * Copyright 1996-2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#pragma weak swapcontext = _swapcontext
+
+#include "synonyms.h"
+#include <ucontext.h>
+#include <sys/types.h>
+#include "libc.h"
+
+int
+swapcontext(ucontext_t *oucp, const ucontext_t *nucp)
+{
+ greg_t *reg;
+
+ if (__getcontext_syscall(oucp))
+ return (-1);
+
+ /*
+ * Note that %o1 and %g1 are modified by the system call
+ * routine. ABI calling conventions specify that the caller
+ * can not depend upon %o0 thru %o5 nor g1, so no effort is
+ * made to maintain these registers. %o0 is forced to reflect
+ * an affirmative return code.
+ */
+ reg = oucp->uc_mcontext.gregs;
+ reg[REG_SP] = getfp();
+ reg[REG_O7] = caller();
+ reg[REG_PC] = reg[REG_O7] + 8;
+ reg[REG_nPC] = reg[REG_PC] + 4;
+ reg[REG_O0] = 0;
+
+ return (setcontext((ucontext_t *)nucp));
+}
diff --git a/usr/src/lib/libc/sparc/gen/sync_instruction_memory.s b/usr/src/lib/libc/sparc/gen/sync_instruction_memory.s
new file mode 100644
index 0000000000..d4cae952f5
--- /dev/null
+++ b/usr/src/lib/libc/sparc/gen/sync_instruction_memory.s
@@ -0,0 +1,79 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1995-1997, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+.ident "%Z%%M% %I% %E% SMI"
+
+ .file "%M%"
+
+#include <sys/asm_linkage.h>
+
+/*
+ * void sync_instruction_memory(caddr_t addr, int len)
+ *
+ * Make the memory at {addr, addr+len} valid for instruction execution.
+ */
+
+#ifdef lint
+#define nop
+void
+sync_instruction_memory(caddr_t addr, int len)
+{
+ caddr_t end = addr + len;
+ caddr_t start = addr & ~7;
+ for (; start < end; start += 8)
+ flush(start);
+ nop; nop; nop; nop; nop;
+ return;
+}
+#else
+ ENTRY(sync_instruction_memory)
+ add %o0, %o1, %o2
+ andn %o0, 7, %o0
+
+ cmp %o0, %o2
+ bgeu 2f
+ nop
+ flush %o0
+1:
+ add %o0, 8, %o0
+ cmp %o0, %o2
+ blu,a 1b
+ flush %o0
+ !
+ ! when we get here, we have executed 3 instructions after the
+ ! last flush; SPARC V8 requires 2 more for flush to be visible
+ ! The retl;nop pair will do it.
+ !
+2:
+ retl
+ clr %o0
+ SET_SIZE(sync_instruction_memory)
+
+ ENTRY(nop)
+ retl
+ nop
+ SET_SIZE(nop)
+#endif