1 /* XL compiler hardware transactional execution intrinsics 2 Copyright (C) 2013-2019 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 44 __TM_simple_begin () 45 { 46 return __builtin_tbegin_nofloat (0); 47 } 48 49 long 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__)) 56 __TM_end () 57 { 58 return __builtin_tend (); 59 } 60 61 extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) 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__)) 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__)) 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__)) 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__)) 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__)) 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__)) 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__)) 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__)) 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__)) 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__)) 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__)) 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__)) 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