1*67e74705SXin Li /*===---- htmxlintrin.h - XL compiler HTM execution intrinsics-------------===*\
2*67e74705SXin Li *
3*67e74705SXin Li * Permission is hereby granted, free of charge, to any person obtaining a copy
4*67e74705SXin Li * of this software and associated documentation files (the "Software"), to deal
5*67e74705SXin Li * in the Software without restriction, including without limitation the rights
6*67e74705SXin Li * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7*67e74705SXin Li * copies of the Software, and to permit persons to whom the Software is
8*67e74705SXin Li * furnished to do so, subject to the following conditions:
9*67e74705SXin Li *
10*67e74705SXin Li * The above copyright notice and this permission notice shall be included in
11*67e74705SXin Li * all copies or substantial portions of the Software.
12*67e74705SXin Li *
13*67e74705SXin Li * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14*67e74705SXin Li * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15*67e74705SXin Li * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16*67e74705SXin Li * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17*67e74705SXin Li * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18*67e74705SXin Li * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19*67e74705SXin Li * THE SOFTWARE.
20*67e74705SXin Li *
21*67e74705SXin Li \*===----------------------------------------------------------------------===*/
22*67e74705SXin Li
23*67e74705SXin Li #ifndef __HTMXLINTRIN_H
24*67e74705SXin Li #define __HTMXLINTRIN_H
25*67e74705SXin Li
26*67e74705SXin Li #ifndef __HTM__
27*67e74705SXin Li #error "HTM instruction set not enabled"
28*67e74705SXin Li #endif
29*67e74705SXin Li
30*67e74705SXin Li #include <htmintrin.h>
31*67e74705SXin Li
32*67e74705SXin Li #ifdef __powerpc__
33*67e74705SXin Li
34*67e74705SXin Li #ifdef __cplusplus
35*67e74705SXin Li extern "C" {
36*67e74705SXin Li #endif
37*67e74705SXin Li
38*67e74705SXin Li #define _TEXASR_PTR(TM_BUF) \
39*67e74705SXin Li ((texasr_t *)((TM_BUF)+0))
40*67e74705SXin Li #define _TEXASRU_PTR(TM_BUF) \
41*67e74705SXin Li ((texasru_t *)((TM_BUF)+0))
42*67e74705SXin Li #define _TEXASRL_PTR(TM_BUF) \
43*67e74705SXin Li ((texasrl_t *)((TM_BUF)+4))
44*67e74705SXin Li #define _TFIAR_PTR(TM_BUF) \
45*67e74705SXin Li ((tfiar_t *)((TM_BUF)+8))
46*67e74705SXin Li
47*67e74705SXin Li typedef char TM_buff_type[16];
48*67e74705SXin Li
49*67e74705SXin Li /* This macro can be used to determine whether a transaction was successfully
50*67e74705SXin Li started from the __TM_begin() and __TM_simple_begin() intrinsic functions
51*67e74705SXin Li below. */
52*67e74705SXin Li #define _HTM_TBEGIN_STARTED 1
53*67e74705SXin Li
54*67e74705SXin Li extern __inline long
55*67e74705SXin Li __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
__TM_simple_begin(void)56*67e74705SXin Li __TM_simple_begin (void)
57*67e74705SXin Li {
58*67e74705SXin Li if (__builtin_expect (__builtin_tbegin (0), 1))
59*67e74705SXin Li return _HTM_TBEGIN_STARTED;
60*67e74705SXin Li return 0;
61*67e74705SXin Li }
62*67e74705SXin Li
63*67e74705SXin Li extern __inline long
64*67e74705SXin Li __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
__TM_begin(void * const __TM_buff)65*67e74705SXin Li __TM_begin (void* const __TM_buff)
66*67e74705SXin Li {
67*67e74705SXin Li *_TEXASRL_PTR (__TM_buff) = 0;
68*67e74705SXin Li if (__builtin_expect (__builtin_tbegin (0), 1))
69*67e74705SXin Li return _HTM_TBEGIN_STARTED;
70*67e74705SXin Li #ifdef __powerpc64__
71*67e74705SXin Li *_TEXASR_PTR (__TM_buff) = __builtin_get_texasr ();
72*67e74705SXin Li #else
73*67e74705SXin Li *_TEXASRU_PTR (__TM_buff) = __builtin_get_texasru ();
74*67e74705SXin Li *_TEXASRL_PTR (__TM_buff) = __builtin_get_texasr ();
75*67e74705SXin Li #endif
76*67e74705SXin Li *_TFIAR_PTR (__TM_buff) = __builtin_get_tfiar ();
77*67e74705SXin Li return 0;
78*67e74705SXin Li }
79*67e74705SXin Li
80*67e74705SXin Li extern __inline long
81*67e74705SXin Li __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
__TM_end(void)82*67e74705SXin Li __TM_end (void)
83*67e74705SXin Li {
84*67e74705SXin Li if (__builtin_expect (__builtin_tend (0), 1))
85*67e74705SXin Li return 1;
86*67e74705SXin Li return 0;
87*67e74705SXin Li }
88*67e74705SXin Li
89*67e74705SXin Li extern __inline void
90*67e74705SXin Li __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
__TM_abort(void)91*67e74705SXin Li __TM_abort (void)
92*67e74705SXin Li {
93*67e74705SXin Li __builtin_tabort (0);
94*67e74705SXin Li }
95*67e74705SXin Li
96*67e74705SXin Li extern __inline void
97*67e74705SXin Li __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
__TM_named_abort(unsigned char const __code)98*67e74705SXin Li __TM_named_abort (unsigned char const __code)
99*67e74705SXin Li {
100*67e74705SXin Li __builtin_tabort (__code);
101*67e74705SXin Li }
102*67e74705SXin Li
103*67e74705SXin Li extern __inline void
104*67e74705SXin Li __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
__TM_resume(void)105*67e74705SXin Li __TM_resume (void)
106*67e74705SXin Li {
107*67e74705SXin Li __builtin_tresume ();
108*67e74705SXin Li }
109*67e74705SXin Li
110*67e74705SXin Li extern __inline void
111*67e74705SXin Li __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
__TM_suspend(void)112*67e74705SXin Li __TM_suspend (void)
113*67e74705SXin Li {
114*67e74705SXin Li __builtin_tsuspend ();
115*67e74705SXin Li }
116*67e74705SXin Li
117*67e74705SXin Li extern __inline long
118*67e74705SXin Li __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
__TM_is_user_abort(void * const __TM_buff)119*67e74705SXin Li __TM_is_user_abort (void* const __TM_buff)
120*67e74705SXin Li {
121*67e74705SXin Li texasru_t texasru = *_TEXASRU_PTR (__TM_buff);
122*67e74705SXin Li return _TEXASRU_ABORT (texasru);
123*67e74705SXin Li }
124*67e74705SXin Li
125*67e74705SXin Li extern __inline long
126*67e74705SXin Li __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
__TM_is_named_user_abort(void * const __TM_buff,unsigned char * __code)127*67e74705SXin Li __TM_is_named_user_abort (void* const __TM_buff, unsigned char *__code)
128*67e74705SXin Li {
129*67e74705SXin Li texasru_t texasru = *_TEXASRU_PTR (__TM_buff);
130*67e74705SXin Li
131*67e74705SXin Li *__code = _TEXASRU_FAILURE_CODE (texasru);
132*67e74705SXin Li return _TEXASRU_ABORT (texasru);
133*67e74705SXin Li }
134*67e74705SXin Li
135*67e74705SXin Li extern __inline long
136*67e74705SXin Li __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
__TM_is_illegal(void * const __TM_buff)137*67e74705SXin Li __TM_is_illegal (void* const __TM_buff)
138*67e74705SXin Li {
139*67e74705SXin Li texasru_t texasru = *_TEXASRU_PTR (__TM_buff);
140*67e74705SXin Li return _TEXASRU_DISALLOWED (texasru);
141*67e74705SXin Li }
142*67e74705SXin Li
143*67e74705SXin Li extern __inline long
144*67e74705SXin Li __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
__TM_is_footprint_exceeded(void * const __TM_buff)145*67e74705SXin Li __TM_is_footprint_exceeded (void* const __TM_buff)
146*67e74705SXin Li {
147*67e74705SXin Li texasru_t texasru = *_TEXASRU_PTR (__TM_buff);
148*67e74705SXin Li return _TEXASRU_FOOTPRINT_OVERFLOW (texasru);
149*67e74705SXin Li }
150*67e74705SXin Li
151*67e74705SXin Li extern __inline long
152*67e74705SXin Li __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
__TM_nesting_depth(void * const __TM_buff)153*67e74705SXin Li __TM_nesting_depth (void* const __TM_buff)
154*67e74705SXin Li {
155*67e74705SXin Li texasrl_t texasrl;
156*67e74705SXin Li
157*67e74705SXin Li if (_HTM_STATE (__builtin_ttest ()) == _HTM_NONTRANSACTIONAL)
158*67e74705SXin Li {
159*67e74705SXin Li texasrl = *_TEXASRL_PTR (__TM_buff);
160*67e74705SXin Li if (!_TEXASR_FAILURE_SUMMARY (texasrl))
161*67e74705SXin Li texasrl = 0;
162*67e74705SXin Li }
163*67e74705SXin Li else
164*67e74705SXin Li texasrl = (texasrl_t) __builtin_get_texasr ();
165*67e74705SXin Li
166*67e74705SXin Li return _TEXASR_TRANSACTION_LEVEL (texasrl);
167*67e74705SXin Li }
168*67e74705SXin Li
169*67e74705SXin Li extern __inline long
170*67e74705SXin Li __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
__TM_is_nested_too_deep(void * const __TM_buff)171*67e74705SXin Li __TM_is_nested_too_deep(void* const __TM_buff)
172*67e74705SXin Li {
173*67e74705SXin Li texasru_t texasru = *_TEXASRU_PTR (__TM_buff);
174*67e74705SXin Li return _TEXASRU_NESTING_OVERFLOW (texasru);
175*67e74705SXin Li }
176*67e74705SXin Li
177*67e74705SXin Li extern __inline long
178*67e74705SXin Li __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
__TM_is_conflict(void * const __TM_buff)179*67e74705SXin Li __TM_is_conflict(void* const __TM_buff)
180*67e74705SXin Li {
181*67e74705SXin Li texasru_t texasru = *_TEXASRU_PTR (TM_buff);
182*67e74705SXin Li /* Return TEXASR bits 11 (Self-Induced Conflict) through
183*67e74705SXin Li 14 (Translation Invalidation Conflict). */
184*67e74705SXin Li return (_TEXASRU_EXTRACT_BITS (texasru, 14, 4)) ? 1 : 0;
185*67e74705SXin Li }
186*67e74705SXin Li
187*67e74705SXin Li extern __inline long
188*67e74705SXin Li __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
__TM_is_failure_persistent(void * const __TM_buff)189*67e74705SXin Li __TM_is_failure_persistent(void* const __TM_buff)
190*67e74705SXin Li {
191*67e74705SXin Li texasru_t texasru = *_TEXASRU_PTR (__TM_buff);
192*67e74705SXin Li return _TEXASRU_FAILURE_PERSISTENT (texasru);
193*67e74705SXin Li }
194*67e74705SXin Li
195*67e74705SXin Li extern __inline long
196*67e74705SXin Li __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
__TM_failure_address(void * const __TM_buff)197*67e74705SXin Li __TM_failure_address(void* const __TM_buff)
198*67e74705SXin Li {
199*67e74705SXin Li return *_TFIAR_PTR (__TM_buff);
200*67e74705SXin Li }
201*67e74705SXin Li
202*67e74705SXin Li extern __inline long long
203*67e74705SXin Li __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
__TM_failure_code(void * const __TM_buff)204*67e74705SXin Li __TM_failure_code(void* const __TM_buff)
205*67e74705SXin Li {
206*67e74705SXin Li return *_TEXASR_PTR (__TM_buff);
207*67e74705SXin Li }
208*67e74705SXin Li
209*67e74705SXin Li #ifdef __cplusplus
210*67e74705SXin Li }
211*67e74705SXin Li #endif
212*67e74705SXin Li
213*67e74705SXin Li #endif /* __powerpc__ */
214*67e74705SXin Li
215*67e74705SXin Li #ifdef __s390__
216*67e74705SXin Li
217*67e74705SXin Li #include <stdint.h>
218*67e74705SXin Li
219*67e74705SXin Li /* These intrinsics are being made available for compatibility with
220*67e74705SXin Li the IBM XL compiler. For documentation please see the "z/OS XL
221*67e74705SXin Li C/C++ Programming Guide" publically available on the web. */
222*67e74705SXin Li
223*67e74705SXin Li static __inline long __attribute__((__always_inline__, __nodebug__))
__TM_simple_begin()224*67e74705SXin Li __TM_simple_begin ()
225*67e74705SXin Li {
226*67e74705SXin Li return __builtin_tbegin_nofloat (0);
227*67e74705SXin Li }
228*67e74705SXin Li
229*67e74705SXin Li static __inline long __attribute__((__always_inline__, __nodebug__))
__TM_begin(void * const __tdb)230*67e74705SXin Li __TM_begin (void* const __tdb)
231*67e74705SXin Li {
232*67e74705SXin Li return __builtin_tbegin_nofloat (__tdb);
233*67e74705SXin Li }
234*67e74705SXin Li
235*67e74705SXin Li static __inline long __attribute__((__always_inline__, __nodebug__))
__TM_end()236*67e74705SXin Li __TM_end ()
237*67e74705SXin Li {
238*67e74705SXin Li return __builtin_tend ();
239*67e74705SXin Li }
240*67e74705SXin Li
241*67e74705SXin Li static __inline void __attribute__((__always_inline__))
__TM_abort()242*67e74705SXin Li __TM_abort ()
243*67e74705SXin Li {
244*67e74705SXin Li return __builtin_tabort (_HTM_FIRST_USER_ABORT_CODE);
245*67e74705SXin Li }
246*67e74705SXin Li
247*67e74705SXin Li static __inline void __attribute__((__always_inline__, __nodebug__))
__TM_named_abort(unsigned char const __code)248*67e74705SXin Li __TM_named_abort (unsigned char const __code)
249*67e74705SXin Li {
250*67e74705SXin Li return __builtin_tabort ((int)_HTM_FIRST_USER_ABORT_CODE + __code);
251*67e74705SXin Li }
252*67e74705SXin Li
253*67e74705SXin Li static __inline void __attribute__((__always_inline__, __nodebug__))
__TM_non_transactional_store(void * const __addr,long long const __value)254*67e74705SXin Li __TM_non_transactional_store (void* const __addr, long long const __value)
255*67e74705SXin Li {
256*67e74705SXin Li __builtin_non_tx_store ((uint64_t*)__addr, (uint64_t)__value);
257*67e74705SXin Li }
258*67e74705SXin Li
259*67e74705SXin Li static __inline long __attribute__((__always_inline__, __nodebug__))
__TM_nesting_depth(void * const __tdb_ptr)260*67e74705SXin Li __TM_nesting_depth (void* const __tdb_ptr)
261*67e74705SXin Li {
262*67e74705SXin Li int depth = __builtin_tx_nesting_depth ();
263*67e74705SXin Li struct __htm_tdb *tdb = (struct __htm_tdb*)__tdb_ptr;
264*67e74705SXin Li
265*67e74705SXin Li if (depth != 0)
266*67e74705SXin Li return depth;
267*67e74705SXin Li
268*67e74705SXin Li if (tdb->format != 1)
269*67e74705SXin Li return 0;
270*67e74705SXin Li return tdb->nesting_depth;
271*67e74705SXin Li }
272*67e74705SXin Li
273*67e74705SXin Li /* Transaction failure diagnostics */
274*67e74705SXin Li
275*67e74705SXin Li static __inline long __attribute__((__always_inline__, __nodebug__))
__TM_is_user_abort(void * const __tdb_ptr)276*67e74705SXin Li __TM_is_user_abort (void* const __tdb_ptr)
277*67e74705SXin Li {
278*67e74705SXin Li struct __htm_tdb *tdb = (struct __htm_tdb*)__tdb_ptr;
279*67e74705SXin Li
280*67e74705SXin Li if (tdb->format != 1)
281*67e74705SXin Li return 0;
282*67e74705SXin Li
283*67e74705SXin Li return !!(tdb->abort_code >= _HTM_FIRST_USER_ABORT_CODE);
284*67e74705SXin Li }
285*67e74705SXin Li
286*67e74705SXin Li static __inline long __attribute__((__always_inline__, __nodebug__))
__TM_is_named_user_abort(void * const __tdb_ptr,unsigned char * __code)287*67e74705SXin Li __TM_is_named_user_abort (void* const __tdb_ptr, unsigned char* __code)
288*67e74705SXin Li {
289*67e74705SXin Li struct __htm_tdb *tdb = (struct __htm_tdb*)__tdb_ptr;
290*67e74705SXin Li
291*67e74705SXin Li if (tdb->format != 1)
292*67e74705SXin Li return 0;
293*67e74705SXin Li
294*67e74705SXin Li if (tdb->abort_code >= _HTM_FIRST_USER_ABORT_CODE)
295*67e74705SXin Li {
296*67e74705SXin Li *__code = tdb->abort_code - _HTM_FIRST_USER_ABORT_CODE;
297*67e74705SXin Li return 1;
298*67e74705SXin Li }
299*67e74705SXin Li return 0;
300*67e74705SXin Li }
301*67e74705SXin Li
302*67e74705SXin Li static __inline long __attribute__((__always_inline__, __nodebug__))
__TM_is_illegal(void * const __tdb_ptr)303*67e74705SXin Li __TM_is_illegal (void* const __tdb_ptr)
304*67e74705SXin Li {
305*67e74705SXin Li struct __htm_tdb *tdb = (struct __htm_tdb*)__tdb_ptr;
306*67e74705SXin Li
307*67e74705SXin Li return (tdb->format == 1
308*67e74705SXin Li && (tdb->abort_code == 4 /* unfiltered program interruption */
309*67e74705SXin Li || tdb->abort_code == 11 /* restricted instruction */));
310*67e74705SXin Li }
311*67e74705SXin Li
312*67e74705SXin Li static __inline long __attribute__((__always_inline__, __nodebug__))
__TM_is_footprint_exceeded(void * const __tdb_ptr)313*67e74705SXin Li __TM_is_footprint_exceeded (void* const __tdb_ptr)
314*67e74705SXin Li {
315*67e74705SXin Li struct __htm_tdb *tdb = (struct __htm_tdb*)__tdb_ptr;
316*67e74705SXin Li
317*67e74705SXin Li return (tdb->format == 1
318*67e74705SXin Li && (tdb->abort_code == 7 /* fetch overflow */
319*67e74705SXin Li || tdb->abort_code == 8 /* store overflow */));
320*67e74705SXin Li }
321*67e74705SXin Li
322*67e74705SXin Li static __inline long __attribute__((__always_inline__, __nodebug__))
__TM_is_nested_too_deep(void * const __tdb_ptr)323*67e74705SXin Li __TM_is_nested_too_deep (void* const __tdb_ptr)
324*67e74705SXin Li {
325*67e74705SXin Li struct __htm_tdb *tdb = (struct __htm_tdb*)__tdb_ptr;
326*67e74705SXin Li
327*67e74705SXin Li return tdb->format == 1 && tdb->abort_code == 13; /* depth exceeded */
328*67e74705SXin Li }
329*67e74705SXin Li
330*67e74705SXin Li static __inline long __attribute__((__always_inline__, __nodebug__))
__TM_is_conflict(void * const __tdb_ptr)331*67e74705SXin Li __TM_is_conflict (void* const __tdb_ptr)
332*67e74705SXin Li {
333*67e74705SXin Li struct __htm_tdb *tdb = (struct __htm_tdb*)__tdb_ptr;
334*67e74705SXin Li
335*67e74705SXin Li return (tdb->format == 1
336*67e74705SXin Li && (tdb->abort_code == 9 /* fetch conflict */
337*67e74705SXin Li || tdb->abort_code == 10 /* store conflict */));
338*67e74705SXin Li }
339*67e74705SXin Li
340*67e74705SXin Li static __inline long __attribute__((__always_inline__, __nodebug__))
__TM_is_failure_persistent(long const __result)341*67e74705SXin Li __TM_is_failure_persistent (long const __result)
342*67e74705SXin Li {
343*67e74705SXin Li return __result == _HTM_TBEGIN_PERSISTENT;
344*67e74705SXin Li }
345*67e74705SXin Li
346*67e74705SXin Li static __inline long __attribute__((__always_inline__, __nodebug__))
__TM_failure_address(void * const __tdb_ptr)347*67e74705SXin Li __TM_failure_address (void* const __tdb_ptr)
348*67e74705SXin Li {
349*67e74705SXin Li struct __htm_tdb *tdb = (struct __htm_tdb*)__tdb_ptr;
350*67e74705SXin Li return tdb->atia;
351*67e74705SXin Li }
352*67e74705SXin Li
353*67e74705SXin Li static __inline long __attribute__((__always_inline__, __nodebug__))
__TM_failure_code(void * const __tdb_ptr)354*67e74705SXin Li __TM_failure_code (void* const __tdb_ptr)
355*67e74705SXin Li {
356*67e74705SXin Li struct __htm_tdb *tdb = (struct __htm_tdb*)__tdb_ptr;
357*67e74705SXin Li
358*67e74705SXin Li return tdb->abort_code;
359*67e74705SXin Li }
360*67e74705SXin Li
361*67e74705SXin Li #endif /* __s390__ */
362*67e74705SXin Li
363*67e74705SXin Li #endif /* __HTMXLINTRIN_H */
364