1/* $NetBSD: atomic.S,v 1.19 2011/01/12 23:12:10 joerg 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 51ENTRY(_atomic_add_32) 52 movl 4(%esp), %edx 53 movl 8(%esp), %eax 54 LOCK(1) 55 addl %eax, (%edx) 56 ret 57 58ENTRY(_atomic_add_32_nv) 59 movl 4(%esp), %edx 60 movl 8(%esp), %eax 61 movl %eax, %ecx 62 LOCK(2) 63 xaddl %eax, (%edx) 64 addl %ecx, %eax 65 ret 66 67ENTRY(_atomic_and_32) 68 movl 4(%esp), %edx 69 movl 8(%esp), %eax 70 LOCK(3) 71 andl %eax, (%edx) 72 ret 73 74ENTRY(_atomic_and_32_nv) 75 movl 4(%esp), %edx 76 movl (%edx), %eax 770: 78 movl %eax, %ecx 79 andl 8(%esp), %ecx 80 LOCK(4) 81 cmpxchgl %ecx, (%edx) 82 jnz 1f 83 movl %ecx, %eax 84 ret 851: 86 jmp 0b 87 88ENTRY(_atomic_dec_32) 89 movl 4(%esp), %edx 90 LOCK(5) 91 decl (%edx) 92 ret 93 94ENTRY(_atomic_dec_32_nv) 95 movl 4(%esp), %edx 96 movl $-1, %eax 97 LOCK(6) 98 xaddl %eax, (%edx) 99 decl %eax 100 ret 101 102ENTRY(_atomic_inc_32) 103 movl 4(%esp), %edx 104 LOCK(7) 105 incl (%edx) 106 ret 107 108ENTRY(_atomic_inc_32_nv) 109 movl 4(%esp), %edx 110 movl $1, %eax 111 LOCK(8) 112 xaddl %eax, (%edx) 113 incl %eax 114 ret 115 116ENTRY(_atomic_or_32) 117 movl 4(%esp), %edx 118 movl 8(%esp), %eax 119 LOCK(9) 120 orl %eax, (%edx) 121 ret 122 123ENTRY(_atomic_or_32_nv) 124 movl 4(%esp), %edx 125 movl (%edx), %eax 1260: 127 movl %eax, %ecx 128 orl 8(%esp), %ecx 129 LOCK(10) 130 cmpxchgl %ecx, (%edx) 131 jnz 1f 132 movl %ecx, %eax 133 ret 1341: 135 jmp 0b 136 137ENTRY(_atomic_swap_32) 138 movl 4(%esp), %edx 139 movl 8(%esp), %eax 140 xchgl %eax, (%edx) 141 ret 142 143ENTRY(_atomic_cas_32) 144 movl 4(%esp), %edx 145 movl 8(%esp), %eax 146 movl 12(%esp), %ecx 147 LOCK(12) 148 cmpxchgl %ecx, (%edx) 149 /* %eax now contains the old value */ 150 ret 151 152ENTRY(_atomic_cas_32_ni) 153 movl 4(%esp), %edx 154 movl 8(%esp), %eax 155 movl 12(%esp), %ecx 156 cmpxchgl %ecx, (%edx) 157 /* %eax now contains the old value */ 158 ret 159 160ENTRY(_membar_consumer) 161 LOCK(13) 162 addl $0, -4(%esp) 163 ret 164ENDLABEL(membar_consumer_end) 165 166ENTRY(_membar_producer) 167 /* A store is enough */ 168 movl $0, -4(%esp) 169 ret 170ENDLABEL(membar_producer_end) 171 172ENTRY(_membar_sync) 173 LOCK(14) 174 addl $0, -4(%esp) 175 ret 176ENDLABEL(membar_sync_end) 177 178#ifdef _HARDKERNEL 179ENTRY(_atomic_cas_64) 180 pushf 181 cli 182 pushl %edi 183 pushl %ebx 184 movl 12(%esp), %edi 185 movl 16(%esp), %eax 186 movl 20(%esp), %edx 187 movl 24(%esp), %ebx 188 movl 28(%esp), %ecx 189 cmpl 0(%edi), %eax 190 jne 2f 191 cmpl 4(%edi), %edx 192 jne 2f 193 movl %ebx, 0(%edi) 194 movl %ecx, 4(%edi) 1951: 196 popl %ebx 197 popl %edi 198 popf 199 ret 2002: 201 movl 0(%edi), %eax 202 movl 4(%edi), %edx 203 jmp 1b 204ENDLABEL(_atomic_cas_64_end) 205 206ENTRY(_atomic_cas_cx8) 207 pushl %edi 208 pushl %ebx 209 movl 12(%esp), %edi 210 movl 16(%esp), %eax 211 movl 20(%esp), %edx 212 movl 24(%esp), %ebx 213 movl 28(%esp), %ecx 214 LOCK(15) 215 cmpxchg8b (%edi) 216 popl %ebx 217 popl %edi 218 ret 219#ifdef GPROF 220 .space 16, 0x90 221#else 222 .space 32, 0x90 223#endif 224ENDLABEL(_atomic_cas_cx8_end) 225 226ENTRY(sse2_lfence) 227 lfence 228 ret 229ENDLABEL(sse2_lfence_end) 230 231ENTRY(sse2_mfence) 232 mfence 233 ret 234ENDLABEL(sse2_mfence_end) 235 236atomic_lockpatch: 237 .globl atomic_lockpatch 238 .long .Lpatch1, .Lpatch2, .Lpatch3, .Lpatch4, .Lpatch5 239 .long .Lpatch6, .Lpatch7, .Lpatch8, .Lpatch9, .Lpatch10 240 .long .Lpatch12, .Lpatch13, .Lpatch14, .Lpatch15, 0 241#else 242ENTRY(_atomic_cas_64) 243 pushl %edi 244 pushl %ebx 245 movl 12(%esp), %edi 246 movl 16(%esp), %eax 247 movl 20(%esp), %edx 248 movl 24(%esp), %ebx 249 movl 28(%esp), %ecx 250 lock 251 cmpxchg8b (%edi) 252 popl %ebx 253 popl %edi 254 ret 255#endif /* _HARDKERNEL */ 256 257ALIAS(atomic_add_32,_atomic_add_32) 258ALIAS(atomic_add_int,_atomic_add_32) 259ALIAS(atomic_add_long,_atomic_add_32) 260ALIAS(atomic_add_ptr,_atomic_add_32) 261 262ALIAS(atomic_add_32_nv,_atomic_add_32_nv) 263ALIAS(atomic_add_int_nv,_atomic_add_32_nv) 264ALIAS(atomic_add_long_nv,_atomic_add_32_nv) 265ALIAS(atomic_add_ptr_nv,_atomic_add_32_nv) 266 267ALIAS(atomic_and_32,_atomic_and_32) 268ALIAS(atomic_and_uint,_atomic_and_32) 269ALIAS(atomic_and_ulong,_atomic_and_32) 270ALIAS(atomic_and_ptr,_atomic_and_32) 271 272ALIAS(atomic_and_32_nv,_atomic_and_32_nv) 273ALIAS(atomic_and_uint_nv,_atomic_and_32_nv) 274ALIAS(atomic_and_ulong_nv,_atomic_and_32_nv) 275ALIAS(atomic_and_ptr_nv,_atomic_and_32_nv) 276 277ALIAS(atomic_dec_32,_atomic_dec_32) 278ALIAS(atomic_dec_uint,_atomic_dec_32) 279ALIAS(atomic_dec_ulong,_atomic_dec_32) 280ALIAS(atomic_dec_ptr,_atomic_dec_32) 281 282ALIAS(atomic_dec_32_nv,_atomic_dec_32_nv) 283ALIAS(atomic_dec_uint_nv,_atomic_dec_32_nv) 284ALIAS(atomic_dec_ulong_nv,_atomic_dec_32_nv) 285ALIAS(atomic_dec_ptr_nv,_atomic_dec_32_nv) 286 287ALIAS(atomic_inc_32,_atomic_inc_32) 288ALIAS(atomic_inc_uint,_atomic_inc_32) 289ALIAS(atomic_inc_ulong,_atomic_inc_32) 290ALIAS(atomic_inc_ptr,_atomic_inc_32) 291 292ALIAS(atomic_inc_32_nv,_atomic_inc_32_nv) 293ALIAS(atomic_inc_uint_nv,_atomic_inc_32_nv) 294ALIAS(atomic_inc_ulong_nv,_atomic_inc_32_nv) 295ALIAS(atomic_inc_ptr_nv,_atomic_inc_32_nv) 296 297ALIAS(atomic_or_32,_atomic_or_32) 298ALIAS(atomic_or_uint,_atomic_or_32) 299ALIAS(atomic_or_ulong,_atomic_or_32) 300ALIAS(atomic_or_ptr,_atomic_or_32) 301 302ALIAS(atomic_or_32_nv,_atomic_or_32_nv) 303ALIAS(atomic_or_uint_nv,_atomic_or_32_nv) 304ALIAS(atomic_or_ulong_nv,_atomic_or_32_nv) 305ALIAS(atomic_or_ptr_nv,_atomic_or_32_nv) 306 307ALIAS(atomic_swap_32,_atomic_swap_32) 308ALIAS(atomic_swap_uint,_atomic_swap_32) 309ALIAS(atomic_swap_ulong,_atomic_swap_32) 310ALIAS(atomic_swap_ptr,_atomic_swap_32) 311 312ALIAS(atomic_cas_32,_atomic_cas_32) 313ALIAS(atomic_cas_uint,_atomic_cas_32) 314ALIAS(atomic_cas_ulong,_atomic_cas_32) 315ALIAS(atomic_cas_ptr,_atomic_cas_32) 316 317ALIAS(atomic_cas_32_ni,_atomic_cas_32_ni) 318ALIAS(atomic_cas_uint_ni,_atomic_cas_32_ni) 319ALIAS(atomic_cas_ulong_ni,_atomic_cas_32_ni) 320ALIAS(atomic_cas_ptr_ni,_atomic_cas_32_ni) 321 322ALIAS(atomic_cas_64,_atomic_cas_64) 323ALIAS(atomic_cas_64_ni,_atomic_cas_64) 324 325ALIAS(membar_consumer,_membar_consumer) 326ALIAS(membar_producer,_membar_producer) 327ALIAS(membar_enter,_membar_consumer) 328ALIAS(membar_exit,_membar_producer) 329ALIAS(membar_sync,_membar_sync) 330 331STRONG_ALIAS(_atomic_add_int,_atomic_add_32) 332STRONG_ALIAS(_atomic_add_long,_atomic_add_32) 333STRONG_ALIAS(_atomic_add_ptr,_atomic_add_32) 334 335STRONG_ALIAS(_atomic_add_int_nv,_atomic_add_32_nv) 336STRONG_ALIAS(_atomic_add_long_nv,_atomic_add_32_nv) 337STRONG_ALIAS(_atomic_add_ptr_nv,_atomic_add_32_nv) 338 339STRONG_ALIAS(_atomic_and_uint,_atomic_and_32) 340STRONG_ALIAS(_atomic_and_ulong,_atomic_and_32) 341STRONG_ALIAS(_atomic_and_ptr,_atomic_and_32) 342 343STRONG_ALIAS(_atomic_and_uint_nv,_atomic_and_32_nv) 344STRONG_ALIAS(_atomic_and_ulong_nv,_atomic_and_32_nv) 345STRONG_ALIAS(_atomic_and_ptr_nv,_atomic_and_32_nv) 346 347STRONG_ALIAS(_atomic_dec_uint,_atomic_dec_32) 348STRONG_ALIAS(_atomic_dec_ulong,_atomic_dec_32) 349STRONG_ALIAS(_atomic_dec_ptr,_atomic_dec_32) 350 351STRONG_ALIAS(_atomic_dec_uint_nv,_atomic_dec_32_nv) 352STRONG_ALIAS(_atomic_dec_ulong_nv,_atomic_dec_32_nv) 353STRONG_ALIAS(_atomic_dec_ptr_nv,_atomic_dec_32_nv) 354 355STRONG_ALIAS(_atomic_inc_uint,_atomic_inc_32) 356STRONG_ALIAS(_atomic_inc_ulong,_atomic_inc_32) 357STRONG_ALIAS(_atomic_inc_ptr,_atomic_inc_32) 358 359STRONG_ALIAS(_atomic_inc_uint_nv,_atomic_inc_32_nv) 360STRONG_ALIAS(_atomic_inc_ulong_nv,_atomic_inc_32_nv) 361STRONG_ALIAS(_atomic_inc_ptr_nv,_atomic_inc_32_nv) 362 363STRONG_ALIAS(_atomic_or_uint,_atomic_or_32) 364STRONG_ALIAS(_atomic_or_ulong,_atomic_or_32) 365STRONG_ALIAS(_atomic_or_ptr,_atomic_or_32) 366 367STRONG_ALIAS(_atomic_or_uint_nv,_atomic_or_32_nv) 368STRONG_ALIAS(_atomic_or_ulong_nv,_atomic_or_32_nv) 369STRONG_ALIAS(_atomic_or_ptr_nv,_atomic_or_32_nv) 370 371STRONG_ALIAS(_atomic_swap_uint,_atomic_swap_32) 372STRONG_ALIAS(_atomic_swap_ulong,_atomic_swap_32) 373STRONG_ALIAS(_atomic_swap_ptr,_atomic_swap_32) 374 375STRONG_ALIAS(_atomic_cas_uint,_atomic_cas_32) 376STRONG_ALIAS(_atomic_cas_ulong,_atomic_cas_32) 377STRONG_ALIAS(_atomic_cas_ptr,_atomic_cas_32) 378 379STRONG_ALIAS(_atomic_cas_uint_ni,_atomic_cas_32_ni) 380STRONG_ALIAS(_atomic_cas_ulong_ni,_atomic_cas_32_ni) 381STRONG_ALIAS(_atomic_cas_ptr_ni,_atomic_cas_32_ni) 382 383STRONG_ALIAS(_membar_enter,_membar_consumer) 384STRONG_ALIAS(_membar_exit,_membar_producer) 385