~ubuntu-branches/ubuntu/wily/qtbase-opensource-src/wily

« back to all changes in this revision

Viewing changes to src/corelib/arch/qatomic_mips.h

  • Committer: Package Import Robot
  • Author(s): Timo Jyrinki
  • Date: 2013-02-05 12:46:17 UTC
  • Revision ID: package-import@ubuntu.com-20130205124617-c8jouts182j002fx
Tags: upstream-5.0.1+dfsg
ImportĀ upstreamĀ versionĀ 5.0.1+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
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
 
6
**
 
7
** This file is part of the QtCore module of the Qt Toolkit.
 
8
**
 
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.
 
17
**
 
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.
 
25
**
 
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.
 
29
**
 
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.
 
37
**
 
38
**
 
39
** $QT_END_LICENSE$
 
40
**
 
41
****************************************************************************/
 
42
 
 
43
#ifndef QATOMIC_MIPS_H
 
44
#define QATOMIC_MIPS_H
 
45
 
 
46
#include <QtCore/qgenericatomic.h>
 
47
 
 
48
QT_BEGIN_HEADER
 
49
 
 
50
QT_BEGIN_NAMESPACE
 
51
 
 
52
#if 0
 
53
// silence syncqt warnings
 
54
QT_END_NAMESPACE
 
55
QT_END_HEADER
 
56
 
 
57
#pragma qt_sync_stop_processing
 
58
#endif
 
59
 
 
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
 
64
 
 
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
 
70
 
 
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
 
74
 
 
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 }; };
 
83
#endif
 
84
 
 
85
template <int size> struct QBasicAtomicOps: QGenericAtomicOps<QBasicAtomicOps<size> >
 
86
{
 
87
    template <typename T>
 
88
    static void acquireMemoryFence(const T &) Q_DECL_NOTHROW;
 
89
    template <typename T>
 
90
    static void releaseMemoryFence(const T &) Q_DECL_NOTHROW;
 
91
    template <typename T>
 
92
    static void orderedMemoryFence(const T &) Q_DECL_NOTHROW;
 
93
 
 
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;
 
97
 
 
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;
 
101
 
 
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;
 
104
 
 
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;
 
108
};
 
109
 
 
110
template <typename T> struct QAtomicOps : QBasicAtomicOps<sizeof(T)>
 
111
{
 
112
    typedef T Type;
 
113
};
 
114
 
 
115
#if defined(Q_CC_GNU)
 
116
 
 
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)"
 
120
#endif
 
121
 
 
122
template <int size> template <typename T> inline
 
123
void QBasicAtomicOps<size>::acquireMemoryFence(const T &) Q_DECL_NOTHROW
 
124
{
 
125
    asm volatile ("sync 0x11" ::: "memory");
 
126
}
 
127
 
 
128
template <int size> template <typename T> inline
 
129
void QBasicAtomicOps<size>::releaseMemoryFence(const T &) Q_DECL_NOTHROW
 
130
{
 
131
    asm volatile ("sync 0x12" ::: "memory");
 
132
}
 
133
 
 
134
template <int size> template <typename T> inline
 
135
void QBasicAtomicOps<size>::orderedMemoryFence(const T &) Q_DECL_NOTHROW
 
136
{
 
137
    asm volatile ("sync 0" ::: "memory");
 
138
}
 
139
 
 
140
template<> template<typename T> inline
 
141
bool QBasicAtomicOps<4>::ref(T &_q_value) Q_DECL_NOTHROW
 
142
{
 
143
    register T originalValue;
 
144
    register T newValue;
 
145
    asm volatile("0:\n"
 
146
                 "ll %[originalValue], %[_q_value]\n"
 
147
                 "addiu %[newValue], %[originalValue], %[one]\n"
 
148
                 "sc %[newValue], %[_q_value]\n"
 
149
                 "beqz %[newValue], 0b\n"
 
150
                 "nop\n"
 
151
                 : [originalValue] "=&r" (originalValue),
 
152
                   [_q_value] "+m" (_q_value),
 
153
                   [newValue] "=&r" (newValue)
 
154
                 : [one] "i" (1)
 
155
                 : "cc", "memory");
 
156
    return originalValue != T(-1);
 
157
}
 
158
 
 
159
template<> template<typename T> inline
 
160
bool QBasicAtomicOps<4>::deref(T &_q_value) Q_DECL_NOTHROW
 
