1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2010 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Redistribution and use in source and binary forms, with or without
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// modification, are permitted provided that the following conditions are
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// met:
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//     * Redistributions of source code must retain the above copyright
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//       notice, this list of conditions and the following disclaimer.
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//     * Redistributions in binary form must reproduce the above
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//       copyright notice, this list of conditions and the following
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//       disclaimer in the documentation and/or other materials provided
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//       with the distribution.
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//     * Neither the name of Google Inc. nor the names of its
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//       contributors may be used to endorse or promote products derived
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//       from this software without specific prior written permission.
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// This file is an internal atomic implementation, use atomicops.h instead.
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifndef V8_BASE_ATOMICOPS_INTERNALS_MIPS_GCC_H_
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define V8_BASE_ATOMICOPS_INTERNALS_MIPS_GCC_H_
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 {
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace base {
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Atomically execute:
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//      result = *ptr;
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//      if (*ptr == old_value)
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//        *ptr = new_value;
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//      return result;
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value".
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Always return the old value of "*ptr"
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// This routine implies no memory barriers.
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         Atomic32 old_value,
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         Atomic32 new_value) {
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Atomic32 prev, tmp;
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __asm__ __volatile__(".set push\n"
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       ".set noreorder\n"
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       "1:\n"
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       "ll %0, %5\n"  // prev = *ptr
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       "bne %0, %3, 2f\n"  // if (prev != old_value) goto 2
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       "move %2, %4\n"  // tmp = new_value
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       "sc %2, %1\n"  // *ptr = tmp (with atomic check)
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       "beqz %2, 1b\n"  // start again on atomic error
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       "nop\n"  // delay slot nop
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       "2:\n"
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       ".set pop\n"
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       : "=&r" (prev), "=m" (*ptr), "=&r" (tmp)
628a80363ecf90dfcd3563b170ffdd606333f445cbPaul Lind                       : "r" (old_value), "r" (new_value), "m" (*ptr)
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       : "memory");
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return prev;
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Atomically store new_value into *ptr, returning the previous value held in
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// *ptr.  This routine implies no memory barriers.
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         Atomic32 new_value) {
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Atomic32 temp, old;
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __asm__ __volatile__(".set push\n"
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       ".set noreorder\n"
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       "1:\n"
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       "ll %1, %2\n"  // old = *ptr
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       "move %0, %3\n"  // temp = new_value
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       "sc %0, %2\n"  // *ptr = temp (with atomic check)
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       "beqz %0, 1b\n"  // start again on atomic error
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       "nop\n"  // delay slot nop
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       ".set pop\n"
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       : "=&r" (temp), "=&r" (old), "=m" (*ptr)
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       : "r" (new_value), "m" (*ptr)
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       : "memory");
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return old;
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Atomically increment *ptr by "increment".  Returns the new value of
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// *ptr with the increment applied.  This routine implies no memory barriers.
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          Atomic32 increment) {
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Atomic32 temp, temp2;
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  __asm__ __volatile__(
9521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      ".set push\n"
9621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      ".set noreorder\n"
9721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      "1:\n"
9821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      "ll %0, %2\n"        // temp = *ptr
9921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      "addu %1, %0, %3\n"  // temp2 = temp + increment
10021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      "sc %1, %2\n"        // *ptr = temp2 (with atomic check)
10121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      "beqz %1, 1b\n"      // start again on atomic error
10221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      "addu %1, %0, %3\n"  // temp2 = temp + increment
10321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      ".set pop\n"
10421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      : "=&r"(temp), "=&r"(temp2), "=ZC"(*ptr)
10521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      : "Ir"(increment), "m"(*ptr)
10621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      : "memory");
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // temp2 now holds the final value.
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return temp2;
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        Atomic32 increment) {
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemoryBarrier();
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Atomic32 res = NoBarrier_AtomicIncrement(ptr, increment);
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemoryBarrier();
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return res;
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// "Acquire" operations
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ensure that no later memory access can be reordered ahead of the operation.
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// "Release" operations ensure that no previous memory access can be reordered
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// after the operation.  "Barrier" operations have both "Acquire" and "Release"
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// semantics.   A MemoryBarrier() has "Barrier" semantics, but does no memory
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// access.
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Atomic32 old_value,
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Atomic32 new_value) {
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Atomic32 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemoryBarrier();
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return res;
131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Atomic32 old_value,
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Atomic32 new_value) {
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemoryBarrier();
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline void NoBarrier_Store(volatile Atomic8* ptr, Atomic8 value) {
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *ptr = value;
142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *ptr = value;
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline void MemoryBarrier() {
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __asm__ __volatile__("sync" : : : "memory");
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *ptr = value;
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemoryBarrier();
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemoryBarrier();
159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *ptr = value;
160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline Atomic8 NoBarrier_Load(volatile const Atomic8* ptr) {
163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return *ptr;
164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return *ptr;
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Atomic32 value = *ptr;
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemoryBarrier();
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return value;
174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline Atomic32 Release_Load(volatile const Atomic32* ptr) {
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemoryBarrier();
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return *ptr;
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 64-bit versions of the atomic ops.
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         Atomic64 old_value,
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         Atomic64 new_value) {
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Atomic64 prev, tmp;
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __asm__ __volatile__(".set push\n"
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       ".set noreorder\n"
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       "1:\n"
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       "lld %0, %5\n"  // prev = *ptr
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       "bne %0, %3, 2f\n"  // if (prev != old_value) goto 2
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       "move %2, %4\n"  // tmp = new_value
194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       "scd %2, %1\n"  // *ptr = tmp (with atomic check)
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       "beqz %2, 1b\n"  // start again on atomic error
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       "nop\n"  // delay slot nop
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       "2:\n"
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       ".set pop\n"
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       : "=&r" (prev), "=m" (*ptr), "=&r" (tmp)
2008a80363ecf90dfcd3563b170ffdd606333f445cbPaul Lind                       : "r" (old_value), "r" (new_value), "m" (*ptr)
201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       : "memory");
202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return prev;
203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Atomically store new_value into *ptr, returning the previous value held in
206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// *ptr.  This routine implies no memory barriers.
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         Atomic64 new_value) {
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Atomic64 temp, old;
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __asm__ __volatile__(".set push\n"
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       ".set noreorder\n"
212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       "1:\n"
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       "lld %1, %2\n"  // old = *ptr
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       "move %0, %3\n"  // temp = new_value
215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       "scd %0, %2\n"  // *ptr = temp (with atomic check)
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       "beqz %0, 1b\n"  // start again on atomic error
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       "nop\n"  // delay slot nop
218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       ".set pop\n"
219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       : "=&r" (temp), "=&r" (old), "=m" (*ptr)
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       : "r" (new_value), "m" (*ptr)
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       : "memory");
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return old;
224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Atomically increment *ptr by "increment".  Returns the new value of
227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// *ptr with the increment applied.  This routine implies no memory barriers.
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          Atomic64 increment) {
230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Atomic64 temp, temp2;
231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  __asm__ __volatile__(
23321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      ".set push\n"
23421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      ".set noreorder\n"
23521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      "1:\n"
23621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      "lld %0, %2\n"        // temp = *ptr
23721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      "daddu %1, %0, %3\n"  // temp2 = temp + increment
23821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      "scd %1, %2\n"        // *ptr = temp2 (with atomic check)
23921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      "beqz %1, 1b\n"       // start again on atomic error
24021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      "daddu %1, %0, %3\n"  // temp2 = temp + increment
24121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      ".set pop\n"
24221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      : "=&r"(temp), "=&r"(temp2), "=ZC"(*ptr)
24321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      : "Ir"(increment), "m"(*ptr)
24421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      : "memory");
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // temp2 now holds the final value.
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return temp2;
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        Atomic64 increment) {
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemoryBarrier();
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Atomic64 res = NoBarrier_AtomicIncrement(ptr, increment);
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemoryBarrier();
254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return res;
255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// "Acquire" operations
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ensure that no later memory access can be reordered ahead of the operation.
259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// "Release" operations ensure that no previous memory access can be reordered
260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// after the operation.  "Barrier" operations have both "Acquire" and "Release"
261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// semantics.   A MemoryBarrier() has "Barrier" semantics, but does no memory
262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// access.
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Atomic64 old_value,
265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Atomic64 new_value) {
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Atomic64 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemoryBarrier();
268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return res;
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Atomic64 old_value,
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Atomic64 new_value) {
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemoryBarrier();
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *ptr = value;
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *ptr = value;
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemoryBarrier();
285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemoryBarrier();
289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *ptr = value;
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return *ptr;
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Atomic64 value = *ptr;
298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemoryBarrier();
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return value;
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline Atomic64 Release_Load(volatile const Atomic64* ptr) {
303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemoryBarrier();
304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return *ptr;
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace base
308014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // V8_BASE_ATOMICOPS_INTERNALS_MIPS_GCC_H_
311