strncpy.s revision 2
2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 2N/A * Use is subject to license terms. 2N/A * Copy string s2 to s1, truncating or null-padding to always copy n bytes 2N/A * Fast assembler language version of the following C-program for strncpy 2N/A * which represents the `standard' for the C-library. 2N/A * strncpy(char *s1, const char *s2, size_t n) 2N/A * while ((--n != 0) && ((*s1++ = *s2++) != '\0')) 2N/A sub %i2, 4, %i2 ! adjust for dest pre-incr in cpy loops 2N/A or %l1, %lo(0x01010101),%l1! finish loading magic1 2N/A andcc %l0, 3, %g1 ! destination word aligned ? 2N/A bnz .dstnotaligned ! nope 2N/A sll %l1, 7, %i5 ! create Alan Mycroft's
magic2 2N/A !
we don't get here unless there were >= 8 bytes to pad to begin 2N/A ! with, and we have padded at most 3 bytes suring dst aligning 2N/A add %i4, 3, %i2 ! round up to next word boundary 2N/A and %i2, -4, %l1 ! pointer to next word boundary 2N/A and %i2, 4, %i2 ! word count odd ? 4 : 0 2N/A stw %g0, [%l0] ! store first word 2N/A addcc %l1, %i2, %l1 ! dword count == 1 ? 2N/A add %i4, %i2, %i4 ! if word count odd, n -= 4 2N/A bz .bytepad ! if word count == 1, pad bytes left 2N/A add %l0, %i2, %l0 ! bump dst if word count odd 2N/A addcc %l1, 8, %l1 ! count -= 8 2N/A stw %g0, [%l0] ! dst[n] = 0 2N/A stw %g0, [%l0 + 4] ! dst[n+4] = 0 2N/A add %l0, 8, %l0 ! dst += 8 2N/A bcc .fillword ! fill words until count == 0 2N/A addcc %i4, 8, %i4 ! n -= 8 2N/A bz .done ! if n == 0, we are done 2N/A and %i4, 1, %i2 ! byte count odd ? 1 : 0 2N/A stb %g0, [%l0] ! store first byte 2N/A addcc %i4, %i2, %i4 ! byte count == 1 ? 2N/A bz .done ! yup, we are done 2N/A add %l0, %i2, %l0 ! bump pointer if odd 2N/A addcc %i4, 2, %i4 ! n -= 2 2N/A stb %g0, [%l0] ! dst[n] = 0 2N/A stb %g0, [%l0 + 1] ! dst[n+1] = 0 2N/A bnz .fillbyte ! fill until n == 0 2N/A add %l0, 2, %l0 ! dst += 2 2N/A restore %i0, %g0, %o0 ! restore reg window, return dst 2N/A ! this is the last word. It may contain null bytes. store bytes 2N/A ! until n == 0. if null byte encountered, continue 2N/A sub %i4, 4, %i4 ! undo counter pre-increment 2N/A add %i2, 4, %i2 ! adjust dst for counter un-bumping 2N/A srl %i1, 24, %g1 ! first byte 2N/A stb %g1, [%i2 + %i4] ! store it 2N/A and %g1, 0xff, %g1 ! isolate byte 2N/A sub %g1, 1, %g1 ! byte == 0 ? -1 : byte - 1 2N/A sra %g1, 31, %g1 ! byte == 0 ? -1 : 0 2N/A andn %i1, %g1, %i1 ! if byte == 0, start padding with null 2N/A srl %i1, 8, %g1 ! third byte 2N/A stb %g1, [%i2 + %i4] ! store it