Cygwin: x86_64: import new memset.S from NetBSD

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
Corinna Vinschen 2022-12-20 10:03:17 +01:00
parent 8e83ca675f
commit 3830325502
1 changed files with 82 additions and 58 deletions

View File

@ -1,69 +1,93 @@
/* These functions are almost verbatim FreeBSD code (even if the header of /* $NetBSD: memset.S,v 1.5 2014/05/22 16:47:31 pooka Exp $ */
one file mentiones NetBSD), just wrapped in the minimum required code to
make them work under the MS AMD64 ABI.
See FreeBSD src/lib/libc/amd64/string/memset.S */
/* /*-
* Written by J.T. Conklin <jtc@NetBSD.org>. * Copyright (c) 2009 The NetBSD Foundation, Inc.
* Public domain. * All rights reserved.
* Adapted for NetBSD/x86_64 by *
* Frank van der Linden <fvdl@wasabisystems.com> * This code is derived from software contributed to The NetBSD Foundation
* by David Laight.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/ */
.globl memset #include <machine/asm.h>
.seh_proc memset
memset:
movq %rsi,8(%rsp)
movq %rdi,16(%rsp)
.seh_endprologue
movq %rcx,%rdi
movq %rdx,%rsi
movq %r8,%rdx
movq %rsi,%rax #if defined(LIBC_SCCS)
andq $0xff,%rax RCSID("$NetBSD: memset.S,v 1.5 2014/05/22 16:47:31 pooka Exp $")
movq %rdx,%rcx #endif
movq %rdi,%r11
cld /* set fill direction forward */ #ifndef _KERNEL
/* bzero, %rdi is buffer, %rsi length */
/* if the string is too short, it's really not worth the ENTRY2(bzero)
* overhead of aligning to word boundries, etc. So we jump to mov %rsi,%rdx /* length */
* a plain unaligned set. */ xor %eax,%eax /* value to write */
cmpq $0x0f,%rcx jmp 1f
jle L1 END(bzero)
#endif
movb %al,%ah /* copy char to all bytes in word */ /* memset, %rdi is buffer, %rsi char to fill, %rdx length */
movl %eax,%edx
sall $16,%eax
orl %edx,%eax
movl %eax,%edx ENTRY3(memset)
salq $32,%rax movzbq %sil,%rax /* byte value to fill */
orq %rdx,%rax mov %rdx,%rsi /* copy of length */
mov $0x0101010101010101,%r9
imul %r9,%rax /* fill value in all bytes */
movq %rdi,%rdx /* compute misalignment */ 1:
negq %rdx mov %rdi,%r9 /* Need to return buffer address */
andq $7,%rdx or %edi,%edx /* address | length */
movq %rcx,%r8 mov %rsi,%rcx
subq %rdx,%r8 cmp $7,%rsi
jbe 10f /* jump if short fill */
test $7,%dl /* check for misaligned fill */
jnz 20f /* jump if misaligned */
movq %rdx,%rcx /* set until word aligned */ /* Target aligned and length multiple of 8 */
rep 2:
stosb shr $3,%rcx
rep stosq
movq %r8,%rcx mov %r9,%rax
shrq $3,%rcx /* set by words */
rep
stosq
movq %r8,%rcx /* set remainder by bytes */
andq $7,%rcx
L1: rep
stosb
movq %r11,%rax
movq 8(%rsp),%rsi
movq 16(%rsp),%rdi
ret ret
.seh_endproc
/*
* Short transfer, any faffing here will generate mispredicted branches.
* So we keep it simple.
*/
10: rep stosb
mov %r9,%rax
ret
/*
* Buffer or length misaligned.
* Write pattern to first and last word of buffer, then fill middle.
* (This writes to some bytes more than once - possibly three times!.)
*/
20:
mov %rax,(%rdi)
movzbq %dil,%rdx /* low address for alignment */
mov %rax,-8(%rcx,%rdi)
and $7,%dl /* offset in word */
sub %rdx,%rcx /* adjust length ... */
add %rdx,%rdi /* ... and target */
jmp 2b
END(memset)