Tue, 29 Apr 2014 22:05:10 -0700
8042059: Various fixes to linux/sparc
Reviewed-by: twisti, kvn
phh@568 | 1 | /* |
simonis@4675 | 2 | * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. |
phh@568 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
phh@568 | 4 | * |
phh@568 | 5 | * This code is free software; you can redistribute it and/or modify it |
phh@568 | 6 | * under the terms of the GNU General Public License version 2 only, as |
phh@568 | 7 | * published by the Free Software Foundation. |
phh@568 | 8 | * |
phh@568 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
phh@568 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
phh@568 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
phh@568 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
phh@568 | 13 | * accompanied this code). |
phh@568 | 14 | * |
phh@568 | 15 | * You should have received a copy of the GNU General Public License version |
phh@568 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
phh@568 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
phh@568 | 18 | * |
trims@1907 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
trims@1907 | 20 | * or visit www.oracle.com if you need additional information or have any |
trims@1907 | 21 | * questions. |
phh@568 | 22 | * |
phh@568 | 23 | */ |
phh@568 | 24 | |
stefank@2314 | 25 | #ifndef OS_CPU_LINUX_SPARC_VM_ATOMIC_LINUX_SPARC_INLINE_HPP |
stefank@2314 | 26 | #define OS_CPU_LINUX_SPARC_VM_ATOMIC_LINUX_SPARC_INLINE_HPP |
stefank@2314 | 27 | |
stefank@2314 | 28 | #include "runtime/atomic.hpp" |
stefank@2314 | 29 | #include "runtime/os.hpp" |
stefank@2314 | 30 | #include "vm_version_sparc.hpp" |
stefank@2314 | 31 | |
phh@568 | 32 | // Implementation of class atomic |
phh@568 | 33 | |
phh@568 | 34 | inline void Atomic::store (jbyte store_value, jbyte* dest) { *dest = store_value; } |
phh@568 | 35 | inline void Atomic::store (jshort store_value, jshort* dest) { *dest = store_value; } |
phh@568 | 36 | inline void Atomic::store (jint store_value, jint* dest) { *dest = store_value; } |
phh@568 | 37 | inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; } |
phh@568 | 38 | inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) { *dest = store_value; } |
phh@568 | 39 | inline void Atomic::store_ptr(void* store_value, void* dest) { *(void**)dest = store_value; } |
phh@568 | 40 | |
phh@568 | 41 | inline void Atomic::store (jbyte store_value, volatile jbyte* dest) { *dest = store_value; } |
phh@568 | 42 | inline void Atomic::store (jshort store_value, volatile jshort* dest) { *dest = store_value; } |
phh@568 | 43 | inline void Atomic::store (jint store_value, volatile jint* dest) { *dest = store_value; } |
phh@568 | 44 | inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; } |
phh@568 | 45 | inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; } |
phh@568 | 46 | inline void Atomic::store_ptr(void* store_value, volatile void* dest) { *(void* volatile *)dest = store_value; } |
phh@568 | 47 | |
phh@568 | 48 | inline void Atomic::inc (volatile jint* dest) { (void)add (1, dest); } |
phh@568 | 49 | inline void Atomic::inc_ptr(volatile intptr_t* dest) { (void)add_ptr(1, dest); } |
phh@568 | 50 | inline void Atomic::inc_ptr(volatile void* dest) { (void)add_ptr(1, dest); } |
phh@568 | 51 | |
phh@568 | 52 | inline void Atomic::dec (volatile jint* dest) { (void)add (-1, dest); } |
phh@568 | 53 | inline void Atomic::dec_ptr(volatile intptr_t* dest) { (void)add_ptr(-1, dest); } |
phh@568 | 54 | inline void Atomic::dec_ptr(volatile void* dest) { (void)add_ptr(-1, dest); } |
phh@568 | 55 | |
kvn@2434 | 56 | inline jlong Atomic::load(volatile jlong* src) { return *src; } |
kvn@2434 | 57 | |
phh@568 | 58 | inline jint Atomic::add (jint add_value, volatile jint* dest) { |
phh@568 | 59 | intptr_t rv; |
phh@568 | 60 | __asm__ volatile( |
phh@568 | 61 | "1: \n\t" |
phh@568 | 62 | " ld [%2], %%o2\n\t" |
phh@568 | 63 | " add %1, %%o2, %%o3\n\t" |
phh@568 | 64 | " cas [%2], %%o2, %%o3\n\t" |
phh@568 | 65 | " cmp %%o2, %%o3\n\t" |
phh@568 | 66 | " bne 1b\n\t" |
phh@568 | 67 | " nop\n\t" |
phh@568 | 68 | " add %1, %%o2, %0\n\t" |
phh@568 | 69 | : "=r" (rv) |
phh@568 | 70 | : "r" (add_value), "r" (dest) |
phh@568 | 71 | : "memory", "o2", "o3"); |
phh@568 | 72 | return rv; |
phh@568 | 73 | } |
phh@568 | 74 | |
phh@568 | 75 | inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) { |
phh@568 | 76 | intptr_t rv; |
phh@568 | 77 | #ifdef _LP64 |
phh@568 | 78 | __asm__ volatile( |
phh@568 | 79 | "1: \n\t" |
phh@568 | 80 | " ldx [%2], %%o2\n\t" |
mikael@6683 | 81 | " add %1, %%o2, %%o3\n\t" |
phh@568 | 82 | " casx [%2], %%o2, %%o3\n\t" |
phh@568 | 83 | " cmp %%o2, %%o3\n\t" |
phh@568 | 84 | " bne %%xcc, 1b\n\t" |
phh@568 | 85 | " nop\n\t" |
mikael@6683 | 86 | " add %1, %%o2, %0\n\t" |
phh@568 | 87 | : "=r" (rv) |
phh@568 | 88 | : "r" (add_value), "r" (dest) |
phh@568 | 89 | : "memory", "o2", "o3"); |
phh@568 | 90 | #else |
phh@568 | 91 | __asm__ volatile( |
phh@568 | 92 | "1: \n\t" |
phh@568 | 93 | " ld [%2], %%o2\n\t" |
phh@568 | 94 | " add %1, %%o2, %%o3\n\t" |
phh@568 | 95 | " cas [%2], %%o2, %%o3\n\t" |
phh@568 | 96 | " cmp %%o2, %%o3\n\t" |
phh@568 | 97 | " bne 1b\n\t" |
phh@568 | 98 | " nop\n\t" |
phh@568 | 99 | " add %1, %%o2, %0\n\t" |
phh@568 | 100 | : "=r" (rv) |
phh@568 | 101 | : "r" (add_value), "r" (dest) |
phh@568 | 102 | : "memory", "o2", "o3"); |
phh@568 | 103 | #endif // _LP64 |
phh@568 | 104 | return rv; |
phh@568 | 105 | } |
phh@568 | 106 | |
phh@568 | 107 | inline void* Atomic::add_ptr(intptr_t add_value, volatile void* dest) { |
phh@568 | 108 | return (void*)add_ptr((intptr_t)add_value, (volatile intptr_t*)dest); |
phh@568 | 109 | } |
phh@568 | 110 | |
phh@568 | 111 | |
phh@568 | 112 | inline jint Atomic::xchg (jint exchange_value, volatile jint* dest) { |
phh@568 | 113 | intptr_t rv = exchange_value; |
phh@568 | 114 | __asm__ volatile( |
phh@568 | 115 | " swap [%2],%1\n\t" |
phh@568 | 116 | : "=r" (rv) |
phh@568 | 117 | : "0" (exchange_value) /* we use same register as for return value */, "r" (dest) |
phh@568 | 118 | : "memory"); |
phh@568 | 119 | return rv; |
phh@568 | 120 | } |
phh@568 | 121 | |
phh@568 | 122 | inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) { |
phh@568 | 123 | intptr_t rv = exchange_value; |
phh@568 | 124 | #ifdef _LP64 |
phh@568 | 125 | __asm__ volatile( |
phh@568 | 126 | "1:\n\t" |
phh@568 | 127 | " mov %1, %%o3\n\t" |
phh@568 | 128 | " ldx [%2], %%o2\n\t" |
phh@568 | 129 | " casx [%2], %%o2, %%o3\n\t" |
phh@568 | 130 | " cmp %%o2, %%o3\n\t" |
phh@568 | 131 | " bne %%xcc, 1b\n\t" |
phh@568 | 132 | " nop\n\t" |
phh@568 | 133 | " mov %%o2, %0\n\t" |
phh@568 | 134 | : "=r" (rv) |
phh@568 | 135 | : "r" (exchange_value), "r" (dest) |
phh@568 | 136 | : "memory", "o2", "o3"); |
phh@568 | 137 | #else |
phh@568 | 138 | __asm__ volatile( |
phh@568 | 139 | "swap [%2],%1\n\t" |
phh@568 | 140 | : "=r" (rv) |
phh@568 | 141 | : "0" (exchange_value) /* we use same register as for return value */, "r" (dest) |
phh@568 | 142 | : "memory"); |
phh@568 | 143 | #endif // _LP64 |
phh@568 | 144 | return rv; |
phh@568 | 145 | } |
phh@568 | 146 | |
phh@568 | 147 | inline void* Atomic::xchg_ptr(void* exchange_value, volatile void* dest) { |
phh@568 | 148 | return (void*)xchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest); |
phh@568 | 149 | } |
phh@568 | 150 | |
phh@568 | 151 | |
phh@568 | 152 | inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) { |
phh@568 | 153 | jint rv; |
phh@568 | 154 | __asm__ volatile( |
phh@568 | 155 | " cas [%2], %3, %0" |
phh@568 | 156 | : "=r" (rv) |
phh@568 | 157 | : "0" (exchange_value), "r" (dest), "r" (compare_value) |
phh@568 | 158 | : "memory"); |
phh@568 | 159 | return rv; |
phh@568 | 160 | } |
phh@568 | 161 | |
phh@568 | 162 | inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value) { |
phh@568 | 163 | #ifdef _LP64 |
phh@568 | 164 | jlong rv; |
phh@568 | 165 | __asm__ volatile( |
phh@568 | 166 | " casx [%2], %3, %0" |
phh@568 | 167 | : "=r" (rv) |
phh@568 | 168 | : "0" (exchange_value), "r" (dest), "r" (compare_value) |
phh@568 | 169 | : "memory"); |
phh@568 | 170 | return rv; |
phh@568 | 171 | #else |
phh@568 | 172 | volatile jlong_accessor evl, cvl, rv; |
phh@568 | 173 | evl.long_value = exchange_value; |
phh@568 | 174 | cvl.long_value = compare_value; |
phh@568 | 175 | |
phh@568 | 176 | __asm__ volatile( |
phh@568 | 177 | " sllx %2, 32, %2\n\t" |
phh@568 | 178 | " srl %3, 0, %3\n\t" |
phh@568 | 179 | " or %2, %3, %2\n\t" |
phh@568 | 180 | " sllx %5, 32, %5\n\t" |
phh@568 | 181 | " srl %6, 0, %6\n\t" |
phh@568 | 182 | " or %5, %6, %5\n\t" |
phh@568 | 183 | " casx [%4], %5, %2\n\t" |
phh@568 | 184 | " srl %2, 0, %1\n\t" |
phh@568 | 185 | " srlx %2, 32, %0\n\t" |
phh@568 | 186 | : "=r" (rv.words[0]), "=r" (rv.words[1]) |
phh@568 | 187 | : "r" (evl.words[0]), "r" (evl.words[1]), "r" (dest), "r" (cvl.words[0]), "r" (cvl.words[1]) |
phh@568 | 188 | : "memory"); |
phh@568 | 189 | |
phh@568 | 190 | return rv.long_value; |
phh@568 | 191 | #endif |
phh@568 | 192 | } |
phh@568 | 193 | |
phh@568 | 194 | inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) { |
phh@568 | 195 | intptr_t rv; |
phh@568 | 196 | #ifdef _LP64 |
phh@568 | 197 | __asm__ volatile( |
phh@568 | 198 | " casx [%2], %3, %0" |
phh@568 | 199 | : "=r" (rv) |
phh@568 | 200 | : "0" (exchange_value), "r" (dest), "r" (compare_value) |
phh@568 | 201 | : "memory"); |
phh@568 | 202 | #else |
phh@568 | 203 | __asm__ volatile( |
phh@568 | 204 | " cas [%2], %3, %0" |
phh@568 | 205 | : "=r" (rv) |
phh@568 | 206 | : "0" (exchange_value), "r" (dest), "r" (compare_value) |
phh@568 | 207 | : "memory"); |
phh@568 | 208 | #endif // _LP64 |
phh@568 | 209 | return rv; |
phh@568 | 210 | } |
phh@568 | 211 | |
phh@568 | 212 | inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) { |
phh@568 | 213 | return (void*)cmpxchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest, (intptr_t)compare_value); |
phh@568 | 214 | } |
stefank@2314 | 215 | |
stefank@2314 | 216 | #endif // OS_CPU_LINUX_SPARC_VM_ATOMIC_LINUX_SPARC_INLINE_HPP |