xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/s390/htmxlintrin.h (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
1 /* XL compiler hardware transactional execution intrinsics
2    Copyright (C) 2013-2020 Free Software Foundation, Inc.
3    Contributed by Andreas Krebbel (Andreas.Krebbel@de.ibm.com)
4 
5 This file is part of GCC.
6 
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
11 
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3.  If not see
19 <http://www.gnu.org/licenses/>.  */
20 
21 #ifndef _HTMXLINTRIN_H
22 #define _HTMXLINTRIN_H
23 
24 #include <stdint.h>
25 
26 #include <htmintrin.h>
27 
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31 
32 /* These intrinsics are being made available for compatibility with
33    the IBM XL compiler.  For documentation please see the "z/OS XL
34    C/C++ Programming Guide" publicly available on the web.  */
35 
36 /* FIXME: __TM_simple_begin and __TM_begin should be marked
37    __always_inline__ as well but this currently produces an error
38    since the tbegin builtins are "returns_twice" and setjmp_call_p
39    (calls.c) therefore identifies the functions as calling setjmp.
40    The tree inliner currently refuses to inline functions calling
41    setjmp.  */
42 
43 long
__TM_simple_begin()44 __TM_simple_begin ()
45 {
46   return __builtin_tbegin_nofloat (0);
47 }
48 
49 long
__TM_begin(void * const tdb)50 __TM_begin (void* const tdb)
51 {
52   return __builtin_tbegin_nofloat (tdb);
53 }
54 
55 extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_end()56 __TM_end ()
57 {
58   return __builtin_tend ();
59 }
60 
61 extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_abort()62 __TM_abort ()
63 {
64   return __builtin_tabort (_HTM_FIRST_USER_ABORT_CODE);
65 }
66 
67 extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_named_abort(unsigned char const code)68 __TM_named_abort (unsigned char const code)
69 {
70   return __builtin_tabort ((int)_HTM_FIRST_USER_ABORT_CODE + code);
71 }
72 
73 extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_non_transactional_store(void * const addr,long long const value)74 __TM_non_transactional_store (void* const addr, long long const value)
75 {
76   __builtin_non_tx_store ((uint64_t*)addr, (uint64_t)value);
77 }
78 
79 extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_nesting_depth(void * const tdb_ptr)80 __TM_nesting_depth (void* const tdb_ptr)
81 {
82   int depth = __builtin_tx_nesting_depth ();
83   struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
84 
85   if (depth != 0)
86     return depth;
87 
88   if (tdb->format != 1)
89     return 0;
90   return tdb->nesting_depth;
91 }
92 
93 /* Transaction failure diagnostics */
94 
95 extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_is_user_abort(void * const tdb_ptr)96 __TM_is_user_abort (void* const tdb_ptr)
97 {
98   struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
99 
100   if (tdb->format != 1)
101     return 0;
102 
103   return !!(tdb->abort_code >= _HTM_FIRST_USER_ABORT_CODE);
104 }
105 
106 extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_is_named_user_abort(void * const tdb_ptr,unsigned char * code)107 __TM_is_named_user_abort (void* const tdb_ptr, unsigned char* code)
108 {
109   struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
110 
111   if (tdb->format != 1)
112     return 0;
113 
114   if (tdb->abort_code >= _HTM_FIRST_USER_ABORT_CODE)
115     {
116       *code = tdb->abort_code - _HTM_FIRST_USER_ABORT_CODE;
117       return 1;
118     }
119   return 0;
120 }
121 
122 extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_is_illegal(void * const tdb_ptr)123 __TM_is_illegal (void* const tdb_ptr)
124 {
125   struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
126 
127   return (tdb->format == 1
128 	  && (tdb->abort_code == 4 /* unfiltered program interruption */
129 	      || tdb->abort_code == 11 /* restricted instruction */));
130 }
131 
132 extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_is_footprint_exceeded(void * const tdb_ptr)133 __TM_is_footprint_exceeded (void* const tdb_ptr)
134 {
135   struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
136 
137   return (tdb->format == 1
138 	  && (tdb->abort_code == 7 /* fetch overflow */
139 	      || tdb->abort_code == 8 /* store overflow */));
140 }
141 
142 extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_is_nested_too_deep(void * const tdb_ptr)143 __TM_is_nested_too_deep (void* const tdb_ptr)
144 {
145   struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
146 
147   return tdb->format == 1 && tdb->abort_code == 13; /* depth exceeded */
148 }
149 
150 extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_is_conflict(void * const tdb_ptr)151 __TM_is_conflict (void* const tdb_ptr)
152 {
153   struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
154 
155   return (tdb->format == 1
156 	  && (tdb->abort_code == 9 /* fetch conflict */
157 	      || tdb->abort_code == 10 /* store conflict */));
158 }
159 
160 extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_is_failure_persistent(long const result)161 __TM_is_failure_persistent (long const result)
162 {
163   return result == _HTM_TBEGIN_PERSISTENT;
164 }
165 
166 extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_failure_address(void * const tdb_ptr)167 __TM_failure_address (void* const tdb_ptr)
168 {
169   struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
170 #ifdef __s390x__
171   return tdb->atia;
172 #else
173   return tdb->atia & 0xffffffff;
174 #endif
175 }
176 
177 extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_failure_code(void * const tdb_ptr)178 __TM_failure_code (void* const tdb_ptr)
179 {
180   struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
181 
182   return tdb->abort_code;
183 }
184 
185 #ifdef __cplusplus
186 }
187 #endif
188 
189 #endif /* _HTMXLINTRIN_H */
190