9b4c0e34d2
x86-64. Since there's no hardware available yet, this port is only known to run on the Simics simulator for at the moment, and as such uses the PC devices that it simulates for now. It will be developed more (and cleaned up) as the hardware becomes available.
439 lines
8.5 KiB
ArmAsm
439 lines
8.5 KiB
ArmAsm
/* $NetBSD: copy.S,v 1.1 2001/06/19 00:21:16 fvdl Exp $ */
|
|
|
|
/*
|
|
* Copyright (c) 2001 Wasabi Systems, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* Written by Frank van der Linden for Wasabi Systems, Inc.
|
|
*
|
|
* 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.
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
* must display the following acknowledgement:
|
|
* This product includes software developed for the NetBSD Project by
|
|
* Wasabi Systems, Inc.
|
|
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
|
|
* or promote products derived from this software without specific prior
|
|
* written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
|
|
* 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.
|
|
*/
|
|
|
|
#include "assym.h"
|
|
|
|
#include <sys/errno.h>
|
|
#include <sys/syscall.h>
|
|
|
|
#include <machine/param.h>
|
|
#include <machine/asm.h>
|
|
|
|
/*
|
|
* Copy routines from and to userland, plus a few more. See the
|
|
* section 9 manpages for info. Some cases can be optimized more.
|
|
*
|
|
* I wonder if it's worthwhile to make these use SSE2 registers.
|
|
*/
|
|
|
|
/*
|
|
* XXXfvdl appears only to be used by pccons.
|
|
*
|
|
* fillw(short pattern, caddr_t addr, size_t len);
|
|
* Write len copies of pattern at addr.
|
|
* appears to be used by pccons.
|
|
*/
|
|
ENTRY(fillw)
|
|
movl %edi,%eax
|
|
movq %rsi,%rdi
|
|
movw %ax,%cx
|
|
rorl $16,%eax
|
|
movw %cx,%ax
|
|
cld
|
|
movq %rdx,%rcx
|
|
shrq %rcx
|
|
rep
|
|
stosl
|
|
movq %rdx,%rcx
|
|
andq $1,%rcx
|
|
rep
|
|
stosw
|
|
ret
|
|
|
|
ENTRY(kcopy)
|
|
movq _C_LABEL(curpcb)(%rip),%rax
|
|
pushq PCB_ONFAULT(%rax)
|
|
leaq _C_LABEL(copy_fault)(%rip),%r11
|
|
movq %r11, PCB_ONFAULT(%rax)
|
|
|
|
xchgq %rdi,%rsi
|
|
movq %rdx,%rcx
|
|
|
|
movq %rdi,%rax
|
|
subq %rsi,%rax
|
|
cmpq %rcx,%rax # overlapping?
|
|
jb 1f
|
|
cld # nope, copy forward
|
|
shrq $3,%rcx # copy by 64-bit words
|
|
rep
|
|
movsq
|
|
|
|
movq %rdx,%rcx
|
|
andl $7,%ecx # any bytes left?
|
|
rep
|
|
movsb
|
|
|
|
movq _C_LABEL(curpcb)(%rip),%rdx
|
|
popq PCB_ONFAULT(%rdx)
|
|
xorq %rax,%rax
|
|
ret
|
|
|
|
1: addq %rcx,%rdi # copy backward
|
|
addq %rcx,%rsi
|
|
std
|
|
andq $7,%rcx # any fractional bytes?
|
|
decq %rdi
|
|
decq %rsi
|
|
rep
|
|
movsb
|
|
movq %rdx,%rcx # copy remainder by 64-bit words
|
|
shrq $3,%rcx
|
|
subq $7,%rsi
|
|
subq $7,%rdi
|
|
rep
|
|
movsq
|
|
cld
|
|
|
|
movq _C_LABEL(curpcb)(%rip),%rdx
|
|
popq PCB_ONFAULT(%rdx)
|
|
xorq %rax,%rax
|
|
ret
|
|
|
|
ENTRY(copyout)
|
|
pushq $0
|
|
|
|
xchgq %rdi,%rsi
|
|
movq %rdx,%rax
|
|
|
|
movq %rdi,%rdx
|
|
addq %rax,%rdx
|
|
jc _C_LABEL(copy_efault)
|
|
movq $VM_MAXUSER_ADDRESS,%r8
|
|
cmpq %r8,%rdx
|
|
ja _C_LABEL(copy_efault)
|
|
|
|
movq _C_LABEL(curpcb)(%rip),%rdx
|
|
leaq _C_LABEL(copy_fault)(%rip),%r11
|
|
movq %r11,PCB_ONFAULT(%rdx)
|
|
|
|
cld
|
|
movq %rax,%rcx
|
|
shrq $3,%rcx
|
|
rep
|
|
movsq
|
|
movb %al,%cl
|
|
andb $7,%cl
|
|
rep
|
|
movsb
|
|
|
|
popq PCB_ONFAULT(%rdx)
|
|
xorl %eax,%eax
|
|
ret
|
|
|
|
ENTRY(copyin)
|
|
movq _C_LABEL(curpcb)(%rip),%rax
|
|
pushq $0
|
|
leaq _C_LABEL(copy_fault)(%rip),%r11
|
|
movq %r11,PCB_ONFAULT(%rax)
|
|
|
|
xchgq %rdi,%rsi
|
|
movq %rdx,%rax
|
|
|
|
movq %rsi,%rdx
|
|
addq %rax,%rdx
|
|
jc _C_LABEL(copy_efault)
|
|
movq $VM_MAXUSER_ADDRESS,%r8
|
|
cmpq %r8,%rdx
|
|
ja _C_LABEL(copy_efault)
|
|
|
|
3: /* bcopy(%rsi, %rdi, %rax); */
|
|
cld
|
|
movq %rax,%rcx
|
|
shrq $3,%rcx
|
|
rep
|
|
movsq
|
|
movb %al,%cl
|
|
andb $7,%cl
|
|
rep
|
|
movsb
|
|
|
|
movq _C_LABEL(curpcb)(%rip),%rdx
|
|
popq PCB_ONFAULT(%rdx)
|
|
xorl %eax,%eax
|
|
ret
|
|
|
|
ENTRY(copy_efault)
|
|
movq $EFAULT,%rax
|
|
|
|
ENTRY(copy_fault)
|
|
movq _C_LABEL(curpcb)(%rip),%rdx
|
|
popq PCB_ONFAULT(%rdx)
|
|
ret
|
|
|
|
ENTRY(copyoutstr)
|
|
xchgq %rdi,%rsi
|
|
movq %rdx,%r8
|
|
movq %rcx,%r9
|
|
|
|
5: movq _C_LABEL(curpcb)(%rip),%rax
|
|
leaq _C_LABEL(copystr_fault)(%rip),%r11
|
|
movq %r11,PCB_ONFAULT(%rax)
|
|
/*
|
|
* Get min(%rdx, VM_MAXUSER_ADDRESS-%rdi).
|
|
*/
|
|
movq $VM_MAXUSER_ADDRESS,%rax
|
|
subq %rdi,%rax
|
|
cmpq %rdx,%rax
|
|
jae 1f
|
|
movq %rax,%rdx
|
|
movq %rax,%r8
|
|
|
|
1: incq %rdx
|
|
cld
|
|
|
|
1: decq %rdx
|
|
jz 2f
|
|
lodsb
|
|
stosb
|
|
testb %al,%al
|
|
jnz 1b
|
|
|
|
/* Success -- 0 byte reached. */
|
|
decq %rdx
|
|
xorq %rax,%rax
|
|
jmp copystr_return
|
|
|
|
2: /* rdx is zero -- return EFAULT or ENAMETOOLONG. */
|
|
movq $VM_MAXUSER_ADDRESS,%r11
|
|
cmpq %r11,%rdi
|
|
jae _C_LABEL(copystr_efault)
|
|
movq $ENAMETOOLONG,%rax
|
|
jmp copystr_return
|
|
|
|
ENTRY(copyinstr)
|
|
xchgq %rdi,%rsi
|
|
movq %rdx,%r8
|
|
movq %rcx,%r9
|
|
|
|
movq _C_LABEL(curpcb)(%rip),%rcx
|
|
leaq _C_LABEL(copystr_fault)(%rip),%r11
|
|
movq %r11,PCB_ONFAULT(%rcx)
|
|
|
|
/*
|
|
* Get min(%rdx, VM_MAXUSER_ADDRESS-%rsi).
|
|
*/
|
|
movq $VM_MAXUSER_ADDRESS,%rax
|
|
subq %rsi,%rax
|
|
cmpq %rdx,%rax
|
|
jae 1f
|
|
movq %rax,%rdx
|
|
movq %rax,%r8
|
|
|
|
1: incq %rdx
|
|
cld
|
|
|
|
1: decq %rdx
|
|
jz 2f
|
|
lodsb
|
|
stosb
|
|
testb %al,%al
|
|
jnz 1b
|
|
|
|
/* Success -- 0 byte reached. */
|
|
decq %rdx
|
|
xorq %rax,%rax
|
|
jmp copystr_return
|
|
|
|
2: /* edx is zero -- return EFAULT or ENAMETOOLONG. */
|
|
movq $VM_MAXUSER_ADDRESS,%r11
|
|
cmpq %r11,%rsi
|
|
jae _C_LABEL(copystr_efault)
|
|
movq $ENAMETOOLONG,%rax
|
|
jmp copystr_return
|
|
|
|
ENTRY(copystr_efault)
|
|
movl $EFAULT,%eax
|
|
|
|
ENTRY(copystr_fault)
|
|
copystr_return:
|
|
/* Set *lencopied and return %eax. */
|
|
movq _C_LABEL(curpcb)(%rip),%rcx
|
|
movq $0,PCB_ONFAULT(%rcx)
|
|
testq %r9,%r9
|
|
jz 8f
|
|
subq %rdx,%r8
|
|
movq %r8,(%r9)
|
|
|
|
8: ret
|
|
|
|
ENTRY(copystr)
|
|
xchgq %rdi,%rsi
|
|
movq %rdx,%r8
|
|
|
|
incq %rdx
|
|
cld
|
|
|
|
1: decq %rdx
|
|
jz 4f
|
|
lodsb
|
|
stosb
|
|
testb %al,%al
|
|
jnz 1b
|
|
|
|
/* Success -- 0 byte reached. */
|
|
decq %rdx
|
|
xorl %eax,%eax
|
|
jmp 6f
|
|
|
|
4: /* edx is zero -- return ENAMETOOLONG. */
|
|
movl $ENAMETOOLONG,%eax
|
|
|
|
6: /* Set *lencopied and return %eax. */
|
|
testq %rcx,%rcx
|
|
jz 7f
|
|
subq %rdx,%r8
|
|
movq %r8,(%rcx)
|
|
|
|
7: ret
|
|
|
|
ENTRY(fuword)
|
|
movq $VM_MAXUSER_ADDRESS-4,%r11
|
|
cmpq %r11,%rdi
|
|
ja _C_LABEL(fusuaddrfault)
|
|
movq _C_LABEL(curpcb)(%rip),%rcx
|
|
leaq _C_LABEL(fusufailure)(%rip),%r11
|
|
movq %r11,PCB_ONFAULT(%rcx)
|
|
movl (%rdi),%eax
|
|
movq $0,PCB_ONFAULT(%rcx)
|
|
ret
|
|
|
|
ENTRY(fusword)
|
|
movq $VM_MAXUSER_ADDRESS-2,%r11
|
|
cmpq %r11,%rdi
|
|
ja _C_LABEL(fusuaddrfault)
|
|
movq _C_LABEL(curpcb)(%rip),%rcx
|
|
leaq _C_LABEL(fusufailure)(%rip),%r11
|
|
movq %r11,PCB_ONFAULT(%rcx)
|
|
movzwl (%rdi),%eax
|
|
movq $0,PCB_ONFAULT(%rcx)
|
|
ret
|
|
|
|
ENTRY(fuswintr)
|
|
movq $VM_MAXUSER_ADDRESS-2,%r11
|
|
cmpq %r11,%rdi
|
|
ja _C_LABEL(fusuaddrfault)
|
|
movq _C_LABEL(curpcb)(%rip),%rcx
|
|
leaq _C_LABEL(fusuintrfailure)(%rip),%r11
|
|
movq %r11,PCB_ONFAULT(%rcx)
|
|
movzwl (%rdi),%eax
|
|
movq $0,PCB_ONFAULT(%rcx)
|
|
ret
|
|
|
|
ENTRY(fubyte)
|
|
movq $VM_MAXUSER_ADDRESS-1,%r11
|
|
cmpq %r11,%rdi
|
|
ja _C_LABEL(fusuaddrfault)
|
|
movq _C_LABEL(curpcb)(%rip),%rcx
|
|
leaq _C_LABEL(fusuintrfailure)(%rip),%r11
|
|
movq %r11,PCB_ONFAULT(%rcx)
|
|
movzbl (%rdi),%eax
|
|
movq $0,PCB_ONFAULT(%rcx)
|
|
ret
|
|
|
|
/*
|
|
* These are the same, but must reside at different addresses,
|
|
* because trap.c checks for them.
|
|
*/
|
|
ENTRY(fusuintrfailure)
|
|
movq $0,PCB_ONFAULT(%rcx)
|
|
movl $-1,%eax
|
|
ret
|
|
|
|
ENTRY(fusufailure)
|
|
movq $0,PCB_ONFAULT(%rcx)
|
|
movl $-1,%eax
|
|
ret
|
|
|
|
ENTRY(fusuaddrfault)
|
|
movl $-1,%eax
|
|
ret
|
|
|
|
ENTRY(suword)
|
|
movq $VM_MAXUSER_ADDRESS-4,%r11
|
|
cmpq %r11,%rdi
|
|
ja _C_LABEL(fusuaddrfault)
|
|
|
|
movq _C_LABEL(curpcb)(%rip),%rcx
|
|
leaq _C_LABEL(fusufailure)(%rip),%r11
|
|
movq %r11,PCB_ONFAULT(%rcx)
|
|
|
|
movq %rsi,(%rdi)
|
|
xorq %rax,%rax
|
|
movq %rax,PCB_ONFAULT(%rcx)
|
|
ret
|
|
|
|
ENTRY(susword)
|
|
movq $VM_MAXUSER_ADDRESS-2,%r11
|
|
cmpq %r11,%rdi
|
|
ja _C_LABEL(fusuaddrfault)
|
|
|
|
movq _C_LABEL(curpcb)(%rip),%rcx
|
|
leaq _C_LABEL(fusufailure)(%rip),%r11
|
|
movq %r11,PCB_ONFAULT(%rcx)
|
|
|
|
movw %si,(%rdi)
|
|
xorq %rax,%rax
|
|
movq %rax,PCB_ONFAULT(%rcx)
|
|
ret
|
|
|
|
ENTRY(suswintr)
|
|
movq $VM_MAXUSER_ADDRESS-2,%r11
|
|
cmpq %r11,%rdi
|
|
ja _C_LABEL(fusuaddrfault)
|
|
movq _C_LABEL(curpcb)(%rip),%rcx
|
|
leaq _C_LABEL(fusuintrfailure)(%rip),%r11
|
|
movq %r11,PCB_ONFAULT(%rcx)
|
|
|
|
movw %si,(%rdi)
|
|
xorq %rax,%rax
|
|
movq %rax,PCB_ONFAULT(%rcx)
|
|
ret
|
|
|
|
ENTRY(subyte)
|
|
movq $VM_MAXUSER_ADDRESS-1,%r11
|
|
cmpq %r11,%rdi
|
|
ja _C_LABEL(fusuaddrfault)
|
|
|
|
movq _C_LABEL(curpcb)(%rip),%rcx
|
|
leaq _C_LABEL(fusufailure)(%rip),%r11
|
|
movq %r11,PCB_ONFAULT(%rcx)
|
|
|
|
movb %sil,(%rdi)
|
|
xorq %rax,%rax
|
|
movq %rax,PCB_ONFAULT(%rcx)
|
|
ret
|