1
/****************************************************************************
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4
** Copyright (C) 2011 Thiago Macieira <thiago@kde.org>
5
** Contact: http://www.qt-project.org/legal
7
** This file is part of the QtCore module of the Qt Toolkit.
9
** $QT_BEGIN_LICENSE:LGPL$
10
** Commercial License Usage
11
** Licensees holding valid commercial Qt licenses may use this file in
12
** accordance with the commercial license agreement provided with the
13
** Software or, alternatively, in accordance with the terms contained in
14
** a written agreement between you and Digia. For licensing terms and
15
** conditions see http://qt.digia.com/licensing. For further information
16
** use the contact form at http://qt.digia.com/contact-us.
18
** GNU Lesser General Public License Usage
19
** Alternatively, this file may be used under the terms of the GNU Lesser
20
** General Public License version 2.1 as published by the Free Software
21
** Foundation and appearing in the file LICENSE.LGPL included in the
22
** packaging of this file. Please review the following information to
23
** ensure the GNU Lesser General Public License version 2.1 requirements
24
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
26
** In addition, as a special exception, Digia gives you certain additional
27
** rights. These rights are described in the Digia Qt LGPL Exception
28
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
30
** GNU General Public License Usage
31
** Alternatively, this file may be used under the terms of the GNU
32
** General Public License version 3.0 as published by the Free Software
33
** Foundation and appearing in the file LICENSE.GPL included in the
34
** packaging of this file. Please review the following information to
35
** ensure the GNU General Public License version 3.0 requirements will be
36
** met: http://www.gnu.org/copyleft/gpl.html.
41
****************************************************************************/
43
#ifndef QATOMIC_MIPS_H
44
#define QATOMIC_MIPS_H
46
#include <QtCore/qgenericatomic.h>
53
// silence syncqt warnings
57
#pragma qt_sync_stop_processing
60
#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
61
#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
62
#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
63
#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
65
#define Q_ATOMIC_INT32_IS_SUPPORTED
66
#define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
67
#define Q_ATOMIC_INT32_TEST_AND_SET_IS_ALWAYS_NATIVE
68
#define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_ALWAYS_NATIVE
69
#define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_ALWAYS_NATIVE
71
#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
72
#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
73
#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
75
template<> struct QAtomicIntegerTraits<int> { enum { IsInteger = 1 }; };
76
template<> struct QAtomicIntegerTraits<unsigned int> { enum { IsInteger = 1 }; };
77
#if defined(Q_COMPILER_UNICODE_STRINGS) && !defined(Q_PROCESSOR_MIPS_64)
78
// for MIPS32, ensure that char32_t (an uint_least32_t), is 32-bit
79
// it's extremely unlikely it won't be on a 32-bit MIPS, but just to be sure
80
// For MIPS64, we're sure it works, but the definition is below
81
template<> struct QAtomicIntegerTraits<char32_t>
82
{ enum { IsInteger = sizeof(char32_t) == sizeof(int) ? 1 : -1 }; };
85
template <int size> struct QBasicAtomicOps: QGenericAtomicOps<QBasicAtomicOps<size> >
88
static void acquireMemoryFence(const T &) Q_DECL_NOTHROW;
90
static void releaseMemoryFence(const T &) Q_DECL_NOTHROW;
92
static void orderedMemoryFence(const T &) Q_DECL_NOTHROW;
94
static inline Q_DECL_CONSTEXPR bool isReferenceCountingNative() Q_DECL_NOTHROW { return true; }
95
template <typename T> static bool ref(T &_q_value) Q_DECL_NOTHROW;
96
template <typename T> static bool deref(T &_q_value) Q_DECL_NOTHROW;
98
static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW { return true; }
99
static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return false; }
100
template <typename T> static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW;
102
static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return true; }
103
template <typename T> static T fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW;
105
static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return true; }
106
template <typename T> static
107
T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW;
110
template <typename T> struct QAtomicOps : QBasicAtomicOps<sizeof(T)>
115
#if defined(Q_CC_GNU)
117
#if defined(_MIPS_ARCH_MIPS1) || (defined(__mips) && __mips - 0 == 1)
118
# error "Sorry, the MIPS1 architecture is not supported"
119
# error "please set '-march=' to your architecture (e.g., -march=mips32)"
122
template <int size> template <typename T> inline
123
void QBasicAtomicOps<size>::acquireMemoryFence(const T &) Q_DECL_NOTHROW
125
asm volatile ("sync 0x11" ::: "memory");
128
template <int size> template <typename T> inline
129
void QBasicAtomicOps<size>::releaseMemoryFence(const T &) Q_DECL_NOTHROW
131
asm volatile ("sync 0x12" ::: "memory");
134
template <int size> template <typename T> inline
135
void QBasicAtomicOps<size>::orderedMemoryFence(const T &) Q_DECL_NOTHROW
137
asm volatile ("sync 0" ::: "memory");
140
template<> template<typename T> inline
141
bool QBasicAtomicOps<4>::ref(T &_q_value) Q_DECL_NOTHROW
143
register T originalValue;
146
"ll %[originalValue], %[_q_value]\n"
147
"addiu %[newValue], %[originalValue], %[one]\n"
148
"sc %[newValue], %[_q_value]\n"
149
"beqz %[newValue], 0b\n"
151
: [originalValue] "=&r" (originalValue),
152
[_q_value] "+m" (_q_value),
153
[newValue] "=&r" (newValue)
156
return originalValue != T(-1);
159
template<> template<typename T> inline
160
bool QBasicAtomicOps<4>::deref(T &_q_value) Q_DECL_NOTHROW
162
register T originalValue;
165
"ll %[originalValue], %[_q_value]\n"
166
"addiu %[newValue], %[originalValue], %[minusOne]\n"
167
"sc %[newValue], %[_q_value]\n"
168
"beqz %[newValue], 0b\n"
170
: [originalValue] "=&r" (originalValue),
171
[_q_value] "+m" (_q_value),
172
[newValue] "=&r" (newValue)
173
: [minusOne] "i" (-1)
175
return originalValue != 1;
178
template<> template <typename T> inline
179
bool QBasicAtomicOps<4>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW
182
register T tempValue;
184
"ll %[result], %[_q_value]\n"
185
"xor %[result], %[result], %[expectedValue]\n"
186
"bnez %[result], 0f\n"
188
"move %[tempValue], %[newValue]\n"
189
"sc %[tempValue], %[_q_value]\n"
190
"beqz %[tempValue], 0b\n"
193
: [result] "=&r" (result),
194
[tempValue] "=&r" (tempValue),
195
[_q_value] "+m" (_q_value)
196
: [expectedValue] "r" (expectedValue),
197
[newValue] "r" (newValue)
202
template<> template <typename T> inline
203
T QBasicAtomicOps<4>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW
205
register T originalValue;
206
register T tempValue;
208
"ll %[originalValue], %[_q_value]\n"
209
"move %[tempValue], %[newValue]\n"
210
"sc %[tempValue], %[_q_value]\n"
211
"beqz %[tempValue], 0b\n"
213
: [originalValue] "=&r" (originalValue),
214
[tempValue] "=&r" (tempValue),
215
[_q_value] "+m" (_q_value)
216
: [newValue] "r" (newValue)
218
return originalValue;
221
template<> template <typename T> inline
222
T QBasicAtomicOps<4>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
224
register T originalValue;
227
"ll %[originalValue], %[_q_value]\n"
228
"addu %[newValue], %[originalValue], %[valueToAdd]\n"
229
"sc %[newValue], %[_q_value]\n"
230
"beqz %[newValue], 0b\n"
232
: [originalValue] "=&r" (originalValue),
233
[_q_value] "+m" (_q_value),
234
[newValue] "=&r" (newValue)
235
: [valueToAdd] "r" (valueToAdd * QAtomicAdditiveType<T>::AddScale)
237
return originalValue;
240
#if defined(Q_PROCESSOR_MIPS_64)
242
#define Q_ATOMIC_INT64_IS_SUPPORTED
243
#define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
244
#define Q_ATOMIC_INT64_TEST_AND_SET_IS_ALWAYS_NATIVE
245
#define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_ALWAYS_NATIVE
246
#define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_ALWAYS_NATIVE
248
template<> struct QAtomicIntegerTraits<long long> { enum { IsInteger = 1 }; };
249
template<> struct QAtomicIntegerTraits<unsigned long long > { enum { IsInteger = 1 }; };
251
#ifdef Q_COMPILER_UNICODE_STRINGS
252
template<> struct QAtomicIntegerTraits<char16_t>
253
{ enum { IsInteger = sizeof(char16_t) == sizeof(int) ? 1 : -1 }; };
254
template<> struct QAtomicIntegerTraits<char32_t> { enum { IsInteger = 1 }; };
257
template<> template<typename T> inline
258
bool QBasicAtomicOps<8>::ref(T &_q_value) Q_DECL_NOTHROW
260
register T originalValue;
263
"lld %[originalValue], %[_q_value]\n"
264
"addiu %[newValue], %[originalValue], %[one]\n"
265
"scd %[newValue], %[_q_value]\n"
266
"beqz %[newValue], 0b\n"
268
: [originalValue] "=&r" (originalValue),
269
[_q_value] "+m" (_q_value),
270
[newValue] "=&r" (newValue)
273
return originalValue != T(-1);
276
template<> template<typename T> inline
277
bool QBasicAtomicOps<8>::deref(T &_q_value) Q_DECL_NOTHROW
279
register T originalValue;
282
"lld %[originalValue], %[_q_value]\n"
283
"addiu %[newValue], %[originalValue], %[minusOne]\n"
284
"scd %[newValue], %[_q_value]\n"
285
"beqz %[newValue], 0b\n"
287
: [originalValue] "=&r" (originalValue),
288
[_q_value] "+m" (_q_value),
289
[newValue] "=&r" (newValue)
290
: [minusOne] "i" (-1)
292
return originalValue != 1;
295
template<> template <typename T> inline
296
bool QBasicAtomicOps<8>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW
299
register T tempValue;
301
"lld %[result], %[_q_value]\n"
302
"xor %[result], %[result], %[expectedValue]\n"
303
"bnez %[result], 0f\n"
305
"move %[tempValue], %[newValue]\n"
306
"scd %[tempValue], %[_q_value]\n"
307
"beqz %[tempValue], 0b\n"
310
: [result] "=&r" (result),
311
[tempValue] "=&r" (tempValue),
312
[_q_value] "+m" (_q_value)
313
: [expectedValue] "r" (expectedValue),
314
[newValue] "r" (newValue)
319
template<> template <typename T> inline
320
T QBasicAtomicOps<8>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW
322
register T originalValue;
323
register T tempValue;
325
"lld %[originalValue], %[_q_value]\n"
326
"move %[tempValue], %[newValue]\n"
327
"scd %[tempValue], %[_q_value]\n"
328
"beqz %[tempValue], 0b\n"
330
: [originalValue] "=&r" (originalValue),
331
[tempValue] "=&r" (tempValue),
332
[_q_value] "+m" (_q_value)
333
: [newValue] "r" (newValue)
335
return originalValue;
338
template<> template <typename T> inline
339
T QBasicAtomicOps<8>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
341
register T originalValue;
344
"lld %[originalValue], %[_q_value]\n"
345
"addu %[newValue], %[originalValue], %[valueToAdd]\n"
346
"scd %[newValue], %[_q_value]\n"
347
"beqz %[newValue], 0b\n"
349
: [originalValue] "=&r" (originalValue),
350
[_q_value] "+m" (_q_value),
351
[newValue] "=&r" (newValue)
352
: [valueToAdd] "r" (valueToAdd * QAtomicAdditiveType<T>::AddScale)
354
return originalValue;
360
# error "This compiler for MIPS is not supported"
367
#endif // QATOMIC_MIPS_H