annotate DEPENDENCIES/generic/include/boost/atomic/detail/ops_gcc_ppc.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents f46d142149f5
children
rev   line source
Chris@102 1 /*
Chris@102 2 * Distributed under the Boost Software License, Version 1.0.
Chris@102 3 * (See accompanying file LICENSE_1_0.txt or copy at
Chris@102 4 * http://www.boost.org/LICENSE_1_0.txt)
Chris@102 5 *
Chris@102 6 * Copyright (c) 2009 Helge Bahmann
Chris@102 7 * Copyright (c) 2013 Tim Blechmann
Chris@102 8 * Copyright (c) 2014 Andrey Semashev
Chris@102 9 */
Chris@102 10 /*!
Chris@102 11 * \file atomic/detail/ops_gcc_ppc.hpp
Chris@102 12 *
Chris@102 13 * This header contains implementation of the \c operations template.
Chris@102 14 */
Chris@102 15
Chris@102 16 #ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_PPC_HPP_INCLUDED_
Chris@102 17 #define BOOST_ATOMIC_DETAIL_OPS_GCC_PPC_HPP_INCLUDED_
Chris@102 18
Chris@102 19 #include <boost/memory_order.hpp>
Chris@102 20 #include <boost/atomic/detail/config.hpp>
Chris@102 21 #include <boost/atomic/detail/storage_type.hpp>
Chris@102 22 #include <boost/atomic/detail/operations_fwd.hpp>
Chris@102 23 #include <boost/atomic/capabilities.hpp>
Chris@102 24
Chris@102 25 #ifdef BOOST_HAS_PRAGMA_ONCE
Chris@102 26 #pragma once
Chris@102 27 #endif
Chris@102 28
Chris@102 29 namespace boost {
Chris@102 30 namespace atomics {
Chris@102 31 namespace detail {
Chris@102 32
Chris@102 33 /*
Chris@102 34 Refer to: Motorola: "Programming Environments Manual for 32-Bit
Chris@102 35 Implementations of the PowerPC Architecture", Appendix E:
Chris@102 36 "Synchronization Programming Examples" for an explanation of what is
Chris@102 37 going on here (can be found on the web at various places by the
Chris@102 38 name "MPCFPE32B.pdf", Google is your friend...)
Chris@102 39
Chris@102 40 Most of the atomic operations map to instructions in a relatively
Chris@102 41 straight-forward fashion, but "load"s may at first glance appear
Chris@102 42 a bit strange as they map to:
Chris@102 43
Chris@102 44 lwz %rX, addr
Chris@102 45 cmpw %rX, %rX
Chris@102 46 bne- 1f
Chris@102 47 1:
Chris@102 48
Chris@102 49 That is, the CPU is forced to perform a branch that "formally" depends
Chris@102 50 on the value retrieved from memory. This scheme has an overhead of
Chris@102 51 about 1-2 clock cycles per load, but it allows to map "acquire" to
Chris@102 52 the "isync" instruction instead of "sync" uniformly and for all type
Chris@102 53 of atomic operations. Since "isync" has a cost of about 15 clock
Chris@102 54 cycles, while "sync" hast a cost of about 50 clock cycles, the small
Chris@102 55 penalty to atomic loads more than compensates for this.
Chris@102 56
Chris@102 57 Byte- and halfword-sized atomic values are realized by encoding the
Chris@102 58 value to be represented into a word, performing sign/zero extension
Chris@102 59 as appropriate. This means that after add/sub operations the value
Chris@102 60 needs fixing up to accurately preserve the wrap-around semantic of
Chris@102 61 the smaller type. (Nothing special needs to be done for the bit-wise
Chris@102 62 and the "exchange type" operators as the compiler already sees to
Chris@102 63 it that values carried in registers are extended appropriately and
Chris@102 64 everything falls into place naturally).
Chris@102 65
Chris@102 66 The register constraint "b" instructs gcc to use any register
Chris@102 67 except r0; this is sometimes required because the encoding for
Chris@102 68 r0 is used to signify "constant zero" in a number of instructions,
Chris@102 69 making r0 unusable in this place. For simplicity this constraint
Chris@102 70 is used everywhere since I am to lazy to look this up on a
Chris@102 71 per-instruction basis, and ppc has enough registers for this not
Chris@102 72 to pose a problem.
Chris@102 73 */
Chris@102 74
Chris@102 75 // A note about memory_order_consume. Technically, this architecture allows to avoid
Chris@102 76 // unnecessary memory barrier after consume load since it supports data dependency ordering.
Chris@102 77 // However, some compiler optimizations may break a seemingly valid code relying on data
Chris@102 78 // dependency tracking by injecting bogus branches to aid out of order execution.
Chris@102 79 // This may happen not only in Boost.Atomic code but also in user's code, which we have no
Chris@102 80 // control of. See this thread: http://lists.boost.org/Archives/boost/2014/06/213890.php.
Chris@102 81 // For this reason we promote memory_order_consume to memory_order_acquire.
Chris@102 82
Chris@102 83 struct gcc_ppc_operations_base
Chris@102 84 {
Chris@102 85 static BOOST_FORCEINLINE void fence_before(memory_order order) BOOST_NOEXCEPT
Chris@102 86 {
Chris@102 87 #if defined(__powerpc64__)
Chris@102 88 if (order == memory_order_seq_cst)
Chris@102 89 __asm__ __volatile__ ("sync" ::: "memory");
Chris@102 90 else if ((order & memory_order_release) != 0)
Chris@102 91 __asm__ __volatile__ ("lwsync" ::: "memory");
Chris@102 92 #else
Chris@102 93 if ((order & memory_order_release) != 0)
Chris@102 94 __asm__ __volatile__ ("sync" ::: "memory");
Chris@102 95 #endif
Chris@102 96 }
Chris@102 97
Chris@102 98 static BOOST_FORCEINLINE void fence_after(memory_order order) BOOST_NOEXCEPT
Chris@102 99 {
Chris@102 100 if ((order & (memory_order_consume | memory_order_acquire)) != 0)
Chris@102 101 __asm__ __volatile__ ("isync" ::: "memory");
Chris@102 102 }
Chris@102 103
Chris@102 104 static BOOST_FORCEINLINE void fence_after_store(memory_order order) BOOST_NOEXCEPT
Chris@102 105 {
Chris@102 106 if (order == memory_order_seq_cst)
Chris@102 107 __asm__ __volatile__ ("sync" ::: "memory");
Chris@102 108 }
Chris@102 109 };
Chris@102 110
Chris@102 111
Chris@102 112 template< bool Signed >
Chris@102 113 struct operations< 4u, Signed > :
Chris@102 114 public gcc_ppc_operations_base
Chris@102 115 {
Chris@102 116 typedef typename make_storage_type< 4u, Signed >::type storage_type;
Chris@102 117
Chris@102 118 static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
Chris@102 119 {
Chris@102 120 fence_before(order);
Chris@102 121 __asm__ __volatile__
Chris@102 122 (
Chris@102 123 "stw %1, %0\n"
Chris@102 124 : "+m" (storage)
Chris@102 125 : "r" (v)
Chris@102 126 );
Chris@102 127 fence_after_store(order);
Chris@102 128 }
Chris@102 129
Chris@102 130 static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
Chris@102 131 {
Chris@102 132 storage_type v;
Chris@102 133 __asm__ __volatile__
Chris@102 134 (
Chris@102 135 "lwz %0, %1\n"
Chris@102 136 "cmpw %0, %0\n"
Chris@102 137 "bne- 1f\n"
Chris@102 138 "1:\n"
Chris@102 139 : "=&r" (v)
Chris@102 140 : "m" (storage)
Chris@102 141 : "cr0"
Chris@102 142 );
Chris@102 143 fence_after(order);
Chris@102 144 return v;
Chris@102 145 }
Chris@102 146
Chris@102 147 static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
Chris@102 148 {
Chris@102 149 storage_type original;
Chris@102 150 fence_before(order);
Chris@102 151 __asm__ __volatile__
Chris@102 152 (
Chris@102 153 "1:\n"
Chris@102 154 "lwarx %0,%y1\n"
Chris@102 155 "stwcx. %2,%y1\n"
Chris@102 156 "bne- 1b\n"
Chris@102 157 : "=&b" (original), "+Z" (storage)
Chris@102 158 : "b" (v)
Chris@102 159 : "cr0"
Chris@102 160 );
Chris@102 161 fence_after(order);
Chris@102 162 return original;
Chris@102 163 }
Chris@102 164
Chris@102 165 static BOOST_FORCEINLINE bool compare_exchange_weak(
Chris@102 166 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
Chris@102 167 {
Chris@102 168 int success;
Chris@102 169 fence_before(success_order);
Chris@102 170 __asm__ __volatile__
Chris@102 171 (
Chris@102 172 "li %1, 0\n"
Chris@102 173 "lwarx %0,%y2\n"
Chris@102 174 "cmpw %0, %3\n"
Chris@102 175 "bne- 1f\n"
Chris@102 176 "stwcx. %4,%y2\n"
Chris@102 177 "bne- 1f\n"
Chris@102 178 "li %1, 1\n"
Chris@102 179 "1:"
Chris@102 180 : "=&b" (expected), "=&b" (success), "+Z" (storage)
Chris@102 181 : "b" (expected), "b" (desired)
Chris@102 182 : "cr0"
Chris@102 183 );
Chris@102 184 if (success)
Chris@102 185 fence_after(success_order);
Chris@102 186 else
Chris@102 187 fence_after(failure_order);
Chris@102 188 return !!success;
Chris@102 189 }
Chris@102 190
Chris@102 191 static BOOST_FORCEINLINE bool compare_exchange_strong(
Chris@102 192 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
Chris@102 193 {
Chris@102 194 int success;
Chris@102 195 fence_before(success_order);
Chris@102 196 __asm__ __volatile__
Chris@102 197 (
Chris@102 198 "li %1, 0\n"
Chris@102 199 "0: lwarx %0,%y2\n"
Chris@102 200 "cmpw %0, %3\n"
Chris@102 201 "bne- 1f\n"
Chris@102 202 "stwcx. %4,%y2\n"
Chris@102 203 "bne- 0b\n"
Chris@102 204 "li %1, 1\n"
Chris@102 205 "1:"
Chris@102 206 : "=&b" (expected), "=&b" (success), "+Z" (storage)
Chris@102 207 : "b" (expected), "b" (desired)
Chris@102 208 : "cr0"
Chris@102 209 );
Chris@102 210 if (success)
Chris@102 211 fence_after(success_order);
Chris@102 212 else
Chris@102 213 fence_after(failure_order);
Chris@102 214 return !!success;
Chris@102 215 }
Chris@102 216
Chris@102 217 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
Chris@102 218 {
Chris@102 219 storage_type original, tmp;
Chris@102 220 fence_before(order);
Chris@102 221 __asm__ __volatile__
Chris@102 222 (
Chris@102 223 "1:\n"
Chris@102 224 "lwarx %0,%y2\n"
Chris@102 225 "add %1,%0,%3\n"
Chris@102 226 "stwcx. %1,%y2\n"
Chris@102 227 "bne- 1b\n"
Chris@102 228 : "=&b" (original), "=&b" (tmp), "+Z" (storage)
Chris@102 229 : "b" (v)
Chris@102 230 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
Chris@102 231 );
Chris@102 232 fence_after(order);
Chris@102 233 return original;
Chris@102 234 }
Chris@102 235
Chris@102 236 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
Chris@102 237 {
Chris@102 238 storage_type original, tmp;
Chris@102 239 fence_before(order);
Chris@102 240 __asm__ __volatile__
Chris@102 241 (
Chris@102 242 "1:\n"
Chris@102 243 "lwarx %0,%y2\n"
Chris@102 244 "sub %1,%0,%3\n"
Chris@102 245 "stwcx. %1,%y2\n"
Chris@102 246 "bne- 1b\n"
Chris@102 247 : "=&b" (original), "=&b" (tmp), "+Z" (storage)
Chris@102 248 : "b" (v)
Chris@102 249 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
Chris@102 250 );
Chris@102 251 fence_after(order);
Chris@102 252 return original;
Chris@102 253 }
Chris@102 254
Chris@102 255 static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
Chris@102 256 {
Chris@102 257 storage_type original, tmp;
Chris@102 258 fence_before(order);
Chris@102 259 __asm__ __volatile__
Chris@102 260 (
Chris@102 261 "1:\n"
Chris@102 262 "lwarx %0,%y2\n"
Chris@102 263 "and %1,%0,%3\n"
Chris@102 264 "stwcx. %1,%y2\n"
Chris@102 265 "bne- 1b\n"
Chris@102 266 : "=&b" (original), "=&b" (tmp), "+Z" (storage)
Chris@102 267 : "b" (v)
Chris@102 268 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
Chris@102 269 );
Chris@102 270 fence_after(order);
Chris@102 271 return original;
Chris@102 272 }
Chris@102 273
Chris@102 274 static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
Chris@102 275 {
Chris@102 276 storage_type original, tmp;
Chris@102 277 fence_before(order);
Chris@102 278 __asm__ __volatile__
Chris@102 279 (
Chris@102 280 "1:\n"
Chris@102 281 "lwarx %0,%y2\n"
Chris@102 282 "or %1,%0,%3\n"
Chris@102 283 "stwcx. %1,%y2\n"
Chris@102 284 "bne- 1b\n"
Chris@102 285 : "=&b" (original), "=&b" (tmp), "+Z" (storage)
Chris@102 286 : "b" (v)
Chris@102 287 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
Chris@102 288 );
Chris@102 289 fence_after(order);
Chris@102 290 return original;
Chris@102 291 }
Chris@102 292
Chris@102 293 static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
Chris@102 294 {
Chris@102 295 storage_type original, tmp;
Chris@102 296 fence_before(order);
Chris@102 297 __asm__ __volatile__
Chris@102 298 (
Chris@102 299 "1:\n"
Chris@102 300 "lwarx %0,%y2\n"
Chris@102 301 "xor %1,%0,%3\n"
Chris@102 302 "stwcx. %1,%y2\n"
Chris@102 303 "bne- 1b\n"
Chris@102 304 : "=&b" (original), "=&b" (tmp), "+Z" (storage)
Chris@102 305 : "b" (v)
Chris@102 306 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
Chris@102 307 );
Chris@102 308 fence_after(order);
Chris@102 309 return original;
Chris@102 310 }
Chris@102 311
Chris@102 312 static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
Chris@102 313 {
Chris@102 314 return !!exchange(storage, (storage_type)1, order);
Chris@102 315 }
Chris@102 316
Chris@102 317 static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
Chris@102 318 {
Chris@102 319 store(storage, 0, order);
Chris@102 320 }
Chris@102 321
Chris@102 322 static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
Chris@102 323 {
Chris@102 324 return true;
Chris@102 325 }
Chris@102 326 };
Chris@102 327
Chris@102 328
Chris@102 329 template< >
Chris@102 330 struct operations< 1u, false > :
Chris@102 331 public operations< 4u, false >
Chris@102 332 {
Chris@102 333 typedef operations< 4u, false > base_type;
Chris@102 334 typedef base_type::storage_type storage_type;
Chris@102 335
Chris@102 336 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
Chris@102 337 {
Chris@102 338 storage_type original, tmp;
Chris@102 339 fence_before(order);
Chris@102 340 __asm__ __volatile__
Chris@102 341 (
Chris@102 342 "1:\n"
Chris@102 343 "lwarx %0,%y2\n"
Chris@102 344 "add %1,%0,%3\n"
Chris@102 345 "rlwinm %1, %1, 0, 0xff\n"
Chris@102 346 "stwcx. %1,%y2\n"
Chris@102 347 "bne- 1b\n"
Chris@102 348 : "=&b" (original), "=&b" (tmp), "+Z" (storage)
Chris@102 349 : "b" (v)
Chris@102 350 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
Chris@102 351 );
Chris@102 352 fence_after(order);
Chris@102 353 return original;
Chris@102 354 }
Chris@102 355
Chris@102 356 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
Chris@102 357 {
Chris@102 358 storage_type original, tmp;
Chris@102 359 fence_before(order);
Chris@102 360 __asm__ __volatile__
Chris@102 361 (
Chris@102 362 "1:\n"
Chris@102 363 "lwarx %0,%y2\n"
Chris@102 364 "sub %1,%0,%3\n"
Chris@102 365 "rlwinm %1, %1, 0, 0xff\n"
Chris@102 366 "stwcx. %1,%y2\n"
Chris@102 367 "bne- 1b\n"
Chris@102 368 : "=&b" (original), "=&b" (tmp), "+Z" (storage)
Chris@102 369 : "b" (v)
Chris@102 370 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
Chris@102 371 );
Chris@102 372 fence_after(order);
Chris@102 373 return original;
Chris@102 374 }
Chris@102 375 };
Chris@102 376
Chris@102 377 template< >
Chris@102 378 struct operations< 1u, true > :
Chris@102 379 public operations< 4u, true >
Chris@102 380 {
Chris@102 381 typedef operations< 4u, true > base_type;
Chris@102 382 typedef base_type::storage_type storage_type;
Chris@102 383
Chris@102 384 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
Chris@102 385 {
Chris@102 386 storage_type original, tmp;
Chris@102 387 fence_before(order);
Chris@102 388 __asm__ __volatile__
Chris@102 389 (
Chris@102 390 "1:\n"
Chris@102 391 "lwarx %0,%y2\n"
Chris@102 392 "add %1,%0,%3\n"
Chris@102 393 "extsb %1, %1\n"
Chris@102 394 "stwcx. %1,%y2\n"
Chris@102 395 "bne- 1b\n"
Chris@102 396 : "=&b" (original), "=&b" (tmp), "+Z" (storage)
Chris@102 397 : "b" (v)
Chris@102 398 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
Chris@102 399 );
Chris@102 400 fence_after(order);
Chris@102 401 return original;
Chris@102 402 }
Chris@102 403
Chris@102 404 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
Chris@102 405 {
Chris@102 406 storage_type original, tmp;
Chris@102 407 fence_before(order);
Chris@102 408 __asm__ __volatile__
Chris@102 409 (
Chris@102 410 "1:\n"
Chris@102 411 "lwarx %0,%y2\n"
Chris@102 412 "sub %1,%0,%3\n"
Chris@102 413 "extsb %1, %1\n"
Chris@102 414 "stwcx. %1,%y2\n"
Chris@102 415 "bne- 1b\n"
Chris@102 416 : "=&b" (original), "=&b" (tmp), "+Z" (storage)
Chris@102 417 : "b" (v)
Chris@102 418 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
Chris@102 419 );
Chris@102 420 fence_after(order);
Chris@102 421 return original;
Chris@102 422 }
Chris@102 423 };
Chris@102 424
Chris@102 425
Chris@102 426 template< >
Chris@102 427 struct operations< 2u, false > :
Chris@102 428 public operations< 4u, false >
Chris@102 429 {
Chris@102 430 typedef operations< 4u, false > base_type;
Chris@102 431 typedef base_type::storage_type storage_type;
Chris@102 432
Chris@102 433 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
Chris@102 434 {
Chris@102 435 storage_type original, tmp;
Chris@102 436 fence_before(order);
Chris@102 437 __asm__ __volatile__
Chris@102 438 (
Chris@102 439 "1:\n"
Chris@102 440 "lwarx %0,%y2\n"
Chris@102 441 "add %1,%0,%3\n"
Chris@102 442 "rlwinm %1, %1, 0, 0xffff\n"
Chris@102 443 "stwcx. %1,%y2\n"
Chris@102 444 "bne- 1b\n"
Chris@102 445 : "=&b" (original), "=&b" (tmp), "+Z" (storage)
Chris@102 446 : "b" (v)
Chris@102 447 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
Chris@102 448 );
Chris@102 449 fence_after(order);
Chris@102 450 return original;
Chris@102 451 }
Chris@102 452
Chris@102 453 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
Chris@102 454 {
Chris@102 455 storage_type original, tmp;
Chris@102 456 fence_before(order);
Chris@102 457 __asm__ __volatile__
Chris@102 458 (
Chris@102 459 "1:\n"
Chris@102 460 "lwarx %0,%y2\n"
Chris@102 461 "sub %1,%0,%3\n"
Chris@102 462 "rlwinm %1, %1, 0, 0xffff\n"
Chris@102 463 "stwcx. %1,%y2\n"
Chris@102 464 "bne- 1b\n"
Chris@102 465 : "=&b" (original), "=&b" (tmp), "+Z" (storage)
Chris@102 466 : "b" (v)
Chris@102 467 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
Chris@102 468 );
Chris@102 469 fence_after(order);
Chris@102 470 return original;
Chris@102 471 }
Chris@102 472 };
Chris@102 473
Chris@102 474 template< >
Chris@102 475 struct operations< 2u, true > :
Chris@102 476 public operations< 4u, true >
Chris@102 477 {
Chris@102 478 typedef operations< 4u, true > base_type;
Chris@102 479 typedef base_type::storage_type storage_type;
Chris@102 480
Chris@102 481 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
Chris@102 482 {
Chris@102 483 storage_type original, tmp;
Chris@102 484 fence_before(order);
Chris@102 485 __asm__ __volatile__
Chris@102 486 (
Chris@102 487 "1:\n"
Chris@102 488 "lwarx %0,%y2\n"
Chris@102 489 "add %1,%0,%3\n"
Chris@102 490 "extsh %1, %1\n"
Chris@102 491 "stwcx. %1,%y2\n"
Chris@102 492 "bne- 1b\n"
Chris@102 493 : "=&b" (original), "=&b" (tmp), "+Z" (storage)
Chris@102 494 : "b" (v)
Chris@102 495 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
Chris@102 496 );
Chris@102 497 fence_after(order);
Chris@102 498 return original;
Chris@102 499 }
Chris@102 500
Chris@102 501 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
Chris@102 502 {
Chris@102 503 storage_type original, tmp;
Chris@102 504 fence_before(order);
Chris@102 505 __asm__ __volatile__
Chris@102 506 (
Chris@102 507 "1:\n"
Chris@102 508 "lwarx %0,%y2\n"
Chris@102 509 "sub %1,%0,%3\n"
Chris@102 510 "extsh %1, %1\n"
Chris@102 511 "stwcx. %1,%y2\n"
Chris@102 512 "bne- 1b\n"
Chris@102 513 : "=&b" (original), "=&b" (tmp), "+Z" (storage)
Chris@102 514 : "b" (v)
Chris@102 515 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
Chris@102 516 );
Chris@102 517 fence_after(order);
Chris@102 518 return original;
Chris@102 519 }
Chris@102 520 };
Chris@102 521
Chris@102 522
Chris@102 523 #if defined(__powerpc64__)
Chris@102 524
Chris@102 525 template< bool Signed >
Chris@102 526 struct operations< 8u, Signed > :
Chris@102 527 public gcc_ppc_operations_base
Chris@102 528 {
Chris@102 529 typedef typename make_storage_type< 8u, Signed >::type storage_type;
Chris@102 530
Chris@102 531 static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
Chris@102 532 {
Chris@102 533 fence_before(order);
Chris@102 534 __asm__ __volatile__
Chris@102 535 (
Chris@102 536 "std %1, %0\n"
Chris@102 537 : "+m" (storage)
Chris@102 538 : "r" (v)
Chris@102 539 );
Chris@102 540 fence_after_store(order);
Chris@102 541 }
Chris@102 542
Chris@102 543 static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
Chris@102 544 {
Chris@102 545 storage_type v;
Chris@102 546 __asm__ __volatile__
Chris@102 547 (
Chris@102 548 "ld %0, %1\n"
Chris@102 549 "cmpd %0, %0\n"
Chris@102 550 "bne- 1f\n"
Chris@102 551 "1:\n"
Chris@102 552 : "=&b" (v)
Chris@102 553 : "m" (storage)
Chris@102 554 : "cr0"
Chris@102 555 );
Chris@102 556 fence_after(order);
Chris@102 557 return v;
Chris@102 558 }
Chris@102 559
Chris@102 560 static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
Chris@102 561 {
Chris@102 562 storage_type original;
Chris@102 563 fence_before(order);
Chris@102 564 __asm__ __volatile__
Chris@102 565 (
Chris@102 566 "1:\n"
Chris@102 567 "ldarx %0,%y1\n"
Chris@102 568 "stdcx. %2,%y1\n"
Chris@102 569 "bne- 1b\n"
Chris@102 570 : "=&b" (original), "+Z" (storage)
Chris@102 571 : "b" (v)
Chris@102 572 : "cr0"
Chris@102 573 );
Chris@102 574 fence_after(order);
Chris@102 575 return original;
Chris@102 576 }
Chris@102 577
Chris@102 578 static BOOST_FORCEINLINE bool compare_exchange_weak(
Chris@102 579 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
Chris@102 580 {
Chris@102 581 int success;
Chris@102 582 fence_before(success_order);
Chris@102 583 __asm__ __volatile__
Chris@102 584 (
Chris@102 585 "li %1, 0\n"
Chris@102 586 "ldarx %0,%y2\n"
Chris@102 587 "cmpd %0, %3\n"
Chris@102 588 "bne- 1f\n"
Chris@102 589 "stdcx. %4,%y2\n"
Chris@102 590 "bne- 1f\n"
Chris@102 591 "li %1, 1\n"
Chris@102 592 "1:"
Chris@102 593 : "=&b" (expected), "=&b" (success), "+Z" (storage)
Chris@102 594 : "b" (expected), "b" (desired)
Chris@102 595 : "cr0"
Chris@102 596 );
Chris@102 597 if (success)
Chris@102 598 fence_after(success_order);
Chris@102 599 else
Chris@102 600 fence_after(failure_order);
Chris@102 601 return !!success;
Chris@102 602 }
Chris@102 603
Chris@102 604 static BOOST_FORCEINLINE bool compare_exchange_strong(
Chris@102 605 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
Chris@102 606 {
Chris@102 607 int success;
Chris@102 608 fence_before(success_order);
Chris@102 609 __asm__ __volatile__
Chris@102 610 (
Chris@102 611 "li %1, 0\n"
Chris@102 612 "0: ldarx %0,%y2\n"
Chris@102 613 "cmpd %0, %3\n"
Chris@102 614 "bne- 1f\n"
Chris@102 615 "stdcx. %4,%y2\n"
Chris@102 616 "bne- 0b\n"
Chris@102 617 "li %1, 1\n"
Chris@102 618 "1:"
Chris@102 619 : "=&b" (expected), "=&b" (success), "+Z" (storage)
Chris@102 620 : "b" (expected), "b" (desired)
Chris@102 621 : "cr0"
Chris@102 622 );
Chris@102 623 if (success)
Chris@102 624 fence_after(success_order);
Chris@102 625 else
Chris@102 626 fence_after(failure_order);
Chris@102 627 return !!success;
Chris@102 628 }
Chris@102 629
Chris@102 630 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
Chris@102 631 {
Chris@102 632 storage_type original, tmp;
Chris@102 633 fence_before(order);
Chris@102 634 __asm__ __volatile__
Chris@102 635 (
Chris@102 636 "1:\n"
Chris@102 637 "ldarx %0,%y2\n"
Chris@102 638 "add %1,%0,%3\n"
Chris@102 639 "stdcx. %1,%y2\n"
Chris@102 640 "bne- 1b\n"
Chris@102 641 : "=&b" (original), "=&b" (tmp), "+Z" (storage)
Chris@102 642 : "b" (v)
Chris@102 643 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
Chris@102 644 );
Chris@102 645 fence_after(order);
Chris@102 646 return original;
Chris@102 647 }
Chris@102 648
Chris@102 649 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
Chris@102 650 {
Chris@102 651 storage_type original, tmp;
Chris@102 652 fence_before(order);
Chris@102 653 __asm__ __volatile__
Chris@102 654 (
Chris@102 655 "1:\n"
Chris@102 656 "ldarx %0,%y2\n"
Chris@102 657 "sub %1,%0,%3\n"
Chris@102 658 "stdcx. %1,%y2\n"
Chris@102 659 "bne- 1b\n"
Chris@102 660 : "=&b" (original), "=&b" (tmp), "+Z" (storage)
Chris@102 661 : "b" (v)
Chris@102 662 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
Chris@102 663 );
Chris@102 664 fence_after(order);
Chris@102 665 return original;
Chris@102 666 }
Chris@102 667
Chris@102 668 static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
Chris@102 669 {
Chris@102 670 storage_type original, tmp;
Chris@102 671 fence_before(order);
Chris@102 672 __asm__ __volatile__
Chris@102 673 (
Chris@102 674 "1:\n"
Chris@102 675 "ldarx %0,%y2\n"
Chris@102 676 "and %1,%0,%3\n"
Chris@102 677 "stdcx. %1,%y2\n"
Chris@102 678 "bne- 1b\n"
Chris@102 679 : "=&b" (original), "=&b" (tmp), "+Z" (storage)
Chris@102 680 : "b" (v)
Chris@102 681 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
Chris@102 682 );
Chris@102 683 fence_after(order);
Chris@102 684 return original;
Chris@102 685 }
Chris@102 686
Chris@102 687 static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
Chris@102 688 {
Chris@102 689 storage_type original, tmp;
Chris@102 690 fence_before(order);
Chris@102 691 __asm__ __volatile__
Chris@102 692 (
Chris@102 693 "1:\n"
Chris@102 694 "ldarx %0,%y2\n"
Chris@102 695 "or %1,%0,%3\n"
Chris@102 696 "stdcx. %1,%y2\n"
Chris@102 697 "bne- 1b\n"
Chris@102 698 : "=&b" (original), "=&b" (tmp), "+Z" (storage)
Chris@102 699 : "b" (v)
Chris@102 700 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
Chris@102 701 );
Chris@102 702 fence_after(order);
Chris@102 703 return original;
Chris@102 704 }
Chris@102 705
Chris@102 706 static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
Chris@102 707 {
Chris@102 708 storage_type original, tmp;
Chris@102 709 fence_before(order);
Chris@102 710 __asm__ __volatile__
Chris@102 711 (
Chris@102 712 "1:\n"
Chris@102 713 "ldarx %0,%y2\n"
Chris@102 714 "xor %1,%0,%3\n"
Chris@102 715 "stdcx. %1,%y2\n"
Chris@102 716 "bne- 1b\n"
Chris@102 717 : "=&b" (original), "=&b" (tmp), "+Z" (storage)
Chris@102 718 : "b" (v)
Chris@102 719 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
Chris@102 720 );
Chris@102 721 fence_after(order);
Chris@102 722 return original;
Chris@102 723 }
Chris@102 724
Chris@102 725 static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
Chris@102 726 {
Chris@102 727 return !!exchange(storage, (storage_type)1, order);
Chris@102 728 }
Chris@102 729
Chris@102 730 static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
Chris@102 731 {
Chris@102 732 store(storage, 0, order);
Chris@102 733 }
Chris@102 734
Chris@102 735 static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
Chris@102 736 {
Chris@102 737 return true;
Chris@102 738 }
Chris@102 739 };
Chris@102 740
Chris@102 741 #endif // defined(__powerpc64__)
Chris@102 742
Chris@102 743
Chris@102 744 BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
Chris@102 745 {
Chris@102 746 switch (order)
Chris@102 747 {
Chris@102 748 case memory_order_consume:
Chris@102 749 case memory_order_acquire:
Chris@102 750 __asm__ __volatile__ ("isync" ::: "memory");
Chris@102 751 break;
Chris@102 752 case memory_order_release:
Chris@102 753 #if defined(__powerpc64__)
Chris@102 754 __asm__ __volatile__ ("lwsync" ::: "memory");
Chris@102 755 break;
Chris@102 756 #endif
Chris@102 757 case memory_order_acq_rel:
Chris@102 758 case memory_order_seq_cst:
Chris@102 759 __asm__ __volatile__ ("sync" ::: "memory");
Chris@102 760 break;
Chris@102 761 default:;
Chris@102 762 }
Chris@102 763 }
Chris@102 764
Chris@102 765 BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
Chris@102 766 {
Chris@102 767 if (order != memory_order_relaxed)
Chris@102 768 __asm__ __volatile__ ("" ::: "memory");
Chris@102 769 }
Chris@102 770
Chris@102 771 } // namespace detail
Chris@102 772 } // namespace atomics
Chris@102 773 } // namespace boost
Chris@102 774
Chris@102 775 #endif // BOOST_ATOMIC_DETAIL_OPS_GCC_PPC_HPP_INCLUDED_