1 1.1 matt /*- 2 1.1 matt * Copyright (c) 2013 The NetBSD Foundation, Inc. 3 1.1 matt * All rights reserved. 4 1.1 matt * 5 1.1 matt * This code is derived from software contributed to The NetBSD Foundation 6 1.1 matt * by Matt Thomas of 3am Software Foundry. 7 1.1 matt * 8 1.1 matt * Redistribution and use in source and binary forms, with or without 9 1.1 matt * modification, are permitted provided that the following conditions 10 1.1 matt * are met: 11 1.1 matt * 1. Redistributions of source code must retain the above copyright 12 1.1 matt * notice, this list of conditions and the following disclaimer. 13 1.1 matt * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 matt * notice, this list of conditions and the following disclaimer in the 15 1.1 matt * documentation and/or other materials provided with the distribution. 16 1.1 matt * 17 1.1 matt * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18 1.1 matt * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 1.1 matt * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 1.1 matt * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 1.1 matt * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 1.1 matt * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 1.1 matt * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 1.1 matt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 1.1 matt * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 1.1 matt * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 1.1 matt * POSSIBILITY OF SUCH DAMAGE. 28 1.1 matt */ 29 1.1 matt 30 1.1 matt #include <machine/asm.h> 31 1.1 matt 32 1.2 mlelstv RCSID("$NetBSD: memset_naive.S,v 1.2 2023/01/19 18:03:03 mlelstv Exp $") 33 1.1 matt 34 1.1 matt /* 35 1.1 matt * This isn't quite as simple/short as it could be but the truly trivial 36 1.1 matt * memset was an order of magnitude slower than this. 37 1.1 matt */ 38 1.1 matt 39 1.1 matt ENTRY(memset) 40 1.1 matt /* LINTSTUB: void *memset(void *, int, size_t) */ 41 1.1 matt mov ip, r0 /* need to preserve r0 */ 42 1.1 matt cmp r2, #10 /* 10 bytes or less? */ 43 1.2 mlelstv bls .Lbyte_by_byte /* yes, bytewise is faster */ 44 1.1 matt ands r3, r1, #0xff /* we are dealing with bytes */ 45 1.1 matt orrne r3, r3, r3, lsl #8 /* move value into 2nd byte lane */ 46 1.1 matt orrne r3, r3, r3, lsl #16 /* move value into all byte lanes */ 47 1.1 matt mov r1, r2 /* move count */ 48 1.1 matt ands r2, ip, #7 /* are we dword aligned? */ 49 1.1 matt beq 1f /* yes we are */ 50 1.1 matt rsb r2, r2, #8 /* how many bytes until aligned? */ 51 1.1 matt sub r1, r1, r2 /* subtract from count */ 52 1.1 matt tst ip, #1 /* halfword aligned? */ 53 1.1 matt strneb r3, [ip], #1 /* nope, write a byte */ 54 1.1 matt tst ip, #2 /* word aligned? */ 55 1.1 matt strneh r3, [ip], #2 /* nope, write a halfword */ 56 1.1 matt tst ip, #4 /* dword aligned? */ 57 1.1 matt strne r3, [ip], #4 /* nope, write a word */ 58 1.1 matt /* 59 1.1 matt * At this point, we are dword aligned. 60 1.1 matt */ 61 1.1 matt 1: mov r2, r3 /* duplicate fill value */ 62 1.1 matt 2: subs r1, r1, #16 /* can we write 16 bytes? */ 63 1.2 mlelstv stmhsia ip!, {r2,r3} /* yes, write the first 8 of them */ 64 1.2 mlelstv stmhsia ip!, {r2,r3} /* yes, write the second 8 of them */ 65 1.2 mlelstv bhi 2b /* more left to fill */ 66 1.1 matt RETc(eq) /* no, return */ 67 1.1 matt /* 68 1.1 matt * Our count went negative but the bits below 16 haven't changed. 69 1.1 matt * So we are effectively testing modulo 16. 70 1.1 matt */ 71 1.1 matt tst r1, #8 /* can we write at least 8 bytes? */ 72 1.1 matt stmneia ip!, {r2,r3} /* so do it */ 73 1.1 matt tst r1, #4 /* can we write at least 4 bytes? */ 74 1.1 matt strne r3, [ip], #4 /* so do it */ 75 1.1 matt tst r1, #2 /* can we write at least 2 bytes? */ 76 1.1 matt strneh r3, [ip], #2 /* so do it */ 77 1.1 matt tst r1, #1 /* can we write 1 bytes? */ 78 1.1 matt strneb r3, [ip], #1 /* so do it */ 79 1.1 matt RET /* return */ 80 1.1 matt 81 1.1 matt .Lbyte_by_byte: 82 1.1 matt subs r2, r2, #1 /* can we write a byte? */ 83 1.2 mlelstv RETc(lo) /* no, return */ 84 1.1 matt strb r3, [ip], #1 /* write a byte */ 85 1.1 matt b .Lbyte_by_byte /* do next byte */ 86 1.1 matt END(memset) 87