OSDN Git Service

* config/mips/mips.h (ISA_HAS_EXTS): New macro.
[pf3gnuchains/gcc-fork.git] / gcc / config / sync.c
1 /* Out-of-line libgcc versions of __sync_* builtins.  */
2 /* Copyright (C) 2008  Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
9 version.
10
11 In addition to the permissions in the GNU General Public License, the
12 Free Software Foundation gives you unlimited permission to link the
13 compiled version of this file into combinations with other programs,
14 and to distribute those combinations without any restriction coming
15 from the use of this file.  (The General Public License restrictions
16 do apply in other respects; for example, they cover modification of
17 the file, and distribution when not linked into a combine
18 executable.)
19
20 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
21 WARRANTY; without even the implied warranty of MERCHANTABILITY or
22 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
23 for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with GCC; see the file COPYING.  If not, write to the Free
27 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
28 02110-1301, USA.  */
29
30 /* This file is used by targets whose makefiles define LIBGCC_SYNC
31    to "yes".  It is compiled with LIBGCC_SYNC_CFLAGS and provides
32    out-of-line versions of all relevant __sync_* primitives.
33
34    These routines are intended for targets like MIPS that have two
35    ISA encodings (the "normal" ISA and the MIPS16 ISA).  The normal
36    ISA provides full synchronization capabilities but the MIPS16 ISA
37    has no encoding for them.  MIPS16 code must therefore call external
38    non-MIPS16 implementations of the __sync_* routines.
39
40    The file is compiled once for each routine.  The following __foo
41    routines are selected by defining a macro called L<foo>:
42
43        __sync_synchronize
44
45    The following __foo_N routines are selected by defining FN=foo
46    and SIZE=N:
47
48        __sync_fetch_and_add_N
49        __sync_fetch_and_sub_N
50        __sync_fetch_and_or_N
51        __sync_fetch_and_and_N
52        __sync_fetch_and_xor_N
53        __sync_fetch_and_nand_N
54        __sync_add_and_fetch_N
55        __sync_sub_and_fetch_N
56        __sync_or_and_fetch_N
57        __sync_and_and_fetch_N
58        __sync_xor_and_fetch_N
59        __sync_nand_and_fetch_N
60        __sync_bool_compare_and_swap_N
61        __sync_val_compare_and_swap_N
62        __sync_lock_test_and_set_N
63
64    SIZE can be 1, 2, 4, 8 or 16.  __foo_N is omitted if the target does
65    not provide __sync_compare_and_swap_N.
66
67    Note that __sync_lock_release does not fall back on external
68    __sync_lock_release_N functions.  The default implementation
69    of __sync_lock_release is a call to __sync_synchronize followed
70    by a store of zero, so we don't need separate library functions
71    for it.  */
72
73 #if defined FN
74
75 /* Define macros for each __sync_* function type.  Each macro defines a
76    local function called <NAME>_<UNITS> that acts like __<NAME>_<UNITS>.
77    TYPE is a type that has UNITS bytes.  */
78
79 #define DEFINE_V_PV(NAME, UNITS, TYPE)                                  \
80   static TYPE                                                           \
81   NAME##_##UNITS (TYPE *ptr, TYPE value)                                \
82   {                                                                     \
83     return __##NAME (ptr, value);                                       \
84   }
85
86 #define DEFINE_V_PVV(NAME, UNITS, TYPE)                         \
87   static TYPE                                                           \
88   NAME##_##UNITS (TYPE *ptr, TYPE value1, TYPE value2)                  \
89   {                                                                     \
90     return __##NAME (ptr, value1, value2);                              \
91   }
92
93 #define DEFINE_BOOL_PVV(NAME, UNITS, TYPE)                              \
94   static _Bool                                                          \
95   NAME##_##UNITS (TYPE *ptr, TYPE value1, TYPE value2)                  \
96   {                                                                     \
97     return __##NAME (ptr, value1, value2);                              \
98   }
99
100 /* Map function names to the appropriate DEFINE_* macro.  */
101
102 #define local_sync_fetch_and_add DEFINE_V_PV
103 #define local_sync_fetch_and_sub DEFINE_V_PV
104 #define local_sync_fetch_and_or DEFINE_V_PV
105 #define local_sync_fetch_and_and DEFINE_V_PV
106 #define local_sync_fetch_and_xor DEFINE_V_PV
107 #define local_sync_fetch_and_nand DEFINE_V_PV
108
109 #define local_sync_add_and_fetch DEFINE_V_PV
110 #define local_sync_sub_and_fetch DEFINE_V_PV
111 #define local_sync_or_and_fetch DEFINE_V_PV
112 #define local_sync_and_and_fetch DEFINE_V_PV
113 #define local_sync_xor_and_fetch DEFINE_V_PV
114 #define local_sync_nand_and_fetch DEFINE_V_PV
115
116 #define local_sync_bool_compare_and_swap DEFINE_BOOL_PVV
117 #define local_sync_val_compare_and_swap DEFINE_V_PVV
118
119 #define local_sync_lock_test_and_set DEFINE_V_PV
120
121 /* Define the function __<NAME>_<UNITS>, given that TYPE is a type with
122    UNITS bytes.  */
123 #define DEFINE1(NAME, UNITS, TYPE) \
124   static int unused[sizeof (TYPE) == UNITS ? 1 : -1]    \
125     __attribute__((unused));                            \
126   local_##NAME (NAME, UNITS, TYPE);                     \
127   typeof (NAME##_##UNITS) __##NAME##_##UNITS            \
128     __attribute__((alias (#NAME "_" #UNITS)));
129
130 /* As above, but performing macro expansion on the arguments.  */
131 #define DEFINE(NAME, UNITS, TYPE) DEFINE1 (NAME, UNITS, TYPE)
132
133 /* Find an appropriate type TYPE for SIZE and invoke DEFINE (FN, SIZE, TYPE).
134
135    The types chosen here may be incorrect for some targets.
136    For example, targets with 16-byte atomicity support might not
137    support OImode.  We would need some kind of target-specific
138    override if that becomes a problem.  */
139
140 #if SIZE == 1 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
141
142 typedef unsigned int UQItype __attribute__((mode (QI)));
143 DEFINE (FN, 1, UQItype)
144
145 #elif SIZE == 2 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
146
147 typedef unsigned int UHItype __attribute__((mode (HI)));
148 DEFINE (FN, 2, UHItype)
149
150 #elif SIZE == 4 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
151
152 typedef unsigned int USItype __attribute__((mode (SI)));
153 DEFINE (FN, 4, USItype)
154
155 #elif SIZE == 8 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
156
157 typedef unsigned int UDItype __attribute__((mode (DI)));
158 DEFINE (FN, 8, UDItype)
159
160 #elif SIZE == 16 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
161
162 typedef unsigned int UOItype __attribute__((mode (OI)));
163 DEFINE (FN, 8, UOItype)
164
165 #endif
166
167 #elif __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 \
168       || __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 \
169       || __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 \
170       || __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 \
171       || __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
172
173 #if defined Lsync_synchronize
174
175 static void
176 sync_synchronize (void)
177 {
178   __sync_synchronize ();
179 }
180 typeof (sync_synchronize) __sync_synchronize \
181   __attribute__((alias ("sync_synchronize")));
182
183 #endif
184
185 #endif