| 1 | /* Shared HTM header. Emulate transactional execution facility intrinsics for |
| 2 | compilers and assemblers that do not support the intrinsics and instructions |
| 3 | yet. |
| 4 | |
| 5 | Copyright (C) 2015-2024 Free Software Foundation, Inc. |
| 6 | This file is part of the GNU C Library. |
| 7 | |
| 8 | The GNU C Library is free software; you can redistribute it and/or |
| 9 | modify it under the terms of the GNU Lesser General Public |
| 10 | License as published by the Free Software Foundation; either |
| 11 | version 2.1 of the License, or (at your option) any later version. |
| 12 | |
| 13 | The GNU C Library is distributed in the hope that it will be useful, |
| 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 16 | Lesser General Public License for more details. |
| 17 | |
| 18 | You should have received a copy of the GNU Lesser General Public |
| 19 | License along with the GNU C Library; if not, see |
| 20 | <https://www.gnu.org/licenses/>. */ |
| 21 | |
| 22 | #ifndef _HTM_H |
| 23 | #define _HTM_H 1 |
| 24 | |
| 25 | #ifdef __ASSEMBLER__ |
| 26 | |
| 27 | /* tbegin. */ |
| 28 | .macro TBEGIN |
| 29 | .long 0x7c00051d |
| 30 | .endm |
| 31 | |
| 32 | /* tend. 0 */ |
| 33 | .macro TEND |
| 34 | .long 0x7c00055d |
| 35 | .endm |
| 36 | |
| 37 | /* tabort. code */ |
| 38 | .macro TABORT code |
| 39 | .byte 0x7c |
| 40 | .byte \code |
| 41 | .byte 0x07 |
| 42 | .byte 0x1d |
| 43 | .endm |
| 44 | |
| 45 | /*"TEXASR - Transaction EXception And Summary Register" |
| 46 | mfspr %dst,130 */ |
| 47 | .macro TEXASR dst |
| 48 | mfspr \dst,130 |
| 49 | .endm |
| 50 | |
| 51 | #else |
| 52 | |
| 53 | #include <bits/endian.h> |
| 54 | |
| 55 | /* Official HTM intrinsics interface matching GCC, but works |
| 56 | on older GCC compatible compilers and binutils. |
| 57 | We should somehow detect if the compiler supports it, because |
| 58 | it may be able to generate slightly better code. */ |
| 59 | |
| 60 | #define TBEGIN ".long 0x7c00051d" |
| 61 | #define TEND ".long 0x7c00055d" |
| 62 | #if __BYTE_ORDER == __LITTLE_ENDIAN |
| 63 | # define TABORT ".byte 0x1d,0x07,%1,0x7c" |
| 64 | #else |
| 65 | # define TABORT ".byte 0x7c,%1,0x07,0x1d" |
| 66 | #endif |
| 67 | |
| 68 | #define __force_inline inline __attribute__((__always_inline__)) |
| 69 | |
| 70 | #ifndef __HTM__ |
| 71 | |
| 72 | #define (TEXASR,BITNUM,SIZE) \ |
| 73 | (((TEXASR) >> (31-(BITNUM))) & ((1<<(SIZE))-1)) |
| 74 | #define _TEXASRU_FAILURE_PERSISTENT(TEXASRU) \ |
| 75 | _TEXASRU_EXTRACT_BITS(TEXASRU, 7, 1) |
| 76 | |
| 77 | #define _tbegin() \ |
| 78 | ({ unsigned int __ret; \ |
| 79 | asm volatile ( \ |
| 80 | TBEGIN "\t\n" \ |
| 81 | "mfcr %0\t\n" \ |
| 82 | "rlwinm %0,%0,3,1\t\n" \ |
| 83 | "xori %0,%0,1\t\n" \ |
| 84 | : "=r" (__ret) : \ |
| 85 | : "cr0", "memory"); \ |
| 86 | __ret; \ |
| 87 | }) |
| 88 | |
| 89 | #define _tend() \ |
| 90 | ({ unsigned int __ret; \ |
| 91 | asm volatile ( \ |
| 92 | TEND "\t\n" \ |
| 93 | "mfcr %0\t\n" \ |
| 94 | "rlwinm %0,%0,3,1\t\n" \ |
| 95 | "xori %0,%0,1\t\n" \ |
| 96 | : "=r" (__ret) : \ |
| 97 | : "cr0", "memory"); \ |
| 98 | __ret; \ |
| 99 | }) |
| 100 | |
| 101 | #define _tabort(__code) \ |
| 102 | ({ unsigned int __ret; \ |
| 103 | asm volatile ( \ |
| 104 | TABORT "\t\n" \ |
| 105 | "mfcr %0\t\n" \ |
| 106 | "rlwinm %0,%0,3,1\t\n" \ |
| 107 | "xori %0,%0,1\t\n" \ |
| 108 | : "=r" (__ret) : "r" (__code) \ |
| 109 | : "cr0", "memory"); \ |
| 110 | __ret; \ |
| 111 | }) |
| 112 | |
| 113 | #define _texasru() \ |
| 114 | ({ unsigned long __ret; \ |
| 115 | asm volatile ( \ |
| 116 | "mfspr %0,131\t\n" \ |
| 117 | : "=r" (__ret)); \ |
| 118 | __ret; \ |
| 119 | }) |
| 120 | |
| 121 | #define __libc_tbegin(tdb) _tbegin () |
| 122 | #define __libc_tend(nested) _tend () |
| 123 | #define __libc_tabort(abortcode) _tabort (abortcode) |
| 124 | #define __builtin_get_texasru() _texasru () |
| 125 | |
| 126 | #else |
| 127 | # include <htmintrin.h> |
| 128 | |
| 129 | # ifdef __TM_FENCE__ |
| 130 | /* New GCC behavior. */ |
| 131 | # define __libc_tbegin(R) __builtin_tbegin (R) |
| 132 | # define __libc_tend(R) __builtin_tend (R) |
| 133 | # define __libc_tabort(R) __builtin_tabort (R) |
| 134 | # else |
| 135 | /* Workaround an old GCC behavior. Earlier releases of GCC 4.9 and 5.0, |
| 136 | didn't use to treat __builtin_tbegin, __builtin_tend and |
| 137 | __builtin_tabort as compiler barriers, moving instructions into and |
| 138 | out the transaction. |
| 139 | Remove this when glibc drops support for GCC 5.0. */ |
| 140 | # define __libc_tbegin(R) \ |
| 141 | ({ __asm__ volatile("" ::: "memory"); \ |
| 142 | unsigned int __ret = __builtin_tbegin (R); \ |
| 143 | __asm__ volatile("" ::: "memory"); \ |
| 144 | __ret; \ |
| 145 | }) |
| 146 | # define __libc_tabort(R) \ |
| 147 | ({ __asm__ volatile("" ::: "memory"); \ |
| 148 | unsigned int __ret = __builtin_tabort (R); \ |
| 149 | __asm__ volatile("" ::: "memory"); \ |
| 150 | __ret; \ |
| 151 | }) |
| 152 | # define __libc_tend(R) \ |
| 153 | ({ __asm__ volatile("" ::: "memory"); \ |
| 154 | unsigned int __ret = __builtin_tend (R); \ |
| 155 | __asm__ volatile("" ::: "memory"); \ |
| 156 | __ret; \ |
| 157 | }) |
| 158 | # endif /* __TM_FENCE__ */ |
| 159 | #endif /* __HTM__ */ |
| 160 | |
| 161 | #endif /* __ASSEMBLER__ */ |
| 162 | |
| 163 | /* Definitions used for TEXASR Failure code (bits 0:7). If the failure |
| 164 | should be persistent, the abort code must be odd. 0xd0 through 0xff |
| 165 | are reserved for the kernel and potential hypervisor. */ |
| 166 | #define _ABORT_PERSISTENT 0x01 /* An unspecified persistent abort. */ |
| 167 | #define _ABORT_LOCK_BUSY 0x34 /* Busy lock, not persistent. */ |
| 168 | #define _ABORT_NESTED_TRYLOCK (0x32 | _ABORT_PERSISTENT) |
| 169 | #define _ABORT_SYSCALL (0x30 | _ABORT_PERSISTENT) |
| 170 | |
| 171 | #endif |
| 172 | |