1*5d9d9091SRichard Lowe/* 2*5d9d9091SRichard Lowe * CDDL HEADER START 3*5d9d9091SRichard Lowe * 4*5d9d9091SRichard Lowe * The contents of this file are subject to the terms of the 5*5d9d9091SRichard Lowe * Common Development and Distribution License (the "License"). 6*5d9d9091SRichard Lowe * You may not use this file except in compliance with the License. 7*5d9d9091SRichard Lowe * 8*5d9d9091SRichard Lowe * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*5d9d9091SRichard Lowe * or http://www.opensolaris.org/os/licensing. 10*5d9d9091SRichard Lowe * See the License for the specific language governing permissions 11*5d9d9091SRichard Lowe * and limitations under the License. 12*5d9d9091SRichard Lowe * 13*5d9d9091SRichard Lowe * When distributing Covered Code, include this CDDL HEADER in each 14*5d9d9091SRichard Lowe * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*5d9d9091SRichard Lowe * If applicable, add the following below this CDDL HEADER, with the 16*5d9d9091SRichard Lowe * fields enclosed by brackets "[]" replaced with your own identifying 17*5d9d9091SRichard Lowe * information: Portions Copyright [yyyy] [name of copyright owner] 18*5d9d9091SRichard Lowe * 19*5d9d9091SRichard Lowe * CDDL HEADER END 20*5d9d9091SRichard Lowe */ 21*5d9d9091SRichard Lowe 22*5d9d9091SRichard Lowe/* 23*5d9d9091SRichard Lowe * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24*5d9d9091SRichard Lowe * Use is subject to license terms. 25*5d9d9091SRichard Lowe */ 26*5d9d9091SRichard Lowe 27*5d9d9091SRichard Lowe .file "atomic.s" 28*5d9d9091SRichard Lowe 29*5d9d9091SRichard Lowe#include <sys/asm_linkage.h> 30*5d9d9091SRichard Lowe 31*5d9d9091SRichard Lowe#if defined(_KERNEL) 32*5d9d9091SRichard Lowe /* 33*5d9d9091SRichard Lowe * Legacy kernel interfaces; they will go away the moment our closed 34*5d9d9091SRichard Lowe * bins no longer require them. 35*5d9d9091SRichard Lowe */ 36*5d9d9091SRichard Lowe ANSI_PRAGMA_WEAK2(cas8,atomic_cas_8,function) 37*5d9d9091SRichard Lowe ANSI_PRAGMA_WEAK2(cas32,atomic_cas_32,function) 38*5d9d9091SRichard Lowe ANSI_PRAGMA_WEAK2(cas64,atomic_cas_64,function) 39*5d9d9091SRichard Lowe ANSI_PRAGMA_WEAK2(caslong,atomic_cas_ulong,function) 40*5d9d9091SRichard Lowe ANSI_PRAGMA_WEAK2(casptr,atomic_cas_ptr,function) 41*5d9d9091SRichard Lowe ANSI_PRAGMA_WEAK2(atomic_and_long,atomic_and_ulong,function) 42*5d9d9091SRichard Lowe ANSI_PRAGMA_WEAK2(atomic_or_long,atomic_or_ulong,function) 43*5d9d9091SRichard Lowe ANSI_PRAGMA_WEAK2(swapl,atomic_swap_32,function) 44*5d9d9091SRichard Lowe#endif 45*5d9d9091SRichard Lowe 46*5d9d9091SRichard Lowe /* 47*5d9d9091SRichard Lowe * NOTE: If atomic_inc_8 and atomic_inc_8_nv are ever 48*5d9d9091SRichard Lowe * separated, you need to also edit the libc sparc platform 49*5d9d9091SRichard Lowe * specific mapfile and remove the NODYNSORT attribute 50*5d9d9091SRichard Lowe * from atomic_inc_8_nv. 51*5d9d9091SRichard Lowe */ 52*5d9d9091SRichard Lowe ENTRY(atomic_inc_8) 53*5d9d9091SRichard Lowe ALTENTRY(atomic_inc_8_nv) 54*5d9d9091SRichard Lowe ALTENTRY(atomic_inc_uchar) 55*5d9d9091SRichard Lowe ALTENTRY(atomic_inc_uchar_nv) 56*5d9d9091SRichard Lowe ba add_8 57*5d9d9091SRichard Lowe add %g0, 1, %o1 58*5d9d9091SRichard Lowe SET_SIZE(atomic_inc_uchar_nv) 59*5d9d9091SRichard Lowe SET_SIZE(atomic_inc_uchar) 60*5d9d9091SRichard Lowe SET_SIZE(atomic_inc_8_nv) 61*5d9d9091SRichard Lowe SET_SIZE(atomic_inc_8) 62*5d9d9091SRichard Lowe 63*5d9d9091SRichard Lowe /* 64*5d9d9091SRichard Lowe * NOTE: If atomic_dec_8 and atomic_dec_8_nv are ever 65*5d9d9091SRichard Lowe * separated, you need to also edit the libc sparc platform 66*5d9d9091SRichard Lowe * specific mapfile and remove the NODYNSORT attribute 67*5d9d9091SRichard Lowe * from atomic_dec_8_nv. 68*5d9d9091SRichard Lowe */ 69*5d9d9091SRichard Lowe ENTRY(atomic_dec_8) 70*5d9d9091SRichard Lowe ALTENTRY(atomic_dec_8_nv) 71*5d9d9091SRichard Lowe ALTENTRY(atomic_dec_uchar) 72*5d9d9091SRichard Lowe ALTENTRY(atomic_dec_uchar_nv) 73*5d9d9091SRichard Lowe ba add_8 74*5d9d9091SRichard Lowe sub %g0, 1, %o1 75*5d9d9091SRichard Lowe SET_SIZE(atomic_dec_uchar_nv) 76*5d9d9091SRichard Lowe SET_SIZE(atomic_dec_uchar) 77*5d9d9091SRichard Lowe SET_SIZE(atomic_dec_8_nv) 78*5d9d9091SRichard Lowe SET_SIZE(atomic_dec_8) 79*5d9d9091SRichard Lowe 80*5d9d9091SRichard Lowe /* 81*5d9d9091SRichard Lowe * NOTE: If atomic_add_8 and atomic_add_8_nv are ever 82*5d9d9091SRichard Lowe * separated, you need to also edit the libc sparc platform 83*5d9d9091SRichard Lowe * specific mapfile and remove the NODYNSORT attribute 84*5d9d9091SRichard Lowe * from atomic_add_8_nv. 85*5d9d9091SRichard Lowe */ 86*5d9d9091SRichard Lowe ENTRY(atomic_add_8) 87*5d9d9091SRichard Lowe ALTENTRY(atomic_add_8_nv) 88*5d9d9091SRichard Lowe ALTENTRY(atomic_add_char) 89*5d9d9091SRichard Lowe ALTENTRY(atomic_add_char_nv) 90*5d9d9091SRichard Loweadd_8: 91*5d9d9091SRichard Lowe and %o0, 0x3, %o4 ! %o4 = byte offset, left-to-right 92*5d9d9091SRichard Lowe xor %o4, 0x3, %g1 ! %g1 = byte offset, right-to-left 93*5d9d9091SRichard Lowe sll %g1, 3, %g1 ! %g1 = bit offset, right-to-left 94*5d9d9091SRichard Lowe set 0xff, %o3 ! %o3 = mask 95*5d9d9091SRichard Lowe sll %o3, %g1, %o3 ! %o3 = shifted to bit offset 96*5d9d9091SRichard Lowe sll %o1, %g1, %o1 ! %o1 = shifted to bit offset 97*5d9d9091SRichard Lowe and %o1, %o3, %o1 ! %o1 = single byte value 98*5d9d9091SRichard Lowe andn %o0, 0x3, %o0 ! %o0 = word address 99*5d9d9091SRichard Lowe ld [%o0], %o2 ! read old value 100*5d9d9091SRichard Lowe1: 101*5d9d9091SRichard Lowe add %o2, %o1, %o5 ! add value to the old value 102*5d9d9091SRichard Lowe and %o5, %o3, %o5 ! clear other bits 103*5d9d9091SRichard Lowe andn %o2, %o3, %o4 ! clear target bits 104*5d9d9091SRichard Lowe or %o4, %o5, %o5 ! insert the new value 105*5d9d9091SRichard Lowe cas [%o0], %o2, %o5 106*5d9d9091SRichard Lowe cmp %o2, %o5 107*5d9d9091SRichard Lowe bne,a,pn %icc, 1b 108*5d9d9091SRichard Lowe mov %o5, %o2 ! %o2 = old value 109*5d9d9091SRichard Lowe add %o2, %o1, %o5 110*5d9d9091SRichard Lowe and %o5, %o3, %o5 111*5d9d9091SRichard Lowe retl 112*5d9d9091SRichard Lowe srl %o5, %g1, %o0 ! %o0 = new value 113*5d9d9091SRichard Lowe SET_SIZE(atomic_add_char_nv) 114*5d9d9091SRichard Lowe SET_SIZE(atomic_add_char) 115*5d9d9091SRichard Lowe SET_SIZE(atomic_add_8_nv) 116*5d9d9091SRichard Lowe SET_SIZE(atomic_add_8) 117*5d9d9091SRichard Lowe 118*5d9d9091SRichard Lowe /* 119*5d9d9091SRichard Lowe * NOTE: If atomic_inc_16 and atomic_inc_16_nv are ever 120*5d9d9091SRichard Lowe * separated, you need to also edit the libc sparc platform 121*5d9d9091SRichard Lowe * specific mapfile and remove the NODYNSORT attribute 122*5d9d9091SRichard Lowe * from atomic_inc_16_nv. 123*5d9d9091SRichard Lowe */ 124*5d9d9091SRichard Lowe ENTRY(atomic_inc_16) 125*5d9d9091SRichard Lowe ALTENTRY(atomic_inc_16_nv) 126*5d9d9091SRichard Lowe ALTENTRY(atomic_inc_ushort) 127*5d9d9091SRichard Lowe ALTENTRY(atomic_inc_ushort_nv) 128*5d9d9091SRichard Lowe ba add_16 129*5d9d9091SRichard Lowe add %g0, 1, %o1 130*5d9d9091SRichard Lowe SET_SIZE(atomic_inc_ushort_nv) 131*5d9d9091SRichard Lowe SET_SIZE(atomic_inc_ushort) 132*5d9d9091SRichard Lowe SET_SIZE(atomic_inc_16_nv) 133*5d9d9091SRichard Lowe SET_SIZE(atomic_inc_16) 134*5d9d9091SRichard Lowe 135*5d9d9091SRichard Lowe /* 136*5d9d9091SRichard Lowe * NOTE: If atomic_dec_16 and atomic_dec_16_nv are ever 137*5d9d9091SRichard Lowe * separated, you need to also edit the libc sparc platform 138*5d9d9091SRichard Lowe * specific mapfile and remove the NODYNSORT attribute 139*5d9d9091SRichard Lowe * from atomic_dec_16_nv. 140*5d9d9091SRichard Lowe */ 141*5d9d9091SRichard Lowe ENTRY(atomic_dec_16) 142*5d9d9091SRichard Lowe ALTENTRY(atomic_dec_16_nv) 143*5d9d9091SRichard Lowe ALTENTRY(atomic_dec_ushort) 144*5d9d9091SRichard Lowe ALTENTRY(atomic_dec_ushort_nv) 145*5d9d9091SRichard Lowe ba add_16 146*5d9d9091SRichard Lowe sub %g0, 1, %o1 147*5d9d9091SRichard Lowe SET_SIZE(atomic_dec_ushort_nv) 148*5d9d9091SRichard Lowe SET_SIZE(atomic_dec_ushort) 149*5d9d9091SRichard Lowe SET_SIZE(atomic_dec_16_nv) 150*5d9d9091SRichard Lowe SET_SIZE(atomic_dec_16) 151*5d9d9091SRichard Lowe 152*5d9d9091SRichard Lowe /* 153*5d9d9091SRichard Lowe * NOTE: If atomic_add_16 and atomic_add_16_nv are ever 154*5d9d9091SRichard Lowe * separated, you need to also edit the libc sparc platform 155*5d9d9091SRichard Lowe * specific mapfile and remove the NODYNSORT attribute 156*5d9d9091SRichard Lowe * from atomic_add_16_nv. 157*5d9d9091SRichard Lowe */ 158*5d9d9091SRichard Lowe ENTRY(atomic_add_16) 159*5d9d9091SRichard Lowe ALTENTRY(atomic_add_16_nv) 160*5d9d9091SRichard Lowe ALTENTRY(atomic_add_short) 161*5d9d9091SRichard Lowe ALTENTRY(atomic_add_short_nv) 162*5d9d9091SRichard Loweadd_16: 163*5d9d9091SRichard Lowe and %o0, 0x2, %o4 ! %o4 = byte offset, left-to-right 164*5d9d9091SRichard Lowe xor %o4, 0x2, %g1 ! %g1 = byte offset, right-to-left 165*5d9d9091SRichard Lowe sll %o4, 3, %o4 ! %o4 = bit offset, left-to-right 166*5d9d9091SRichard Lowe sll %g1, 3, %g1 ! %g1 = bit offset, right-to-left 167*5d9d9091SRichard Lowe sethi %hi(0xffff0000), %o3 ! %o3 = mask 168*5d9d9091SRichard Lowe srl %o3, %o4, %o3 ! %o3 = shifted to bit offset 169*5d9d9091SRichard Lowe sll %o1, %g1, %o1 ! %o1 = shifted to bit offset 170*5d9d9091SRichard Lowe and %o1, %o3, %o1 ! %o1 = single short value 171*5d9d9091SRichard Lowe andn %o0, 0x2, %o0 ! %o0 = word address 172*5d9d9091SRichard Lowe ! if low-order bit is 1, we will properly get an alignment fault here 173*5d9d9091SRichard Lowe ld [%o0], %o2 ! read old value 174*5d9d9091SRichard Lowe1: 175*5d9d9091SRichard Lowe add %o1, %o2, %o5 ! add value to the old value 176*5d9d9091SRichard Lowe and %o5, %o3, %o5 ! clear other bits 177*5d9d9091SRichard Lowe andn %o2, %o3, %o4 ! clear target bits 178*5d9d9091SRichard Lowe or %o4, %o5, %o5 ! insert the new value 179*5d9d9091SRichard Lowe cas [%o0], %o2, %o5 180*5d9d9091SRichard Lowe cmp %o2, %o5 181*5d9d9091SRichard Lowe bne,a,pn %icc, 1b 182*5d9d9091SRichard Lowe mov %o5, %o2 ! %o2 = old value 183*5d9d9091SRichard Lowe add %o1, %o2, %o5 184*5d9d9091SRichard Lowe and %o5, %o3, %o5 185*5d9d9091SRichard Lowe retl 186*5d9d9091SRichard Lowe srl %o5, %g1, %o0 ! %o0 = new value 187*5d9d9091SRichard Lowe SET_SIZE(atomic_add_short_nv) 188*5d9d9091SRichard Lowe SET_SIZE(atomic_add_short) 189*5d9d9091SRichard Lowe SET_SIZE(atomic_add_16_nv) 190*5d9d9091SRichard Lowe SET_SIZE(atomic_add_16) 191*5d9d9091SRichard Lowe 192*5d9d9091SRichard Lowe /* 193*5d9d9091SRichard Lowe * NOTE: If atomic_inc_32 and atomic_inc_32_nv are ever 194*5d9d9091SRichard Lowe * separated, you need to also edit the libc sparc platform 195*5d9d9091SRichard Lowe * specific mapfile and remove the NODYNSORT attribute 196*5d9d9091SRichard Lowe * from atomic_inc_32_nv. 197*5d9d9091SRichard Lowe */ 198*5d9d9091SRichard Lowe ENTRY(atomic_inc_32) 199*5d9d9091SRichard Lowe ALTENTRY(atomic_inc_32_nv) 200*5d9d9091SRichard Lowe ALTENTRY(atomic_inc_uint) 201*5d9d9091SRichard Lowe ALTENTRY(atomic_inc_uint_nv) 202*5d9d9091SRichard Lowe ALTENTRY(atomic_inc_ulong) 203*5d9d9091SRichard Lowe ALTENTRY(atomic_inc_ulong_nv) 204*5d9d9091SRichard Lowe ba add_32 205*5d9d9091SRichard Lowe add %g0, 1, %o1 206*5d9d9091SRichard Lowe SET_SIZE(atomic_inc_ulong_nv) 207*5d9d9091SRichard Lowe SET_SIZE(atomic_inc_ulong) 208*5d9d9091SRichard Lowe SET_SIZE(atomic_inc_uint_nv) 209*5d9d9091SRichard Lowe SET_SIZE(atomic_inc_uint) 210*5d9d9091SRichard Lowe SET_SIZE(atomic_inc_32_nv) 211*5d9d9091SRichard Lowe SET_SIZE(atomic_inc_32) 212*5d9d9091SRichard Lowe 213*5d9d9091SRichard Lowe /* 214*5d9d9091SRichard Lowe * NOTE: If atomic_dec_32 and atomic_dec_32_nv are ever 215*5d9d9091SRichard Lowe * separated, you need to also edit the libc sparc platform 216*5d9d9091SRichard Lowe * specific mapfile and remove the NODYNSORT attribute 217*5d9d9091SRichard Lowe * from atomic_dec_32_nv. 218*5d9d9091SRichard Lowe */ 219*5d9d9091SRichard Lowe ENTRY(atomic_dec_32) 220*5d9d9091SRichard Lowe ALTENTRY(atomic_dec_32_nv) 221*5d9d9091SRichard Lowe ALTENTRY(atomic_dec_uint) 222*5d9d9091SRichard Lowe ALTENTRY(atomic_dec_uint_nv) 223*5d9d9091SRichard Lowe ALTENTRY(atomic_dec_ulong) 224*5d9d9091SRichard Lowe ALTENTRY(atomic_dec_ulong_nv) 225*5d9d9091SRichard Lowe ba add_32 226*5d9d9091SRichard Lowe sub %g0, 1, %o1 227*5d9d9091SRichard Lowe SET_SIZE(atomic_dec_ulong_nv) 228*5d9d9091SRichard Lowe SET_SIZE(atomic_dec_ulong) 229*5d9d9091SRichard Lowe SET_SIZE(atomic_dec_uint_nv) 230*5d9d9091SRichard Lowe SET_SIZE(atomic_dec_uint) 231*5d9d9091SRichard Lowe SET_SIZE(atomic_dec_32_nv) 232*5d9d9091SRichard Lowe SET_SIZE(atomic_dec_32) 233*5d9d9091SRichard Lowe 234*5d9d9091SRichard Lowe /* 235*5d9d9091SRichard Lowe * NOTE: If atomic_add_32 and atomic_add_32_nv are ever 236*5d9d9091SRichard Lowe * separated, you need to also edit the libc sparc platform 237*5d9d9091SRichard Lowe * specific mapfile and remove the NODYNSORT attribute 238*5d9d9091SRichard Lowe * from atomic_add_32_nv. 239*5d9d9091SRichard Lowe */ 240*5d9d9091SRichard Lowe ENTRY(atomic_add_32) 241*5d9d9091SRichard Lowe ALTENTRY(atomic_add_32_nv) 242*5d9d9091SRichard Lowe ALTENTRY(atomic_add_int) 243*5d9d9091SRichard Lowe ALTENTRY(atomic_add_int_nv) 244*5d9d9091SRichard Lowe ALTENTRY(atomic_add_ptr) 245*5d9d9091SRichard Lowe ALTENTRY(atomic_add_ptr_nv) 246*5d9d9091SRichard Lowe ALTENTRY(atomic_add_long) 247*5d9d9091SRichard Lowe ALTENTRY(atomic_add_long_nv) 248*5d9d9091SRichard Loweadd_32: 249*5d9d9091SRichard Lowe ld [%o0], %o2 250*5d9d9091SRichard Lowe1: 251*5d9d9091SRichard Lowe add %o2, %o1, %o3 252*5d9d9091SRichard Lowe cas [%o0], %o2, %o3 253*5d9d9091SRichard Lowe cmp %o2, %o3 254*5d9d9091SRichard Lowe bne,a,pn %icc, 1b 255*5d9d9091SRichard Lowe mov %o3, %o2 256*5d9d9091SRichard Lowe retl 257*5d9d9091SRichard Lowe add %o2, %o1, %o0 ! return new value 258*5d9d9091SRichard Lowe SET_SIZE(atomic_add_long_nv) 259*5d9d9091SRichard Lowe SET_SIZE(atomic_add_long) 260*5d9d9091SRichard Lowe SET_SIZE(atomic_add_ptr_nv) 261*5d9d9091SRichard Lowe SET_SIZE(atomic_add_ptr) 262*5d9d9091SRichard Lowe SET_SIZE(atomic_add_int_nv) 263*5d9d9091SRichard Lowe SET_SIZE(atomic_add_int) 264*5d9d9091SRichard Lowe SET_SIZE(atomic_add_32_nv) 265*5d9d9091SRichard Lowe SET_SIZE(atomic_add_32) 266*5d9d9091SRichard Lowe 267*5d9d9091SRichard Lowe /* 268*5d9d9091SRichard Lowe * NOTE: If atomic_inc_64 and atomic_inc_64_nv are ever 269*5d9d9091SRichard Lowe * separated, you need to also edit the libc sparc platform 270*5d9d9091SRichard Lowe * specific mapfile and remove the NODYNSORT attribute 271*5d9d9091SRichard Lowe * from atomic_inc_64_nv. 272*5d9d9091SRichard Lowe */ 273*5d9d9091SRichard Lowe ENTRY(atomic_inc_64) 274*5d9d9091SRichard Lowe ALTENTRY(atomic_inc_64_nv) 275*5d9d9091SRichard Lowe ba add_64 276*5d9d9091SRichard Lowe add %g0, 1, %o1 277*5d9d9091SRichard Lowe SET_SIZE(atomic_inc_64_nv) 278*5d9d9091SRichard Lowe SET_SIZE(atomic_inc_64) 279*5d9d9091SRichard Lowe 280*5d9d9091SRichard Lowe /* 281*5d9d9091SRichard Lowe * NOTE: If atomic_dec_64 and atomic_dec_64_nv are ever 282*5d9d9091SRichard Lowe * separated, you need to also edit the libc sparc platform 283*5d9d9091SRichard Lowe * specific mapfile and remove the NODYNSORT attribute 284*5d9d9091SRichard Lowe * from atomic_dec_64_nv. 285*5d9d9091SRichard Lowe */ 286*5d9d9091SRichard Lowe ENTRY(atomic_dec_64) 287*5d9d9091SRichard Lowe ALTENTRY(atomic_dec_64_nv) 288*5d9d9091SRichard Lowe ba add_64 289*5d9d9091SRichard Lowe sub %g0, 1, %o1 290*5d9d9091SRichard Lowe SET_SIZE(atomic_dec_64_nv) 291*5d9d9091SRichard Lowe SET_SIZE(atomic_dec_64) 292*5d9d9091SRichard Lowe 293*5d9d9091SRichard Lowe /* 294*5d9d9091SRichard Lowe * NOTE: If atomic_add_64 and atomic_add_64_nv are ever 295*5d9d9091SRichard Lowe * separated, you need to also edit the libc sparc platform 296*5d9d9091SRichard Lowe * specific mapfile and remove the NODYNSORT attribute 297*5d9d9091SRichard Lowe * from atomic_add_64_nv. 298*5d9d9091SRichard Lowe */ 299*5d9d9091SRichard Lowe ENTRY(atomic_add_64) 300*5d9d9091SRichard Lowe ALTENTRY(atomic_add_64_nv) 301*5d9d9091SRichard Lowe sllx %o1, 32, %o1 ! upper 32 in %o1, lower in %o2 302*5d9d9091SRichard Lowe srl %o2, 0, %o2 303*5d9d9091SRichard Lowe add %o1, %o2, %o1 ! convert 2 32-bit args into 1 64-bit 304*5d9d9091SRichard Loweadd_64: 305*5d9d9091SRichard Lowe ldx [%o0], %o2 306*5d9d9091SRichard Lowe1: 307*5d9d9091SRichard Lowe add %o2, %o1, %o3 308*5d9d9091SRichard Lowe casx [%o0], %o2, %o3 309*5d9d9091SRichard Lowe cmp %o2, %o3 310*5d9d9091SRichard Lowe bne,a,pn %xcc, 1b 311*5d9d9091SRichard Lowe mov %o3, %o2 312*5d9d9091SRichard Lowe add %o2, %o1, %o1 ! return lower 32-bits in %o1 313*5d9d9091SRichard Lowe retl 314*5d9d9091SRichard Lowe srlx %o1, 32, %o0 ! return upper 32-bits in %o0 315*5d9d9091SRichard Lowe SET_SIZE(atomic_add_64_nv) 316*5d9d9091SRichard Lowe SET_SIZE(atomic_add_64) 317*5d9d9091SRichard Lowe 318*5d9d9091SRichard Lowe /* 319*5d9d9091SRichard Lowe * NOTE: If atomic_or_8 and atomic_or_8_nv are ever 320*5d9d9091SRichard Lowe * separated, you need to also edit the libc sparc platform 321*5d9d9091SRichard Lowe * specific mapfile and remove the NODYNSORT attribute 322*5d9d9091SRichard Lowe * from atomic_or_8_nv. 323*5d9d9091SRichard Lowe */ 324*5d9d9091SRichard Lowe ENTRY(atomic_or_8) 325*5d9d9091SRichard Lowe ALTENTRY(atomic_or_8_nv) 326*5d9d9091SRichard Lowe ALTENTRY(atomic_or_uchar) 327*5d9d9091SRichard Lowe ALTENTRY(atomic_or_uchar_nv) 328*5d9d9091SRichard Lowe and %o0, 0x3, %o4 ! %o4 = byte offset, left-to-right 329*5d9d9091SRichard Lowe xor %o4, 0x3, %g1 ! %g1 = byte offset, right-to-left 330*5d9d9091SRichard Lowe sll %g1, 3, %g1 ! %g1 = bit offset, right-to-left 331*5d9d9091SRichard Lowe set 0xff, %o3 ! %o3 = mask 332*5d9d9091SRichard Lowe sll %o3, %g1, %o3 ! %o3 = shifted to bit offset 333*5d9d9091SRichard Lowe sll %o1, %g1, %o1 ! %o1 = shifted to bit offset 334*5d9d9091SRichard Lowe and %o1, %o3, %o1 ! %o1 = single byte value 335*5d9d9091SRichard Lowe andn %o0, 0x3, %o0 ! %o0 = word address 336*5d9d9091SRichard Lowe ld [%o0], %o2 ! read old value 337*5d9d9091SRichard Lowe1: 338*5d9d9091SRichard Lowe or %o2, %o1, %o5 ! or in the new value 339*5d9d9091SRichard Lowe cas [%o0], %o2, %o5 340*5d9d9091SRichard Lowe cmp %o2, %o5 341*5d9d9091SRichard Lowe bne,a,pn %icc, 1b 342*5d9d9091SRichard Lowe mov %o5, %o2 ! %o2 = old value 343*5d9d9091SRichard Lowe or %o2, %o1, %o5 344*5d9d9091SRichard Lowe and %o5, %o3, %o5 345*5d9d9091SRichard Lowe retl 346*5d9d9091SRichard Lowe srl %o5, %g1, %o0 ! %o0 = new value 347*5d9d9091SRichard Lowe SET_SIZE(atomic_or_uchar_nv) 348*5d9d9091SRichard Lowe SET_SIZE(atomic_or_uchar) 349*5d9d9091SRichard Lowe SET_SIZE(atomic_or_8_nv) 350*5d9d9091SRichard Lowe SET_SIZE(atomic_or_8) 351*5d9d9091SRichard Lowe 352*5d9d9091SRichard Lowe /* 353*5d9d9091SRichard Lowe * NOTE: If atomic_or_16 and atomic_or_16_nv are ever 354*5d9d9091SRichard Lowe * separated, you need to also edit the libc sparc platform 355*5d9d9091SRichard Lowe * specific mapfile and remove the NODYNSORT attribute 356*5d9d9091SRichard Lowe * from atomic_or_16_nv. 357*5d9d9091SRichard Lowe */ 358*5d9d9091SRichard Lowe ENTRY(atomic_or_16) 359*5d9d9091SRichard Lowe ALTENTRY(atomic_or_16_nv) 360*5d9d9091SRichard Lowe ALTENTRY(atomic_or_ushort) 361*5d9d9091SRichard Lowe ALTENTRY(atomic_or_ushort_nv) 362*5d9d9091SRichard Lowe and %o0, 0x2, %o4 ! %o4 = byte offset, left-to-right 363*5d9d9091SRichard Lowe xor %o4, 0x2, %g1 ! %g1 = byte offset, right-to-left 364*5d9d9091SRichard Lowe sll %o4, 3, %o4 ! %o4 = bit offset, left-to-right 365*5d9d9091SRichard Lowe sll %g1, 3, %g1 ! %g1 = bit offset, right-to-left 366*5d9d9091SRichard Lowe sethi %hi(0xffff0000), %o3 ! %o3 = mask 367*5d9d9091SRichard Lowe srl %o3, %o4, %o3 ! %o3 = shifted to bit offset 368*5d9d9091SRichard Lowe sll %o1, %g1, %o1 ! %o1 = shifted to bit offset 369*5d9d9091SRichard Lowe and %o1, %o3, %o1 ! %o1 = single short value 370*5d9d9091SRichard Lowe andn %o0, 0x2, %o0 ! %o0 = word address 371*5d9d9091SRichard Lowe ! if low-order bit is 1, we will properly get an alignment fault here 372*5d9d9091SRichard Lowe ld [%o0], %o2 ! read old value 373*5d9d9091SRichard Lowe1: 374*5d9d9091SRichard Lowe or %o2, %o1, %o5 ! or in the new value 375*5d9d9091SRichard Lowe cas [%o0], %o2, %o5 376*5d9d9091SRichard Lowe cmp %o2, %o5 377*5d9d9091SRichard Lowe bne,a,pn %icc, 1b 378*5d9d9091SRichard Lowe mov %o5, %o2 ! %o2 = old value 379*5d9d9091SRichard Lowe or %o2, %o1, %o5 ! or in the new value 380*5d9d9091SRichard Lowe and %o5, %o3, %o5 381*5d9d9091SRichard Lowe retl 382*5d9d9091SRichard Lowe srl %o5, %g1, %o0 ! %o0 = new value 383*5d9d9091SRichard Lowe SET_SIZE(atomic_or_ushort_nv) 384*5d9d9091SRichard Lowe SET_SIZE(atomic_or_ushort) 385*5d9d9091SRichard Lowe SET_SIZE(atomic_or_16_nv) 386*5d9d9091SRichard Lowe SET_SIZE(atomic_or_16) 387*5d9d9091SRichard Lowe 388*5d9d9091SRichard Lowe /* 389*5d9d9091SRichard Lowe * NOTE: If atomic_or_32 and atomic_or_32_nv are ever 390*5d9d9091SRichard Lowe * separated, you need to also edit the libc sparc platform 391*5d9d9091SRichard Lowe * specific mapfile and remove the NODYNSORT attribute 392*5d9d9091SRichard Lowe * from atomic_or_32_nv. 393*5d9d9091SRichard Lowe */ 394*5d9d9091SRichard Lowe ENTRY(atomic_or_32) 395*5d9d9091SRichard Lowe ALTENTRY(atomic_or_32_nv) 396*5d9d9091SRichard Lowe ALTENTRY(atomic_or_uint) 397*5d9d9091SRichard Lowe ALTENTRY(atomic_or_uint_nv) 398*5d9d9091SRichard Lowe ALTENTRY(atomic_or_ulong) 399*5d9d9091SRichard Lowe ALTENTRY(atomic_or_ulong_nv) 400*5d9d9091SRichard Lowe ld [%o0], %o2 401*5d9d9091SRichard Lowe1: 402*5d9d9091SRichard Lowe or %o2, %o1, %o3 403*5d9d9091SRichard Lowe cas [%o0], %o2, %o3 404*5d9d9091SRichard Lowe cmp %o2, %o3 405*5d9d9091SRichard Lowe bne,a,pn %icc, 1b 406*5d9d9091SRichard Lowe mov %o3, %o2 407*5d9d9091SRichard Lowe retl 408*5d9d9091SRichard Lowe or %o2, %o1, %o0 ! return new value 409*5d9d9091SRichard Lowe SET_SIZE(atomic_or_ulong_nv) 410*5d9d9091SRichard Lowe SET_SIZE(atomic_or_ulong) 411*5d9d9091SRichard Lowe SET_SIZE(atomic_or_uint_nv) 412*5d9d9091SRichard Lowe SET_SIZE(atomic_or_uint) 413*5d9d9091SRichard Lowe SET_SIZE(atomic_or_32_nv) 414*5d9d9091SRichard Lowe SET_SIZE(atomic_or_32) 415*5d9d9091SRichard Lowe 416*5d9d9091SRichard Lowe /* 417*5d9d9091SRichard Lowe * NOTE: If atomic_or_64 and atomic_or_64_nv are ever 418*5d9d9091SRichard Lowe * separated, you need to also edit the libc sparc platform 419*5d9d9091SRichard Lowe * specific mapfile and remove the NODYNSORT attribute 420*5d9d9091SRichard Lowe * from atomic_or_64_nv. 421*5d9d9091SRichard Lowe */ 422*5d9d9091SRichard Lowe ENTRY(atomic_or_64) 423*5d9d9091SRichard Lowe ALTENTRY(atomic_or_64_nv) 424*5d9d9091SRichard Lowe sllx %o1, 32, %o1 ! upper 32 in %o1, lower in %o2 425*5d9d9091SRichard Lowe srl %o2, 0, %o2 426*5d9d9091SRichard Lowe add %o1, %o2, %o1 ! convert 2 32-bit args into 1 64-bit 427*5d9d9091SRichard Lowe ldx [%o0], %o2 428*5d9d9091SRichard Lowe1: 429*5d9d9091SRichard Lowe or %o2, %o1, %o3 430*5d9d9091SRichard Lowe casx [%o0], %o2, %o3 431*5d9d9091SRichard Lowe cmp %o2, %o3 432*5d9d9091SRichard Lowe bne,a,pn %xcc, 1b 433*5d9d9091SRichard Lowe mov %o3, %o2 434*5d9d9091SRichard Lowe or %o2, %o1, %o1 ! return lower 32-bits in %o1 435*5d9d9091SRichard Lowe retl 436*5d9d9091SRichard Lowe srlx %o1, 32, %o0 ! return upper 32-bits in %o0 437*5d9d9091SRichard Lowe SET_SIZE(atomic_or_64_nv) 438*5d9d9091SRichard Lowe SET_SIZE(atomic_or_64) 439*5d9d9091SRichard Lowe 440*5d9d9091SRichard Lowe /* 441*5d9d9091SRichard Lowe * NOTE: If atomic_and_8 and atomic_and_8_nv are ever 442*5d9d9091SRichard Lowe * separated, you need to also edit the libc sparc platform 443*5d9d9091SRichard Lowe * specific mapfile and remove the NODYNSORT attribute 444*5d9d9091SRichard Lowe * from atomic_and_8_nv. 445*5d9d9091SRichard Lowe */ 446*5d9d9091SRichard Lowe ENTRY(atomic_and_8) 447*5d9d9091SRichard Lowe ALTENTRY(atomic_and_8_nv) 448*5d9d9091SRichard Lowe ALTENTRY(atomic_and_uchar) 449*5d9d9091SRichard Lowe ALTENTRY(atomic_and_uchar_nv) 450*5d9d9091SRichard Lowe and %o0, 0x3, %o4 ! %o4 = byte offset, left-to-right 451*5d9d9091SRichard Lowe xor %o4, 0x3, %g1 ! %g1 = byte offset, right-to-left 452*5d9d9091SRichard Lowe sll %g1, 3, %g1 ! %g1 = bit offset, right-to-left 453*5d9d9091SRichard Lowe set 0xff, %o3 ! %o3 = mask 454*5d9d9091SRichard Lowe sll %o3, %g1, %o3 ! %o3 = shifted to bit offset 455*5d9d9091SRichard Lowe sll %o1, %g1, %o1 ! %o1 = shifted to bit offset 456*5d9d9091SRichard Lowe orn %o1, %o3, %o1 ! all ones in other bytes 457*5d9d9091SRichard Lowe andn %o0, 0x3, %o0 ! %o0 = word address 458*5d9d9091SRichard Lowe ld [%o0], %o2 ! read old value 459*5d9d9091SRichard Lowe1: 460*5d9d9091SRichard Lowe and %o2, %o1, %o5 ! and in the new value 461*5d9d9091SRichard Lowe cas [%o0], %o2, %o5 462*5d9d9091SRichard Lowe cmp %o2, %o5 463*5d9d9091SRichard Lowe bne,a,pn %icc, 1b 464*5d9d9091SRichard Lowe mov %o5, %o2 ! %o2 = old value 465*5d9d9091SRichard Lowe and %o2, %o1, %o5 466*5d9d9091SRichard Lowe and %o5, %o3, %o5 467*5d9d9091SRichard Lowe retl 468*5d9d9091SRichard Lowe srl %o5, %g1, %o0 ! %o0 = new value 469*5d9d9091SRichard Lowe SET_SIZE(atomic_and_uchar_nv) 470*5d9d9091SRichard Lowe SET_SIZE(atomic_and_uchar) 471*5d9d9091SRichard Lowe SET_SIZE(atomic_and_8_nv) 472*5d9d9091SRichard Lowe SET_SIZE(atomic_and_8) 473*5d9d9091SRichard Lowe 474*5d9d9091SRichard Lowe /* 475*5d9d9091SRichard Lowe * NOTE: If atomic_and_16 and atomic_and_16_nv are ever 476*5d9d9091SRichard Lowe * separated, you need to also edit the libc sparc platform 477*5d9d9091SRichard Lowe * specific mapfile and remove the NODYNSORT attribute 478*5d9d9091SRichard Lowe * from atomic_and_16_nv. 479*5d9d9091SRichard Lowe */ 480*5d9d9091SRichard Lowe ENTRY(atomic_and_16) 481*5d9d9091SRichard Lowe ALTENTRY(atomic_and_16_nv) 482*5d9d9091SRichard Lowe ALTENTRY(atomic_and_ushort) 483*5d9d9091SRichard Lowe ALTENTRY(atomic_and_ushort_nv) 484*5d9d9091SRichard Lowe and %o0, 0x2, %o4 ! %o4 = byte offset, left-to-right 485*5d9d9091SRichard Lowe xor %o4, 0x2, %g1 ! %g1 = byte offset, right-to-left 486*5d9d9091SRichard Lowe sll %o4, 3, %o4 ! %o4 = bit offset, left-to-right 487*5d9d9091SRichard Lowe sll %g1, 3, %g1 ! %g1 = bit offset, right-to-left 488*5d9d9091SRichard Lowe sethi %hi(0xffff0000), %o3 ! %o3 = mask 489*5d9d9091SRichard Lowe srl %o3, %o4, %o3 ! %o3 = shifted to bit offset 490*5d9d9091SRichard Lowe sll %o1, %g1, %o1 ! %o1 = shifted to bit offset 491*5d9d9091SRichard Lowe orn %o1, %o3, %o1 ! all ones in the other half 492*5d9d9091SRichard Lowe andn %o0, 0x2, %o0 ! %o0 = word address 493*5d9d9091SRichard Lowe ! if low-order bit is 1, we will properly get an alignment fault here 494*5d9d9091SRichard Lowe ld [%o0], %o2 ! read old value 495*5d9d9091SRichard Lowe1: 496*5d9d9091SRichard Lowe and %o2, %o1, %o5 ! and in the new value 497*5d9d9091SRichard Lowe cas [%o0], %o2, %o5 498*5d9d9091SRichard Lowe cmp %o2, %o5 499*5d9d9091SRichard Lowe bne,a,pn %icc, 1b 500*5d9d9091SRichard Lowe mov %o5, %o2 ! %o2 = old value 501*5d9d9091SRichard Lowe and %o2, %o1, %o5 502*5d9d9091SRichard Lowe and %o5, %o3, %o5 503*5d9d9091SRichard Lowe retl 504*5d9d9091SRichard Lowe srl %o5, %g1, %o0 ! %o0 = new value 505*5d9d9091SRichard Lowe SET_SIZE(atomic_and_ushort_nv) 506*5d9d9091SRichard Lowe SET_SIZE(atomic_and_ushort) 507*5d9d9091SRichard Lowe SET_SIZE(atomic_and_16_nv) 508*5d9d9091SRichard Lowe SET_SIZE(atomic_and_16) 509*5d9d9091SRichard Lowe 510*5d9d9091SRichard Lowe /* 511*5d9d9091SRichard Lowe * NOTE: If atomic_and_32 and atomic_and_32_nv are ever 512*5d9d9091SRichard Lowe * separated, you need to also edit the libc sparc platform 513*5d9d9091SRichard Lowe * specific mapfile and remove the NODYNSORT attribute 514*5d9d9091SRichard Lowe * from atomic_and_32_nv. 515*5d9d9091SRichard Lowe */ 516*5d9d9091SRichard Lowe ENTRY(atomic_and_32) 517*5d9d9091SRichard Lowe ALTENTRY(atomic_and_32_nv) 518*5d9d9091SRichard Lowe ALTENTRY(atomic_and_uint) 519*5d9d9091SRichard Lowe ALTENTRY(atomic_and_uint_nv) 520*5d9d9091SRichard Lowe ALTENTRY(atomic_and_ulong) 521*5d9d9091SRichard Lowe ALTENTRY(atomic_and_ulong_nv) 522*5d9d9091SRichard Lowe ld [%o0], %o2 523*5d9d9091SRichard Lowe1: 524*5d9d9091SRichard Lowe and %o2, %o1, %o3 525*5d9d9091SRichard Lowe cas [%o0], %o2, %o3 526*5d9d9091SRichard Lowe cmp %o2, %o3 527*5d9d9091SRichard Lowe bne,a,pn %icc, 1b 528*5d9d9091SRichard Lowe mov %o3, %o2 529*5d9d9091SRichard Lowe retl 530*5d9d9091SRichard Lowe and %o2, %o1, %o0 ! return new value 531*5d9d9091SRichard Lowe SET_SIZE(atomic_and_ulong_nv) 532*5d9d9091SRichard Lowe SET_SIZE(atomic_and_ulong) 533*5d9d9091SRichard Lowe SET_SIZE(atomic_and_uint_nv) 534*5d9d9091SRichard Lowe SET_SIZE(atomic_and_uint) 535*5d9d9091SRichard Lowe SET_SIZE(atomic_and_32_nv) 536*5d9d9091SRichard Lowe SET_SIZE(atomic_and_32) 537*5d9d9091SRichard Lowe 538*5d9d9091SRichard Lowe /* 539*5d9d9091SRichard Lowe * NOTE: If atomic_and_64 and atomic_and_64_nv are ever 540*5d9d9091SRichard Lowe * separated, you need to also edit the libc sparc platform 541*5d9d9091SRichard Lowe * specific mapfile and remove the NODYNSORT attribute 542*5d9d9091SRichard Lowe * from atomic_and_64_nv. 543*5d9d9091SRichard Lowe */ 544*5d9d9091SRichard Lowe ENTRY(atomic_and_64) 545*5d9d9091SRichard Lowe ALTENTRY(atomic_and_64_nv) 546*5d9d9091SRichard Lowe sllx %o1, 32, %o1 ! upper 32 in %o1, lower in %o2 547*5d9d9091SRichard Lowe srl %o2, 0, %o2 548*5d9d9091SRichard Lowe add %o1, %o2, %o1 ! convert 2 32-bit args into 1 64-bit 549*5d9d9091SRichard Lowe ldx [%o0], %o2 550*5d9d9091SRichard Lowe1: 551*5d9d9091SRichard Lowe and %o2, %o1, %o3 552*5d9d9091SRichard Lowe casx [%o0], %o2, %o3 553*5d9d9091SRichard Lowe cmp %o2, %o3 554*5d9d9091SRichard Lowe bne,a,pn %xcc, 1b 555*5d9d9091SRichard Lowe mov %o3, %o2 556*5d9d9091SRichard Lowe and %o2, %o1, %o1 ! return lower 32-bits in %o1 557*5d9d9091SRichard Lowe retl 558*5d9d9091SRichard Lowe srlx %o1, 32, %o0 ! return upper 32-bits in %o0 559*5d9d9091SRichard Lowe SET_SIZE(atomic_and_64_nv) 560*5d9d9091SRichard Lowe SET_SIZE(atomic_and_64) 561*5d9d9091SRichard Lowe 562*5d9d9091SRichard Lowe ENTRY(atomic_cas_8) 563*5d9d9091SRichard Lowe ALTENTRY(atomic_cas_uchar) 564*5d9d9091SRichard Lowe and %o0, 0x3, %o4 ! %o4 = byte offset, left-to-right 565*5d9d9091SRichard Lowe xor %o4, 0x3, %g1 ! %g1 = byte offset, right-to-left 566*5d9d9091SRichard Lowe sll %g1, 3, %g1 ! %g1 = bit offset, right-to-left 567*5d9d9091SRichard Lowe set 0xff, %o3 ! %o3 = mask 568*5d9d9091SRichard Lowe sll %o3, %g1, %o3 ! %o3 = shifted to bit offset 569*5d9d9091SRichard Lowe sll %o1, %g1, %o1 ! %o1 = shifted to bit offset 570*5d9d9091SRichard Lowe and %o1, %o3, %o1 ! %o1 = single byte value 571*5d9d9091SRichard Lowe sll %o2, %g1, %o2 ! %o2 = shifted to bit offset 572*5d9d9091SRichard Lowe and %o2, %o3, %o2 ! %o2 = single byte value 573*5d9d9091SRichard Lowe andn %o0, 0x3, %o0 ! %o0 = word address 574*5d9d9091SRichard Lowe ld [%o0], %o4 ! read old value 575*5d9d9091SRichard Lowe1: 576*5d9d9091SRichard Lowe andn %o4, %o3, %o4 ! clear target bits 577*5d9d9091SRichard Lowe or %o4, %o2, %o5 ! insert the new value 578*5d9d9091SRichard Lowe or %o4, %o1, %o4 ! insert the comparison value 579*5d9d9091SRichard Lowe cas [%o0], %o4, %o5 580*5d9d9091SRichard Lowe cmp %o4, %o5 ! did we succeed? 581*5d9d9091SRichard Lowe be,pt %icc, 2f 582*5d9d9091SRichard Lowe and %o5, %o3, %o4 ! isolate the old value 583*5d9d9091SRichard Lowe cmp %o1, %o4 ! should we have succeeded? 584*5d9d9091SRichard Lowe be,a,pt %icc, 1b ! yes, try again 585*5d9d9091SRichard Lowe mov %o5, %o4 ! %o4 = old value 586*5d9d9091SRichard Lowe2: 587*5d9d9091SRichard Lowe retl 588*5d9d9091SRichard Lowe srl %o4, %g1, %o0 ! %o0 = old value 589*5d9d9091SRichard Lowe SET_SIZE(atomic_cas_uchar) 590*5d9d9091SRichard Lowe SET_SIZE(atomic_cas_8) 591*5d9d9091SRichard Lowe 592*5d9d9091SRichard Lowe ENTRY(atomic_cas_16) 593*5d9d9091SRichard Lowe ALTENTRY(atomic_cas_ushort) 594*5d9d9091SRichard Lowe and %o0, 0x2, %o4 ! %o4 = byte offset, left-to-right 595*5d9d9091SRichard Lowe xor %o4, 0x2, %g1 ! %g1 = byte offset, right-to-left 596*5d9d9091SRichard Lowe sll %o4, 3, %o4 ! %o4 = bit offset, left-to-right 597*5d9d9091SRichard Lowe sll %g1, 3, %g1 ! %g1 = bit offset, right-to-left 598*5d9d9091SRichard Lowe sethi %hi(0xffff0000), %o3 ! %o3 = mask 599*5d9d9091SRichard Lowe srl %o3, %o4, %o3 ! %o3 = shifted to bit offset 600*5d9d9091SRichard Lowe sll %o1, %g1, %o1 ! %o1 = shifted to bit offset 601*5d9d9091SRichard Lowe and %o1, %o3, %o1 ! %o1 = single short value 602*5d9d9091SRichard Lowe sll %o2, %g1, %o2 ! %o2 = shifted to bit offset 603*5d9d9091SRichard Lowe and %o2, %o3, %o2 ! %o2 = single short value 604*5d9d9091SRichard Lowe andn %o0, 0x2, %o0 ! %o0 = word address 605*5d9d9091SRichard Lowe ! if low-order bit is 1, we will properly get an alignment fault here 606*5d9d9091SRichard Lowe ld [%o0], %o4 ! read old value 607*5d9d9091SRichard Lowe1: 608*5d9d9091SRichard Lowe andn %o4, %o3, %o4 ! clear target bits 609*5d9d9091SRichard Lowe or %o4, %o2, %o5 ! insert the new value 610*5d9d9091SRichard Lowe or %o4, %o1, %o4 ! insert the comparison value 611*5d9d9091SRichard Lowe cas [%o0], %o4, %o5 612*5d9d9091SRichard Lowe cmp %o4, %o5 ! did we succeed? 613*5d9d9091SRichard Lowe be,pt %icc, 2f 614*5d9d9091SRichard Lowe and %o5, %o3, %o4 ! isolate the old value 615*5d9d9091SRichard Lowe cmp %o1, %o4 ! should we have succeeded? 616*5d9d9091SRichard Lowe be,a,pt %icc, 1b ! yes, try again 617*5d9d9091SRichard Lowe mov %o5, %o4 ! %o4 = old value 618*5d9d9091SRichard Lowe2: 619*5d9d9091SRichard Lowe retl 620*5d9d9091SRichard Lowe srl %o4, %g1, %o0 ! %o0 = old value 621*5d9d9091SRichard Lowe SET_SIZE(atomic_cas_ushort) 622*5d9d9091SRichard Lowe SET_SIZE(atomic_cas_16) 623*5d9d9091SRichard Lowe 624*5d9d9091SRichard Lowe ENTRY(atomic_cas_32) 625*5d9d9091SRichard Lowe ALTENTRY(atomic_cas_uint) 626*5d9d9091SRichard Lowe ALTENTRY(atomic_cas_ptr) 627*5d9d9091SRichard Lowe ALTENTRY(atomic_cas_ulong) 628*5d9d9091SRichard Lowe cas [%o0], %o1, %o2 629*5d9d9091SRichard Lowe retl 630*5d9d9091SRichard Lowe mov %o2, %o0 631*5d9d9091SRichard Lowe SET_SIZE(atomic_cas_ulong) 632*5d9d9091SRichard Lowe SET_SIZE(atomic_cas_ptr) 633*5d9d9091SRichard Lowe SET_SIZE(atomic_cas_uint) 634*5d9d9091SRichard Lowe SET_SIZE(atomic_cas_32) 635*5d9d9091SRichard Lowe 636*5d9d9091SRichard Lowe ENTRY(atomic_cas_64) 637*5d9d9091SRichard Lowe sllx %o1, 32, %o1 ! cmp's upper 32 in %o1, lower in %o2 638*5d9d9091SRichard Lowe srl %o2, 0, %o2 ! convert 2 32-bit args into 1 64-bit 639*5d9d9091SRichard Lowe add %o1, %o2, %o1 640*5d9d9091SRichard Lowe sllx %o3, 32, %o2 ! newval upper 32 in %o3, lower in %o4 641*5d9d9091SRichard Lowe srl %o4, 0, %o4 ! setup %o2 to have newval 642*5d9d9091SRichard Lowe add %o2, %o4, %o2 643*5d9d9091SRichard Lowe casx [%o0], %o1, %o2 644*5d9d9091SRichard Lowe srl %o2, 0, %o1 ! return lower 32-bits in %o1 645*5d9d9091SRichard Lowe retl 646*5d9d9091SRichard Lowe srlx %o2, 32, %o0 ! return upper 32-bits in %o0 647*5d9d9091SRichard Lowe SET_SIZE(atomic_cas_64) 648*5d9d9091SRichard Lowe 649*5d9d9091SRichard Lowe ENTRY(atomic_swap_8) 650*5d9d9091SRichard Lowe ALTENTRY(atomic_swap_uchar) 651*5d9d9091SRichard Lowe and %o0, 0x3, %o4 ! %o4 = byte offset, left-to-right 652*5d9d9091SRichard Lowe xor %o4, 0x3, %g1 ! %g1 = byte offset, right-to-left 653*5d9d9091SRichard Lowe sll %g1, 3, %g1 ! %g1 = bit offset, right-to-left 654*5d9d9091SRichard Lowe set 0xff, %o3 ! %o3 = mask 655*5d9d9091SRichard Lowe sll %o3, %g1, %o3 ! %o3 = shifted to bit offset 656*5d9d9091SRichard Lowe sll %o1, %g1, %o1 ! %o1 = shifted to bit offset 657*5d9d9091SRichard Lowe and %o1, %o3, %o1 ! %o1 = single byte value 658*5d9d9091SRichard Lowe andn %o0, 0x3, %o0 ! %o0 = word address 659*5d9d9091SRichard Lowe ld [%o0], %o2 ! read old value 660*5d9d9091SRichard Lowe1: 661*5d9d9091SRichard Lowe andn %o2, %o3, %o5 ! clear target bits 662*5d9d9091SRichard Lowe or %o5, %o1, %o5 ! insert the new value 663*5d9d9091SRichard Lowe cas [%o0], %o2, %o5 664*5d9d9091SRichard Lowe cmp %o2, %o5 665*5d9d9091SRichard Lowe bne,a,pn %icc, 1b 666*5d9d9091SRichard Lowe mov %o5, %o2 ! %o2 = old value 667*5d9d9091SRichard Lowe and %o5, %o3, %o5 668*5d9d9091SRichard Lowe retl 669*5d9d9091SRichard Lowe srl %o5, %g1, %o0 ! %o0 = old value 670*5d9d9091SRichard Lowe SET_SIZE(atomic_swap_uchar) 671*5d9d9091SRichard Lowe SET_SIZE(atomic_swap_8) 672*5d9d9091SRichard Lowe 673*5d9d9091SRichard Lowe ENTRY(atomic_swap_16) 674*5d9d9091SRichard Lowe ALTENTRY(atomic_swap_ushort) 675*5d9d9091SRichard Lowe and %o0, 0x2, %o4 ! %o4 = byte offset, left-to-right 676*5d9d9091SRichard Lowe xor %o4, 0x2, %g1 ! %g1 = byte offset, right-to-left 677*5d9d9091SRichard Lowe sll %o4, 3, %o4 ! %o4 = bit offset, left-to-right 678*5d9d9091SRichard Lowe sll %g1, 3, %g1 ! %g1 = bit offset, right-to-left 679*5d9d9091SRichard Lowe sethi %hi(0xffff0000), %o3 ! %o3 = mask 680*5d9d9091SRichard Lowe srl %o3, %o4, %o3 ! %o3 = shifted to bit offset 681*5d9d9091SRichard Lowe sll %o1, %g1, %o1 ! %o1 = shifted to bit offset 682*5d9d9091SRichard Lowe and %o1, %o3, %o1 ! %o1 = single short value 683*5d9d9091SRichard Lowe andn %o0, 0x2, %o0 ! %o0 = word address 684*5d9d9091SRichard Lowe ! if low-order bit is 1, we will properly get an alignment fault here 685*5d9d9091SRichard Lowe ld [%o0], %o2 ! read old value 686*5d9d9091SRichard Lowe1: 687*5d9d9091SRichard Lowe andn %o2, %o3, %o5 ! clear target bits 688*5d9d9091SRichard Lowe or %o5, %o1, %o5 ! insert the new value 689*5d9d9091SRichard Lowe cas [%o0], %o2, %o5 690*5d9d9091SRichard Lowe cmp %o2, %o5 691*5d9d9091SRichard Lowe bne,a,pn %icc, 1b 692*5d9d9091SRichard Lowe mov %o5, %o2 ! %o2 = old value 693*5d9d9091SRichard Lowe and %o5, %o3, %o5 694*5d9d9091SRichard Lowe retl 695*5d9d9091SRichard Lowe srl %o5, %g1, %o0 ! %o0 = old value 696*5d9d9091SRichard Lowe SET_SIZE(atomic_swap_ushort) 697*5d9d9091SRichard Lowe SET_SIZE(atomic_swap_16) 698*5d9d9091SRichard Lowe 699*5d9d9091SRichard Lowe ENTRY(atomic_swap_32) 700*5d9d9091SRichard Lowe ALTENTRY(atomic_swap_uint) 701*5d9d9091SRichard Lowe ALTENTRY(atomic_swap_ptr) 702*5d9d9091SRichard Lowe ALTENTRY(atomic_swap_ulong) 703*5d9d9091SRichard Lowe ld [%o0], %o2 704*5d9d9091SRichard Lowe1: 705*5d9d9091SRichard Lowe mov %o1, %o3 706*5d9d9091SRichard Lowe cas [%o0], %o2, %o3 707*5d9d9091SRichard Lowe cmp %o2, %o3 708*5d9d9091SRichard Lowe bne,a,pn %icc, 1b 709*5d9d9091SRichard Lowe mov %o3, %o2 710*5d9d9091SRichard Lowe retl 711*5d9d9091SRichard Lowe mov %o3, %o0 712*5d9d9091SRichard Lowe SET_SIZE(atomic_swap_ulong) 713*5d9d9091SRichard Lowe SET_SIZE(atomic_swap_ptr) 714*5d9d9091SRichard Lowe SET_SIZE(atomic_swap_uint) 715*5d9d9091SRichard Lowe SET_SIZE(atomic_swap_32) 716*5d9d9091SRichard Lowe 717*5d9d9091SRichard Lowe ENTRY(atomic_swap_64) 718*5d9d9091SRichard Lowe sllx %o1, 32, %o1 ! upper 32 in %o1, lower in %o2 719*5d9d9091SRichard Lowe srl %o2, 0, %o2 720*5d9d9091SRichard Lowe add %o1, %o2, %o1 ! convert 2 32-bit args into 1 64-bit 721*5d9d9091SRichard Lowe ldx [%o0], %o2 722*5d9d9091SRichard Lowe1: 723*5d9d9091SRichard Lowe mov %o1, %o3 724*5d9d9091SRichard Lowe casx [%o0], %o2, %o3 725*5d9d9091SRichard Lowe cmp %o2, %o3 726*5d9d9091SRichard Lowe bne,a,pn %xcc, 1b 727*5d9d9091SRichard Lowe mov %o3, %o2 728*5d9d9091SRichard Lowe srl %o3, 0, %o1 ! return lower 32-bits in %o1 729*5d9d9091SRichard Lowe retl 730*5d9d9091SRichard Lowe srlx %o3, 32, %o0 ! return upper 32-bits in %o0 731*5d9d9091SRichard Lowe SET_SIZE(atomic_swap_64) 732*5d9d9091SRichard Lowe 733*5d9d9091SRichard Lowe ENTRY(atomic_set_long_excl) 734*5d9d9091SRichard Lowe mov 1, %o3 735*5d9d9091SRichard Lowe slln %o3, %o1, %o3 736*5d9d9091SRichard Lowe ldn [%o0], %o2 737*5d9d9091SRichard Lowe1: 738*5d9d9091SRichard Lowe andcc %o2, %o3, %g0 ! test if the bit is set 739*5d9d9091SRichard Lowe bnz,a,pn %ncc, 2f ! if so, then fail out 740*5d9d9091SRichard Lowe mov -1, %o0 741*5d9d9091SRichard Lowe or %o2, %o3, %o4 ! set the bit, and try to commit it 742*5d9d9091SRichard Lowe casn [%o0], %o2, %o4 743*5d9d9091SRichard Lowe cmp %o2, %o4 744*5d9d9091SRichard Lowe bne,a,pn %ncc, 1b ! failed to commit, try again 745*5d9d9091SRichard Lowe mov %o4, %o2 746*5d9d9091SRichard Lowe mov %g0, %o0 747*5d9d9091SRichard Lowe2: 748*5d9d9091SRichard Lowe retl 749*5d9d9091SRichard Lowe nop 750*5d9d9091SRichard Lowe SET_SIZE(atomic_set_long_excl) 751*5d9d9091SRichard Lowe 752*5d9d9091SRichard Lowe ENTRY(atomic_clear_long_excl) 753*5d9d9091SRichard Lowe mov 1, %o3 754*5d9d9091SRichard Lowe slln %o3, %o1, %o3 755*5d9d9091SRichard Lowe ldn [%o0], %o2 756*5d9d9091SRichard Lowe1: 757*5d9d9091SRichard Lowe andncc %o3, %o2, %g0 ! test if the bit is clear 758*5d9d9091SRichard Lowe bnz,a,pn %ncc, 2f ! if so, then fail out 759*5d9d9091SRichard Lowe mov -1, %o0 760*5d9d9091SRichard Lowe andn %o2, %o3, %o4 ! clear the bit, and try to commit it 761*5d9d9091SRichard Lowe casn [%o0], %o2, %o4 762*5d9d9091SRichard Lowe cmp %o2, %o4 763*5d9d9091SRichard Lowe bne,a,pn %ncc, 1b ! failed to commit, try again 764*5d9d9091SRichard Lowe mov %o4, %o2 765*5d9d9091SRichard Lowe mov %g0, %o0 766*5d9d9091SRichard Lowe2: 767*5d9d9091SRichard Lowe retl 768*5d9d9091SRichard Lowe nop 769*5d9d9091SRichard Lowe SET_SIZE(atomic_clear_long_excl) 770*5d9d9091SRichard Lowe 771*5d9d9091SRichard Lowe#if !defined(_KERNEL) 772*5d9d9091SRichard Lowe 773*5d9d9091SRichard Lowe /* 774*5d9d9091SRichard Lowe * Spitfires and Blackbirds have a problem with membars in the 775*5d9d9091SRichard Lowe * delay slot (SF_ERRATA_51). For safety's sake, we assume 776*5d9d9091SRichard Lowe * that the whole world needs the workaround. 777*5d9d9091SRichard Lowe */ 778*5d9d9091SRichard Lowe ENTRY(membar_enter) 779*5d9d9091SRichard Lowe membar #StoreLoad|#StoreStore 780*5d9d9091SRichard Lowe retl 781*5d9d9091SRichard Lowe nop 782*5d9d9091SRichard Lowe SET_SIZE(membar_enter) 783*5d9d9091SRichard Lowe 784*5d9d9091SRichard Lowe ENTRY(membar_exit) 785*5d9d9091SRichard Lowe membar #LoadStore|#StoreStore 786*5d9d9091SRichard Lowe retl 787*5d9d9091SRichard Lowe nop 788*5d9d9091SRichard Lowe SET_SIZE(membar_exit) 789*5d9d9091SRichard Lowe 790*5d9d9091SRichard Lowe ENTRY(membar_producer) 791*5d9d9091SRichard Lowe membar #StoreStore 792*5d9d9091SRichard Lowe retl 793*5d9d9091SRichard Lowe nop 794*5d9d9091SRichard Lowe SET_SIZE(membar_producer) 795*5d9d9091SRichard Lowe 796*5d9d9091SRichard Lowe ENTRY(membar_consumer) 797*5d9d9091SRichard Lowe membar #LoadLoad 798*5d9d9091SRichard Lowe retl 799*5d9d9091SRichard Lowe nop 800*5d9d9091SRichard Lowe SET_SIZE(membar_consumer) 801*5d9d9091SRichard Lowe 802*5d9d9091SRichard Lowe#endif /* !_KERNEL */ 803