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