1/* XL compiler hardware transactional execution intrinsics 2 Copyright (C) 2013-2015 Free Software Foundation, Inc. 3 Contributed by Andreas Krebbel (Andreas.Krebbel@de.ibm.com) 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify it under 8the terms of the GNU General Public License as published by the Free 9Software Foundation; either version 3, or (at your option) any later 10version. 11 12GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13WARRANTY; without even the implied warranty of MERCHANTABILITY or 14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15for more details. 16 17You should have received a copy of the GNU General Public License 18along 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 29extern "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 43long 44__TM_simple_begin () 45{ 46 return __builtin_tbegin_nofloat (0); 47} 48 49long 50__TM_begin (void* const tdb) 51{ 52 return __builtin_tbegin_nofloat (tdb); 53} 54 55extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) 56__TM_end () 57{ 58 return __builtin_tend (); 59} 60 61extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) 62__TM_abort () 63{ 64 return __builtin_tabort (_HTM_FIRST_USER_ABORT_CODE); 65} 66 67extern __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 73extern __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 79extern __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 95extern __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 106extern __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 122extern __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 132extern __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 142extern __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 150extern __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 160extern __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 166extern __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 177extern __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