NetBSD-5.0.2/sys/arch/powerpc/powerpc/darwin_commpage_machdep.S

Compare this file to the similar file:
Show the results in this format:

/*	$NetBSD: darwin_commpage_machdep.S,v 1.8 2008/05/04 00:18:16 martin Exp $ */

/*
 * Copyright (c) 2004 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Emmanuel Dreyfus, Peter Grehan, and Wolfgang Solfrank.
 *
 * 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.
 */

#include <machine/asm.h>

#include <compat/mach/mach_syscall.h>
#include <compat/darwin/darwin_syscall.h>

#include <compat/mach/arch/powerpc/fasttraps/mach_fasttraps_syscall.h>
#define	MACH_FASTTRAPS		0x00007ff0	/* should be in xxx.h XXX */

/*
 *	void bzero(void *src, size_t len); 
 */
	.globl	_C_LABEL(darwin_commpage_bzero)
_C_LABEL(darwin_commpage_bzero):
	cmplwi  %r4,0
	beqlr
	li      %r0,0
	cmplwi  %r4,6
	bgt-    bzero1
	addi    %r3,%r3,-1
bzero8:
	mtctr   %r4
bzero2:
	stbu    %r0,1(%r3)
	bdnz+   bzero2
	blr
bzero1:
	andi.   %r5,%r3,3
	beq+    bzero3
	andi.   %r5,%r3,1
	beq-    bzero5
	stb     %r0,0(%r3)
	addi    %r3,%r3,1
	addi    %r4,%r4,-1
	andi.   %r5,%r3,2
	beq-    bzero3
bzero5:
	sth     %r0,0(%r3)
	addi    %r3,%r3,2
	addi    %r4,%r4,-2
bzero3:
	cmplwi  %r4,4
	blt-    bzero6
	rlwinm  %r5,%r4,30,2,31
	mtctr   %r5
	addi    %r3,%r3,-4
bzero7:
	stwu    %r0,4(%r3)
	bdnz+   bzero7
bzero6:
	andi.   %r4,%r4,3
	beqlr+
	addi    %r3,%r3,3
	b       bzero8
	.globl	_C_LABEL(darwin_commpage_bzero_size)
_C_LABEL(darwin_commpage_bzero_size) = .-_C_LABEL(darwin_commpage_bzero)


/*
 *	mach_cproc_t *pthread_self(void);
 */
	.globl	_C_LABEL(darwin_commpage_pthread_self)
_C_LABEL(darwin_commpage_pthread_self):
	li 	%r0,MACH_FASTTRAPS_SYS_cthread_self+MACH_FASTTRAPS
	sc
	blr
	.globl	_C_LABEL(darwin_commpage_pthread_self_size)
_C_LABEL(darwin_commpage_pthread_self_size) = .-_C_LABEL(darwin_commpage_pthread_self)

/*
 *	int gettimeofday(struct timeval *tv, struct timezone *tz);
 */
	.globl	_C_LABEL(darwin_commpage_gettimeofday)
_C_LABEL(darwin_commpage_gettimeofday):
	li 	%r0,DARWIN_SYS_gettimeofday
	sc
	blr	/* Skipped on success */
	blr
	.globl	_C_LABEL(darwin_commpage_gettimeofday_size)
_C_LABEL(darwin_commpage_gettimeofday_size) = .-_C_LABEL(darwin_commpage_gettimeofday)

/* 
 *	void bigcopy(void *ignored, void *src, size_t len, ..., void *dst);
 *
 * The ... does not mean vararg here. Here is the calling convention:
 * src => r4
 * len => r5
 * dst => r12
 */
	.globl	_C_LABEL(darwin_commpage_bigcopy)
_C_LABEL(darwin_commpage_bigcopy):
	stwu	%r1,-16(%r1)
	stw	%r31,0(%r1)
1:	lwz	%r31,0(%r12)
	stw	%r31,0(%r4)
	addi	%r5,%r5,-4
	cmplwi	%r5,0
	bgt	1b
	lwz	%r31,0(%r1)
	blr
	.globl	_C_LABEL(darwin_commpage_bigcopy_size)
_C_LABEL(darwin_commpage_bigcopy_size) = .-_C_LABEL(darwin_commpage_bigcopy)

/*
 *	void bcopy(void *src, void *dst, size_t len);
 */
	.globl	_C_LABEL(darwin_commpage_bcopy)
