112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Copyright 2010 the V8 project authors. All rights reserved.
212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Redistribution and use in source and binary forms, with or without
312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// modification, are permitted provided that the following conditions are
412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// met:
512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org//
612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org//     * Redistributions of source code must retain the above copyright
712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org//       notice, this list of conditions and the following disclaimer.
812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org//     * Redistributions in binary form must reproduce the above
912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org//       copyright notice, this list of conditions and the following
1012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org//       disclaimer in the documentation and/or other materials provided
1112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org//       with the distribution.
1212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org//     * Neither the name of Google Inc. nor the names of its
1312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org//       contributors may be used to endorse or promote products derived
1412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org//       from this software without specific prior written permission.
1512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org//
1612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
2812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// This file is an internal atomic implementation, use atomicops.h instead.
2912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
3012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#ifndef V8_BASE_ATOMICOPS_INTERNALS_MIPS_GCC_H_
3112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#define V8_BASE_ATOMICOPS_INTERNALS_MIPS_GCC_H_
3212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
3312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgnamespace v8 {
3412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgnamespace base {
3512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
3612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Atomically execute:
3712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org//      result = *ptr;
3812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org//      if (*ptr == old_value)
3912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org//        *ptr = new_value;
4012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org//      return result;
4112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org//
4212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value".
4312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Always return the old value of "*ptr"
4412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org//
4512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// This routine implies no memory barriers.
4612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orginline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
4712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                         Atomic32 old_value,
4812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                         Atomic32 new_value) {
4912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  Atomic32 prev, tmp;
5012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  __asm__ __volatile__(".set push\n"
5112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       ".set noreorder\n"
5212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "1:\n"
5312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "ll %0, %5\n"  // prev = *ptr
5412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "bne %0, %3, 2f\n"  // if (prev != old_value) goto 2
5512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "move %2, %4\n"  // tmp = new_value
5612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "sc %2, %1\n"  // *ptr = tmp (with atomic check)
5712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "beqz %2, 1b\n"  // start again on atomic error
5812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "nop\n"  // delay slot nop
5912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "2:\n"
6012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       ".set pop\n"
6112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       : "=&r" (prev), "=m" (*ptr), "=&r" (tmp)
6212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       : "Ir" (old_value), "r" (new_value), "m" (*ptr)
6312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       : "memory");
6412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return prev;
6512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
6612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
6712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Atomically store new_value into *ptr, returning the previous value held in
6812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// *ptr.  This routine implies no memory barriers.
6912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orginline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
7012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                         Atomic32 new_value) {
7112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  Atomic32 temp, old;
7212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  __asm__ __volatile__(".set push\n"
7312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       ".set noreorder\n"
7412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "1:\n"
7512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "ll %1, %2\n"  // old = *ptr
7612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "move %0, %3\n"  // temp = new_value
7712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "sc %0, %2\n"  // *ptr = temp (with atomic check)
7812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "beqz %0, 1b\n"  // start again on atomic error
7912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "nop\n"  // delay slot nop
8012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       ".set pop\n"
8112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       : "=&r" (temp), "=&r" (old), "=m" (*ptr)
8212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       : "r" (new_value), "m" (*ptr)
8312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       : "memory");
8412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
8512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return old;
8612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
8712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
8812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Atomically increment *ptr by "increment".  Returns the new value of
8912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// *ptr with the increment applied.  This routine implies no memory barriers.
9012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orginline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
9112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                          Atomic32 increment) {
9212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  Atomic32 temp, temp2;
9312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
9412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  __asm__ __volatile__(".set push\n"
9512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       ".set noreorder\n"
9612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "1:\n"
9712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "ll %0, %2\n"  // temp = *ptr
9812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "addu %1, %0, %3\n"  // temp2 = temp + increment
9912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "sc %1, %2\n"  // *ptr = temp2 (with atomic check)
10012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "beqz %1, 1b\n"  // start again on atomic error
10112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "addu %1, %0, %3\n"  // temp2 = temp + increment
10212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       ".set pop\n"
10312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       : "=&r" (temp), "=&r" (temp2), "=m" (*ptr)
10412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       : "Ir" (increment), "m" (*ptr)
10512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       : "memory");
10612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // temp2 now holds the final value.
10712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return temp2;
10812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
10912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
11012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orginline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
11112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                        Atomic32 increment) {
11212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  MemoryBarrier();
11312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  Atomic32 res = NoBarrier_AtomicIncrement(ptr, increment);
11412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  MemoryBarrier();
11512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return res;
11612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
11712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
11812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// "Acquire" operations
11912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// ensure that no later memory access can be reordered ahead of the operation.
12012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// "Release" operations ensure that no previous memory access can be reordered
12112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// after the operation.  "Barrier" operations have both "Acquire" and "Release"
12212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// semantics.   A MemoryBarrier() has "Barrier" semantics, but does no memory
12312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// access.
12412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orginline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
12512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                       Atomic32 old_value,
12612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                       Atomic32 new_value) {
12712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  Atomic32 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
12812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  MemoryBarrier();
12912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return res;
13012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
13112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
13212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orginline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
13312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                       Atomic32 old_value,
13412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                       Atomic32 new_value) {
13512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  MemoryBarrier();
13612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
13712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
13812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
13912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orginline void NoBarrier_Store(volatile Atomic8* ptr, Atomic8 value) {
14012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  *ptr = value;
14112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
14212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
14312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orginline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
14412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  *ptr = value;
14512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
14612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
14712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orginline void MemoryBarrier() {
14812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  __asm__ __volatile__("sync" : : : "memory");
14912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
15012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
15112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orginline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
15212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  *ptr = value;
15312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  MemoryBarrier();
15412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
15512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
15612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orginline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
15712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  MemoryBarrier();
15812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  *ptr = value;
15912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
16012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
16112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orginline Atomic8 NoBarrier_Load(volatile const Atomic8* ptr) {
16212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return *ptr;
16312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
16412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
16512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orginline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
16612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return *ptr;
16712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
16812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
16912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orginline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
17012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  Atomic32 value = *ptr;
17112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  MemoryBarrier();
17212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return value;
17312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
17412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
17512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orginline Atomic32 Release_Load(volatile const Atomic32* ptr) {
17612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  MemoryBarrier();
17712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return *ptr;
17812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
17912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
18012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
18112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// 64-bit versions of the atomic ops.
18212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
18312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orginline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
18412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                         Atomic64 old_value,
18512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                         Atomic64 new_value) {
18612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  Atomic64 prev, tmp;
18712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  __asm__ __volatile__(".set push\n"
18812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       ".set noreorder\n"
18912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "1:\n"
19012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "lld %0, %5\n"  // prev = *ptr
19112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "bne %0, %3, 2f\n"  // if (prev != old_value) goto 2
19212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "move %2, %4\n"  // tmp = new_value
19312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "scd %2, %1\n"  // *ptr = tmp (with atomic check)
19412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "beqz %2, 1b\n"  // start again on atomic error
19512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "nop\n"  // delay slot nop
19612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "2:\n"
19712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       ".set pop\n"
19812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       : "=&r" (prev), "=m" (*ptr), "=&r" (tmp)
19912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       : "Ir" (old_value), "r" (new_value), "m" (*ptr)
20012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       : "memory");
20112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return prev;
20212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
20312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
20412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Atomically store new_value into *ptr, returning the previous value held in
20512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// *ptr.  This routine implies no memory barriers.
20612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orginline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
20712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                         Atomic64 new_value) {
20812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  Atomic64 temp, old;
20912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  __asm__ __volatile__(".set push\n"
21012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       ".set noreorder\n"
21112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "1:\n"
21212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "lld %1, %2\n"  // old = *ptr
21312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "move %0, %3\n"  // temp = new_value
21412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "scd %0, %2\n"  // *ptr = temp (with atomic check)
21512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "beqz %0, 1b\n"  // start again on atomic error
21612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "nop\n"  // delay slot nop
21712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       ".set pop\n"
21812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       : "=&r" (temp), "=&r" (old), "=m" (*ptr)
21912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       : "r" (new_value), "m" (*ptr)
22012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       : "memory");
22112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
22212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return old;
22312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
22412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
22512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Atomically increment *ptr by "increment".  Returns the new value of
22612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// *ptr with the increment applied.  This routine implies no memory barriers.
22712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orginline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
22812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                          Atomic64 increment) {
22912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  Atomic64 temp, temp2;
23012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
23112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  __asm__ __volatile__(".set push\n"
23212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       ".set noreorder\n"
23312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "1:\n"
23412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "lld %0, %2\n"  // temp = *ptr
23512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "daddu %1, %0, %3\n"  // temp2 = temp + increment
23612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "scd %1, %2\n"  // *ptr = temp2 (with atomic check)
23712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "beqz %1, 1b\n"  // start again on atomic error
23812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       "daddu %1, %0, %3\n"  // temp2 = temp + increment
23912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       ".set pop\n"
24012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       : "=&r" (temp), "=&r" (temp2), "=m" (*ptr)
24112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       : "Ir" (increment), "m" (*ptr)
24212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       : "memory");
24312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // temp2 now holds the final value.
24412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return temp2;
24512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
24612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
24712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orginline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
24812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                        Atomic64 increment) {
24912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  MemoryBarrier();
25012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  Atomic64 res = NoBarrier_AtomicIncrement(ptr, increment);
25112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  MemoryBarrier();
25212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return res;
25312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
25412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
25512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// "Acquire" operations
25612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// ensure that no later memory access can be reordered ahead of the operation.
25712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// "Release" operations ensure that no previous memory access can be reordered
25812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// after the operation.  "Barrier" operations have both "Acquire" and "Release"
25912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// semantics.   A MemoryBarrier() has "Barrier" semantics, but does no memory
26012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// access.
26112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orginline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
26212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                       Atomic64 old_value,
26312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                       Atomic64 new_value) {
26412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  Atomic64 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
26512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  MemoryBarrier();
26612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return res;
26712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
26812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
26912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orginline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
27012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                       Atomic64 old_value,
27112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                       Atomic64 new_value) {
27212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  MemoryBarrier();
27312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
27412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
27512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
27612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orginline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
27712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  *ptr = value;
27812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
27912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
28012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orginline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
28112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  *ptr = value;
28212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  MemoryBarrier();
28312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
28412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
28512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orginline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
28612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  MemoryBarrier();
28712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  *ptr = value;
28812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
28912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
29012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orginline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
29112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return *ptr;
29212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
29312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
29412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orginline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
29512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  Atomic64 value = *ptr;
29612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  MemoryBarrier();
29712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return value;
29812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
29912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
30012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orginline Atomic64 Release_Load(volatile const Atomic64* ptr) {
30112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  MemoryBarrier();
30212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return *ptr;
30312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
30412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
30512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} }  // namespace v8::base
30612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
30712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#endif  // V8_BASE_ATOMICOPS_INTERNALS_MIPS_GCC_H_
308