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-2022 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 | |