xref: /qemu/accel/tcg/atomic_template.h (revision 5507c2bf35aa6b4705939349184e71afd5e058b2)
1c482cb11SRichard Henderson /*
2c482cb11SRichard Henderson  * Atomic helper templates
3c482cb11SRichard Henderson  * Included from tcg-runtime.c and cputlb.c.
4c482cb11SRichard Henderson  *
5c482cb11SRichard Henderson  * Copyright (c) 2016 Red Hat, Inc
6c482cb11SRichard Henderson  *
7c482cb11SRichard Henderson  * This library is free software; you can redistribute it and/or
8c482cb11SRichard Henderson  * modify it under the terms of the GNU Lesser General Public
9c482cb11SRichard Henderson  * License as published by the Free Software Foundation; either
10c482cb11SRichard Henderson  * version 2 of the License, or (at your option) any later version.
11c482cb11SRichard Henderson  *
12c482cb11SRichard Henderson  * This library is distributed in the hope that it will be useful,
13c482cb11SRichard Henderson  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14c482cb11SRichard Henderson  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15c482cb11SRichard Henderson  * Lesser General Public License for more details.
16c482cb11SRichard Henderson  *
17c482cb11SRichard Henderson  * You should have received a copy of the GNU Lesser General Public
18c482cb11SRichard Henderson  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19c482cb11SRichard Henderson  */
20c482cb11SRichard Henderson 
217ebee43eSRichard Henderson #if DATA_SIZE == 16
227ebee43eSRichard Henderson # define SUFFIX     o
237ebee43eSRichard Henderson # define DATA_TYPE  Int128
247ebee43eSRichard Henderson # define BSWAP      bswap128
257ebee43eSRichard Henderson #elif DATA_SIZE == 8
26c482cb11SRichard Henderson # define SUFFIX     q
27c482cb11SRichard Henderson # define DATA_TYPE  uint64_t
28*5507c2bfSRichard Henderson # define SDATA_TYPE int64_t
29c482cb11SRichard Henderson # define BSWAP      bswap64
30c482cb11SRichard Henderson #elif DATA_SIZE == 4
31c482cb11SRichard Henderson # define SUFFIX     l
32c482cb11SRichard Henderson # define DATA_TYPE  uint32_t
33*5507c2bfSRichard Henderson # define SDATA_TYPE int32_t
34c482cb11SRichard Henderson # define BSWAP      bswap32
35c482cb11SRichard Henderson #elif DATA_SIZE == 2
36c482cb11SRichard Henderson # define SUFFIX     w
37c482cb11SRichard Henderson # define DATA_TYPE  uint16_t
38*5507c2bfSRichard Henderson # define SDATA_TYPE int16_t
39c482cb11SRichard Henderson # define BSWAP      bswap16
40c482cb11SRichard Henderson #elif DATA_SIZE == 1
41c482cb11SRichard Henderson # define SUFFIX     b
42c482cb11SRichard Henderson # define DATA_TYPE  uint8_t
43*5507c2bfSRichard Henderson # define SDATA_TYPE int8_t
44c482cb11SRichard Henderson # define BSWAP
45c482cb11SRichard Henderson #else
46c482cb11SRichard Henderson # error unsupported data size
47c482cb11SRichard Henderson #endif
48c482cb11SRichard Henderson 
49c482cb11SRichard Henderson #if DATA_SIZE >= 4
50c482cb11SRichard Henderson # define ABI_TYPE  DATA_TYPE
51c482cb11SRichard Henderson #else
52c482cb11SRichard Henderson # define ABI_TYPE  uint32_t
53c482cb11SRichard Henderson #endif
54c482cb11SRichard Henderson 
55c482cb11SRichard Henderson /* Define host-endian atomic operations.  Note that END is used within
56c482cb11SRichard Henderson    the ATOMIC_NAME macro, and redefined below.  */
57c482cb11SRichard Henderson #if DATA_SIZE == 1
58c482cb11SRichard Henderson # define END
59c482cb11SRichard Henderson #elif defined(HOST_WORDS_BIGENDIAN)
60c482cb11SRichard Henderson # define END  _be
61c482cb11SRichard Henderson #else
62c482cb11SRichard Henderson # define END  _le
63c482cb11SRichard Henderson #endif
64c482cb11SRichard Henderson 
65c482cb11SRichard Henderson ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
66c482cb11SRichard Henderson                               ABI_TYPE cmpv, ABI_TYPE newv EXTRA_ARGS)
67c482cb11SRichard Henderson {
6834d49937SPeter Maydell     ATOMIC_MMU_DECLS;
69c482cb11SRichard Henderson     DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
70ec603b55SRichard Henderson     DATA_TYPE ret = atomic_cmpxchg__nocheck(haddr, cmpv, newv);
71ec603b55SRichard Henderson     ATOMIC_MMU_CLEANUP;
72ec603b55SRichard Henderson     return ret;
73c482cb11SRichard Henderson }
74c482cb11SRichard Henderson 
757ebee43eSRichard Henderson #if DATA_SIZE >= 16
767ebee43eSRichard Henderson ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr EXTRA_ARGS)
777ebee43eSRichard Henderson {
7834d49937SPeter Maydell     ATOMIC_MMU_DECLS;
797ebee43eSRichard Henderson     DATA_TYPE val, *haddr = ATOMIC_MMU_LOOKUP;
807ebee43eSRichard Henderson     __atomic_load(haddr, &val, __ATOMIC_RELAXED);
81ec603b55SRichard Henderson     ATOMIC_MMU_CLEANUP;
827ebee43eSRichard Henderson     return val;
837ebee43eSRichard Henderson }
847ebee43eSRichard Henderson 
857ebee43eSRichard Henderson void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr,
867ebee43eSRichard Henderson                      ABI_TYPE val EXTRA_ARGS)
877ebee43eSRichard Henderson {
8834d49937SPeter Maydell     ATOMIC_MMU_DECLS;
897ebee43eSRichard Henderson     DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
907ebee43eSRichard Henderson     __atomic_store(haddr, &val, __ATOMIC_RELAXED);
91ec603b55SRichard Henderson     ATOMIC_MMU_CLEANUP;
927ebee43eSRichard Henderson }
937ebee43eSRichard Henderson #else
94c482cb11SRichard Henderson ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr,
95c482cb11SRichard Henderson                            ABI_TYPE val EXTRA_ARGS)
96c482cb11SRichard Henderson {
9734d49937SPeter Maydell     ATOMIC_MMU_DECLS;
98c482cb11SRichard Henderson     DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
99ec603b55SRichard Henderson     DATA_TYPE ret = atomic_xchg__nocheck(haddr, val);
100ec603b55SRichard Henderson     ATOMIC_MMU_CLEANUP;
101ec603b55SRichard Henderson     return ret;
102c482cb11SRichard Henderson }
103c482cb11SRichard Henderson 
104c482cb11SRichard Henderson #define GEN_ATOMIC_HELPER(X)                                        \
105c482cb11SRichard Henderson ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr,       \
106c482cb11SRichard Henderson                  ABI_TYPE val EXTRA_ARGS)                           \
107c482cb11SRichard Henderson {                                                                   \
10834d49937SPeter Maydell     ATOMIC_MMU_DECLS;                                               \
109c482cb11SRichard Henderson     DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;                           \
110ec603b55SRichard Henderson     DATA_TYPE ret = atomic_##X(haddr, val);                         \
111ec603b55SRichard Henderson     ATOMIC_MMU_CLEANUP;                                             \
112ec603b55SRichard Henderson     return ret;                                                     \
113ec603b55SRichard Henderson }
114c482cb11SRichard Henderson 
115c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_add)
116c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_and)
117c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_or)
118c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_xor)
119c482cb11SRichard Henderson GEN_ATOMIC_HELPER(add_fetch)
120c482cb11SRichard Henderson GEN_ATOMIC_HELPER(and_fetch)
121c482cb11SRichard Henderson GEN_ATOMIC_HELPER(or_fetch)
122c482cb11SRichard Henderson GEN_ATOMIC_HELPER(xor_fetch)
123c482cb11SRichard Henderson 
124c482cb11SRichard Henderson #undef GEN_ATOMIC_HELPER
125*5507c2bfSRichard Henderson 
126*5507c2bfSRichard Henderson /* These helpers are, as a whole, full barriers.  Within the helper,
127*5507c2bfSRichard Henderson  * the leading barrier is explicit and the trailing barrier is within
128*5507c2bfSRichard Henderson  * cmpxchg primitive.
129*5507c2bfSRichard Henderson  */
130*5507c2bfSRichard Henderson #define GEN_ATOMIC_HELPER_FN(X, FN, XDATA_TYPE, RET)                \
131*5507c2bfSRichard Henderson ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr,       \
132*5507c2bfSRichard Henderson                         ABI_TYPE xval EXTRA_ARGS)                   \
133*5507c2bfSRichard Henderson {                                                                   \
134*5507c2bfSRichard Henderson     ATOMIC_MMU_DECLS;                                               \
135*5507c2bfSRichard Henderson     XDATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;                          \
136*5507c2bfSRichard Henderson     XDATA_TYPE cmp, old, new, val = xval;                           \
137*5507c2bfSRichard Henderson     smp_mb();                                                       \
138*5507c2bfSRichard Henderson     cmp = atomic_read__nocheck(haddr);                              \
139*5507c2bfSRichard Henderson     do {                                                            \
140*5507c2bfSRichard Henderson         old = cmp; new = FN(old, val);                              \
141*5507c2bfSRichard Henderson         cmp = atomic_cmpxchg__nocheck(haddr, old, new);             \
142*5507c2bfSRichard Henderson     } while (cmp != old);                                           \
143*5507c2bfSRichard Henderson     ATOMIC_MMU_CLEANUP;                                             \
144*5507c2bfSRichard Henderson     return RET;                                                     \
145*5507c2bfSRichard Henderson }
146*5507c2bfSRichard Henderson 
147*5507c2bfSRichard Henderson GEN_ATOMIC_HELPER_FN(fetch_smin, MIN, SDATA_TYPE, old)
148*5507c2bfSRichard Henderson GEN_ATOMIC_HELPER_FN(fetch_umin, MIN,  DATA_TYPE, old)
149*5507c2bfSRichard Henderson GEN_ATOMIC_HELPER_FN(fetch_smax, MAX, SDATA_TYPE, old)
150*5507c2bfSRichard Henderson GEN_ATOMIC_HELPER_FN(fetch_umax, MAX,  DATA_TYPE, old)
151*5507c2bfSRichard Henderson 
152*5507c2bfSRichard Henderson GEN_ATOMIC_HELPER_FN(smin_fetch, MIN, SDATA_TYPE, new)
153*5507c2bfSRichard Henderson GEN_ATOMIC_HELPER_FN(umin_fetch, MIN,  DATA_TYPE, new)
154*5507c2bfSRichard Henderson GEN_ATOMIC_HELPER_FN(smax_fetch, MAX, SDATA_TYPE, new)
155*5507c2bfSRichard Henderson GEN_ATOMIC_HELPER_FN(umax_fetch, MAX,  DATA_TYPE, new)
156*5507c2bfSRichard Henderson 
157*5507c2bfSRichard Henderson #undef GEN_ATOMIC_HELPER_FN
1587ebee43eSRichard Henderson #endif /* DATA SIZE >= 16 */
1597ebee43eSRichard Henderson 
160c482cb11SRichard Henderson #undef END
161c482cb11SRichard Henderson 
162c482cb11SRichard Henderson #if DATA_SIZE > 1
163c482cb11SRichard Henderson 
164c482cb11SRichard Henderson /* Define reverse-host-endian atomic operations.  Note that END is used
165c482cb11SRichard Henderson    within the ATOMIC_NAME macro.  */
166c482cb11SRichard Henderson #ifdef HOST_WORDS_BIGENDIAN
167c482cb11SRichard Henderson # define END  _le
168c482cb11SRichard Henderson #else
169c482cb11SRichard Henderson # define END  _be
170c482cb11SRichard Henderson #endif
171c482cb11SRichard Henderson 
172c482cb11SRichard Henderson ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
173c482cb11SRichard Henderson                               ABI_TYPE cmpv, ABI_TYPE newv EXTRA_ARGS)
174c482cb11SRichard Henderson {
17534d49937SPeter Maydell     ATOMIC_MMU_DECLS;
176c482cb11SRichard Henderson     DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
177ec603b55SRichard Henderson     DATA_TYPE ret = atomic_cmpxchg__nocheck(haddr, BSWAP(cmpv), BSWAP(newv));
178ec603b55SRichard Henderson     ATOMIC_MMU_CLEANUP;
179ec603b55SRichard Henderson     return BSWAP(ret);
180c482cb11SRichard Henderson }
181c482cb11SRichard Henderson 
1827ebee43eSRichard Henderson #if DATA_SIZE >= 16
1837ebee43eSRichard Henderson ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr EXTRA_ARGS)
1847ebee43eSRichard Henderson {
18534d49937SPeter Maydell     ATOMIC_MMU_DECLS;
1867ebee43eSRichard Henderson     DATA_TYPE val, *haddr = ATOMIC_MMU_LOOKUP;
1877ebee43eSRichard Henderson     __atomic_load(haddr, &val, __ATOMIC_RELAXED);
188ec603b55SRichard Henderson     ATOMIC_MMU_CLEANUP;
1897ebee43eSRichard Henderson     return BSWAP(val);
1907ebee43eSRichard Henderson }
1917ebee43eSRichard Henderson 
1927ebee43eSRichard Henderson void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr,
1937ebee43eSRichard Henderson                      ABI_TYPE val EXTRA_ARGS)
1947ebee43eSRichard Henderson {
19534d49937SPeter Maydell     ATOMIC_MMU_DECLS;
1967ebee43eSRichard Henderson     DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
1977ebee43eSRichard Henderson     val = BSWAP(val);
1987ebee43eSRichard Henderson     __atomic_store(haddr, &val, __ATOMIC_RELAXED);
199ec603b55SRichard Henderson     ATOMIC_MMU_CLEANUP;
2007ebee43eSRichard Henderson }
2017ebee43eSRichard Henderson #else
202c482cb11SRichard Henderson ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr,
203c482cb11SRichard Henderson                            ABI_TYPE val EXTRA_ARGS)
204c482cb11SRichard Henderson {
20534d49937SPeter Maydell     ATOMIC_MMU_DECLS;
206c482cb11SRichard Henderson     DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
207ec603b55SRichard Henderson     ABI_TYPE ret = atomic_xchg__nocheck(haddr, BSWAP(val));
208ec603b55SRichard Henderson     ATOMIC_MMU_CLEANUP;
209ec603b55SRichard Henderson     return BSWAP(ret);
210c482cb11SRichard Henderson }
211c482cb11SRichard Henderson 
212c482cb11SRichard Henderson #define GEN_ATOMIC_HELPER(X)                                        \
213c482cb11SRichard Henderson ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr,       \
214c482cb11SRichard Henderson                  ABI_TYPE val EXTRA_ARGS)                           \
215c482cb11SRichard Henderson {                                                                   \
21634d49937SPeter Maydell     ATOMIC_MMU_DECLS;                                               \
217c482cb11SRichard Henderson     DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;                           \
218ec603b55SRichard Henderson     DATA_TYPE ret = atomic_##X(haddr, BSWAP(val));                  \
219ec603b55SRichard Henderson     ATOMIC_MMU_CLEANUP;                                             \
220ec603b55SRichard Henderson     return BSWAP(ret);                                              \
221c482cb11SRichard Henderson }
222c482cb11SRichard Henderson 
223c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_and)
224c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_or)
225c482cb11SRichard Henderson GEN_ATOMIC_HELPER(fetch_xor)
226c482cb11SRichard Henderson GEN_ATOMIC_HELPER(and_fetch)
227c482cb11SRichard Henderson GEN_ATOMIC_HELPER(or_fetch)
228c482cb11SRichard Henderson GEN_ATOMIC_HELPER(xor_fetch)
229c482cb11SRichard Henderson 
230c482cb11SRichard Henderson #undef GEN_ATOMIC_HELPER
231c482cb11SRichard Henderson 
232c482cb11SRichard Henderson /* Note that for addition, we need to use a separate cmpxchg loop instead
233c482cb11SRichard Henderson    of bswaps for the reverse-host-endian helpers.  */
234c482cb11SRichard Henderson ABI_TYPE ATOMIC_NAME(fetch_add)(CPUArchState *env, target_ulong addr,
235c482cb11SRichard Henderson                          ABI_TYPE val EXTRA_ARGS)
236c482cb11SRichard Henderson {
23734d49937SPeter Maydell     ATOMIC_MMU_DECLS;
238c482cb11SRichard Henderson     DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
239c482cb11SRichard Henderson     DATA_TYPE ldo, ldn, ret, sto;
240c482cb11SRichard Henderson 
241c482cb11SRichard Henderson     ldo = atomic_read__nocheck(haddr);
242c482cb11SRichard Henderson     while (1) {
243c482cb11SRichard Henderson         ret = BSWAP(ldo);
244c482cb11SRichard Henderson         sto = BSWAP(ret + val);
245c482cb11SRichard Henderson         ldn = atomic_cmpxchg__nocheck(haddr, ldo, sto);
246c482cb11SRichard Henderson         if (ldn == ldo) {
247ec603b55SRichard Henderson             ATOMIC_MMU_CLEANUP;
248c482cb11SRichard Henderson             return ret;
249c482cb11SRichard Henderson         }
250c482cb11SRichard Henderson         ldo = ldn;
251c482cb11SRichard Henderson     }
252c482cb11SRichard Henderson }
253c482cb11SRichard Henderson 
254c482cb11SRichard Henderson ABI_TYPE ATOMIC_NAME(add_fetch)(CPUArchState *env, target_ulong addr,
255c482cb11SRichard Henderson                          ABI_TYPE val EXTRA_ARGS)
256c482cb11SRichard Henderson {
25734d49937SPeter Maydell     ATOMIC_MMU_DECLS;
258c482cb11SRichard Henderson     DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
259c482cb11SRichard Henderson     DATA_TYPE ldo, ldn, ret, sto;
260c482cb11SRichard Henderson 
261c482cb11SRichard Henderson     ldo = atomic_read__nocheck(haddr);
262c482cb11SRichard Henderson     while (1) {
263c482cb11SRichard Henderson         ret = BSWAP(ldo) + val;
264c482cb11SRichard Henderson         sto = BSWAP(ret);
265c482cb11SRichard Henderson         ldn = atomic_cmpxchg__nocheck(haddr, ldo, sto);
266c482cb11SRichard Henderson         if (ldn == ldo) {
267ec603b55SRichard Henderson             ATOMIC_MMU_CLEANUP;
268c482cb11SRichard Henderson             return ret;
269c482cb11SRichard Henderson         }
270c482cb11SRichard Henderson         ldo = ldn;
271c482cb11SRichard Henderson     }
272c482cb11SRichard Henderson }
273*5507c2bfSRichard Henderson 
274*5507c2bfSRichard Henderson /* These helpers are, as a whole, full barriers.  Within the helper,
275*5507c2bfSRichard Henderson  * the leading barrier is explicit and the trailing barrier is within
276*5507c2bfSRichard Henderson  * cmpxchg primitive.
277*5507c2bfSRichard Henderson  */
278*5507c2bfSRichard Henderson #define GEN_ATOMIC_HELPER_FN(X, FN, XDATA_TYPE, RET)                \
279*5507c2bfSRichard Henderson ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr,       \
280*5507c2bfSRichard Henderson                         ABI_TYPE xval EXTRA_ARGS)                   \
281*5507c2bfSRichard Henderson {                                                                   \
282*5507c2bfSRichard Henderson     ATOMIC_MMU_DECLS;                                               \
283*5507c2bfSRichard Henderson     XDATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;                          \
284*5507c2bfSRichard Henderson     XDATA_TYPE ldo, ldn, old, new, val = xval;                      \
285*5507c2bfSRichard Henderson     smp_mb();                                                       \
286*5507c2bfSRichard Henderson     ldn = atomic_read__nocheck(haddr);                              \
287*5507c2bfSRichard Henderson     do {                                                            \
288*5507c2bfSRichard Henderson         ldo = ldn; old = BSWAP(ldo); new = FN(old, val);            \
289*5507c2bfSRichard Henderson         ldn = atomic_cmpxchg__nocheck(haddr, ldo, BSWAP(new));      \
290*5507c2bfSRichard Henderson     } while (ldo != ldn);                                           \
291*5507c2bfSRichard Henderson     ATOMIC_MMU_CLEANUP;                                             \
292*5507c2bfSRichard Henderson     return RET;                                                     \
293*5507c2bfSRichard Henderson }
294*5507c2bfSRichard Henderson 
295*5507c2bfSRichard Henderson GEN_ATOMIC_HELPER_FN(fetch_smin, MIN, SDATA_TYPE, old)
296*5507c2bfSRichard Henderson GEN_ATOMIC_HELPER_FN(fetch_umin, MIN,  DATA_TYPE, old)
297*5507c2bfSRichard Henderson GEN_ATOMIC_HELPER_FN(fetch_smax, MAX, SDATA_TYPE, old)
298*5507c2bfSRichard Henderson GEN_ATOMIC_HELPER_FN(fetch_umax, MAX,  DATA_TYPE, old)
299*5507c2bfSRichard Henderson 
300*5507c2bfSRichard Henderson GEN_ATOMIC_HELPER_FN(smin_fetch, MIN, SDATA_TYPE, new)
301*5507c2bfSRichard Henderson GEN_ATOMIC_HELPER_FN(umin_fetch, MIN,  DATA_TYPE, new)
302*5507c2bfSRichard Henderson GEN_ATOMIC_HELPER_FN(smax_fetch, MAX, SDATA_TYPE, new)
303*5507c2bfSRichard Henderson GEN_ATOMIC_HELPER_FN(umax_fetch, MAX,  DATA_TYPE, new)
304*5507c2bfSRichard Henderson 
305*5507c2bfSRichard Henderson #undef GEN_ATOMIC_HELPER_FN
3067ebee43eSRichard Henderson #endif /* DATA_SIZE >= 16 */
307c482cb11SRichard Henderson 
308c482cb11SRichard Henderson #undef END
309c482cb11SRichard Henderson #endif /* DATA_SIZE > 1 */
310c482cb11SRichard Henderson 
311c482cb11SRichard Henderson #undef BSWAP
312c482cb11SRichard Henderson #undef ABI_TYPE
313c482cb11SRichard Henderson #undef DATA_TYPE
314*5507c2bfSRichard Henderson #undef SDATA_TYPE
315c482cb11SRichard Henderson #undef SUFFIX
316c482cb11SRichard Henderson #undef DATA_SIZE
317