1*016e43caSmatt/*	$NetBSD: atomic_cas_64.S,v 1.3 2013/08/10 19:59:21 matt Exp $	*/
24e0ad64aSmatt/*-
34e0ad64aSmatt * Copyright (c) 2012 The NetBSD Foundation, Inc.
44e0ad64aSmatt * All rights reserved.
54e0ad64aSmatt *
64e0ad64aSmatt * This code is derived from software contributed to The NetBSD Foundation
74e0ad64aSmatt * by Matt Thomas <matt@3am-software.com>
84e0ad64aSmatt *
94e0ad64aSmatt * Redistribution and use in source and binary forms, with or without
104e0ad64aSmatt * modification, are permitted provided that the following conditions
114e0ad64aSmatt * are met:
124e0ad64aSmatt * 1. Redistributions of source code must retain the above copyright
134e0ad64aSmatt *    notice, this list of conditions and the following disclaimer.
144e0ad64aSmatt * 2. Redistributions in binary form must reproduce the above copyright
154e0ad64aSmatt *    notice, this list of conditions and the following disclaimer in the
164e0ad64aSmatt *    documentation and/or other materials provided with the distribution.
174e0ad64aSmatt *
184e0ad64aSmatt * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
194e0ad64aSmatt * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
204e0ad64aSmatt * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
214e0ad64aSmatt * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
224e0ad64aSmatt * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
234e0ad64aSmatt * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
244e0ad64aSmatt * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
254e0ad64aSmatt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
264e0ad64aSmatt * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
274e0ad64aSmatt * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
284e0ad64aSmatt * POSSIBILITY OF SUCH DAMAGE.
294e0ad64aSmatt */
304e0ad64aSmatt
314e0ad64aSmatt#include "atomic_op_asm.h"
324e0ad64aSmatt
334e0ad64aSmatt#if defined(_ARM_ARCH_6)
344e0ad64aSmatt/*
354e0ad64aSmatt * ARMv6 has load-exclusive/store-exclusive which works for both user
364e0ad64aSmatt * and kernel.
374e0ad64aSmatt */
384e0ad64aSmattENTRY_NP(_atomic_cas_64)
39*016e43caSmatt	push	{r4, r5, r6}		/* save temporaries */
40*016e43caSmatt	mov	ip, r0			/* we need r0 for return value */
414e0ad64aSmatt#ifdef __ARM_EABI__
424e0ad64aSmatt	ldrd	r4, [sp]		/* fetch new value */
434e0ad64aSmatt#else
444e0ad64aSmatt	ldr	r4, [sp, #0]		/* fetch new value */
45*016e43caSmatt	ldr	r5, [sp, #4]		/* fetch new value */
464e0ad64aSmatt	mov	r3, r2			/* r2 will be overwritten by r1 which ... */
474e0ad64aSmatt	mov	r2, r1			/* r1 will be overwritten by ldrexd */
484e0ad64aSmatt#endif
494e0ad64aSmatt1:
50*016e43caSmatt	ldrexd	r0, [ip]		/* load current value */
51*016e43caSmatt	cmp	r0, r2			/*   compare to old? 1st half */
52*016e43caSmatt#ifdef __thumb__
534e0ad64aSmatt	bne	2f			/*     jump to return if different */
54*016e43caSmatt	cmp	r1, r3			/*   compare to old? 2nd half */
55*016e43caSmatt#else
56*016e43caSmatt	cmpeq	r1, r3			/*   compare to old? 2nd half */
57*016e43caSmatt#endif
58*016e43caSmatt	bne	2f			/*     jump to return if different */
59*016e43caSmatt	strexd	r6, r4, [ip]		/* store new value */
60*016e43caSmatt	cmp	r6, #0			/*   succeed? */
614e0ad64aSmatt	bne	1b			/*     nope, try again. */
624e0ad64aSmatt#ifdef _ARM_ARCH_7
634e0ad64aSmatt	dsb
644e0ad64aSmatt#else
654e0ad64aSmatt	mcr	p15, 0, ip, c7, c10, 4	/* data synchronization barrier */
664e0ad64aSmatt#endif
674e0ad64aSmatt2:
68*016e43caSmatt	pop	{r4, r5, r6}		/* restore temporaries */
694e0ad64aSmatt	RET				/* return. */
704e0ad64aSmattEND(_atomic_cas_64)
714e0ad64aSmatt
724e0ad64aSmattATOMIC_OP_ALIAS(atomic_cas_64,_atomic_cas_64)
734e0ad64aSmatt
74fe7beba6Schs#endif /* _ARM_ARCH_6 */
75