1 //
   2 // Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
   3 // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4 //
   5 // This code is free software; you can redistribute it and/or modify it
   6 // under the terms of the GNU General Public License version 2 only, as
   7 // published by the Free Software Foundation.
   8 //
   9 // This code is distributed in the hope that it will be useful, but WITHOUT
  10 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12 // version 2 for more details (a copy is included in the LICENSE file that
  13 // accompanied this code).
  14 //
  15 // You should have received a copy of the GNU General Public License version
  16 // 2 along with this work; if not, write to the Free Software Foundation,
  17 // Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18 //
  19 // Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20 // or visit www.oracle.com if you need additional information or have any
  21 // questions.
  22 //  
  23 //
  24 
  25   // Get the raw thread ID from %g7
  26 
  27        .inline  _raw_thread_id, 0
  28        .register %g7,#scratch
  29        .volatile
  30        mov     %g7, %o0
  31        .nonvolatile
  32        .end
  33 
  34 
  35   // Clear SPARC fprs.FEF DU and DL bits --
  36   // allows the kernel to avoid saving FPU state at context-switch time.
  37   // Use for state-transition points (into _thread_blocked) or when
  38   // parking. 
  39       
  40        .inline _mark_fpu_nosave, 0
  41        .volatile
  42        wr   %g0, 0, %fprs       
  43        .nonvolatile
  44        .end
  45 
  46   // Support for jint Atomic::xchg(jint exchange_value, volatile jint* dest).
  47   //
  48   // Arguments:
  49   //      exchange_value: O0
  50   //      dest:           O1
  51   //
  52   // Results:
  53   //     O0: the value previously stored in dest
  54 
  55         .inline _Atomic_swap32, 2
  56         .volatile
  57         swap    [%o1],%o0
  58         .nonvolatile
  59         .end
  60 
  61 
  62   // Support for intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t * dest).
  63   //
  64   // 64-bit
  65   //
  66   // Arguments:
  67   //      exchange_value: O0
  68   //      dest:           O1
  69   //
  70   // Results:
  71   //     O0: the value previously stored in dest
  72 
  73         .inline _Atomic_swap64, 2
  74         .volatile
  75     1:
  76         mov     %o0, %o3
  77         ldx     [%o1], %o2
  78         casx    [%o1], %o2, %o3
  79         cmp     %o2, %o3
  80         bne     %xcc, 1b
  81          nop
  82         mov     %o2, %o0
  83         .nonvolatile
  84         .end
  85 
  86 
  87   // Support for jint Atomic::cmpxchg(jint           exchange_value,
  88   //                                  volatile jint* dest, 
  89   //                                  jint           compare_value)
  90   //
  91   // Arguments:
  92   //      exchange_value: O0
  93   //      dest:           O1
  94   //      compare_value:  O2
  95   //
  96   // Results:
  97   //     O0: the value previously stored in dest
  98 
  99         .inline _Atomic_cas32, 3
 100         .volatile
 101         cas     [%o1], %o2, %o0
 102         .nonvolatile
 103         .end
 104 
 105 
 106   // Support for intptr_t Atomic::cmpxchg_ptr(intptr_t           exchange_value, 
 107   //                                          volatile intptr_t* dest, 
 108   //                                          intptr_t           compare_value)
 109   //
 110   // 64-bit
 111   //
 112   // Arguments:
 113   //      exchange_value: O0
 114   //      dest:           O1
 115   //      compare_value:  O2
 116   //
 117   // Results:
 118   //     O0: the value previously stored in dest
 119 
 120         .inline _Atomic_cas64, 3
 121         .volatile
 122         casx    [%o1], %o2, %o0
 123         .nonvolatile
 124         .end
 125 
 126 
 127   // Support for jlong Atomic::cmpxchg(jlong           exchange_value, 
 128   //                                   volatile jlong* dest, 
 129   //                                   jlong           compare_value)
 130   //
 131   // 32-bit calling conventions
 132   //
 133   // Arguments:
 134   //      exchange_value: O1:O0
 135   //      dest:           O2
 136   //      compare_value:  O4:O3
 137   //
 138   // Results:
 139   //     O1:O0: the value previously stored in dest
 140 
 141         .inline _Atomic_casl, 3
 142         .volatile
 143         sllx    %o0, 32, %o0
 144         srl     %o1, 0, %o1
 145         or      %o0,%o1,%o0
 146         sllx    %o3, 32, %o3
 147         srl     %o4, 0, %o4
 148         or      %o3,%o4,%o3
 149         casx    [%o2], %o3, %o0
 150         srl     %o0, 0, %o1
 151         srlx    %o0, 32, %o0
 152         .nonvolatile
 153         .end
 154 
 155   // Support for jlong Atomic::load and Atomic::store on v9.
 156   //
 157   // void _Atomic_move_long_v9(volatile jlong* src, volatile jlong* dst)
 158   //
 159   // Arguments:
 160   //      src:  O0
 161   //      dest: O1
 162   //
 163   // Overwrites O2
 164 
 165         .inline _Atomic_move_long_v9,2
 166         .volatile
 167         ldx     [%o0], %o2
 168         stx     %o2, [%o1]
 169         .nonvolatile
 170         .end
 171 
 172   // Support for jint Atomic::add(jint add_value, volatile jint* dest).
 173   //
 174   // Arguments:
 175   //      add_value: O0   (e.g., +1 or -1)
 176   //      dest:      O1
 177   //
 178   // Results:
 179   //     O0: the new value stored in dest
 180   //
 181   // Overwrites O3
 182 
 183         .inline _Atomic_add32, 2
 184         .volatile
 185     2:
 186         ld      [%o1], %o2
 187         add     %o0, %o2, %o3
 188         cas     [%o1], %o2, %o3
 189         cmp     %o2, %o3
 190         bne     2b
 191          nop
 192         add     %o0, %o2, %o0
 193         .nonvolatile
 194         .end
 195 
 196 
 197   // Support for intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest)
 198   //
 199   // 64-bit
 200   //
 201   // Arguments:
 202   //      add_value: O0   (e.g., +1 or -1)
 203   //      dest:      O1
 204   //
 205   // Results:
 206   //     O0: the new value stored in dest
 207   //
 208   // Overwrites O3
 209 
 210         .inline _Atomic_add64, 2
 211         .volatile
 212     3:
 213         ldx     [%o1], %o2
 214         add     %o0, %o2, %o3
 215         casx    [%o1], %o2, %o3
 216         cmp     %o2, %o3
 217         bne     %xcc, 3b
 218          nop
 219         add     %o0, %o2, %o0
 220         .nonvolatile
 221         .end
 222 
 223 
 224   // Support for void OrderAccess::acquire()
 225   // The method is intentionally empty.  
 226   // It exists for the sole purpose of generating
 227   // a C/C++ sequence point over which the compiler won't 
 228   // reorder code.
 229 
 230         .inline _OrderAccess_acquire,0
 231         .volatile
 232         .nonvolatile
 233         .end
 234 
 235 
 236   // Support for void OrderAccess::fence()
 237 
 238         .inline _OrderAccess_fence,0
 239         .volatile
 240         membar  #StoreLoad
 241         .nonvolatile
 242         .end
 243 
 244 
 245   // Support for void Prefetch::read(void *loc, intx interval)
 246   //
 247   // Prefetch for several reads.
 248 
 249         .inline _Prefetch_read, 2
 250         .volatile
 251         prefetch [%o0+%o1], 0
 252         .nonvolatile
 253         .end
 254 
 255 
 256   // Support for void Prefetch::write(void *loc, intx interval)
 257   //
 258   // Prefetch for several writes.
 259 
 260         .inline _Prefetch_write, 2
 261         .volatile
 262         prefetch [%o0+%o1], 2
 263         .nonvolatile
 264         .end
 265 
 266 
 267   // Support for void Copy::conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count)
 268   //
 269   // 32-bit
 270   //
 271   // Arguments:
 272   //      from:  O0
 273   //      to:    O1
 274   //      count: O2 treated as signed
 275   //
 276   // Clobbers:
 277   //      long_value: O2, O3
 278   //      count:      O4
 279   //
 280   // if (from > to) {
 281   //   while (--count >= 0) {
 282   //     *to++ = *from++;
 283   //   }
 284   // } else {
 285   //   while (--count >= 0) {
 286   //     to[count] = from[count];
 287   //   }
 288   // }
 289         .inline _Copy_conjoint_jlongs_atomic, 3
 290         .volatile
 291         cmp     %o0, %o1
 292         bleu    4f
 293         sll     %o2, 3, %o4
 294         ba      2f
 295     1:
 296         subcc   %o4, 8, %o4
 297         std     %o2, [%o1]
 298         add     %o0, 8, %o0
 299         add     %o1, 8, %o1
 300     2:
 301         bge,a   1b
 302         ldd     [%o0], %o2
 303         ba      5f
 304         nop
 305     3:
 306         std     %o2, [%o1+%o4]
 307     4:
 308         subcc   %o4, 8, %o4
 309         bge,a   3b
 310         ldd     [%o0+%o4], %o2
 311     5:
 312         .nonvolatile
 313         .end