161
{
 
162
    register T originalValue;
 
163
    register T newValue;
 
164
    asm volatile("0:\n"
 
165
                 "ll %[originalValue], %[_q_value]\n"
 
166
                 "addiu %[newValue], %[originalValue], %[minusOne]\n"
 
167
                 "sc %[newValue], %[_q_value]\n"
 
168
                 "beqz %[newValue], 0b\n"
 
169
                 "nop\n"
 
170
                 : [originalValue] "=&r" (originalValue),
 
171
                   [_q_value] "+m" (_q_value),
 
172
                   [newValue] "=&r" (newValue)
 
173
                 : [minusOne] "i" (-1)
 
174
                 : "cc", "memory");
 
175
    return originalValue != 1;
 
176
}
 
177
 
 
178
template<> template <typename T> inline
 
179
bool QBasicAtomicOps<4>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW
 
180
{
 
181
    register T result;
 
182
    register T tempValue;
 
183
    asm volatile("0:\n"
 
184
                 "ll %[result], %[_q_value]\n"
 
185
                 "xor %[result], %[result], %[expectedValue]\n"
 
186
                 "bnez %[result], 0f\n"
 
187
                 "nop\n"
 
188
                 "move %[tempValue], %[newValue]\n"
 
189
                 "sc %[tempValue], %[_q_value]\n"
 
190
                 "beqz %[tempValue], 0b\n"
 
191
                 "nop\n"
 
192
                 "0:\n"
 
193
                 : [result] "=&r" (result),
 
194
                   [tempValue] "=&r" (tempValue),
 
195
                   [_q_value] "+m" (_q_value)
 
196
                 : [expectedValue] "r" (expectedValue),
 
197
                   [newValue] "r" (newValue)
 
198
                 : "cc", "memory");
 
199
    return result == 0;
 
200
}
 
201
 
 
202
template<> template <typename T> inline
 
203
T QBasicAtomicOps<4>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW
 
204
{
 
205
    register T originalValue;
 
206
    register T tempValue;
 
207
    asm volatile("0:\n"
 
208
                 "ll %[originalValue], %[_q_value]\n"
 
209
                 "move %[tempValue], %[newValue]\n"
 
210
                 "sc %[tempValue], %[_q_value]\n"
 
211
                 "beqz %[tempValue], 0b\n"
 
212
                 "nop\n"
 
213
                 : [originalValue] "=&r" (originalValue),
 
214
                   [tempValue] "=&r" (tempValue),
 
215
                   [_q_value] "+m" (_q_value)
 
216
                 : [newValue] "r" (newValue)
 
217
                 : "cc", "memory");
 
218
    return originalValue;
 
219
}
 
220
 
 
221
template<> template <typename T> inline
 
222
T QBasicAtomicOps<4>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
 
223
{
 
224
    register T originalValue;
 
225
    register T newValue;
 
226
    asm volatile("0:\n"
 
227
                 "ll %[originalValue], %[_q_value]\n"
 
228
                 "addu %[newValue], %[originalValue], %[valueToAdd]\n"
 
229
                 "sc %[newValue], %[_q_value]\n"
 
230
                 "beqz %[newValue], 0b\n"
 
231
                 "nop\n"
 
232
                 : [originalValue] "=&r" (originalValue),
 
233
                   [_q_value] "+m" (_q_value),
 
234
                   [newValue] "=&r" (newValue)
 
235
                 : [valueToAdd] "r" (valueToAdd * QAtomicAdditiveType<T>::AddScale)
 
236
                 : "cc", "memory");
 
237
    return originalValue;
 
238
}
 
239
 
 
240
#if defined(Q_PROCESSOR_MIPS_64)
 
241
 
 
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
 
247
 
 
248
template<> struct QAtomicIntegerTraits<long long> { enum { IsInteger = 1 }; };
 
249
template<> struct QAtomicIntegerTraits<unsigned long long > { enum { IsInteger = 1 }; };
 
250
 
 
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 }; };
 
255
#endif
 
256
 
 
257
template<> template<typename T> inline
 
258
bool QBasicAtomicOps<8>::ref(T &_q_value) Q_DECL_NOTHROW
 
259
{
 
260
    register T originalValue;
 
261
    register T newValue;
 
262
    asm volatile("0:\n"
 
263
                 "lld %[originalValue], %[_q_value]\n"
 
264
                 "addiu %[newValue], %[originalValue], %[one]\n"
 
265
                 "scd %[newValue], %[_q_value]\n"
 
266
                 "beqz %[newValue], 0b\n"
 
267
                 "nop\n"
 
268
                 : [originalValue] "=&r" (originalValue),
 
269
                   [_q_value] "+m" (_q_value),
 
270
                   [newValue] "=&r" (newValue)
 
271
                 : [one] "i" (1)
 
272
                 : "cc", "memory");
 
273
    return originalValue != T(-1);
 
274
}
 
