/* $OpenBSD: strlcpy.S,v 1.8 2013/02/02 13:29:14 miod Exp $ */ /* * Copyright (c) 1999 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "DEFS.h" /* * It is faster to implement strlcpy() as two distinct operations, * a strlen() and a memcpy(). Note that we *always* add a NUL, unless * the count is 0. * * TODO: try unrolling the two main loops a bit */ ENTRY(strlcpy) movl %sp@(8),%a0 | a0 = src movl %a0,%a1 | working copy of src ptr movl %a0,%d0 | return (d0) value is len(src) notl %d0 | take the complement of d0 strlcpy_len: tstb %a1@+ | did we hit the terminating NUL? bne strlcpy_len | nope, keep going addl %a1,%d0 | now set things up to do the copy movl %sp@(4),%a1 | a1 = dst movl %sp@(12),%d1 | d1 = count beq strlcpy_done | zero count, just return subql #1,%d1 | subtract one for the NUL cmpl %d0, %d1 | must set d1 to MIN(d0, d1) ble strlcpy_check | count - 1 <= len(src), so d1 is ok movl %d0, %d1 | d1 is too big, set it to len(src) strlcpy_check: tstl %d1 | is d1 zero? beq strlcpy_clear | if so, skip copy and set byte to NUL strlcpy_copy: movb %a0@+,%a1@+ | copy a byte subql #1,%d1 | decrement count bne strlcpy_copy | space left? continue copying... strlcpy_clear: clrb %a1@ | clear last byte strlcpy_done: moveal %d0,%a0 rts