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