| /* XL compiler hardware transactional execution intrinsics |
| Copyright (C) 2013-2022 Free Software Foundation, Inc. |
| Contributed by Andreas Krebbel (Andreas.Krebbel@de.ibm.com) |
| |
| This file is part of GCC. |
| |
| GCC is free software; you can redistribute it and/or modify it under |
| the terms of the GNU General Public License as published by the Free |
| Software Foundation; either version 3, or (at your option) any later |
| version. |
| |
| GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
| WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GCC; see the file COPYING3. If not see |
| <http://www.gnu.org/licenses/>. */ |
| |
| #ifndef _HTMXLINTRIN_H |
| #define _HTMXLINTRIN_H |
| |
| #include <stdint.h> |
| |
| #include <htmintrin.h> |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| /* These intrinsics are being made available for compatibility with |
| the IBM XL compiler. For documentation please see the "z/OS XL |
| C/C++ Programming Guide" publicly available on the web. */ |
| |
| /* FIXME: __TM_simple_begin and __TM_begin should be marked |
| __always_inline__ as well but this currently produces an error |
| since the tbegin builtins are "returns_twice" and setjmp_call_p |
| (calls.cc) therefore identifies the functions as calling setjmp. |
| The tree inliner currently refuses to inline functions calling |
| setjmp. */ |
| |
| long |
| __TM_simple_begin () |
| { |
| return __builtin_tbegin_nofloat (0); |
| } |
| |
| long |
| __TM_begin (void* const tdb) |
| { |
| return __builtin_tbegin_nofloat (tdb); |
| } |
| |
| extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) |
| __TM_end () |
| { |
| return __builtin_tend (); |
| } |
| |
| extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) |
| __TM_abort () |
| { |
| return __builtin_tabort (_HTM_FIRST_USER_ABORT_CODE); |
| } |
| |
| extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) |
| __TM_named_abort (unsigned char const code) |
| { |
| return __builtin_tabort ((int)_HTM_FIRST_USER_ABORT_CODE + code); |
| } |
| |
| extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) |
| __TM_non_transactional_store (void* const addr, long long const value) |
| { |
| __builtin_non_tx_store ((uint64_t*)addr, (uint64_t)value); |
| } |
| |
| extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) |
| __TM_nesting_depth (void* const tdb_ptr) |
| { |
| int depth = __builtin_tx_nesting_depth (); |
| struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr; |
| |
| if (depth != 0) |
| return depth; |
| |
| if (tdb->format != 1) |
| return 0; |
| return tdb->nesting_depth; |
| } |
| |
| /* Transaction failure diagnostics */ |
| |
| extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) |
| __TM_is_user_abort (void* const tdb_ptr) |
| { |
| struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr; |
| |
| if (tdb->format != 1) |
| return 0; |
| |
| return !!(tdb->abort_code >= _HTM_FIRST_USER_ABORT_CODE); |
| } |
| |
| extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) |
| __TM_is_named_user_abort (void* const tdb_ptr, unsigned char* code) |
| { |
| struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr; |
| |
| if (tdb->format != 1) |
| return 0; |
| |
| if (tdb->abort_code >= _HTM_FIRST_USER_ABORT_CODE) |
| { |
| *code = tdb->abort_code - _HTM_FIRST_USER_ABORT_CODE; |
| return 1; |
| } |
| return 0; |
| } |
| |
| extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) |
| __TM_is_illegal (void* const tdb_ptr) |
| { |
| struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr; |
| |
| return (tdb->format == 1 |
| && (tdb->abort_code == 4 /* unfiltered program interruption */ |
| || tdb->abort_code == 11 /* restricted instruction */)); |
| } |
| |
| extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) |
| __TM_is_footprint_exceeded (void* const tdb_ptr) |
| { |
| struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr; |
| |
| return (tdb->format == 1 |
| && (tdb->abort_code == 7 /* fetch overflow */ |
| || tdb->abort_code == 8 /* store overflow */)); |
| } |
| |
| extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) |
| __TM_is_nested_too_deep (void* const tdb_ptr) |
| { |
| struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr; |
| |
| return tdb->format == 1 && tdb->abort_code == 13; /* depth exceeded */ |
| } |
| |
| extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) |
| __TM_is_conflict (void* const tdb_ptr) |
| { |
| struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr; |
| |
| return (tdb->format == 1 |
| && (tdb->abort_code == 9 /* fetch conflict */ |
| || tdb->abort_code == 10 /* store conflict */)); |
| } |
| |
| extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) |
| __TM_is_failure_persistent (long const result) |
| { |
| return result == _HTM_TBEGIN_PERSISTENT; |
| } |
| |
| extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) |
| __TM_failure_address (void* const tdb_ptr) |
| { |
| struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr; |
| #ifdef __s390x__ |
| return tdb->atia; |
| #else |
| return tdb->atia & 0xffffffff; |
| #endif |
| } |
| |
| extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) |
| __TM_failure_code (void* const tdb_ptr) |
| { |
| struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr; |
| |
| return tdb->abort_code; |
| } |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* _HTMXLINTRIN_H */ |