Home | History | Annotate | Line # | Download | only in atomic
atomic.S revision 1.15
      1 /*	$NetBSD: atomic.S,v 1.15 2009/11/26 07:40:34 pooka 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, and by Andrew Doran.
      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 <sys/param.h>
     33 #include <machine/asm.h>
     34 
     35 #ifdef _KERNEL
     36 #define	ALIAS(f, t)	STRONG_ALIAS(f,t)
     37 #else
     38 #define	ALIAS(f, t)	WEAK_ALIAS(f,t)
     39 #endif
     40 
     41 #ifdef _HARDKERNEL
     42 #define	LOCK(n)		.Lpatch/**/n:	lock
     43 #define	ENDLABEL(a)	_ALIGN_TEXT; LABEL(a)
     44 #else
     45 #define	LOCK(n)		lock
     46 #define	ENDLABEL(a)	/* nothing */
     47 #endif
     48 
     49 	.text
     50 
     51 /* 32-bit */
     52 
     53 ENTRY(_atomic_add_32)
     54 	LOCK(1)
     55 	addl	%esi, (%rdi)
     56 	ret
     57 
     58 ENTRY(_atomic_add_32_nv)
     59 	movl	%esi, %eax
     60 	LOCK(2)
     61 	xaddl	%eax, (%rdi)
     62 	addl	%esi, %eax
     63 	ret
     64 
     65 ENTRY(_atomic_and_32)
     66 	LOCK(3)
     67 	andl	%esi, (%rdi)
     68 	ret
     69 
     70 ENTRY(_atomic_and_32_nv)
     71 	movl	(%rdi), %eax
     72 1:
     73 	movl	%eax, %ecx
     74 	andl	%esi, %ecx
     75 	LOCK(4)
     76 	cmpxchgl %ecx, (%rdi)
     77 	jnz	1b
     78 	movl	%ecx, %eax
     79 	ret
     80 
     81 ENTRY(_atomic_dec_32)
     82 	LOCK(5)
     83 	decl	(%rdi)
     84 	ret
     85 
     86 ENTRY(_atomic_dec_32_nv)
     87 	movl	$-1, %eax
     88 	LOCK(6)
     89 	xaddl	%eax, (%rdi)
     90 	decl	%eax
     91 	ret
     92 
     93 ENTRY(_atomic_inc_32)
     94 	LOCK(7)
     95 	incl	(%rdi)
     96 	ret
     97 
     98 ENTRY(_atomic_inc_32_nv)
     99 	movl	$1, %eax
    100 	LOCK(8)
    101 	xaddl	%eax, (%rdi)
    102 	incl	%eax
    103 	ret
    104 
    105 ENTRY(_atomic_or_32)
    106 	LOCK(9)
    107 	orl	%esi, (%rdi)
    108 	ret
    109 
    110 ENTRY(_atomic_or_32_nv)
    111 	movl	(%rdi), %eax
    112 1:
    113 	movl	%eax, %ecx
    114 	orl	%esi, %ecx
    115 	LOCK(10)
    116 	cmpxchgl %ecx, (%rdi)
    117 	jnz	1b
    118 	movl	%ecx, %eax
    119 	ret
    120 
    121 ENTRY(_atomic_swap_32)
    122 	movl	%esi, %eax
    123 	xchgl	%eax, (%rdi)
    124 	ret
    125 
    126 ENTRY(_atomic_cas_32)
    127 	movl	%esi, %eax
    128 	LOCK(12)
    129 	cmpxchgl %edx, (%rdi)
    130 	/* %eax now contains the old value */
    131 	ret
    132 
    133 ENTRY(_atomic_cas_32_ni)
    134 	movl	%esi, %eax
    135 	cmpxchgl %edx, (%rdi)
    136 	/* %eax now contains the old value */
    137 	ret
    138 
    139 /* 64-bit */
    140 
    141 ENTRY(_atomic_add_64)
    142 	LOCK(13)
    143 	addq	%rsi, (%rdi)
    144 	ret
    145 
    146 ENTRY(_atomic_add_64_nv)
    147 	movq	%rsi, %rax
    148 	LOCK(14)
    149 	xaddq	%rax, (%rdi)
    150 	addq	%rsi, %rax
    151 	ret
    152 
    153 ENTRY(_atomic_and_64)
    154 	LOCK(15)
    155 	andq	%rsi, (%rdi)
    156 	ret
    157 
    158 ENTRY(_atomic_and_64_nv)
    159 	movq	(%rdi), %rax
    160 1:
    161 	movq	%rax, %rcx
    162 	andq	%rsi, %rcx
    163 	LOCK(16)
    164 	cmpxchgq %rcx, (%rdi)
    165 	jnz	1b
    166 	movq	%rcx, %rax
    167 	ret
    168 
    169 ENTRY(_atomic_dec_64)
    170 	LOCK(17)
    171 	decq	(%rdi)
    172 	ret
    173 
    174 ENTRY(_atomic_dec_64_nv)
    175 	movq	$-1, %rax
    176 	LOCK(18)
    177 	xaddq	%rax, (%rdi)
    178 	decq	%rax
    179 	ret
    180 
    181 ENTRY(_atomic_inc_64)
    182 	LOCK(19)
    183 	incq	(%rdi)
    184 	ret
    185 
    186 ENTRY(_atomic_inc_64_nv)
    187 	movq	$1, %rax
    188 	LOCK(20)
    189 	xaddq	%rax, (%rdi)
    190 	incq	%rax
    191 	ret
    192 
    193 ENTRY(_atomic_or_64)
    194 	LOCK(21)
    195 	orq	%rsi, (%rdi)
    196 	ret
    197 
    198 ENTRY(_atomic_or_64_nv)
    199 	movq	(%rdi), %rax
    200 1:
    201 	movq	%rax, %rcx
    202 	orq	%rsi, %rcx
    203 	LOCK(22)
    204 	cmpxchgq %rcx, (%rdi)
    205 	jnz	1b
    206 	movq	%rcx, %rax
    207 	ret
    208 
    209 ENTRY(_atomic_swap_64)
    210 	movq	%rsi, %rax
    211 	xchgq	%rax, (%rdi)
    212 	ret
    213 
    214 ENTRY(_atomic_cas_64)
    215 	movq	%rsi, %rax
    216 	LOCK(24)
    217 	cmpxchgq %rdx, (%rdi)
    218 	/* %eax now contains the old value */
    219 	ret
    220 
    221 ENTRY(_atomic_cas_64_ni)
    222 	movq	%rsi, %rax
    223 	cmpxchgq %rdx, (%rdi)
    224 	/* %eax now contains the old value */
    225 	ret
    226 
    227 /* memory barriers */
    228 
    229 ENTRY(_membar_consumer)
    230 	LOCK(25)
    231 	addq	$0, -8(%rsp)
    232 	ret
    233 ENDLABEL(membar_consumer_end)
    234 
    235 ENTRY(_membar_producer)
    236 	/* A store is enough */
    237 	movq	$0, -8(%rsp)
    238 	ret
    239 ENDLABEL(membar_producer_end)
    240 
    241 ENTRY(_membar_sync)
    242 	LOCK(26)
    243 	addq	$0, -8(%rsp)
    244 	ret
    245 ENDLABEL(membar_sync_end)
    246 
    247 #ifdef _HARDKERNEL
    248 ENTRY(sse2_lfence)
    249 	lfence
    250 	ret
    251 ENDLABEL(sse2_lfence_end)
    252 
    253 ENTRY(sse2_mfence)
    254 	mfence
    255 	ret
    256 ENDLABEL(sse2_mfence_end)
    257 
    258 atomic_lockpatch:
    259 	.globl	atomic_lockpatch
    260 	.quad	.Lpatch1, .Lpatch2, .Lpatch3, .Lpatch4, .Lpatch5
    261 	.quad	.Lpatch6, .Lpatch7, .Lpatch8, .Lpatch9, .Lpatch10
    262 	.quad	.Lpatch12, .Lpatch13, .Lpatch14, .Lpatch15
    263 	.quad	.Lpatch16, .Lpatch17, .Lpatch18, .Lpatch19, .Lpatch20
    264 	.quad	.Lpatch21, .Lpatch22, .Lpatch24, .Lpatch25
    265 	.quad	.Lpatch26, 0
    266 #endif	/* _HARDKERNEL */
    267 
    268 ALIAS(atomic_add_32,_atomic_add_32)
    269 ALIAS(atomic_add_64,_atomic_add_64)
    270 ALIAS(atomic_add_int,_atomic_add_32)
    271 ALIAS(atomic_add_long,_atomic_add_64)
    272 ALIAS(atomic_add_ptr,_atomic_add_64)
    273 
    274 ALIAS(atomic_add_32_nv,_atomic_add_32_nv)
    275 ALIAS(atomic_add_64_nv,_atomic_add_64_nv)
    276 ALIAS(atomic_add_int_nv,_atomic_add_32_nv)
    277 ALIAS(atomic_add_long_nv,_atomic_add_64_nv)
    278 ALIAS(atomic_add_ptr_nv,_atomic_add_64_nv)
    279 
    280 ALIAS(atomic_and_32,_atomic_and_32)
    281 ALIAS(atomic_and_64,_atomic_and_64)
    282 ALIAS(atomic_and_uint,_atomic_and_32)
    283 ALIAS(atomic_and_ulong,_atomic_and_64)
    284 ALIAS(atomic_and_ptr,_atomic_and_64)
    285 
    286 ALIAS(atomic_and_32_nv,_atomic_and_32_nv)
    287 ALIAS(atomic_and_64_nv,_atomic_and_64_nv)
    288 ALIAS(atomic_and_uint_nv,_atomic_and_32_nv)
    289 ALIAS(atomic_and_ulong_nv,_atomic_and_64_nv)
    290 ALIAS(atomic_and_ptr_nv,_atomic_and_64_nv)
    291 
    292 ALIAS(atomic_dec_32,_atomic_dec_32)
    293 ALIAS(atomic_dec_64,_atomic_dec_64)
    294 ALIAS(atomic_dec_uint,_atomic_dec_32)
    295 ALIAS(atomic_dec_ulong,_atomic_dec_64)
    296 ALIAS(atomic_dec_ptr,_atomic_dec_64)
    297 
    298 ALIAS(atomic_dec_32_nv,_atomic_dec_32_nv)
    299 ALIAS(atomic_dec_64_nv,_atomic_dec_64_nv)
    300 ALIAS(atomic_dec_uint_nv,_atomic_dec_32_nv)
    301 ALIAS(atomic_dec_ulong_nv,_atomic_dec_64_nv)
    302 ALIAS(atomic_dec_ptr_nv,_atomic_dec_64_nv)
    303 
    304 ALIAS(atomic_inc_32,_atomic_inc_32)
    305 ALIAS(atomic_inc_64,_atomic_inc_64)
    306 ALIAS(atomic_inc_uint,_atomic_inc_32)
    307 ALIAS(atomic_inc_ulong,_atomic_inc_64)
    308 ALIAS(atomic_inc_ptr,_atomic_inc_64)
    309 
    310 ALIAS(atomic_inc_32_nv,_atomic_inc_32_nv)
    311 ALIAS(atomic_inc_64_nv,_atomic_inc_64_nv)
    312 ALIAS(atomic_inc_uint_nv,_atomic_inc_32_nv)
    313 ALIAS(atomic_inc_ulong_nv,_atomic_inc_64_nv)
    314 ALIAS(atomic_inc_ptr_nv,_atomic_inc_64_nv)
    315 
    316 ALIAS(atomic_or_32,_atomic_or_32)
    317 ALIAS(atomic_or_uint,_atomic_or_32)
    318 ALIAS(atomic_or_ulong,_atomic_or_64)
    319 ALIAS(atomic_or_ptr,_atomic_or_64)
    320 
    321 ALIAS(atomic_or_32_nv,_atomic_or_32_nv)
    322 ALIAS(atomic_or_64_nv,_atomic_or_64_nv)
    323 ALIAS(atomic_or_uint_nv,_atomic_or_32_nv)
    324 ALIAS(atomic_or_ulong_nv,_atomic_or_64_nv)
    325 ALIAS(atomic_or_ptr_nv,_atomic_or_64_nv)
    326 
    327 ALIAS(atomic_swap_32,_atomic_swap_32)
    328 ALIAS(atomic_swap_64,_atomic_swap_64)
    329 ALIAS(atomic_swap_uint,_atomic_swap_32)
    330 ALIAS(atomic_swap_ulong,_atomic_swap_64)
    331 ALIAS(atomic_swap_ptr,_atomic_swap_64)
    332 
    333 ALIAS(atomic_cas_32,_atomic_cas_32)
    334 ALIAS(atomic_cas_64,_atomic_cas_64)
    335 ALIAS(atomic_cas_uint,_atomic_cas_32)
    336 ALIAS(atomic_cas_ulong,_atomic_cas_64)
    337 ALIAS(atomic_cas_ptr,_atomic_cas_64)
    338 
    339 ALIAS(atomic_cas_32_ni,_atomic_cas_32_ni)
    340 ALIAS(atomic_cas_64_ni,_atomic_cas_64_ni)
    341 ALIAS(atomic_cas_uint_ni,_atomic_cas_32_ni)
    342 ALIAS(atomic_cas_ulong_ni,_atomic_cas_64_ni)
    343 ALIAS(atomic_cas_ptr_ni,_atomic_cas_64_ni)
    344 
    345 ALIAS(membar_consumer,_membar_consumer)
    346 ALIAS(membar_producer,_membar_producer)
    347 ALIAS(membar_enter,_membar_consumer)
    348 ALIAS(membar_exit,_membar_producer)
    349 ALIAS(membar_sync,_membar_sync)
    350 
    351 STRONG_ALIAS(_atomic_add_int,_atomic_add_32)
    352 STRONG_ALIAS(_atomic_add_long,_atomic_add_64)
    353 STRONG_ALIAS(_atomic_add_ptr,_atomic_add_64)
    354 
    355 STRONG_ALIAS(_atomic_add_int_nv,_atomic_add_32_nv)
    356 STRONG_ALIAS(_atomic_add_long_nv,_atomic_add_64_nv)
    357 STRONG_ALIAS(_atomic_add_ptr_nv,_atomic_add_64_nv)
    358 
    359 STRONG_ALIAS(_atomic_and_uint,_atomic_and_32)
    360 STRONG_ALIAS(_atomic_and_ulong,_atomic_and_64)
    361 STRONG_ALIAS(_atomic_and_ptr,_atomic_and_64)
    362 
    363 STRONG_ALIAS(_atomic_and_uint_nv,_atomic_and_32_nv)
    364 STRONG_ALIAS(_atomic_and_ulong_nv,_atomic_and_64_nv)
    365 STRONG_ALIAS(_atomic_and_ptr_nv,_atomic_and_64_nv)
    366 
    367 STRONG_ALIAS(_atomic_dec_uint,_atomic_dec_32)
    368 STRONG_ALIAS(_atomic_dec_ulong,_atomic_dec_64)
    369 STRONG_ALIAS(_atomic_dec_ptr,_atomic_dec_64)
    370 
    371 STRONG_ALIAS(_atomic_dec_uint_nv,_atomic_dec_32_nv)
    372 STRONG_ALIAS(_atomic_dec_ulong_nv,_atomic_dec_64_nv)
    373 STRONG_ALIAS(_atomic_dec_ptr_nv,_atomic_dec_64_nv)
    374 
    375 STRONG_ALIAS(_atomic_inc_uint,_atomic_inc_32)
    376 STRONG_ALIAS(_atomic_inc_ulong,_atomic_inc_64)
    377 STRONG_ALIAS(_atomic_inc_ptr,_atomic_inc_64)
    378 
    379 STRONG_ALIAS(_atomic_inc_uint_nv,_atomic_inc_32_nv)
    380 STRONG_ALIAS(_atomic_inc_ulong_nv,_atomic_inc_64_nv)
    381 STRONG_ALIAS(_atomic_inc_ptr_nv,_atomic_inc_64_nv)
    382 
    383 STRONG_ALIAS(_atomic_or_uint,_atomic_or_32)
    384 STRONG_ALIAS(_atomic_or_ulong,_atomic_or_64)
    385 STRONG_ALIAS(_atomic_or_ptr,_atomic_or_64)
    386 
    387 STRONG_ALIAS(_atomic_or_uint_nv,_atomic_or_32_nv)
    388 STRONG_ALIAS(_atomic_or_ulong_nv,_atomic_or_64_nv)
    389 STRONG_ALIAS(_atomic_or_ptr_nv,_atomic_or_64_nv)
    390 
    391 STRONG_ALIAS(_atomic_swap_uint,_atomic_swap_32)
    392 STRONG_ALIAS(_atomic_swap_ulong,_atomic_swap_64)
    393 STRONG_ALIAS(_atomic_swap_ptr,_atomic_swap_64)
    394 
    395 STRONG_ALIAS(_atomic_cas_uint,_atomic_cas_32)
    396 STRONG_ALIAS(_atomic_cas_ulong,_atomic_cas_64)
    397 STRONG_ALIAS(_atomic_cas_ptr,_atomic_cas_64)
    398 
    399 STRONG_ALIAS(_atomic_cas_uint_ni,_atomic_cas_32_ni)
    400 STRONG_ALIAS(_atomic_cas_ulong_ni,_atomic_cas_64_ni)
    401 STRONG_ALIAS(_atomic_cas_ptr_ni,_atomic_cas_64_ni)
    402 
    403 STRONG_ALIAS(_membar_enter,_membar_consumer)
    404 STRONG_ALIAS(_membar_exit,_membar_producer)
    405