_C_LABEL(darwin_commpage_bcopy):
	mr	%r6,%r3		/* swap $1 and $2 */
	mr	%r3,%r4
	mr	%r4,%r6
	ba	0xffff87a0	/* Absolute branch to memcpy */
	.globl	_C_LABEL(darwin_commpage_bcopy_size)
_C_LABEL(darwin_commpage_bcopy_size) = .-_C_LABEL(darwin_commpage_bcopy)

/*
 *	void *memcpy(void *dst, void *src, size_t len);
 */
	.globl	_C_LABEL(darwin_commpage_memcpy)
_C_LABEL(darwin_commpage_memcpy):
	subfic	%r0,%r5,0
	adde	%r9,%r0,%r5
	stwu	%r1,-16(%r1)
	xor	%r0,%r3,%r4
	subfic	%r8,%r0,0
	adde	%r0,%r8,%r0
	or.	%r11,%r9,%r0
	mr	%r11,%r3
	bne-	memcpy1
	or	%r0,%r4,%r3
	andi.	%r8,%r0,3
	beq-	memcpy2
	xor	%r0,%r4,%r3
	subfic	%r9,%r5,3
	li	%r9,0
	adde	%r9,%r9,%r9
	clrlwi	%r0,%r0,30
	mr	%r10,%r5
	neg	%r0,%r0
	rlwinm	%r0,%r0,1,31,31
	or.	%r8,%r0,%r9
	bne-	memcpy3
	clrlwi	%r0,%r4,30
	subfic	%r10,%r0,4
memcpy3:
	mtctr	%r10
	subf	%r5,%r10,%r5
memcpy4:
	lbz	%r0,0(%r4)
	addi	%r4,%r4,1
	stb	%r0,0(%r11)
	addi	%r11,%r11,1
	bdnz+	memcpy4
memcpy2:
	rlwinm.	%r10,%r5,30,2,31
	beq-	memcpy5
	mtctr	%r10
memcpy6:
	lwz	%r0,0(%r4)
	addi	%r4,%r4,4
	stw	%r0,0(%r11)
	addi	%r11,%r11,4
	bdnz+	memcpy6
memcpy5:
	andi.	%r10,%r5,3
	beq-	memcpy1
	mtctr	%r10
memcpy7:
	lbz	%r0,0(%r4)
	addi	%r4,%r4,1
	stb	%r0,0(%r11)
	addi	%r11,%r11,1
	bdnz+	memcpy7
memcpy1:
	addi	%r1,%r1,16
	blr
	.globl	_C_LABEL(darwin_commpage_memcpy_size)
_C_LABEL(darwin_commpage_memcpy_size) = .-_C_LABEL(darwin_commpage_memcpy)


/*
 *	int pthread_getspecific(pthread_key key);
 */
	.globl	_C_LABEL(darwin_commpage_pthread_getspecific)
_C_LABEL(darwin_commpage_pthread_getspecific):
	rlwinm	%r5,%r3,2,0,29
	li	%r0,MACH_FASTTRAPS_SYS_cthread_self+MACH_FASTTRAPS
	sc
	add	%r5,%r5,%r4
	lwzx	%r3,%r3,%r5
	blr
	.globl	_C_LABEL(darwin_commpage_pthread_getspecific_size)
_C_LABEL(darwin_commpage_pthread_getspecific_size) = .-_C_LABEL(darwin_commpage_pthread_getspecific)

/* 
 *	uint64_t mach_absolute_time(void) 
 */
	.globl	_C_LABEL(darwin_commpage_mach_absolute_time)
_C_LABEL(darwin_commpage_mach_absolute_time):
1:	mftbu	%r3
	mftb	%r4
	mftbu	%r5
	cmpw	%r3,%r5
	bne-	1b
	blr
	.globl	_C_LABEL(darwin_commpage_mach_absolute_time_size)
_C_LABEL(darwin_commpage_mach_absolute_time_size) = .-_C_LABEL(darwin_commpage_mach_absolute_time)

/*
 *	 void sys_dcache_flush(char *addr, size_t len);
 *
 * XXX these routines are fine on G3/G4, but on a G5 a different
 * routine should be used that has a 128-byte cache size
 */
	.globl	_C_LABEL(darwin_commpage_sys_dcache_flush)