275
 
 
276
template<> template<typename T> inline
 
277
bool QBasicAtomicOps<8>::deref(T &_q_value) Q_DECL_NOTHROW
 
278
{
 
279
    register T originalValue;
 
280
    register T newValue;
 
281
    asm volatile("0:\n"
 
282
                 "lld %[originalValue], %[_q_value]\n"
 
283
                 "addiu %[newValue], %[originalValue], %[minusOne]\n"
 
284
                 "scd %[newValue], %[_q_value]\n"
 
285
                 "beqz %[newValue], 0b\n"
 
286
                 "nop\n"
 
287
                 : [originalValue] "=&r" (originalValue),
 
288
                   [_q_value] "+m" (_q_value),
 
289
                   [newValue] "=&r" (newValue)
 
290
                 : [minusOne] "i" (-1)
 
291
                 : "cc", "memory");
 
292
    return originalValue != 1;
 
293
}
 
294
 
 
295
template<> template <typename T> inline
 
296
bool QBasicAtomicOps<8>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW
 
297
{
 
298
    register T result;
 
299
    register T tempValue;
 
300
    asm volatile("0:\n"
 
301
                 "lld %[result], %[_q_value]\n"
 
302
                 "xor %[result], %[result], %[expectedValue]\n"
 
303
                 "bnez %[result], 0f\n"
 
304
                 "nop\n"
 
305
                 "move %[tempValue], %[newValue]\n"
 
306
                 "scd %[tempValue], %[_q_value]\n"
 
307
                 "beqz %[tempValue], 0b\n"
 
308
                 "nop\n"
 
309
                 "0:\n"
 
310
                 : [result] "=&r" (result),
 
311
                   [tempValue] "=&r" (tempValue),
 
312
                   [_q_value] "+m" (_q_value)
 
313
                 : [expectedValue] "r" (expectedValue),
 
314
                   [newValue] "r" (newValue)
 
315
                 : "cc", "memory");
 
316
    return result == 0;
 
317
}
 
318
 
 
319
template<> template <typename T> inline
 
320
T QBasicAtomicOps<8>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW
 
321
{
 
322
    register T originalValue;
 
323
    register T tempValue;
 
324
    asm volatile("0:\n"
 
325
                 "lld %[originalValue], %[_q_value]\n"
 
326
                 "move %[tempValue], %[newValue]\n"
 
327
                 "scd %[tempValue], %[_q_value]\n"
 
328
                 "beqz %[tempValue], 0b\n"
 
329
                 "nop\n"
 
330
                 : [originalValue] "=&r" (originalValue),
 
331
                   [tempValue] "=&r" (tempValue),
 
332
                   [_q_value] "+m" (_q_value)
 
333
                 : [newValue] "r" (newValue)
 
334
                 : "cc", "memory");
 
335
    return originalValue;
 
336
}
 
337
 
 
338
template<> template <typename T> inline
 
339
T QBasicAtomicOps<8>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
 
340
{
 
341
    register T originalValue;
 
342
    register T newValue;
 
343
    asm volatile("0:\n"
 
344
                 "lld %[originalValue], %[_q_value]\n"
 
345
                 "addu %[newValue], %[originalValue], %[valueToAdd]\n"
 
346
                 "scd %[newValue], %[_q_value]\n"
 
347
                 "beqz %[newValue], 0b\n"
 
348
                 "nop\n"
 
349
                 : [originalValue] "=&r" (originalValue),
 
350
                   [_q_value] "+m" (_q_value),
 
351
                   [newValue] "=&r" (newValue)
 
352
                 : [valueToAdd] "r" (valueToAdd * QAtomicAdditiveType<T>::AddScale)
 
353
                 : "cc", "memory");
 
354
    return originalValue;
 
355
}
 
356
 
 
357
#endif // MIPS64
 
358
 
 
359
#else
 
360
# error "This compiler for MIPS is not supported"
 
361
#endif // Q_CC_GNU
 
362
 
 
363
QT_END_NAMESPACE
 
364
 
 
365
QT_END_HEADER
 
366
 
 
367
#endif // QATOMIC_MIPS_H