/*
 * |-----------------------------------------------------------|
 * | Copyright (c) 1991, 1990 MIPS Computer Systems, Inc.      |
 * | All Rights Reserved                                       |
 * |-----------------------------------------------------------|
 * |          Restricted Rights Legend                         |
 * | Use, duplication, or disclosure by the Government is      |
 * | subject to restrictions as set forth in                   |
 * | subparagraph (c)(1)(ii) of the Rights in Technical        |
 * | Data and Computer Software Clause of DFARS 252.227-7013.  |
 * |         MIPS Computer Systems, Inc.                       |
 * |         950 DeGuigne Avenue                               |
 * |         Sunnyvale, California 94088-3650, USA             |
 * |-----------------------------------------------------------|
 */
#ident "$Header: test_and_set.s,v 1.4.1.1 92/06/24 14:02:51 marker Exp $"

#include <sys/regdef.h>
#if defined (SYSTYPE_BSD43)
#include <asm.h>
#else
#include <sys/asm.h>
#endif
#if defined (SYSTYPE_SYSV)
#include "sys/syscall.h"
#include <sys.s>
#include "sys/sysmips.h"
#else if (defined (SYSTYPE_BSD43) || defined (_SYSTYPE_SVR4))
#define SYS_sysmips	(50+1000)
#include "sysv/sys/sysmips.h"
#endif

/*
 * a0 has address, a1 has value.  
 */
LEAF(_test_and_set)
	
	.set 	noreorder
	li	v0,-2
	bgezl	v0,ret
	addi	v0,1
	addi	v0,1
ret:
	/*
	 * If v0 has been incremented twice, then the branch wasn't
	 * taken and this is mips1 instructions.
	 */
	beqz	v0,mipsi
	nop
mipsii:
	/*
	 * If mips 2, use the load-locked and store-conditional instructions
	 */
	ll	v0,(a0)
	move	t0,a1
	sc	t0,(a0)
	beqz	t0,mipsii
	nop
	b	9f
	.set	reorder
mipsi:
/* 
 * If mips1, perform the test_and_set sysmips call.
 * test_and_set(addr,value) ==> syscall(SYS_sysmips,MIPS_ATOMIC_SET,addr,value)
 */
	move	a3,zero
	move	a2,a1
	move	a1,a0
	li	a0,MIPS_ATOMIC_SET
	li	v0,SYS_sysmips 
	syscall 
	beq	a3,zero,9f
	j	__cerror
9:
	j	ra
	.end _test_and_set