_C_LABEL(darwin_commpage_sys_dcache_flush):
1:	dcbf	0,%r3
	addi	%r3,%r3,32	/* CACHELINESIZE */
	addic.	%r4,%r4,-32	/* len -= CACHELINESIZE */
	bgt	1b
	sync
	blr
	.globl	_C_LABEL(darwin_commpage_sys_dcache_flush_size)
_C_LABEL(darwin_commpage_sys_dcache_flush_size) = .-_C_LABEL(darwin_commpage_sys_dcache_flush)

/* 
 *	void sys_icache_invalidate(char *addr, size_t len) 
 */
	.globl	_C_LABEL(darwin_commpage_sys_icache_invalidate)
_C_LABEL(darwin_commpage_sys_icache_invalidate):
	mr	%r5,%r3
	mr	%r6,%r4
	mflr	%r7
	bla	0xffff84e0	/* Absolute branch to dcache_flush */
	mtlr	%r7
1:	icbi	0,%r5
	addi	%r5,%r5,32	/* CACHELINESIZE */
	addic.	%r6,%r6,-32	/* len -= CACHELINESIZE */
	bgt	1b
	isync
	blr
	.globl	_C_LABEL(darwin_commpage_sys_icache_invalidate_size)
_C_LABEL(darwin_commpage_sys_icache_invalidate_size) = .-_C_LABEL(darwin_commpage_sys_icache_invalidate)

/* 
 *	int spinlock_try(int *p) 
 */
	.globl	_C_LABEL(darwin_commpage_spinlock_try)
_C_LABEL(darwin_commpage_spinlock_try):
	li	%r4,1
	lwarx	%r5,0,%r3
	cmpwi	%r5,0
	bne-	2f
/*
 * OSX seems to store the address of the lock here. i.e. the equivalent of
 *	stwcx.	r3,0,r3 !!!
 */
	stwcx.	%r4,0,%r3
	bne-	2f
	mr	%r3,%r4
	isync
	blr
2:	li	%r3,0
	blr
	.globl	_C_LABEL(darwin_commpage_spinlock_try_size)
_C_LABEL(darwin_commpage_spinlock_try_size) = .-_C_LABEL(darwin_commpage_spinlock_try)

/* 
 *	void spinlock_lock(int *p) 
 */
	.globl	_C_LABEL(darwin_commpage_spinlock_lock)
_C_LABEL(darwin_commpage_spinlock_lock):
	mr	%r6,%r3	/* copy *p - r6/r7/r8 used for temps */
	li	%r7,1
1:	lwarx	%r8,0,%r6
	cmpwi	%r8,0
	bnea-	0xffff85c0	/* Absolute branch to spinlock_relinquish */
/*
 * OSX seems to store the address of the lock here. i.e. the equivalent of
 *	stwcx.	r6,0,r3 !!!
 */
	stwcx.	%r7,0,%r6
	bnea-	0xffff85c0	/* Absolute branch to spinlock_relinquish */
	isync
	blr
	.globl	_C_LABEL(darwin_commpage_spinlock_lock_size)
_C_LABEL(darwin_commpage_spinlock_lock_size) = .-_C_LABEL(darwin_commpage_spinlock_lock)

/* 
 *	void spinlock_unlock(int *p) 
 */
	.globl	_C_LABEL(darwin_commpage_spinlock_unlock)
_C_LABEL(darwin_commpage_spinlock_unlock):
	sync
	li	%r4,0
	stw	%r4,0(%r3)
	blr
	.globl	_C_LABEL(darwin_commpage_spinlock_unlock_size)
_C_LABEL(darwin_commpage_spinlock_unlock_size) = .-_C_LABEL(darwin_commpage_spinlock_unlock)

/* 
 *	int spinlock_relinquish(int *p) 
 */
	.globl	_C_LABEL(darwin_commpage_spinlock_relinquish)
_C_LABEL(darwin_commpage_spinlock_relinquish):
	mr	%r6,%r3
	li	%r3,0		/* THREAD_NULL */
	li	%r4,1		/* MACH_SWITCH_OPTION_DEPRESS */
	li	%r5,1		/* 1ms */
	li 	%r0,-MACH_SYS_syscall_thread_switch
	sc
	mr	%r3,%r6
	ba	0xffff8260		/* Absolute branch to spin_lock */
	.globl	_C_LABEL(darwin_commpage_spinlock_relinquish_size)
_C_LABEL(darwin_commpage_spinlock_relinquish_size) = .-_C_LABEL(darwin_commpage_spinlock_relinquish)