1/* $NetBSD: lock_cas.S,v 1.14 2019/12/08 10:12:19 skrll Exp $ */ 2 3/*- 4 * Copyright (c) 2007 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include "opt_arm_debug.h" 33 34#include "assym.h" 35 36#include <machine/asm.h> 37 38#include <arm/locore.h> 39 40 .text 41 .align 0 42 43#if defined(ARM_LOCK_CAS_DEBUG) 44.L_lock_cas_success: 45 .word _C_LABEL(_lock_cas_success) 46.L_lock_cas_fail: 47 .word _C_LABEL(_lock_cas_fail) 48#endif /* ARM_LOCK_CAS_DEBUG */ 49 50#ifndef _ARM_ARCH_6 51/* 52 * _lock_cas: 53 * 54 * Perform an atomic compare-and-swap operation. 55 * 56 * ARM doesn't have a compare-and-swap, so this is implemented 57 * as a restartable atomic sequence. See irq_dispatch.S. 58 * 59 * Returns the old value whether or not the swap happened. 60 * 61 * r0 Address of interest. 62 * r1 Old value to compare. 63 * r2 New value. 64 */ 65 .globl _C_LABEL(_lock_cas_end) 66ENTRY_NP(_lock_cas) 67 ldr r3, [r0] 68 teq r3, r1 69 streq r2, [r0] 70_C_LABEL(_lock_cas_end): 71 mov r0, r3 72#if defined(ARM_LOCK_CAS_DEBUG) 73 ldreq r3, .L_lock_cas_success 74 ldrne r3, .L_lock_cas_fail 75 ldmia r3, {r1-r2} /* load ev_count */ 76#if defined(__ARMEB__) 77 adds r2, r2, #1 /* 64-bit incr (lo) */ 78 adc r1, r1, #0 /* 64-bit incr (hi) */ 79#else 80 adds r1, r1, #1 /* 64-bit incr (lo) */ 81 adc r2, r2, #0 /* 64-bit incr (hi) */ 82#endif /* __ARMEB__ */ 83 stmia r3, {r1-r2} /* store ev_count */ 84#endif /* ARM_LOCK_CAS_DEBUG */ 85 RET 86END(_lock_cas) 87 88STRONG_ALIAS(_atomic_cas_ulong,_lock_cas) 89STRONG_ALIAS(atomic_cas_ulong,_lock_cas) 90STRONG_ALIAS(_atomic_cas_32,_lock_cas) 91STRONG_ALIAS(atomic_cas_32,_lock_cas) 92STRONG_ALIAS(_atomic_cas_uint,_lock_cas) 93STRONG_ALIAS(atomic_cas_uint,_lock_cas) 94STRONG_ALIAS(_atomic_cas_ptr,_lock_cas) 95STRONG_ALIAS(atomic_cas_ptr,_lock_cas) 96 97STRONG_ALIAS(_atomic_cas_ulong_ni,_lock_cas) 98STRONG_ALIAS(atomic_cas_ulong_ni,_lock_cas) 99STRONG_ALIAS(_atomic_cas_32_ni,_lock_cas) 100STRONG_ALIAS(atomic_cas_32_ni,_lock_cas) 101STRONG_ALIAS(_atomic_cas_uint_ni,_lock_cas) 102STRONG_ALIAS(atomic_cas_uint_ni,_lock_cas) 103STRONG_ALIAS(_atomic_cas_ptr_ni,_lock_cas) 104STRONG_ALIAS(atomic_cas_ptr_ni,_lock_cas) 105#endif /* !_ARM_ARCH_6 */ 106 107#define SAVE_REGS push {r4-r5} 108#define RESTORE_REGS pop {r4-r5} 109 110#ifdef _ARM_ARCH_6 111/* 112 * int _ucas_32_mp(volatile uint32_t *uptr, uint32_t old, uint32_t new, 113 * uint32_t *ret); 114 */ 115ENTRY(_ucas_32_mp) 116 SAVE_REGS 117 GET_CURPCB(r4) 118 adr r5, .Lucasfault 119 str r5, [r4, #PCB_ONFAULT] 120 mov ip, r0 /* ip = uptr */ 121 1221: ldrex r5, [ip] /* we should have access */ 123 cmp r1, r5 124 bne 2f 125 strex r0, r2, [ip] 126 cmp r0, #0 127 bne 1b 1282: 129 str r5, [r3] 130 mov r0, #0 /* return value in case of miscompare */ 131.Lucasfault: 132 movs r3, #0 133 str r3, [r4, #PCB_ONFAULT] 134 RESTORE_REGS 135 RET 136END(_ucas_32_mp) 137#endif /* _ARM_ARCH_6 */ 138